Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

travis-after-all

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

travis-after-all - npm Package Compare versions

Comparing version 1.3.0 to 1.4.0

scripts/release.sh

6

CHANGELOG.md

@@ -0,1 +1,7 @@

### 1.4.0 (September 10, 2015)
* Make `travis-after-all` take partial decisions
[[#3](https://github.com/alrra/travis-after-all/issues/3),
[2a656d9](https://github.com/alrra/travis-after-all/commit/2a656d9390543ceba776a2c790805bbfdad68e2b)].
### 1.3.0 (August 12, 2015)

@@ -2,0 +8,0 @@

524

lib/travis-after-all.js

@@ -6,48 +6,72 @@ var crypto = require('crypto');

// Travis CI set environment variables
// http://docs.travis-ci.com/user/ci-environment/#Environment-variables
var travis = {
var TRAVIS_BUILD_ID = parseInt(process.env.TRAVIS_BUILD_ID, 10);
var TRAVIS_CURRENT_JOB_ID = parseInt(process.env.TRAVIS_JOB_ID, 10);
var TRAVIS_CURRENT_JOB_TEST_RESULT = parseInt(process.env.TRAVIS_TEST_RESULT, 10);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Travis CI set environment variables
// http://docs.travis-ci.com/user/ci-environment/#Environment-variables
// Travis CI API URLs
CURRENT_JOB_ID: parseInt(process.env.TRAVIS_JOB_ID, 10),
CURRENT_JOB_TEST_RESULT: parseInt(process.env.TRAVIS_TEST_RESULT, 10),
var TRAVIS_API_BUILD_URL = 'https://api.travis-ci.org/builds/' + TRAVIS_BUILD_ID;
var TRAVIS_API_JOBS_URL = 'https://api.travis-ci.org/jobs/';
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Travis CI API URLs
// http://docs.travis-ci.com/api/
// Other
API_BUILD_URL: 'https://api.travis-ci.org/builds/' + parseInt(process.env.TRAVIS_BUILD_ID, 10),
API_JOBS_URL: 'https://api.travis-ci.org/jobs/'
var CHECK_INTERVAL_LIMIT = 60000;
var checkInterval = 5000;
var KEYS = {
'failure': 'travis-after-all: failed',
'success': 'travis-after-all: succeeded'
};
var LOG_PREFIX='[travis-after-all]';
var configs = {
var returnCode;
callback: undefined,
CHECK_INTERVAL_LIMIT: 60000,
checkInterval: 1000,
keys: {
'FAILURE': 'travis-after-all: failed',
'SUCCESS': 'travis-after-all: succeeded'
},
LOG_PREFIX: '[travis-after-all]',
};
// ---------------------------------------------------------------------
function allJobsAreDone(jobs) {
return jobs.every(function (job) {
return job.result !== null;
});
}
function allJobsPassed(jobs) {
return jobs.every(function (job) {
return jobPassed(job);
// A job passed if it either succeeded or it failed but
// it was allowed to fail (has `allow_failure` set to true).
//
// http://docs.travis-ci.com/user/customizing-the-build/#Rows-that-are-Allowed-to-Fail
return job.result === 0 || ( job.result === 1 && job.allow_failure === true );
});
}
function createReturnFunction(callback) {
function endJob(code, error) {
if ( typeof callback === 'function' ) {
returnCode = callback;
if ( error !== undefined ) {
log(error.message);
}
if ( code === 2 ) {
log('Some other job was assigned to do the task');
}
if ( typeof configs.callback === 'function' ) {
configs.callback(code, error);
} else {
returnCode = function (code, error) {
process.exit(code);
};
process.exit(code);
}

@@ -61,15 +85,21 @@

function getFirstSuccessfulJob(jobs) {
function getBuildData() {
getJSON(travis.API_BUILD_URL, function (data) {
var i = 0;
var numberOfJobs = jobs.length;
var jobs = data.matrix;
for ( i = 0; i < numberOfJobs; i++ ) {
if ( jobs[i].result === 0 ) {
return jobs[i];
}
}
// For the current job the result is already
// known, so there is no need to figure that out.
return undefined;
jobs.some(function (job) {
if ( job.id === travis.CURRENT_JOB_ID ) {
job.result = travis.CURRENT_JOB_TEST_RESULT;
return true;
}
return false;
});
handleJob(jobs);
});
}

@@ -90,8 +120,14 @@

response.on('end', function () {
callback(parseJSON(body));
try {
callback(JSON.parse(body));
} catch (error) {
error.message = 'Failed to parse JSON from "' + url +'".\nError: ' + error.message;
endJob(3, error);
}
});
}).on('error', function (error) {
log('Error: ' + e.message);
returnCode(2, error);
endJob(3, error);
});

@@ -101,17 +137,19 @@

function getJobNumbersOfUndoneJobs(jobs) {
function getJob(jobs, id) {
var undoneJobs = [];
var result;
jobs.forEach(function (job) {
if ( job.result === null ) {
undoneJobs.push(job.number);
jobs.some(function (job) {
if ( job.id === id ) {
result = job;
return true;
}
return false;
});
return undoneJobs;
return result;
}
function getResults(jobList) {
function getJobData(jobList) {

@@ -126,22 +164,10 @@ var currentJob;

if ( currentJob.id === travis.CURRENT_JOB_ID ||
currentJob.finished_at !== null && currentJob.result !== null ) {
// The `result` of a job is only set after the job is finished,
// so, if the value of `result` is different from `null`, it
// means that it was extracted from its log, and thus, there is
// no need to check the log again
getJobData(jobList);
if ( currentJob.result !== null ) {
getResults(jobList);
// Also, there is no need to check the log for the current job
} else if ( currentJob.id === TRAVIS_CURRENT_JOB_ID ) {
currentJob.result = TRAVIS_CURRENT_JOB_TEST_RESULT;
getResults(jobList);
// In all other cases, check the job's log for the result
} else {
getJSON(TRAVIS_API_JOBS_URL + currentJob.id, function (data) {
getJSON(travis.API_JOBS_URL + currentJob.id, function (data) {

@@ -151,12 +177,14 @@ var jobLog = data.log;

// If written, get the result of the job from
// the special token written within the job's log
// the special token written within its log.
if ( jobLog.indexOf(generateToken(currentJob.id, KEYS.success)) !== -1 ) {
if ( jobLog.indexOf(generateToken(currentJob.id, configs.keys.SUCCESS)) !== -1 ) {
currentJob.result = 0;
} else if ( jobLog.indexOf(generateToken(currentJob.id, KEYS.failure)) !== -1 ) {
} else if ( jobLog.indexOf(generateToken(currentJob.id, configs.keys.FAILURE)) !== -1 ) {
currentJob.result = 1;
}
getResults(jobList);
currentJob.finished_at = data.finished_at;
getJobData(jobList);
});

@@ -167,50 +195,42 @@

} else {
handleJob(jobList.jobs);
}
undoneJobs = getJobNumbersOfUndoneJobs(jobList.jobs);
}
function getJobNumbersOfUndoneJobs(jobs) {
// If there are jobs that are not yet done, wait
// a bit, and then check again for their result
var undoneJobs = [];
if ( undoneJobs.length !== 0 ) {
jobs.forEach(function (job) {
if ( job.finished_at === null ) {
undoneJobs.push(job.number);
}
});
log('Waiting for ' + undoneJobs.join(', ').replace(/,(?!.*,)/, ' and') + ' to be done...');
return undoneJobs;
jobList.index = 0;
}
// If the jobs take longer to be done, gradually increase
// the check interval time up to the specified limit
function getPreviousJobs(jobs, id) {
checkInterval = ( checkInterval * 2 > CHECK_INTERVAL_LIMIT ?
CHECK_INTERVAL_LIMIT : checkInterval * 2 );
var result = [];
setTimeout(function () {
getResults(jobList);
}, checkInterval);
jobs.some(function (job) {
// If all jobs are done, make this script
// return with the appropriate exit code
} else {
returnWithAppropriateCode(jobList.jobs);
if ( job.id === id ) {
return true;
}
}
result.push(job);
return false;
}
});
function jobPassed(job) {
return result;
// A job passed if it either succeeded or it has failed but
// it was allowed to fail (has `allow_failure` set to true)
//
// http://docs.travis-ci.com/user/build-configuration/#Rows-That-are-Allowed-To-Fail
return job.result === 0 || ( job.result === 1 && job.allow_failure === true );
}
function log(msg) {
console.log('%s %s', LOG_PREFIX, msg);
console.log('%s %s', configs.LOG_PREFIX, msg);
}

@@ -224,11 +244,11 @@

// Write a special token generated based on the result of
// the job so that the chance of that text existing in the
// log is minimal / non-existent.
// Create a special token based on the result of the job (this
// is done so that the chance of that text existing in the log
// is minimal / non-existent).
if ( TRAVIS_CURRENT_JOB_TEST_RESULT === 0 ) {
token = generateToken(TRAVIS_CURRENT_JOB_ID, KEYS.success);
if ( travis.CURRENT_JOB_TEST_RESULT === 0 ) {
token = generateToken(travis.CURRENT_JOB_ID, configs.keys.SUCCESS);
msg += 'Job succeeded (' + token + ')';
} else {
token = generateToken(TRAVIS_CURRENT_JOB_ID, KEYS.failure);
token = generateToken(travis.CURRENT_JOB_ID, configs.keys.FAILURE);
msg += 'Job failed (' + token + ')';

@@ -242,3 +262,3 @@ }

// e.g.: the user uses multiple scripts that include this
// script)
// script).

@@ -251,60 +271,248 @@ if ( job.log.indexOf(token) === -1 ) {

function parseJSON(data) {
function removeJob(jobs, id) {
var json = '';
var result = [];
try {
json = JSON.parse(data);
} catch (error) {
log('Failed to parse JSON (' + error + ')');
log('Data: "' + data + '"');
returnCode(2, error);
jobs.forEach(function (job) {
if ( job.id !== id ) {
result.push(job);
}
});
return result;
}
function thereIsAFailingJob(jobs) {
return jobs.some(function (job) {
return job.result === 1 && job.allow_failure === false;
});
}
function thereIsASuccessfulJob(jobs) {
return jobs.some(function (job) {
return job.result === 0;
});
}
function waitThenGetJobData(jobs) {
var jobList = {
index: 0,
jobs: jobs
};
var undoneJobs = getJobNumbersOfUndoneJobs(removeJob(jobList.jobs, travis.CURRENT_JOB_ID));
if ( undoneJobs.length !== 0 ) {
log('Waiting for ' + undoneJobs.join(', ').replace(/,(?!.*,)/, ' and') + ' to be done...');
}
return json;
// If the jobs take longer to be done, gradually increase
// the check interval time up to the specified limit.
configs.checkInterval = ( configs.checkInterval * 2 > configs.CHECK_INTERVAL_LIMIT ?
configs.CHECK_INTERVAL_LIMIT : configs.checkInterval * 2 );
setTimeout(function () {
getJobData(jobList);
}, configs.checkInterval);
}
function returnWithAppropriateCode(jobs) {
// ---------------------------------------------------------------------
// Convention for exit codes
//
// 0 - if the current job is the one assigned to run the
// code if the build succeeded
//
// 1 - if the current job is the one assigned to run the
// code if the build failed
//
// 2 - none of the above
//
// Conventions:
//
// * For builds that failed, or for builds that succeeded but had
// all their jobs failed but being allowed to fail), the first
// job will be assign to run the user defined fail tasks.
//
// * For builds that succeeded, the first successful job will be
// assign to run the user defined success tasks.
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function handleJob(jobs) {
var currentJob = getJob(jobs, travis.CURRENT_JOB_ID);
if ( currentJob.result === 1 ) {
if ( currentJob.allow_failure === false ) {
handleFailingJob(currentJob, jobs);
} else {
handleFailingJobAllowedToFail(currentJob, jobs);
}
} else {
handleSuccessfulJob(currentJob, jobs);
}
}
function handleFailingJob(currentJob, jobs) {
// Since the current job failed, the build also failed, therefore,
// the current job can be ended with the appropriate code.
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var firstJob = jobs[0];
var firstSuccesfulJob = getFirstSuccessfulJob(jobs);
if ( allJobsPassed(jobs) &&
// If the current job is the first one in the build, assign it
// to run the user defined fail tasks.
// Even if all jobs passed we still need to check if there
// is at least one successful job (this guards against the
// rare case where all jobs are allowed to fail and they do
// fail)
if ( currentJob.id === firstJob.id ) {
endJob(1);
firstSuccesfulJob !== undefined ) {
// Otherwise, don't assign it to do anything as the first job
// in the build will be assign to run the user defined fail tasks.
if ( firstSuccesfulJob.id !== TRAVIS_CURRENT_JOB_ID ) {
log('Job ' + firstSuccesfulJob.number + ' was assigned to do the "after success" task');
returnCode(2);
} else {
endJob(2);
}
}
function handleFailingJobAllowedToFail(currentJob, jobs) {
// Since the current job failed, but it was allowed to fail,
// the status of the build is unknown, therefore, the current
// job can only be ended with the appropriate code if there is
// enough information about the status of the other jobs.
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var firstJob = jobs[0];
var otherJobs = removeJob(jobs, currentJob.id);
if ( currentJob.id === firstJob.id ) {
// If there is at least one job that failed, the build
// failed, therefore, assign the current job to run the
// user defined fail tasks.
if ( thereIsAFailingJob(otherJobs) ) {
endJob(1);
// Otherwise
} else {
returnCode(0);
// Note: By this point it is known that currently there
// aren't any jobs that were not allowed to fail and did
// fail.
if ( allJobsAreDone(otherJobs) ) {
// If there is a successful job, that job will be
// assigned to run the user defined success tasks,
// therefore, the current job doesn't need to be
// assigned to do anything.
if ( thereIsASuccessfulJob(otherJobs) ) {
endJob(2);
// Otherwise, there are only jobs that where allowed
// to fail and all of them fail, therefore, the build
// failed, so assign the current job to run the user
// defined fail tasks.
} else {
endJob(1);
}
// If this point is reached, it means a decision cannot
// be made because there isn't enough information. So, we
// need to wait a bit, check the status of the other jobs,
// and try again.
} else {
waitThenGetJobData(jobs);
}
}
// If the current job is not the first job, no matter what the
// status of build will be, this job won't be assign to do any
// tasks (if the build failed, the first job will be assign to
// do the fail tasks, and if the build succeeded, the first
// successful job will be assigned to do the success tasks)
} else {
endJob(2);
}
if ( firstJob.id !== TRAVIS_CURRENT_JOB_ID ) {
log('Job ' + firstJob.number + ' was assigned to do the "after failure" task');
returnCode(2);
}
function handleSuccessfulJob(currentJob, jobs) {
// Since the current job is a successful job, the status of the
// build is unknown, therefore, the current job can only be ended
// with the appropriate code if there is enough information about
// the status of the other jobs
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var firstJob = jobs[0];
var otherJobs = removeJob(jobs, currentJob.id);
var previousJobs = getPreviousJobs(jobs, currentJob.id);
// If a job failed, it means the build failed, therefore,
if ( thereIsAFailingJob(otherJobs) ) {
// If the current job is the first one in the build, assign
// it to run the user defined fail tasks.
if ( currentJob.id === firstJob.id ) {
endJob(1);
// Otherwise, don't assign it to do anything as the first
// job in the build will be assign to run the user defined
// fail tasks.
} else {
returnCode(1);
endJob(2);
}
} else {
// If there is a previous successful job, no matter what the
// status of the build will be, this job won't be assign to do
// any tasks (if the build succeeded a previous successful job
// will be assigned to do the success tasks, and if the build
// fails, the first job in the build will be assign to do the
// fail tasks).
if ( thereIsASuccessfulJob(previousJobs) ) {
endJob(2);
} else {
// Note: By this point it is known that currently there
// aren't any jobs that were not allowed to fail and did
// fail, or any previous successful jobs.
// If all jobs are done, it means the current job
// is the first successful job in a successful build,
// therefore, assign it to run the success tasks.
if ( allJobsAreDone(otherJobs) ) {
endJob(0);
// If this point is reached, it means a decision cannot
// be made because there isn't enough information. So, we
// need to wait a bit, check the status of the other jobs,
// and try again.
} else {
waitThenGetJobData(jobs);
}
}
}

@@ -318,23 +526,18 @@

createReturnFunction(callback);
configs.callback = callback;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
getJSON(travis.API_JOBS_URL + travis.CURRENT_JOB_ID, function (data) {
// Write the result of this job in its log if it isn't written
// already (this needs to be done because there isn't any other
// way for the other jobs to know the result of this job without
// it actually be finished)
// Write the result of current job in its log if it isn't
// written already (this needs to be done because there isn't
// any other way for the other jobs to know the result of the
// current job without it actually be finished).
getJSON(TRAVIS_API_JOBS_URL + TRAVIS_CURRENT_JOB_ID, logJobResult);
logJobResult(data);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Get the list of jobs for this build and start checking for
// their results.
// Get the list of jobs for this build, and start checking for
// their results
getBuildData();
getJSON(TRAVIS_API_BUILD_URL, function (data) {
getResults({
index: 0,
jobs: data.matrix
});
});

@@ -346,13 +549,16 @@

// Based on how this script is called, invoke main differentlly:
//
// * if this script is called directly
//
if ( require.main === module || module.parent === undefined ) {
// Based on how this script is called,
// invoke `main` differentlly.
// 1) If this script is called directly:
if ( require.main === module ||
module.parent === undefined ) {
main();
//
// * if required as a module
//
// 2) If it's required as a module:
} else {
module.exports = main;
}

@@ -27,3 +27,4 @@ {

"glob": "^5.0.14",
"mocha": "^2.2.5"
"tap": "^1.3.2",
"tap-mocha-reporter": "0.0.16"
},

@@ -40,5 +41,6 @@ "homepage": "https://github.com/alrra/travis-after-all#readme",

"scripts": {
"test": "mocha --compilers js:babel/register --delay --reporter spec --slow 15m --timeout 30m test/main.js"
"pretest": "rm -rf dist_test && babel test --out-dir dist_test",
"test": "node dist_test/main.js | tap-mocha-reporter spec"
},
"version": "1.3.0"
"version": "1.4.0"
}
# travis-after-all
[![Build Status](https://travis-ci.org/alrra/travis-after-all.svg?branch=master)](https://travis-ci.org/alrra/travis-after-all)

@@ -36,3 +35,3 @@ [![devDependency Status](https://david-dm.org/alrra/travis-after-all/dev-status.svg)](https://david-dm.org/alrra/travis-after-all#info=devDependencies)

* other - job was not assigned to do anything
* `2` - the job that gets this exit code was not assigned to do anything

@@ -134,3 +133,3 @@ --

curl -sSL https://raw.githubusercontent.com/alrra/travis-after-all/1.3.0/lib/travis-after-all.js | node
curl -sSL https://raw.githubusercontent.com/alrra/travis-after-all/1.4.0/lib/travis-after-all.js | node
exitCode=$?

@@ -137,0 +136,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc