lib.js
1 const path = require('path'); 2 const { createHash } = require('crypto'); 3 const { readFileSync } = require('fs'); 4 const { spawn } = require('child_process'); 5 6 const { hashPersonalMessage, ecsign, toBuffer, addHexPrefix } = require('ethereumjs-util'); 7 8 const genCommitFilename = (name, version, commit, buildId, isCodeSigning) => { 9 const winRegex = /exe$/; 10 const macRegex = /dmg$/; 11 const split = name.split(version); 12 const signed = winRegex.test(name) || macRegex.test(name) 13 ? isCodeSigning ? '-signed' : '-unsigned' 14 : ''; 15 16 return `${split[0]}${version}-${commit}-${buildId}${signed}${split[1]}`; 17 }; 18 19 const genFileList = (linux, windows, osx) => { 20 const { platform } = process; 21 if (platform === 'linux') { 22 return [...linux, ...windows]; 23 } else if (platform === 'darwin') { 24 return [...osx]; 25 } else { 26 throw new Error('Unrecognized host platform.'); 27 } 28 }; 29 30 const genSha512 = filePath => { 31 const hash = createHash('sha512'); 32 const data = readFileSync(filePath); 33 hash.update(data); 34 return hash.digest('hex'); 35 }; 36 37 const runChildProcess = cmd => 38 new Promise((resolve, reject) => { 39 const child = spawn('sh', ['-c', cmd]); 40 41 child.stdout.on('data', data => { 42 process.stdout.write(data); 43 }); 44 45 child.stderr.on('data', data => { 46 process.stderr.write(data); 47 }); 48 49 child.on('close', code => { 50 if (code !== 0) { 51 return reject(`Child process exited with code: ${code}`); 52 } 53 resolve(); 54 }); 55 }); 56 57 const uploadToS3 = (localFilePath, s3FilePath) => 58 runChildProcess(`aws s3 cp "${localFilePath}" "${s3FilePath}"`); 59 60 const genS3Url = (filename, commit, bucket) => `s3://${bucket}/${commit}/${filename}`; 61 62 const genManifestFile = manifest => 63 manifest.map(info => ({ 64 Filename: info.commitFilename, 65 SHA512: info.fileHash 66 })); 67 68 const genManifestFilename = (flavor, version, commit, buildId) => 69 `manifest.${flavor}.v${version}.${commit}.${buildId}.json`; 70 71 const genSignatureFile = (manifestHash, pKeyString) => { 72 const pKeyBuffer = Buffer.from(pKeyString, 'hex'); 73 return signMessageWithPrivKeyV2(pKeyBuffer, manifestHash); 74 }; 75 76 const genSignatureFilename = (flavor, version, commit, buildId) => 77 `manifest.${flavor}.v${version}.${commit}.${buildId}.signature`; 78 79 const genManifest = (fileList, version, jenkinsBuildId, gitCommit, gitCommitShort, s3Bucket, isCodeSigning) => 80 fileList.map(filename => { 81 const fullPath = path.resolve('dist/electron-builds/', filename); 82 const commitFilename = genCommitFilename(filename, version, gitCommitShort, jenkinsBuildId, isCodeSigning); 83 84 return { 85 fullPath, 86 filename, 87 commitFilename, 88 fileHash: genSha512(fullPath), 89 s3Url: genS3Url(commitFilename, gitCommit, s3Bucket) 90 }; 91 }); 92 93 function signMessageWithPrivKeyV2(privKey, msg) { 94 const hash = hashPersonalMessage(toBuffer(msg)); 95 const signed = ecsign(hash, privKey); 96 const combined = Buffer.concat([ 97 Buffer.from(signed.r), 98 Buffer.from(signed.s), 99 Buffer.from([signed.v]) 100 ]); 101 const combinedHex = combined.toString('hex'); 102 103 return addHexPrefix(combinedHex); 104 } 105 106 module.exports = { 107 genCommitFilename, 108 genManifestFile, 109 genFileList, 110 genSha512, 111 genS3Url, 112 uploadToS3, 113 signMessageWithPrivKeyV2, 114 genManifestFilename, 115 genManifest, 116 genSignatureFile, 117 genSignatureFilename 118 };