const args = require('minimist')(process.argv.slice(2)) const nugget = require('nugget') const request = require('request') async function makeRequest (requestOptions, parseResponse) { return new Promise((resolve, reject) => { request(requestOptions, (err, res, body) => { if (!err && res.statusCode >= 200 && res.statusCode < 300) { if (parseResponse) { const build = JSON.parse(body) resolve(build) } else { resolve(body) } } else { if (args.verbose) { console.error('Error occurred while requesting:', requestOptions.url) if (parseResponse) { try { console.log('Error: ', `(status ${res.statusCode})`, err || JSON.parse(res.body), requestOptions) } catch (err) { console.log('Error: ', `(status ${res.statusCode})`, err || res.body, requestOptions) } } else { console.log('Error: ', `(status ${res.statusCode})`, err || res.body, requestOptions) } } reject(err) } }) }) } async function downloadArtifact (name, buildNum, dest) { const circleArtifactUrl = `https://circleci.com/api/v1.1/project/github/electron/electron/${args.buildNum}/artifacts?circle-token=${process.env.CIRCLE_TOKEN}` const artifacts = await makeRequest({ method: 'GET', url: circleArtifactUrl, headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' } }, true).catch(err => { if (args.verbose) { console.log('Error calling CircleCI:', err) } else { console.error('Error calling CircleCI to get artifact details') } }) const artifactToDownload = artifacts.find(artifact => { return (artifact.path === name) }) if (!artifactToDownload) { console.log(`Could not find artifact called ${name} to download for build #${buildNum}.`) process.exit(1) } else { console.log(`Downloading ${artifactToDownload.url}.`) let downloadError = false await downloadWithRetry(artifactToDownload.url, dest).catch(err => { if (args.verbose) { console.log(`${artifactToDownload.url} could not be successfully downloaded. Error was:`, err) } else { console.log(`${artifactToDownload.url} could not be successfully downloaded.`) } downloadError = true }) if (!downloadError) { console.log(`Successfully downloaded ${name}.`) } } } async function downloadWithRetry (url, directory) { let lastError const downloadURL = `${url}?circle-token=${process.env.CIRCLE_TOKEN}` for (let i = 0; i < 5; i++) { console.log(`Attempting to download ${url} - attempt #${(i + 1)}`) try { return await downloadFile(downloadURL, directory) } catch (err) { lastError = err await new Promise((resolve, reject) => setTimeout(resolve, 30000)) } } throw lastError } function downloadFile (url, directory) { return new Promise((resolve, reject) => { const nuggetOpts = { dir: directory, quiet: args.verbose } nugget(url, nuggetOpts, (err) => { if (err) { reject(err) } else { resolve() } }) }) } if (!args.name || !args.buildNum || !args.dest) { console.log(`Download CircleCI artifacts. Usage: download-circleci-artifacts.js [--buildNum=CIRCLE_BUILD_NUMBER] [--name=artifactName] [--dest] [--verbose]`) process.exit(0) } else { downloadArtifact(args.name, args.buildNum, args.dest) }