2017-10-23 15:02:50 +00:00
#!/usr/bin/env node
2020-03-20 20:28:31 +00:00
if ( ! process . env . CI ) require ( 'dotenv-safe' ) . load ( ) ;
2019-08-29 14:46:54 +00:00
2018-12-20 03:36:01 +00:00
const args = require ( 'minimist' ) ( process . argv . slice ( 2 ) , {
boolean : [
'validateRelease' ,
2019-01-23 19:47:36 +00:00
'verboseNugget'
] ,
2020-03-20 15:12:18 +00:00
default : { verboseNugget : false }
2020-03-20 20:28:31 +00:00
} ) ;
const fs = require ( 'fs' ) ;
const { execSync } = require ( 'child_process' ) ;
const got = require ( 'got' ) ;
const pkg = require ( '../../package.json' ) ;
const pkgVersion = ` v ${ pkg . version } ` ;
const path = require ( 'path' ) ;
const temp = require ( 'temp' ) . track ( ) ;
const { URL } = require ( 'url' ) ;
2020-08-05 15:59:52 +00:00
const { Octokit } = require ( '@octokit/rest' ) ;
2020-09-30 20:30:10 +00:00
const AWS = require ( 'aws-sdk' ) ;
2020-03-20 20:28:31 +00:00
require ( 'colors' ) ;
const pass = '✓' . green ;
const fail = '✗' . red ;
const { ELECTRON _DIR } = require ( '../lib/utils' ) ;
2021-05-11 16:30:35 +00:00
const getUrlHash = require ( './get-url-hash' ) ;
2019-06-24 17:18:04 +00:00
2020-08-05 15:59:52 +00:00
const octokit = new Octokit ( {
2019-05-08 01:48:40 +00:00
auth : process . env . ELECTRON _GITHUB _TOKEN
2020-03-20 20:28:31 +00:00
} ) ;
2019-01-08 20:05:58 +00:00
2020-03-20 20:28:31 +00:00
const targetRepo = pkgVersion . indexOf ( 'nightly' ) > 0 ? 'nightlies' : 'electron' ;
let failureCount = 0 ;
2017-10-23 15:02:50 +00:00
async function getDraftRelease ( version , skipValidation ) {
2019-01-08 20:05:58 +00:00
const releaseInfo = await octokit . repos . listReleases ( {
owner : 'electron' ,
repo : targetRepo
2020-03-20 20:28:31 +00:00
} ) ;
2019-01-08 20:05:58 +00:00
2020-03-20 20:28:31 +00:00
const versionToCheck = version || pkgVersion ;
2019-01-08 20:05:58 +00:00
const drafts = releaseInfo . data . filter ( release => {
2020-03-20 20:28:31 +00:00
return release . tag _name === versionToCheck && release . draft === true ;
} ) ;
2019-01-08 20:05:58 +00:00
2020-03-20 20:28:31 +00:00
const draft = drafts [ 0 ] ;
2017-10-23 15:02:50 +00:00
if ( ! skipValidation ) {
2020-03-20 20:28:31 +00:00
failureCount = 0 ;
check ( drafts . length === 1 , 'one draft exists' , true ) ;
2018-01-31 00:35:16 +00:00
if ( versionToCheck . indexOf ( 'beta' ) > - 1 ) {
2020-03-20 20:28:31 +00:00
check ( draft . prerelease , 'draft is a prerelease' ) ;
2017-10-23 15:02:50 +00:00
}
2020-03-20 20:28:31 +00:00
check ( draft . body . length > 50 && ! draft . body . includes ( '(placeholder)' ) , 'draft has release notes' ) ;
check ( ( failureCount === 0 ) , 'Draft release looks good to go.' , true ) ;
2017-10-23 15:02:50 +00:00
}
2020-03-20 20:28:31 +00:00
return draft ;
2017-10-23 15:02:50 +00:00
}
2018-01-31 23:40:38 +00:00
async function validateReleaseAssets ( release , validatingRelease ) {
2020-03-20 20:28:31 +00:00
const requiredAssets = assetsForVersion ( release . tag _name , validatingRelease ) . sort ( ) ;
const extantAssets = release . assets . map ( asset => asset . name ) . sort ( ) ;
2021-05-11 16:30:35 +00:00
const downloadUrls = release . assets . map ( asset => ( { url : asset . browser _download _url , file : asset . name } ) ) . sort ( ( a , b ) => a . file . localeCompare ( b . file ) ) ;
2017-10-23 15:02:50 +00:00
2020-03-20 20:28:31 +00:00
failureCount = 0 ;
2017-10-23 15:02:50 +00:00
requiredAssets . forEach ( asset => {
2020-03-20 20:28:31 +00:00
check ( extantAssets . includes ( asset ) , asset ) ;
} ) ;
check ( ( failureCount === 0 ) , 'All required GitHub assets exist for release' , true ) ;
2017-10-23 15:02:50 +00:00
2018-02-22 13:53:32 +00:00
if ( ! validatingRelease || ! release . draft ) {
if ( release . draft ) {
2021-05-11 16:30:35 +00:00
await verifyDraftGitHubReleaseAssets ( release ) ;
2018-02-22 13:53:32 +00:00
} else {
2021-05-11 16:30:35 +00:00
await verifyShasumsForRemoteFiles ( downloadUrls )
2018-02-22 13:53:32 +00:00
. catch ( err => {
2020-03-20 20:28:31 +00:00
console . log ( ` ${ fail } error verifyingShasums ` , err ) ;
} ) ;
2018-02-22 13:53:32 +00:00
}
2021-05-11 16:30:35 +00:00
const s3RemoteFiles = s3RemoteFilesForVersion ( release . tag _name ) ;
await verifyShasumsForRemoteFiles ( s3RemoteFiles , true ) ;
2017-10-23 15:02:50 +00:00
}
}
function check ( condition , statement , exitIfFail = false ) {
if ( condition ) {
2020-03-20 20:28:31 +00:00
console . log ( ` ${ pass } ${ statement } ` ) ;
2017-10-23 15:02:50 +00:00
} else {
2020-03-20 20:28:31 +00:00
failureCount ++ ;
console . log ( ` ${ fail } ${ statement } ` ) ;
if ( exitIfFail ) process . exit ( 1 ) ;
2017-10-23 15:02:50 +00:00
}
}
2018-01-31 23:40:38 +00:00
function assetsForVersion ( version , validatingRelease ) {
2017-10-23 15:02:50 +00:00
const patterns = [
2019-09-04 18:24:46 +00:00
` chromedriver- ${ version } -darwin-x64.zip ` ,
2020-07-21 11:55:00 +00:00
` chromedriver- ${ version } -darwin-arm64.zip ` ,
2019-09-04 18:24:46 +00:00
` chromedriver- ${ version } -linux-arm64.zip ` ,
` chromedriver- ${ version } -linux-armv7l.zip ` ,
` chromedriver- ${ version } -linux-ia32.zip ` ,
` chromedriver- ${ version } -linux-x64.zip ` ,
` chromedriver- ${ version } -mas-x64.zip ` ,
2020-07-21 11:55:00 +00:00
` chromedriver- ${ version } -mas-arm64.zip ` ,
2019-09-04 18:24:46 +00:00
` chromedriver- ${ version } -win32-ia32.zip ` ,
` chromedriver- ${ version } -win32-x64.zip ` ,
` chromedriver- ${ version } -win32-arm64.zip ` ,
2017-10-23 15:02:50 +00:00
` electron- ${ version } -darwin-x64-dsym.zip ` ,
` electron- ${ version } -darwin-x64-symbols.zip ` ,
` electron- ${ version } -darwin-x64.zip ` ,
2020-07-21 11:55:00 +00:00
` electron- ${ version } -darwin-arm64-dsym.zip ` ,
` electron- ${ version } -darwin-arm64-symbols.zip ` ,
` electron- ${ version } -darwin-arm64.zip ` ,
2019-01-22 21:14:01 +00:00
` electron- ${ version } -linux-arm64-symbols.zip ` ,
` electron- ${ version } -linux-arm64.zip ` ,
` electron- ${ version } -linux-armv7l-symbols.zip ` ,
` electron- ${ version } -linux-armv7l.zip ` ,
2017-10-23 15:02:50 +00:00
` electron- ${ version } -linux-ia32-symbols.zip ` ,
` electron- ${ version } -linux-ia32.zip ` ,
2019-11-21 01:21:44 +00:00
` electron- ${ version } -linux-x64-debug.zip ` ,
2017-10-23 15:02:50 +00:00
` electron- ${ version } -linux-x64-symbols.zip ` ,
` electron- ${ version } -linux-x64.zip ` ,
` electron- ${ version } -mas-x64-dsym.zip ` ,
` electron- ${ version } -mas-x64-symbols.zip ` ,
` electron- ${ version } -mas-x64.zip ` ,
2020-07-21 11:55:00 +00:00
` electron- ${ version } -mas-arm64-dsym.zip ` ,
` electron- ${ version } -mas-arm64-symbols.zip ` ,
` electron- ${ version } -mas-arm64.zip ` ,
2017-10-23 15:02:50 +00:00
` electron- ${ version } -win32-ia32-pdb.zip ` ,
` electron- ${ version } -win32-ia32-symbols.zip ` ,
` electron- ${ version } -win32-ia32.zip ` ,
` electron- ${ version } -win32-x64-pdb.zip ` ,
` electron- ${ version } -win32-x64-symbols.zip ` ,
` electron- ${ version } -win32-x64.zip ` ,
2019-09-04 18:24:46 +00:00
` electron- ${ version } -win32-arm64-pdb.zip ` ,
` electron- ${ version } -win32-arm64-symbols.zip ` ,
` electron- ${ version } -win32-arm64.zip ` ,
2020-03-20 15:12:18 +00:00
'electron-api.json' ,
'electron.d.ts' ,
'hunspell_dictionaries.zip' ,
2021-05-22 18:48:38 +00:00
'libcxx_headers.zip' ,
'libcxxabi_headers.zip' ,
` libcxx-objects- ${ version } -linux-arm64.zip ` ,
` libcxx-objects- ${ version } -linux-armv7l.zip ` ,
` libcxx-objects- ${ version } -linux-ia32.zip ` ,
` libcxx-objects- ${ version } -linux-x64.zip ` ,
2017-10-23 15:02:50 +00:00
` ffmpeg- ${ version } -darwin-x64.zip ` ,
2020-07-21 11:55:00 +00:00
` ffmpeg- ${ version } -darwin-arm64.zip ` ,
2019-01-22 21:14:01 +00:00
` ffmpeg- ${ version } -linux-arm64.zip ` ,
` ffmpeg- ${ version } -linux-armv7l.zip ` ,
2017-10-23 15:02:50 +00:00
` ffmpeg- ${ version } -linux-ia32.zip ` ,
` ffmpeg- ${ version } -linux-x64.zip ` ,
` ffmpeg- ${ version } -mas-x64.zip ` ,
2020-07-21 11:55:00 +00:00
` ffmpeg- ${ version } -mas-arm64.zip ` ,
2017-10-23 15:02:50 +00:00
` ffmpeg- ${ version } -win32-ia32.zip ` ,
2019-09-04 18:24:46 +00:00
` ffmpeg- ${ version } -win32-x64.zip ` ,
` ffmpeg- ${ version } -win32-arm64.zip ` ,
` mksnapshot- ${ version } -darwin-x64.zip ` ,
2020-07-21 11:55:00 +00:00
` mksnapshot- ${ version } -darwin-arm64.zip ` ,
2019-09-04 18:24:46 +00:00
` mksnapshot- ${ version } -linux-arm64-x64.zip ` ,
` mksnapshot- ${ version } -linux-armv7l-x64.zip ` ,
` mksnapshot- ${ version } -linux-ia32.zip ` ,
` mksnapshot- ${ version } -linux-x64.zip ` ,
` mksnapshot- ${ version } -mas-x64.zip ` ,
2020-07-21 11:55:00 +00:00
` mksnapshot- ${ version } -mas-arm64.zip ` ,
2019-09-04 18:24:46 +00:00
` mksnapshot- ${ version } -win32-ia32.zip ` ,
` mksnapshot- ${ version } -win32-x64.zip ` ,
2020-01-13 20:40:13 +00:00
` mksnapshot- ${ version } -win32-arm64-x64.zip ` ,
2020-01-14 22:10:08 +00:00
` electron- ${ version } -win32-ia32-toolchain-profile.zip ` ,
` electron- ${ version } -win32-x64-toolchain-profile.zip ` ,
` electron- ${ version } -win32-arm64-toolchain-profile.zip `
2020-03-20 20:28:31 +00:00
] ;
2018-01-31 23:40:38 +00:00
if ( ! validatingRelease ) {
2020-03-20 20:28:31 +00:00
patterns . push ( 'SHASUMS256.txt' ) ;
2018-01-31 23:40:38 +00:00
}
2020-03-20 20:28:31 +00:00
return patterns ;
2017-10-23 15:02:50 +00:00
}
2021-05-11 16:30:35 +00:00
function s3RemoteFilesForVersion ( version ) {
2020-03-20 20:28:31 +00:00
const bucket = 'https://gh-contractor-zcbenz.s3.amazonaws.com/' ;
2021-05-11 16:30:35 +00:00
const versionPrefix = ` ${ bucket } atom-shell/dist/ ${ version } / ` ;
const filePaths = [
` iojs- ${ version } -headers.tar.gz ` ,
` iojs- ${ version } .tar.gz ` ,
` node- ${ version } .tar.gz ` ,
'node.lib' ,
'x64/node.lib' ,
'win-x64/iojs.lib' ,
'win-x86/iojs.lib' ,
'win-arm64/iojs.lib' ,
'win-x64/node.lib' ,
'win-x86/node.lib' ,
'win-arm64/node.lib' ,
'arm64/node.lib' ,
'SHASUMS.txt' ,
'SHASUMS256.txt'
2020-03-20 20:28:31 +00:00
] ;
2021-05-11 16:30:35 +00:00
return filePaths . map ( ( filePath ) => ( {
file : filePath ,
url : ` ${ versionPrefix } ${ filePath } `
} ) ) ;
2017-10-23 15:02:50 +00:00
}
function runScript ( scriptName , scriptArgs , cwd ) {
2020-03-20 20:28:31 +00:00
const scriptCommand = ` ${ scriptName } ${ scriptArgs . join ( ' ' ) } ` ;
2018-10-02 01:56:31 +00:00
const scriptOptions = {
2017-10-23 15:02:50 +00:00
encoding : 'UTF-8'
2020-03-20 20:28:31 +00:00
} ;
if ( cwd ) scriptOptions . cwd = cwd ;
2017-10-23 15:02:50 +00:00
try {
2020-03-20 20:28:31 +00:00
return execSync ( scriptCommand , scriptOptions ) ;
2017-10-23 15:02:50 +00:00
} catch ( err ) {
2020-03-20 20:28:31 +00:00
console . log ( ` ${ fail } Error running ${ scriptName } ` , err ) ;
process . exit ( 1 ) ;
2017-10-23 15:02:50 +00:00
}
}
function uploadNodeShasums ( ) {
2020-03-20 20:28:31 +00:00
console . log ( 'Uploading Node SHASUMS file to S3.' ) ;
const scriptPath = path . join ( ELECTRON _DIR , 'script' , 'release' , 'uploaders' , 'upload-node-checksums.py' ) ;
runScript ( scriptPath , [ '-v' , pkgVersion ] ) ;
console . log ( ` ${ pass } Done uploading Node SHASUMS file to S3. ` ) ;
2017-10-23 15:02:50 +00:00
}
function uploadIndexJson ( ) {
2020-03-20 20:28:31 +00:00
console . log ( 'Uploading index.json to S3.' ) ;
const scriptPath = path . join ( ELECTRON _DIR , 'script' , 'release' , 'uploaders' , 'upload-index-json.py' ) ;
runScript ( scriptPath , [ pkgVersion ] ) ;
console . log ( ` ${ pass } Done uploading index.json to S3. ` ) ;
2017-10-23 15:02:50 +00:00
}
2020-09-30 20:30:10 +00:00
async function mergeShasums ( pkgVersion ) {
// Download individual checksum files for Electron zip files from S3,
// concatenate them, and upload to GitHub.
const bucket = process . env . ELECTRON _S3 _BUCKET ;
const accessKeyId = process . env . ELECTRON _S3 _ACCESS _KEY ;
const secretAccessKey = process . env . ELECTRON _S3 _SECRET _KEY ;
if ( ! bucket || ! accessKeyId || ! secretAccessKey ) {
throw new Error ( 'Please set the $ELECTRON_S3_BUCKET, $ELECTRON_S3_ACCESS_KEY, and $ELECTRON_S3_SECRET_KEY environment variables' ) ;
}
const s3 = new AWS . S3 ( {
apiVersion : '2006-03-01' ,
accessKeyId ,
secretAccessKey ,
region : 'us-west-2'
} ) ;
const objects = await s3 . listObjectsV2 ( {
Bucket : bucket ,
Prefix : ` atom-shell/tmp/ ${ pkgVersion } / ` ,
Delimiter : '/'
} ) . promise ( ) ;
const shasums = [ ] ;
for ( const obj of objects . Contents ) {
if ( obj . Key . endsWith ( '.sha256sum' ) ) {
const data = await s3 . getObject ( {
Bucket : bucket ,
Key : obj . Key
} ) . promise ( ) ;
2020-10-02 20:26:29 +00:00
shasums . push ( data . Body . toString ( 'ascii' ) . trim ( ) ) ;
2020-09-30 20:30:10 +00:00
}
}
return shasums . join ( '\n' ) ;
}
2017-10-23 15:02:50 +00:00
async function createReleaseShasums ( release ) {
2020-03-20 20:28:31 +00:00
const fileName = 'SHASUMS256.txt' ;
const existingAssets = release . assets . filter ( asset => asset . name === fileName ) ;
2017-10-23 15:02:50 +00:00
if ( existingAssets . length > 0 ) {
2020-03-20 20:28:31 +00:00
console . log ( ` ${ fileName } already exists on GitHub; deleting before creating new file. ` ) ;
2019-01-08 20:05:58 +00:00
await octokit . repos . deleteReleaseAsset ( {
2017-10-23 15:02:50 +00:00
owner : 'electron' ,
2018-08-16 15:57:12 +00:00
repo : targetRepo ,
2019-01-08 20:05:58 +00:00
asset _id : existingAssets [ 0 ] . id
2017-10-23 15:02:50 +00:00
} ) . catch ( err => {
2020-03-20 20:28:31 +00:00
console . log ( ` ${ fail } Error deleting ${ fileName } on GitHub: ` , err ) ;
} ) ;
2017-10-23 15:02:50 +00:00
}
2020-03-20 20:28:31 +00:00
console . log ( ` Creating and uploading the release ${ fileName } . ` ) ;
2020-09-30 20:30:10 +00:00
const checksums = await mergeShasums ( pkgVersion ) ;
2019-01-08 20:05:58 +00:00
2020-03-20 20:28:31 +00:00
console . log ( ` ${ pass } Generated release SHASUMS. ` ) ;
const filePath = await saveShaSumFile ( checksums , fileName ) ;
2019-01-08 20:05:58 +00:00
2020-03-20 20:28:31 +00:00
console . log ( ` ${ pass } Created ${ fileName } file. ` ) ;
await uploadShasumFile ( filePath , fileName , release . id ) ;
2019-01-08 20:05:58 +00:00
2020-03-20 20:28:31 +00:00
console . log ( ` ${ pass } Successfully uploaded ${ fileName } to GitHub. ` ) ;
2017-10-23 15:02:50 +00:00
}
2019-01-08 20:05:58 +00:00
async function uploadShasumFile ( filePath , fileName , releaseId ) {
2020-03-20 20:28:31 +00:00
const uploadUrl = ` https://uploads.github.com/repos/electron/ ${ targetRepo } /releases/ ${ releaseId } /assets{?name,label} ` ;
2019-01-08 20:05:58 +00:00
return octokit . repos . uploadReleaseAsset ( {
url : uploadUrl ,
headers : {
'content-type' : 'text/plain' ,
2019-01-11 17:53:13 +00:00
'content-length' : fs . statSync ( filePath ) . size
2019-01-08 20:05:58 +00:00
} ,
2020-08-07 19:00:12 +00:00
data : fs . createReadStream ( filePath ) ,
2017-10-23 15:02:50 +00:00
name : fileName
2019-01-08 20:05:58 +00:00
} ) . catch ( err => {
2020-03-20 20:28:31 +00:00
console . log ( ` ${ fail } Error uploading ${ filePath } to GitHub: ` , err ) ;
process . exit ( 1 ) ;
} ) ;
2017-10-23 15:02:50 +00:00
}
function saveShaSumFile ( checksums , fileName ) {
return new Promise ( ( resolve , reject ) => {
temp . open ( fileName , ( err , info ) => {
if ( err ) {
2020-03-20 20:28:31 +00:00
console . log ( ` ${ fail } Could not create ${ fileName } file ` ) ;
process . exit ( 1 ) ;
2017-10-23 15:02:50 +00:00
} else {
2020-03-20 20:28:31 +00:00
fs . writeFileSync ( info . fd , checksums ) ;
2017-10-23 15:02:50 +00:00
fs . close ( info . fd , ( err ) => {
if ( err ) {
2020-03-20 20:28:31 +00:00
console . log ( ` ${ fail } Could close ${ fileName } file ` ) ;
process . exit ( 1 ) ;
2017-10-23 15:02:50 +00:00
}
2020-03-20 20:28:31 +00:00
resolve ( info . path ) ;
} ) ;
2017-10-23 15:02:50 +00:00
}
2020-03-20 20:28:31 +00:00
} ) ;
} ) ;
2017-10-23 15:02:50 +00:00
}
async function publishRelease ( release ) {
2019-01-08 20:05:58 +00:00
return octokit . repos . updateRelease ( {
2017-10-23 15:02:50 +00:00
owner : 'electron' ,
2018-08-16 15:57:12 +00:00
repo : targetRepo ,
2019-01-08 20:05:58 +00:00
release _id : release . id ,
2017-10-23 15:02:50 +00:00
tag _name : release . tag _name ,
draft : false
2019-01-08 20:05:58 +00:00
} ) . catch ( err => {
2020-03-20 20:28:31 +00:00
console . log ( ` ${ fail } Error publishing release: ` , err ) ;
process . exit ( 1 ) ;
} ) ;
2017-10-23 15:02:50 +00:00
}
async function makeRelease ( releaseToValidate ) {
if ( releaseToValidate ) {
2018-01-31 23:40:38 +00:00
if ( releaseToValidate === true ) {
2020-03-20 20:28:31 +00:00
releaseToValidate = pkgVersion ;
2018-01-31 23:40:38 +00:00
} else {
2020-03-20 20:28:31 +00:00
console . log ( 'Release to validate !=== true' ) ;
2018-01-31 23:40:38 +00:00
}
2020-03-20 20:28:31 +00:00
console . log ( ` Validating release ${ releaseToValidate } ` ) ;
const release = await getDraftRelease ( releaseToValidate ) ;
await validateReleaseAssets ( release , true ) ;
2017-10-23 15:02:50 +00:00
} else {
2020-03-20 20:28:31 +00:00
let draftRelease = await getDraftRelease ( ) ;
uploadNodeShasums ( ) ;
uploadIndexJson ( ) ;
2018-08-16 23:15:00 +00:00
2020-03-20 20:28:31 +00:00
await createReleaseShasums ( draftRelease ) ;
2019-01-08 20:05:58 +00:00
2017-10-23 15:02:50 +00:00
// Fetch latest version of release before verifying
2020-03-20 20:28:31 +00:00
draftRelease = await getDraftRelease ( pkgVersion , true ) ;
await validateReleaseAssets ( draftRelease ) ;
await publishRelease ( draftRelease ) ;
2017-10-23 15:02:50 +00:00
console . log ( ` ${ pass } SUCCESS!!! Release has been published. Please run ` +
2020-03-20 20:28:31 +00:00
'"npm run publish-to-npm" to publish release to npm.' ) ;
2017-10-23 15:02:50 +00:00
}
}
async function makeTempDir ( ) {
return new Promise ( ( resolve , reject ) => {
temp . mkdir ( 'electron-publish' , ( err , dirPath ) => {
if ( err ) {
2020-03-20 20:28:31 +00:00
reject ( err ) ;
2017-10-23 15:02:50 +00:00
} else {
2020-03-20 20:28:31 +00:00
resolve ( dirPath ) ;
2017-10-23 15:02:50 +00:00
}
2020-03-20 20:28:31 +00:00
} ) ;
} ) ;
2017-10-23 15:02:50 +00:00
}
2021-05-11 16:30:35 +00:00
const SHASUM _256 _FILENAME = 'SHASUMS256.txt' ;
const SHASUM _1 _FILENAME = 'SHASUMS.txt' ;
2019-01-08 20:05:58 +00:00
2021-05-11 16:30:35 +00:00
async function verifyDraftGitHubReleaseAssets ( release ) {
console . log ( 'Fetching authenticated GitHub artifact URLs to verify shasums' ) ;
2019-01-08 20:05:58 +00:00
2021-05-11 16:30:35 +00:00
const remoteFilesToHash = await Promise . all ( release . assets . map ( async asset => {
2021-08-12 17:34:49 +00:00
const requestOptions = octokit . repos . getReleaseAsset . endpoint ( {
2019-01-08 20:05:58 +00:00
owner : 'electron' ,
repo : targetRepo ,
2019-01-23 19:47:36 +00:00
asset _id : asset . id ,
headers : {
Accept : 'application/octet-stream'
}
2020-03-20 20:28:31 +00:00
} ) ;
2019-01-23 19:47:36 +00:00
2020-03-20 20:28:31 +00:00
const { url , headers } = requestOptions ;
headers . authorization = ` token ${ process . env . ELECTRON _GITHUB _TOKEN } ` ;
2019-01-23 19:47:36 +00:00
const response = await got ( url , {
followRedirect : false ,
method : 'HEAD' ,
headers
2020-03-20 20:28:31 +00:00
} ) ;
2019-01-23 19:47:36 +00:00
2021-05-11 16:30:35 +00:00
return { url : response . headers . location , file : asset . name } ;
2017-10-23 15:02:50 +00:00
} ) ) . catch ( err => {
2020-03-20 20:28:31 +00:00
console . log ( ` ${ fail } Error downloading files from GitHub ` , err ) ;
process . exit ( 1 ) ;
} ) ;
2019-01-08 20:05:58 +00:00
2021-05-11 16:30:35 +00:00
await verifyShasumsForRemoteFiles ( remoteFilesToHash ) ;
2017-10-23 15:02:50 +00:00
}
2021-05-11 16:30:35 +00:00
async function getShaSumMappingFromUrl ( shaSumFileUrl , fileNamePrefix ) {
const response = await got ( shaSumFileUrl ) ;
const raw = response . body ;
return raw . split ( '\n' ) . map ( line => line . trim ( ) ) . filter ( Boolean ) . reduce ( ( map , line ) => {
2021-05-12 08:49:16 +00:00
const [ sha , file ] = line . replace ( ' ' , ' ' ) . split ( ' ' ) ;
2021-05-11 16:30:35 +00:00
map [ file . slice ( fileNamePrefix . length ) ] = sha ;
return map ;
} , { } ) ;
2017-10-23 15:02:50 +00:00
}
2021-05-11 16:30:35 +00:00
async function validateFileHashesAgainstShaSumMapping ( remoteFilesWithHashes , mapping ) {
for ( const remoteFileWithHash of remoteFilesWithHashes ) {
check ( remoteFileWithHash . hash === mapping [ remoteFileWithHash . file ] , ` Release asset ${ remoteFileWithHash . file } should have hash of ${ mapping [ remoteFileWithHash . file ] } but found ${ remoteFileWithHash . hash } ` , true ) ;
2017-10-23 15:02:50 +00:00
}
}
2021-05-11 16:30:35 +00:00
async function verifyShasumsForRemoteFiles ( remoteFilesToHash , filesAreNodeJSArtifacts = false ) {
console . log ( ` Generating SHAs for ${ remoteFilesToHash . length } files to verify shasums ` ) ;
// Only used for node.js artifact uploads
const shaSum1File = remoteFilesToHash . find ( ( { file } ) => file === SHASUM _1 _FILENAME ) ;
// Used for both node.js artifact uploads and normal electron artifacts
const shaSum256File = remoteFilesToHash . find ( ( { file } ) => file === SHASUM _256 _FILENAME ) ;
remoteFilesToHash = remoteFilesToHash . filter ( ( { file } ) => file !== SHASUM _1 _FILENAME && file !== SHASUM _256 _FILENAME ) ;
const remoteFilesWithHashes = await Promise . all ( remoteFilesToHash . map ( async ( file ) => {
return {
hash : await getUrlHash ( file . url , 'sha256' ) ,
... file
} ;
} ) ) ;
await validateFileHashesAgainstShaSumMapping ( remoteFilesWithHashes , await getShaSumMappingFromUrl ( shaSum256File . url , filesAreNodeJSArtifacts ? '' : '*' ) ) ;
if ( filesAreNodeJSArtifacts ) {
const remoteFilesWithSha1Hashes = await Promise . all ( remoteFilesToHash . map ( async ( file ) => {
return {
hash : await getUrlHash ( file . url , 'sha1' ) ,
... file
} ;
} ) ) ;
await validateFileHashesAgainstShaSumMapping ( remoteFilesWithSha1Hashes , await getShaSumMappingFromUrl ( shaSum1File . url , filesAreNodeJSArtifacts ? '' : '*' ) ) ;
}
2017-10-23 15:02:50 +00:00
}
2021-07-21 07:45:57 +00:00
makeRelease ( args . validateRelease )
. catch ( ( err ) => {
console . error ( 'Error occurred while making release:' , err ) ;
process . exit ( 1 ) ;
} ) ;