From 2b3001c60acccace8b77d4f03edddece68ba0697 Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Tue, 4 Sep 2018 10:56:30 -0700 Subject: [PATCH] Retry npm install in CI (#70) --- .../google-cloud-oslogin/.circleci/config.yml | 92 ++++++++++++++++--- .../.circleci/npm-install-retry.js | 60 ++++++++++++ 2 files changed, 141 insertions(+), 11 deletions(-) create mode 100755 packages/google-cloud-oslogin/.circleci/npm-install-retry.js diff --git a/packages/google-cloud-oslogin/.circleci/config.yml b/packages/google-cloud-oslogin/.circleci/config.yml index b1a04da4d30..80dcf7e67d9 100644 --- a/packages/google-cloud-oslogin/.circleci/config.yml +++ b/packages/google-cloud-oslogin/.circleci/config.yml @@ -23,15 +23,28 @@ workflows: - node8 - node10 filters: *all_commits - - publish_npm: + - system_tests: + requires: + - lint + - docs + filters: &master_and_releases + branches: + only: master + tags: &releases + only: '/^v[\d.]+$/' + - sample_tests: requires: - lint - docs + filters: *master_and_releases + - publish_npm: + requires: + - system_tests + - sample_tests filters: branches: ignore: /.*/ - tags: - only: '/^v[\d.]+$/' + tags: *releases nightly: triggers: - schedule: @@ -46,17 +59,17 @@ jobs: - image: 'node:6' user: node steps: &unit_tests_steps - - checkout + - checkout - run: &npm_install_and_link name: Install and link the module command: |- mkdir -p /home/node/.npm-global - npm install + ./.circleci/npm-install-retry.js environment: NPM_CONFIG_PREFIX: /home/node/.npm-global - run: npm test - run: node_modules/.bin/codecov - + node8: docker: - image: 'node:8' @@ -74,12 +87,12 @@ jobs: steps: - checkout - run: *npm_install_and_link - - run: + - run: &samples_npm_install_and_link name: Link the module being tested to the samples. command: | cd samples/ - npm install npm link ../ + ./../.circleci/npm-install-retry.js environment: NPM_CONFIG_PREFIX: /home/node/.npm-global - run: @@ -94,14 +107,71 @@ jobs: steps: - checkout - run: *npm_install_and_link + - run: npm run docs + sample_tests: + docker: + - image: 'node:8' + user: node + steps: + - checkout - run: - name: Build documentation. - command: npm run docs + name: Decrypt credentials. + command: | + if ! [[ -z "${SYSTEM_TESTS_ENCRYPTION_KEY}" ]]; then + openssl aes-256-cbc -d -in .circleci/key.json.enc \ + -out .circleci/key.json \ + -k "${SYSTEM_TESTS_ENCRYPTION_KEY}" + fi + - run: *npm_install_and_link + - run: *samples_npm_install_and_link + - run: + name: Run sample tests. + command: npm run samples-test + environment: + GCLOUD_PROJECT: long-door-651 + GOOGLE_APPLICATION_CREDENTIALS: /home/node/samples/.circleci/key.json + NPM_CONFIG_PREFIX: /home/node/.npm-global + - run: + name: Remove unencrypted key. + command: | + if ! [[ -z "${SYSTEM_TESTS_ENCRYPTION_KEY}" ]]; then + rm .circleci/key.json + fi + when: always + working_directory: /home/node/samples/ + system_tests: + docker: + - image: 'node:8' + user: node + steps: + - checkout + - run: + name: Decrypt credentials. + command: | + if ! [[ -z "${SYSTEM_TESTS_ENCRYPTION_KEY}" ]]; then + openssl aes-256-cbc -d -in .circleci/key.json.enc \ + -out .circleci/key.json \ + -k "${SYSTEM_TESTS_ENCRYPTION_KEY}" + fi + - run: *npm_install_and_link + - run: + name: Run system tests. + command: npm run system-test + environment: + GOOGLE_APPLICATION_CREDENTIALS: .circleci/key.json + - run: + name: Remove unencrypted key. + command: | + if ! [[ -z "${SYSTEM_TESTS_ENCRYPTION_KEY}" ]]; then + rm .circleci/key.json + fi + when: always publish_npm: docker: - image: 'node:8' user: node steps: - checkout - - run: 'echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc' + - run: ./.circleci/npm-install-retry.js + - run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc - run: npm publish --access=public diff --git a/packages/google-cloud-oslogin/.circleci/npm-install-retry.js b/packages/google-cloud-oslogin/.circleci/npm-install-retry.js new file mode 100755 index 00000000000..ae3220d7348 --- /dev/null +++ b/packages/google-cloud-oslogin/.circleci/npm-install-retry.js @@ -0,0 +1,60 @@ +#!/usr/bin/env node + +let spawn = require('child_process').spawn; + +// +//USE: ./index.js [... NPM ARGS] +// + +let timeout = process.argv[2] || 60000; +let attempts = process.argv[3] || 3; +let args = process.argv.slice(4); +if (args.length === 0) { + args = ['install']; +} + +(function npm() { + let timer; + args.push('--verbose'); + let proc = spawn('npm', args); + proc.stdout.pipe(process.stdout); + proc.stderr.pipe(process.stderr); + proc.stdin.end(); + proc.stdout.on('data', () => { + setTimer(); + }); + proc.stderr.on('data', () => { + setTimer(); + }); + + // side effect: this also restarts when npm exits with a bad code even if it + // didnt timeout + proc.on('close', (code, signal) => { + clearTimeout(timer); + if (code || signal) { + console.log('[npm-are-you-sleeping] npm exited with code ' + code + ''); + + if (--attempts) { + console.log('[npm-are-you-sleeping] restarting'); + npm(); + } else { + console.log('[npm-are-you-sleeping] i tried lots of times. giving up.'); + throw new Error("npm install fails"); + } + } + }); + + function setTimer() { + clearTimeout(timer); + timer = setTimeout(() => { + console.log('[npm-are-you-sleeping] killing npm with SIGTERM'); + proc.kill('SIGTERM'); + // wait a couple seconds + timer = setTimeout(() => { + // its it's still not closed sigkill + console.log('[npm-are-you-sleeping] killing npm with SIGKILL'); + proc.kill('SIGKILL'); + }, 2000); + }, timeout); + } +})();