download-circleci-artifacts.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. const args = require('minimist')(process.argv.slice(2));
  2. const fs = require('fs');
  3. const got = require('got');
  4. const stream = require('stream');
  5. const { promisify } = require('util');
  6. const pipeline = promisify(stream.pipeline);
  7. async function downloadArtifact (name, buildNum, dest) {
  8. const circleArtifactUrl = `https://circleci.com/api/v1.1/project/github/electron/electron/${args.buildNum}/artifacts?circle-token=${process.env.CIRCLE_TOKEN}`;
  9. const responsePromise = got(circleArtifactUrl, {
  10. headers: {
  11. 'Content-Type': 'application/json',
  12. Accept: 'application/json'
  13. }
  14. });
  15. const [response, artifacts] = await Promise.all([responsePromise, responsePromise.json()]);
  16. if (response.statusCode !== 200) {
  17. console.error('Could not fetch circleci artifact list, got status code:', response.statusCode);
  18. }
  19. const artifactToDownload = artifacts.find(artifact => {
  20. return (artifact.path === name);
  21. });
  22. if (!artifactToDownload) {
  23. console.log(`Could not find artifact called ${name} to download for build #${buildNum}.`);
  24. process.exit(1);
  25. } else {
  26. console.log(`Downloading ${artifactToDownload.url}.`);
  27. let downloadError = false;
  28. await downloadWithRetry(artifactToDownload.url, dest).catch(err => {
  29. if (args.verbose) {
  30. console.log(`${artifactToDownload.url} could not be successfully downloaded. Error was:`, err);
  31. } else {
  32. console.log(`${artifactToDownload.url} could not be successfully downloaded.`);
  33. }
  34. downloadError = true;
  35. });
  36. if (!downloadError) {
  37. console.log(`Successfully downloaded ${name}.`);
  38. }
  39. }
  40. }
  41. async function downloadWithRetry (url, directory) {
  42. let lastError;
  43. const downloadURL = `${url}?circle-token=${process.env.CIRCLE_TOKEN}`;
  44. for (let i = 0; i < 5; i++) {
  45. console.log(`Attempting to download ${url} - attempt #${(i + 1)}`);
  46. try {
  47. return await downloadFile(downloadURL, directory);
  48. } catch (err) {
  49. lastError = err;
  50. await new Promise((resolve, reject) => setTimeout(resolve, 30000));
  51. }
  52. }
  53. throw lastError;
  54. }
  55. function downloadFile (url, directory) {
  56. return pipeline(
  57. got.stream(url),
  58. fs.createWriteStream(directory)
  59. );
  60. }
  61. if (!args.name || !args.buildNum || !args.dest) {
  62. console.log(`Download CircleCI artifacts.
  63. Usage: download-circleci-artifacts.js [--buildNum=CIRCLE_BUILD_NUMBER] [--name=artifactName] [--dest] [--verbose]`);
  64. process.exit(0);
  65. } else {
  66. downloadArtifact(args.name, args.buildNum, args.dest);
  67. }