From bd850b18409984e881c482e17778e94291921d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6nnemann?= Date: Thu, 17 Aug 2017 21:48:41 +0200 Subject: [PATCH] feat: elect build leader by highest node version BREAKING CHANGE: The first job in the build matrix is no longer automatically elected to be the build leader. Instead the build job with the highest node version is selected. If you want to control which job is the build leader set the environment variable `BUILD_LEADER_ID`. --- elect-build-leader.js | 23 +++++++++++++++++++++++ index.js | 13 ++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 elect-build-leader.js diff --git a/elect-build-leader.js b/elect-build-leader.js new file mode 100644 index 0000000..f2dc8ec --- /dev/null +++ b/elect-build-leader.js @@ -0,0 +1,23 @@ +const semver = require('semver') + +module.exports = versions => { + // if there is only one candidate, then it's the winner + if (!Array.isArray(versions) || versions.length === 1) return 1 + + // if there is latest stable it's the winner + const stable = versions.indexOf('node') + 1 + if (stable) return stable + + // otherwise we use the lower bound of all valid semver ranges + const validRanges = versions.filter(semver.validRange) + const lowVersionBoundaries = validRanges + .map(semver.Range) + .map(r => r.set[0][0].semver.version) + + // then we find the highest of those + const highestVersion = semver.sort(Array.from(lowVersionBoundaries)).pop() + const highestRange = validRanges[lowVersionBoundaries.indexOf(highestVersion)] + + // and make its build job the winner + return versions.indexOf(highestRange) + 1 +} diff --git a/index.js b/index.js index 749f9c8..5f78f34 100644 --- a/index.js +++ b/index.js @@ -3,11 +3,11 @@ const {promisify} = require('util') const request = require('axios') const Travis = require('travis-ci') +const electBuildLeader = require('./elect-build-leader') + module.exports = async function travisDeployOnce (env = process.env) { if (!env.GH_TOKEN) throw new Error('GitHub token missing') if (env.TRAVIS !== 'true') throw new Error('Not running on Travis') - if (!env.TRAVIS_JOB_NUMBER.endsWith('.1')) return null - if (env.TRAVIS_TEST_RESULT === '1') return false if (env.TRAVIS_TEST_RESULT !== '0') throw new Error('Not running in Travis after_success hook') const {private: pro} = await request({ @@ -32,7 +32,14 @@ module.exports = async function travisDeployOnce (env = process.env) { const buildId = parseInt(env.TRAVIS_BUILD_ID, 10) const buildApi = travis.builds(buildId) - const {build: {job_ids: jobs}} = await promisify(buildApi.get.bind(buildApi))() + const {build: {config, job_ids: jobs}} = await promisify(buildApi.get.bind(buildApi))() + + const buildLeader = env.BUILD_LEADER_ID || (config.node_js + ? electBuildLeader(config.node_js) + : 1) + + if (!env.TRAVIS_JOB_NUMBER.endsWith(`.${buildLeader}`)) return null + if (env.TRAVIS_TEST_RESULT === '1') return false const currentJobId = parseInt(env.TRAVIS_JOB_ID, 10) let attempt = 0