mirror of
https://gitlab.silvrtree.co.uk/martind2000/nci.git
synced 2025-01-26 20:16:17 +00:00
Merge pull request #10 from node-ci/feature_expose_executor
Feature expose executor
This commit is contained in:
commit
84c6b8ee05
12
app.js
12
app.js
@ -16,6 +16,10 @@ var env = process.env.NODE_ENV || 'development',
|
|||||||
ProjectsCollection = require('./lib/project').ProjectsCollection,
|
ProjectsCollection = require('./lib/project').ProjectsCollection,
|
||||||
BuildsCollection = require('./lib/build').BuildsCollection,
|
BuildsCollection = require('./lib/build').BuildsCollection,
|
||||||
libLogger = require('./lib/logger'),
|
libLogger = require('./lib/logger'),
|
||||||
|
libNode = require('./lib/node'),
|
||||||
|
libCommand = require('./lib/command'),
|
||||||
|
libExecutor = require('./lib/executor'),
|
||||||
|
libScm = require('./lib/scm'),
|
||||||
EventEmitter = require('events').EventEmitter,
|
EventEmitter = require('events').EventEmitter,
|
||||||
validateConfig = require('./lib/validateConfig'),
|
validateConfig = require('./lib/validateConfig'),
|
||||||
utils = require('./lib/utils');
|
utils = require('./lib/utils');
|
||||||
@ -64,6 +68,10 @@ app.lib = {};
|
|||||||
app.lib.BaseReaderLoader = BaseReaderLoader;
|
app.lib.BaseReaderLoader = BaseReaderLoader;
|
||||||
app.lib.BaseNotifierTransport = BaseNotifierTransport;
|
app.lib.BaseNotifierTransport = BaseNotifierTransport;
|
||||||
app.lib.logger = libLogger;
|
app.lib.logger = libLogger;
|
||||||
|
app.lib.command = libCommand;
|
||||||
|
app.lib.executor = libExecutor;
|
||||||
|
app.lib.scm = libScm;
|
||||||
|
app.lib.node = libNode;
|
||||||
|
|
||||||
var configDefaults = {
|
var configDefaults = {
|
||||||
notify: {},
|
notify: {},
|
||||||
@ -222,7 +230,7 @@ Steppy(
|
|||||||
completeUncompletedBuilds(this.slot());
|
completeUncompletedBuilds(this.slot());
|
||||||
},
|
},
|
||||||
function() {
|
function() {
|
||||||
require('./distributor').init(app, this.slot());
|
require('./distributor').create(app, this.slot());
|
||||||
},
|
},
|
||||||
function(err, distributor) {
|
function(err, distributor) {
|
||||||
app.builds = new BuildsCollection({
|
app.builds = new BuildsCollection({
|
||||||
@ -236,6 +244,8 @@ Steppy(
|
|||||||
require(plugin).register(app);
|
require(plugin).register(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
distributor.init();
|
||||||
|
|
||||||
app.notifier.init(app.config.notify, this.slot());
|
app.notifier.init(app.config.notify, this.slot());
|
||||||
},
|
},
|
||||||
function() {
|
function() {
|
||||||
|
@ -7,7 +7,7 @@ var Steppy = require('twostep').Steppy,
|
|||||||
logger = require('./lib/logger')('distributor');
|
logger = require('./lib/logger')('distributor');
|
||||||
|
|
||||||
|
|
||||||
exports.init = function(app, callback) {
|
exports.create = function(app, callback) {
|
||||||
var distributor = new Distributor({
|
var distributor = new Distributor({
|
||||||
nodes: app.config.nodes,
|
nodes: app.config.nodes,
|
||||||
projects: app.projects,
|
projects: app.projects,
|
||||||
|
@ -4,23 +4,9 @@ var EventEmitter = require('events').EventEmitter,
|
|||||||
inherits = require('util').inherits;
|
inherits = require('util').inherits;
|
||||||
|
|
||||||
function Command(params) {
|
function Command(params) {
|
||||||
params = params || {};
|
this.setParams(params);
|
||||||
this.emitIn = params.emitIn;
|
|
||||||
this.emitOut = params.emitOut;
|
|
||||||
this.emitErr = params.emitErr;
|
|
||||||
this.attachStderr = params.attachStderr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.Command = Command;
|
exports.Command = Command;
|
||||||
|
|
||||||
inherits(Command, EventEmitter);
|
inherits(Command, EventEmitter);
|
||||||
|
|
||||||
Command.prototype.enableEmitter = function() {
|
|
||||||
this.emitOut = true;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Command.prototype.disableEmitter = function() {
|
|
||||||
this.emitOut = false;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var SpawnCommand = require('./spawn').Command;
|
||||||
|
|
||||||
|
exports.SpawnCommand = SpawnCommand;
|
||||||
|
|
||||||
exports.createCommand = function(params) {
|
exports.createCommand = function(params) {
|
||||||
var Constructor = require('./' + params.type).Command;
|
var Constructor = require('./' + params.type).Command;
|
||||||
return new Constructor(params);
|
return new Constructor(params);
|
||||||
|
@ -6,15 +6,22 @@ var spawn = require('child_process').spawn,
|
|||||||
_ = require('underscore');
|
_ = require('underscore');
|
||||||
|
|
||||||
function Command(params) {
|
function Command(params) {
|
||||||
params = params || {};
|
ParentCommand.call(this, params || {});
|
||||||
ParentCommand.call(this, params);
|
|
||||||
this.cwd = params.cwd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.Command = Command;
|
exports.Command = Command;
|
||||||
|
|
||||||
inherits(Command, ParentCommand);
|
inherits(Command, ParentCommand);
|
||||||
|
|
||||||
|
Command.prototype.setParams = function(params) {
|
||||||
|
if (params.cwd) this.cwd = params.cwd;
|
||||||
|
if (params.emitIn) this.emitIn = params.emitIn;
|
||||||
|
if (params.emitOut) this.emitOut = params.emitOut;
|
||||||
|
if (params.emitErr) this.emitErr = params.emitErr;
|
||||||
|
if (params.attachStderr) this.attachStderr = params.attachStderr;
|
||||||
|
if (params.collectOut) this.collectOut = params.collectOut;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes `params.cmd` with `params.args` and `params.options`
|
* Executes `params.cmd` with `params.args` and `params.options`
|
||||||
*/
|
*/
|
||||||
|
@ -2,42 +2,58 @@
|
|||||||
|
|
||||||
var Steppy = require('twostep').Steppy,
|
var Steppy = require('twostep').Steppy,
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
Node = require('./node').Node,
|
createNode = require('./node').createNode,
|
||||||
EventEmitter = require('events').EventEmitter,
|
EventEmitter = require('events').EventEmitter,
|
||||||
inherits = require('util').inherits,
|
inherits = require('util').inherits,
|
||||||
logger = require('./logger')('distributor');
|
logger = require('./logger')('distributor');
|
||||||
|
|
||||||
|
|
||||||
function Distributor(params) {
|
function Distributor(params) {
|
||||||
var self = this;
|
this.nodes = params.nodes;
|
||||||
// nodes to execute builds
|
|
||||||
self.nodes = _(params.nodes).map(function(nodeParams) {
|
|
||||||
return self._createNode(nodeParams);
|
|
||||||
});
|
|
||||||
// queued projects to build
|
|
||||||
self.queue = [];
|
|
||||||
|
|
||||||
self.saveBuild = params.saveBuild || function(build, callback) {
|
// queued projects to build
|
||||||
|
this.queue = [];
|
||||||
|
|
||||||
|
this.saveBuild = params.saveBuild || function(build, callback) {
|
||||||
callback(null, build);
|
callback(null, build);
|
||||||
};
|
};
|
||||||
|
|
||||||
self.removeBuild = params.removeBuild || function(build, callback) {
|
this.removeBuild = params.removeBuild || function(build, callback) {
|
||||||
callback();
|
callback();
|
||||||
};
|
};
|
||||||
|
|
||||||
self.projects = params.projects;
|
this.projects = params.projects;
|
||||||
self.notifier = params.notifier;
|
this.notifier = params.notifier;
|
||||||
|
|
||||||
self.buildLogLineNumbersHash = {},
|
this.buildLogLineNumbersHash = {},
|
||||||
self.lastLinesHash = {};
|
this.lastLinesHash = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
inherits(Distributor, EventEmitter);
|
inherits(Distributor, EventEmitter);
|
||||||
|
|
||||||
exports.Distributor = Distributor;
|
exports.Distributor = Distributor;
|
||||||
|
|
||||||
Distributor.prototype._createNode = function(nodeParams) {
|
// do deferred initialization (e.g. create nodes after all plugins load)
|
||||||
return new Node(nodeParams);
|
Distributor.prototype.init = function() {
|
||||||
|
var self = this,
|
||||||
|
namesHash = {};
|
||||||
|
|
||||||
|
self.nodes = _(self.nodes).map(function(nodeParams) {
|
||||||
|
if (!nodeParams.name) {
|
||||||
|
nodeParams.name = nodeParams.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (namesHash[nodeParams.name]) {
|
||||||
|
throw new Error('Node name `' + nodeParams.name + '` already used');
|
||||||
|
}
|
||||||
|
namesHash[nodeParams.name] = 1;
|
||||||
|
|
||||||
|
return self._createNode(nodeParams);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Distributor.prototype._createNode = function(params) {
|
||||||
|
return createNode(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
Distributor.prototype._runNext = function(callback) {
|
Distributor.prototype._runNext = function(callback) {
|
||||||
@ -189,7 +205,7 @@ Distributor.prototype._updateWaitReasons = function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
var waitReason = _(waitReasons).compact().join(', ');
|
var waitReason = _(waitReasons).compact().join(', ');
|
||||||
// set only non-empty reasons
|
// set only non-empty and new reasons
|
||||||
if (waitReason && waitReason !== item.build.waitReason) {
|
if (waitReason && waitReason !== item.build.waitReason) {
|
||||||
self._updateBuild(item.build, {waitReason: waitReason});
|
self._updateBuild(item.build, {waitReason: waitReason});
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var Steppy = require('twostep').Steppy,
|
var Steppy = require('twostep').Steppy,
|
||||||
path = require('path'),
|
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
EventEmitter = require('events').EventEmitter,
|
EventEmitter = require('events').EventEmitter,
|
||||||
inherits = require('util').inherits;
|
inherits = require('util').inherits;
|
||||||
|
|
||||||
function Executor(params) {
|
function Executor(params) {
|
||||||
this.project = params.project;
|
this.project = params.project;
|
||||||
this.cwd = path.join(this.project.dir, 'workspace');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.Executor = Executor;
|
exports.Executor = Executor;
|
||||||
@ -20,15 +18,135 @@ Executor.prototype.throttledEmit = _(function() {
|
|||||||
}).throttle(500);
|
}).throttle(500);
|
||||||
|
|
||||||
Executor.prototype._getSources = function(params, callback) {
|
Executor.prototype._getSources = function(params, callback) {
|
||||||
|
var self = this,
|
||||||
|
scm;
|
||||||
|
Steppy(
|
||||||
|
function() {
|
||||||
|
self._getChanges(params, this.slot());
|
||||||
|
},
|
||||||
|
function(err, data) {
|
||||||
|
scm = data.scm;
|
||||||
|
this.pass(data.changes);
|
||||||
|
scm.update(data.rev, this.slot());
|
||||||
|
},
|
||||||
|
function(err, changes) {
|
||||||
|
scm.getCurrent(this.slot());
|
||||||
|
this.pass(changes);
|
||||||
|
scm.getRev(params.rev, this.slot());
|
||||||
|
},
|
||||||
|
function(err, currentRev, changes, latestRev) {
|
||||||
|
this.pass({
|
||||||
|
rev: currentRev,
|
||||||
|
changes: changes,
|
||||||
|
isLatest: currentRev.id === latestRev.id
|
||||||
|
});
|
||||||
|
},
|
||||||
|
callback
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Executor.prototype._runStep = function(params, callback) {
|
Executor.prototype._runStep = function(step, callback) {
|
||||||
|
var self = this,
|
||||||
|
params = _(step).clone();
|
||||||
|
|
||||||
|
Steppy(
|
||||||
|
function() {
|
||||||
|
if (params.type !== 'shell') {
|
||||||
|
throw new Error('Unknown step type: ' + params.type);
|
||||||
|
}
|
||||||
|
// set command cwd to executor cwd
|
||||||
|
params.cwd = self.cwd;
|
||||||
|
var command = self._createCommand(
|
||||||
|
_({
|
||||||
|
emitIn: true,
|
||||||
|
emitOut: true,
|
||||||
|
emitErr: true,
|
||||||
|
attachStderr: true
|
||||||
|
}).extend(params)
|
||||||
|
);
|
||||||
|
|
||||||
|
command.on('stdin', function(data) {
|
||||||
|
self.emit('data', '> ' + String(data));
|
||||||
|
});
|
||||||
|
|
||||||
|
command.on('stdout', function(data) {
|
||||||
|
self.emit('data', String(data));
|
||||||
|
});
|
||||||
|
|
||||||
|
command.on('stderr', function(data) {
|
||||||
|
self.emit('data', 'stderr: ' + String(data));
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: should be fixed properly, currently it's quick fix for
|
||||||
|
// NODE_ENV which affects npm install/prune calls
|
||||||
|
params.options = params.options || {};
|
||||||
|
params.options.env = params.options.env || process.env;
|
||||||
|
delete params.options.env.NODE_ENV;
|
||||||
|
|
||||||
|
command.run(params, this.slot())
|
||||||
|
},
|
||||||
|
callback
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Executor.prototype._getChanges = function(params, callback) {
|
||||||
|
var self = this,
|
||||||
|
scm, isFirstRun, oldRev;
|
||||||
|
Steppy(
|
||||||
|
function() {
|
||||||
|
self._isCloned(this.slot());
|
||||||
|
},
|
||||||
|
function(err, cloned) {
|
||||||
|
var scmParams = {type: params.type};
|
||||||
|
if (cloned) {
|
||||||
|
scmParams.cwd = self.cwd;
|
||||||
|
isFirstRun = false;
|
||||||
|
} else {
|
||||||
|
scmParams.repository = params.repository;
|
||||||
|
isFirstRun = true;
|
||||||
|
}
|
||||||
|
scm = self._createScm(scmParams);
|
||||||
|
|
||||||
|
scm.on('stdin', function(data) {
|
||||||
|
self.emit('data', '> ' + String(data));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isFirstRun) {
|
||||||
|
this.pass(null);
|
||||||
|
} else {
|
||||||
|
scm.getCurrent(this.slot());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function(err, id) {
|
||||||
|
oldRev = id;
|
||||||
|
|
||||||
|
if (isFirstRun) {
|
||||||
|
scm.clone(self.cwd, params.rev, this.slot());
|
||||||
|
} else {
|
||||||
|
scm.pull(params.rev, this.slot())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
scm.getChanges(oldRev && oldRev.id, params.rev, this.slot());
|
||||||
|
},
|
||||||
|
function(err, changes) {
|
||||||
|
var target = self._getTarget(params.rev, changes);
|
||||||
|
this.pass({
|
||||||
|
scm: scm,
|
||||||
|
oldRev: oldRev,
|
||||||
|
rev: target.rev,
|
||||||
|
changes: target.changes
|
||||||
|
});
|
||||||
|
},
|
||||||
|
callback
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Does current project scm has new changes to build
|
// Does current project scm has new changes to build
|
||||||
Executor.prototype.hasScmChanges = function(callback) {
|
Executor.prototype.hasScmChanges = function(callback) {
|
||||||
|
this._getChanges(this.project.scm, function(err, data) {
|
||||||
|
callback(err, !err && data.changes.length > 0);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Executor.prototype.run = function(params, callback) {
|
Executor.prototype.run = function(params, callback) {
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var BaseExecutor = require('./base').Executor;
|
||||||
|
|
||||||
|
exports.BaseExecutor = BaseExecutor;
|
||||||
|
|
||||||
exports.createExecutor = function(params) {
|
exports.createExecutor = function(params) {
|
||||||
var Constructor = require('./' + params.type).Executor;
|
var Constructor = require('./' + params.type).Executor;
|
||||||
return new Constructor(params);
|
return new Constructor(params);
|
||||||
|
@ -6,10 +6,12 @@ var Steppy = require('twostep').Steppy,
|
|||||||
createScm = require('../scm').createScm,
|
createScm = require('../scm').createScm,
|
||||||
createCommand = require('../command').createCommand,
|
createCommand = require('../command').createCommand,
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
_ = require('underscore');
|
path = require('path'),
|
||||||
|
SpawnCommand = require('../command/spawn').Command;
|
||||||
|
|
||||||
function Executor(params) {
|
function Executor(params) {
|
||||||
ParentExecutor.call(this, params);
|
ParentExecutor.call(this, params);
|
||||||
|
this.cwd = path.join(this.project.dir, 'workspace');
|
||||||
}
|
}
|
||||||
|
|
||||||
inherits(Executor, ParentExecutor);
|
inherits(Executor, ParentExecutor);
|
||||||
@ -17,140 +19,17 @@ inherits(Executor, ParentExecutor);
|
|||||||
exports.Executor = Executor;
|
exports.Executor = Executor;
|
||||||
|
|
||||||
Executor.prototype._createScm = function(params) {
|
Executor.prototype._createScm = function(params) {
|
||||||
|
params.command = new SpawnCommand();
|
||||||
|
|
||||||
return createScm(params);
|
return createScm(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
Executor.prototype._getChanges = function(params, callback) {
|
Executor.prototype._createCommand = function(params) {
|
||||||
var self = this,
|
return createCommand(params);
|
||||||
scm, isFirstRun, oldRev;
|
|
||||||
Steppy(
|
|
||||||
function() {
|
|
||||||
var slot = this.slot();
|
|
||||||
fs.exists(self.cwd, function(exists) {
|
|
||||||
slot(null, exists);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function(err, exists) {
|
|
||||||
var scmParams = {type: params.type};
|
|
||||||
if (exists) {
|
|
||||||
scmParams.cwd = self.cwd;
|
|
||||||
isFirstRun = false;
|
|
||||||
} else {
|
|
||||||
scmParams.repository = params.repository;
|
|
||||||
isFirstRun = true;
|
|
||||||
}
|
|
||||||
scm = self._createScm(scmParams);
|
|
||||||
|
|
||||||
scm.on('stdin', function(data) {
|
|
||||||
self.emit('data', '> ' + String(data));
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isFirstRun) {
|
|
||||||
this.pass(null);
|
|
||||||
} else {
|
|
||||||
scm.getCurrent(this.slot());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function(err, id) {
|
|
||||||
oldRev = id;
|
|
||||||
|
|
||||||
if (isFirstRun) {
|
|
||||||
scm.clone(self.cwd, params.rev, this.slot());
|
|
||||||
} else {
|
|
||||||
scm.pull(params.rev, this.slot())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function() {
|
|
||||||
scm.getChanges(oldRev && oldRev.id, params.rev, this.slot());
|
|
||||||
},
|
|
||||||
function(err, changes) {
|
|
||||||
var target = self._getTarget(params.rev, changes);
|
|
||||||
this.pass({
|
|
||||||
scm: scm,
|
|
||||||
oldRev: oldRev,
|
|
||||||
rev: target.rev,
|
|
||||||
changes: target.changes
|
|
||||||
});
|
|
||||||
},
|
|
||||||
callback
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Executor.prototype.hasScmChanges = function(callback) {
|
Executor.prototype._isCloned = function(callback) {
|
||||||
this._getChanges(this.project.scm, function(err, data) {
|
fs.exists(this.cwd, function(exists) {
|
||||||
callback(err, !err && data.changes.length > 0);
|
callback(null, exists);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Executor.prototype._getSources = function(params, callback) {
|
|
||||||
var self = this,
|
|
||||||
scm;
|
|
||||||
Steppy(
|
|
||||||
function() {
|
|
||||||
self._getChanges(params, this.slot());
|
|
||||||
},
|
|
||||||
function(err, data) {
|
|
||||||
scm = data.scm;
|
|
||||||
this.pass(data.changes);
|
|
||||||
scm.update(data.rev, this.slot());
|
|
||||||
},
|
|
||||||
function(err, changes) {
|
|
||||||
scm.getCurrent(this.slot());
|
|
||||||
this.pass(changes);
|
|
||||||
scm.getRev(params.rev, this.slot());
|
|
||||||
},
|
|
||||||
function(err, currentRev, changes, latestRev) {
|
|
||||||
this.pass({
|
|
||||||
rev: currentRev,
|
|
||||||
changes: changes,
|
|
||||||
isLatest: currentRev.id === latestRev.id
|
|
||||||
});
|
|
||||||
},
|
|
||||||
callback
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
Executor.prototype._runStep = function(step, callback) {
|
|
||||||
var self = this,
|
|
||||||
params = _(step).clone();
|
|
||||||
|
|
||||||
Steppy(
|
|
||||||
function() {
|
|
||||||
if (params.type !== 'shell') {
|
|
||||||
throw new Error('Unknown step type: ' + params.type);
|
|
||||||
}
|
|
||||||
// set command cwd to executor cwd
|
|
||||||
params.cwd = self.cwd;
|
|
||||||
var command = createCommand(
|
|
||||||
_({
|
|
||||||
emitIn: true,
|
|
||||||
emitOut: true,
|
|
||||||
emitErr: true,
|
|
||||||
attachStderr: true
|
|
||||||
}).extend(params)
|
|
||||||
);
|
|
||||||
|
|
||||||
command.on('stdin', function(data) {
|
|
||||||
self.emit('data', '> ' + String(data));
|
|
||||||
});
|
|
||||||
|
|
||||||
command.on('stdout', function(data) {
|
|
||||||
self.emit('data', String(data));
|
|
||||||
});
|
|
||||||
|
|
||||||
command.on('stderr', function(data) {
|
|
||||||
self.emit('data', 'stderr: ' + String(data));
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: should be fixed properly, currently it's quick fix for
|
|
||||||
// NODE_ENV which affects npm install/prune calls
|
|
||||||
params.options = params.options || {};
|
|
||||||
params.options.env = params.options.env || process.env;
|
|
||||||
delete params.options.env.NODE_ENV;
|
|
||||||
|
|
||||||
command.run(params, this.slot())
|
|
||||||
},
|
|
||||||
callback
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
@ -1,17 +1,25 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var _ = require('underscore'),
|
var _ = require('underscore');
|
||||||
createExecutor = require('./executor').createExecutor;
|
|
||||||
|
|
||||||
|
|
||||||
function Node(params) {
|
function Node(params) {
|
||||||
this.type = params.type;
|
this.type = params.type;
|
||||||
this.maxExecutorsCount = params.maxExecutorsCount;
|
this.maxExecutorsCount = params.maxExecutorsCount;
|
||||||
|
this.name = params.name;
|
||||||
|
this.usageStrategy = params.usageStrategy || 'maximum';
|
||||||
|
|
||||||
|
if (!this.usageStrategiesHash[this.usageStrategy]) {
|
||||||
|
throw new Error('Unknown usage strategy: ' + this.usageStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
this.executors = {};
|
this.executors = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.Node = Node;
|
exports.Node = Node;
|
||||||
|
|
||||||
|
Node.prototype.usageStrategiesHash = {maximum: 1, specificProject: 1};
|
||||||
|
|
||||||
Node.prototype._getBlockerExecutor = function(getBlockers, getTarget) {
|
Node.prototype._getBlockerExecutor = function(getBlockers, getTarget) {
|
||||||
return _(this.executors).find(function(executor) {
|
return _(this.executors).find(function(executor) {
|
||||||
var target = getTarget(executor);
|
var target = getTarget(executor);
|
||||||
@ -28,10 +36,20 @@ Node.prototype._getBlockerExecutor = function(getBlockers, getTarget) {
|
|||||||
Node.prototype.getExecutorWaitReason = function(project) {
|
Node.prototype.getExecutorWaitReason = function(project) {
|
||||||
var waitReason;
|
var waitReason;
|
||||||
|
|
||||||
if (_(this.executors).size() >= this.maxExecutorsCount) {
|
var targetNodeNames = project.node && project.node.target;
|
||||||
waitReason = 'All executors are busy';
|
|
||||||
|
if (targetNodeNames && !_(targetNodeNames).isArray()) {
|
||||||
|
targetNodeNames = [targetNodeNames];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetNodeNames && !_(targetNodeNames).contains(this.name)) {
|
||||||
|
waitReason = this.name + ': not a target node';
|
||||||
|
} else if (this.usageStrategy === 'specificProject' && !targetNodeNames) {
|
||||||
|
waitReason = this.name + ': only for specific projects';
|
||||||
|
} else if (_(this.executors).size() >= this.maxExecutorsCount) {
|
||||||
|
waitReason = this.name + ': all executors are busy';
|
||||||
} else if (project.name in this.executors) {
|
} else if (project.name in this.executors) {
|
||||||
waitReason = 'Project already running on node';
|
waitReason = this.name + ': project already running on node';
|
||||||
} else {
|
} else {
|
||||||
var blockerExecutor;
|
var blockerExecutor;
|
||||||
|
|
||||||
@ -59,7 +77,7 @@ Node.prototype.getExecutorWaitReason = function(project) {
|
|||||||
|
|
||||||
if (blockerExecutor) {
|
if (blockerExecutor) {
|
||||||
waitReason = (
|
waitReason = (
|
||||||
'Blocked by currently running "' +
|
this.name + ': blocked by currently running "' +
|
||||||
blockerExecutor.project.name + '"'
|
blockerExecutor.project.name + '"'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -76,13 +94,6 @@ Node.prototype.getFreeExecutorsCount = function() {
|
|||||||
return this.maxExecutorsCount - _(this.executors).size();
|
return this.maxExecutorsCount - _(this.executors).size();
|
||||||
};
|
};
|
||||||
|
|
||||||
Node.prototype._createExecutor = function(project) {
|
|
||||||
return createExecutor({
|
|
||||||
type: this.type,
|
|
||||||
project: project
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Node.prototype.hasScmChanges = function(project, callback) {
|
Node.prototype.hasScmChanges = function(project, callback) {
|
||||||
this._createExecutor(project).hasScmChanges(callback);
|
this._createExecutor(project).hasScmChanges(callback);
|
||||||
};
|
};
|
22
lib/node/index.js
Normal file
22
lib/node/index.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var BaseNode = require('./base').Node;
|
||||||
|
|
||||||
|
exports.BaseNode = BaseNode;
|
||||||
|
|
||||||
|
var constructors = {
|
||||||
|
local: require('./local').Node
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.register = function(type, constructor) {
|
||||||
|
constructors[type] = constructor;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.createNode = function(params) {
|
||||||
|
if (params.type in constructors === false) {
|
||||||
|
throw new Error('Unknown node type: ' + params.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
var Constructor = constructors[params.type];
|
||||||
|
return new Constructor(params);
|
||||||
|
};
|
20
lib/node/local.js
Normal file
20
lib/node/local.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
'user strict';
|
||||||
|
|
||||||
|
var inherits = require('util').inherits,
|
||||||
|
ParentNode = require('./base').Node,
|
||||||
|
LocalExecutor = require('../executor/local').Executor;
|
||||||
|
|
||||||
|
function Node(params) {
|
||||||
|
ParentNode.call(this, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(Node, ParentNode);
|
||||||
|
|
||||||
|
exports.Node = Node;
|
||||||
|
|
||||||
|
Node.prototype._createExecutor = function(project) {
|
||||||
|
return new LocalExecutor({
|
||||||
|
type: this.type,
|
||||||
|
project: project
|
||||||
|
});
|
||||||
|
};
|
@ -1,22 +1,48 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var ParentCommand = require('../command/spawn').Command,
|
var EventEmitter = require('events').EventEmitter,
|
||||||
inherits = require('util').inherits;
|
inherits = require('util').inherits,
|
||||||
|
_ = require('underscore');
|
||||||
|
|
||||||
function Scm(params) {
|
function Scm(params) {
|
||||||
ParentCommand.call(this, params);
|
var self = this;
|
||||||
this.repository = params.repository;
|
|
||||||
if (!this.repository && !this.cwd) throw new Error(
|
EventEmitter.call(self);
|
||||||
'`repository` or `cwd` must be set'
|
|
||||||
);
|
self.repository = params.repository;
|
||||||
this.collectOut = true;
|
self.cwd = params.cwd;
|
||||||
this.emitIn = true;
|
|
||||||
this.attachStderr = true;
|
if (!self.repository && !self.cwd) {
|
||||||
|
throw new Error('`repository` or `cwd` must be set');
|
||||||
|
}
|
||||||
|
|
||||||
|
self.command = params.command;
|
||||||
|
|
||||||
|
if (!self.command) throw new Error('`command` is required');
|
||||||
|
|
||||||
|
self.command.setParams({
|
||||||
|
collectOut: true,
|
||||||
|
emitIn: true,
|
||||||
|
attachStderr: true
|
||||||
|
});
|
||||||
|
|
||||||
|
self.command.on('stdin', function(data) {
|
||||||
|
self.emit('stdin', data);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.Scm = Scm;
|
exports.Scm = Scm;
|
||||||
|
|
||||||
inherits(Scm, ParentCommand);
|
inherits(Scm, EventEmitter);
|
||||||
|
|
||||||
|
Scm.prototype._run = function(params, callback) {
|
||||||
|
if (this.cwd) {
|
||||||
|
params.options = params.options || {};
|
||||||
|
params.options.cwd = this.cwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.command.run(params, callback);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone repository to the `dst` update to `rev` and set `this.cwd` to `dst`
|
* Clone repository to the `dst` update to `rev` and set `this.cwd` to `dst`
|
||||||
|
@ -60,14 +60,14 @@ Scm.prototype.clone = function(dst, rev, callback) {
|
|||||||
function() {
|
function() {
|
||||||
// git can't clearly clone specified rev but can clone branch
|
// git can't clearly clone specified rev but can clone branch
|
||||||
// possible solution to change clone params to (dst, branch, callback)
|
// possible solution to change clone params to (dst, branch, callback)
|
||||||
self.run({
|
self._run({
|
||||||
cmd: 'git',
|
cmd: 'git',
|
||||||
args: ['clone', '--recursive', self.repository, dst]
|
args: ['clone', '--recursive', self.repository, dst]
|
||||||
}, this.slot());
|
}, this.slot());
|
||||||
self.cwd = dst;
|
self.cwd = dst;
|
||||||
},
|
},
|
||||||
function() {
|
function() {
|
||||||
self.run({cmd: 'git', args: ['checkout', '-f', rev]}, this.slot());
|
self._run({cmd: 'git', args: ['checkout', '-f', rev]}, this.slot());
|
||||||
},
|
},
|
||||||
callback
|
callback
|
||||||
);
|
);
|
||||||
@ -82,7 +82,7 @@ Scm.prototype.pull = function(rev, callback) {
|
|||||||
},
|
},
|
||||||
function(err, currentRev) {
|
function(err, currentRev) {
|
||||||
this.pass(currentRev);
|
this.pass(currentRev);
|
||||||
self.run({cmd: 'git', args: ['pull']}, this.slot());
|
self._run({cmd: 'git', args: ['pull']}, this.slot());
|
||||||
},
|
},
|
||||||
function(err, currentRev) {
|
function(err, currentRev) {
|
||||||
self.update(currentRev.id, this.slot());
|
self.update(currentRev.id, this.slot());
|
||||||
@ -104,7 +104,7 @@ Scm.prototype.getRev = function(rev, callback) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
Steppy(
|
Steppy(
|
||||||
function() {
|
function() {
|
||||||
self.run({cmd: 'git', args: [
|
self._run({cmd: 'git', args: [
|
||||||
'show', rev,
|
'show', rev,
|
||||||
'--pretty=' + self._revTemplate
|
'--pretty=' + self._revTemplate
|
||||||
]}, this.slot());
|
]}, this.slot());
|
||||||
@ -146,7 +146,7 @@ Scm.prototype.getChanges = function(rev1, rev2, callback) {
|
|||||||
function(err, currentRev) {
|
function(err, currentRev) {
|
||||||
this.pass(currentRev);
|
this.pass(currentRev);
|
||||||
|
|
||||||
self.run({cmd: 'git', args: [
|
self._run({cmd: 'git', args: [
|
||||||
'log', rev1 ? rev1 + '..' + rev2 : rev2,
|
'log', rev1 ? rev1 + '..' + rev2 : rev2,
|
||||||
'--pretty=' + self._revTemplate + self._linesSeparator
|
'--pretty=' + self._revTemplate + self._linesSeparator
|
||||||
]}, this.slot());
|
]}, this.slot());
|
||||||
@ -175,10 +175,10 @@ Scm.prototype.update = function(rev, callback) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
Steppy(
|
Steppy(
|
||||||
function() {
|
function() {
|
||||||
self.run({cmd: 'git', args: ['checkout', '-f', rev]}, this.slot());
|
self._run({cmd: 'git', args: ['checkout', '-f', rev]}, this.slot());
|
||||||
},
|
},
|
||||||
function() {
|
function() {
|
||||||
self.run({cmd: 'git', args: ['submodule', 'update']}, this.slot());
|
self._run({cmd: 'git', args: ['submodule', 'update']}, this.slot());
|
||||||
},
|
},
|
||||||
callback
|
callback
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,23 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var BaseScm = require('./base').Scm;
|
||||||
|
|
||||||
|
exports.BaseScm = BaseScm;
|
||||||
|
|
||||||
|
var constructors = {
|
||||||
|
git: require('./git').Scm,
|
||||||
|
mercurial: require('./mercurial').Scm
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.register = function(type, constructor) {
|
||||||
|
constructors[type] = constructor;
|
||||||
|
};
|
||||||
|
|
||||||
exports.createScm = function(params) {
|
exports.createScm = function(params) {
|
||||||
var Constructor = require('./' + params.type).Scm;
|
if (params.type in constructors === false) {
|
||||||
|
throw new Error('Unknown scm type: ' + params.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
var Constructor = constructors[params.type];
|
||||||
return new Constructor(params);
|
return new Constructor(params);
|
||||||
};
|
};
|
||||||
|
@ -55,7 +55,7 @@ Scm.prototype.clone = function(dst, rev, callback) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
Steppy(
|
Steppy(
|
||||||
function() {
|
function() {
|
||||||
self.run({
|
self._run({
|
||||||
cmd: 'hg',
|
cmd: 'hg',
|
||||||
args: ['clone', '--rev', rev, self.repository, dst]
|
args: ['clone', '--rev', rev, self.repository, dst]
|
||||||
}, this.slot());
|
}, this.slot());
|
||||||
@ -66,14 +66,14 @@ Scm.prototype.clone = function(dst, rev, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Scm.prototype.pull = function(rev, callback) {
|
Scm.prototype.pull = function(rev, callback) {
|
||||||
this.run({cmd: 'hg', args: ['pull', '--rev', rev]}, callback);
|
this._run({cmd: 'hg', args: ['pull', '--rev', rev]}, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Scm.prototype.getCurrent = function(callback) {
|
Scm.prototype.getCurrent = function(callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
Steppy(
|
Steppy(
|
||||||
function() {
|
function() {
|
||||||
self.run({cmd: 'hg', args: [
|
self._run({cmd: 'hg', args: [
|
||||||
'parent', '--template', self._revTemplate
|
'parent', '--template', self._revTemplate
|
||||||
]}, this.slot());
|
]}, this.slot());
|
||||||
},
|
},
|
||||||
@ -88,7 +88,7 @@ Scm.prototype.getChanges = function(rev1, rev2, callback) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
Steppy(
|
Steppy(
|
||||||
function() {
|
function() {
|
||||||
self.run({cmd: 'hg', args: [
|
self._run({cmd: 'hg', args: [
|
||||||
'log', '--rev', rev2 + ':' + rev1,
|
'log', '--rev', rev2 + ':' + rev1,
|
||||||
'--template', self._revTemplate + self._linesSeparator
|
'--template', self._revTemplate + self._linesSeparator
|
||||||
]}, this.slot());
|
]}, this.slot());
|
||||||
@ -111,5 +111,5 @@ Scm.prototype.getChanges = function(rev1, rev2, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Scm.prototype.update = function(rev, callback) {
|
Scm.prototype.update = function(rev, callback) {
|
||||||
this.run({cmd: 'hg', args: ['up', '-C', rev]}, callback);
|
this._run({cmd: 'hg', args: ['up', '-C', rev]}, callback);
|
||||||
};
|
};
|
||||||
|
@ -19,8 +19,11 @@ module.exports = function(config, callback) {
|
|||||||
items: {
|
items: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
type: {type: 'string', enum: ['local']},
|
name: {type: 'string'},
|
||||||
maxExecutorsCount: {type: 'integer'}
|
type: {type: 'string'},
|
||||||
|
usageStrategy: {type: 'string'},
|
||||||
|
maxExecutorsCount: {type: 'integer'},
|
||||||
|
options: {type: 'object'}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
minItems: 1
|
minItems: 1
|
||||||
|
@ -93,7 +93,7 @@ describe('Distributor blocking with max 2 executors count', function() {
|
|||||||
var spy = updateBuildSpy;
|
var spy = updateBuildSpy;
|
||||||
expect(spy.getCall(3).args[0].project.name).equal('project2');
|
expect(spy.getCall(3).args[0].project.name).equal('project2');
|
||||||
expect(spy.getCall(3).args[1].waitReason).equal(
|
expect(spy.getCall(3).args[1].waitReason).equal(
|
||||||
'Blocked by currently running "project1"'
|
'local: blocked by currently running "project1"'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
var _ = require('underscore'),
|
var _ = require('underscore'),
|
||||||
sinon = require('sinon'),
|
sinon = require('sinon'),
|
||||||
Node = require('../../lib/node').Node,
|
createNode = require('../../lib/node').createNode,
|
||||||
EventEmitter = require('events').EventEmitter,
|
EventEmitter = require('events').EventEmitter,
|
||||||
ProjectsCollection = require('../../lib/project').ProjectsCollection,
|
ProjectsCollection = require('../../lib/project').ProjectsCollection,
|
||||||
Distributor = require('../../lib/distributor').Distributor,
|
Distributor = require('../../lib/distributor').Distributor,
|
||||||
Notifier = require('../../lib/notifier').Notifier;
|
Notifier = require('../../lib/notifier').Notifier;
|
||||||
|
|
||||||
|
|
||||||
var createNode = function(executorRun) {
|
var createMockedNode = function(executorRun) {
|
||||||
return function(params) {
|
return function(params) {
|
||||||
var node = new Node(params);
|
var node = createNode(params);
|
||||||
node._createExecutor = function(project) {
|
node._createExecutor = function(project) {
|
||||||
var executor = new EventEmitter();
|
var executor = new EventEmitter();
|
||||||
executor.project = project;
|
executor.project = project;
|
||||||
@ -38,7 +38,7 @@ exports.createDistributor = function(params) {
|
|||||||
distributorParams.executorRun || sinon.stub().callsArgAsync(1)
|
distributorParams.executorRun || sinon.stub().callsArgAsync(1)
|
||||||
);
|
);
|
||||||
// patch method which will be called at constructor
|
// patch method which will be called at constructor
|
||||||
sinon.stub(Distributor.prototype, '_createNode', createNode(
|
sinon.stub(Distributor.prototype, '_createNode', createMockedNode(
|
||||||
executorRun
|
executorRun
|
||||||
));
|
));
|
||||||
delete distributorParams.executorRun;
|
delete distributorParams.executorRun;
|
||||||
@ -52,6 +52,7 @@ exports.createDistributor = function(params) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
var distributor = new Distributor(distributorParams);
|
var distributor = new Distributor(distributorParams);
|
||||||
|
distributor.init();
|
||||||
|
|
||||||
if (mockNode) {
|
if (mockNode) {
|
||||||
Distributor.prototype._createNode.restore();
|
Distributor.prototype._createNode.restore();
|
||||||
|
115
test/node.js
115
test/node.js
@ -1,7 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var Node = require('../lib/node').Node,
|
var createNode = require('../lib/node').createNode,
|
||||||
expect = require('expect.js');
|
expect = require('expect.js'),
|
||||||
|
_ = require('underscore');
|
||||||
|
|
||||||
|
|
||||||
describe('Node', function() {
|
describe('Node', function() {
|
||||||
@ -9,6 +10,114 @@ describe('Node', function() {
|
|||||||
project1 = {name: 'project1'},
|
project1 = {name: 'project1'},
|
||||||
project2 = {name: 'project2'};
|
project2 = {name: 'project2'};
|
||||||
|
|
||||||
|
var createNodeMock = function(params) {
|
||||||
|
params = params || {};
|
||||||
|
|
||||||
|
var node = createNode(_({
|
||||||
|
name: 'executor1',
|
||||||
|
type: 'local',
|
||||||
|
maxExecutorsCount: 1,
|
||||||
|
usageStrategy: 'maximum'
|
||||||
|
}).extend(params));
|
||||||
|
|
||||||
|
// only for testing
|
||||||
|
if (params.executors) {
|
||||||
|
node.executors = params.executors;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('wait reason', function() {
|
||||||
|
|
||||||
|
it('should be not a target node when node target is not match', function() {
|
||||||
|
var waitReason = createNodeMock({
|
||||||
|
name: 'executor1'
|
||||||
|
}).getExecutorWaitReason({
|
||||||
|
name: 'project1',
|
||||||
|
node: {target: 'other executor'}
|
||||||
|
});
|
||||||
|
expect(waitReason).eql('executor1: not a target node');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be falsy when node target match', function() {
|
||||||
|
var waitReason = createNodeMock({
|
||||||
|
name: 'executor1'
|
||||||
|
}).getExecutorWaitReason({
|
||||||
|
name: 'project1',
|
||||||
|
node: {target: 'executor1'}
|
||||||
|
});
|
||||||
|
expect(waitReason).not.ok();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be falsy when node target (array) match', function() {
|
||||||
|
var waitReason = createNodeMock({
|
||||||
|
name: 'executor1'
|
||||||
|
}).getExecutorWaitReason({
|
||||||
|
name: 'project1',
|
||||||
|
node: {target: ['executor1']}
|
||||||
|
});
|
||||||
|
expect(waitReason).not.ok();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be only for specific projects when target is not set', function() {
|
||||||
|
var waitReason = createNodeMock({
|
||||||
|
usageStrategy: 'specificProject'
|
||||||
|
}).getExecutorWaitReason({
|
||||||
|
name: 'project1'
|
||||||
|
});
|
||||||
|
expect(waitReason).eql('executor1: only for specific projects');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be all executors are busy when true', function() {
|
||||||
|
var waitReason = createNodeMock({
|
||||||
|
maxExecutorsCount: 1,
|
||||||
|
executors: {project2: 1}
|
||||||
|
}).getExecutorWaitReason({
|
||||||
|
name: 'project1'
|
||||||
|
});
|
||||||
|
expect(waitReason).eql('executor1: all executors are busy');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be project already running on node when true', function() {
|
||||||
|
var waitReason = createNodeMock({
|
||||||
|
maxExecutorsCount: 2,
|
||||||
|
executors: {project1: 1}
|
||||||
|
}).getExecutorWaitReason({
|
||||||
|
name: 'project1'
|
||||||
|
});
|
||||||
|
expect(waitReason).eql('executor1: project already running on node');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be blocked by project when blocked by executing', function() {
|
||||||
|
var waitReason = createNodeMock({
|
||||||
|
maxExecutorsCount: 2,
|
||||||
|
executors: {project2: {project: {name: 'project2'}}}
|
||||||
|
}).getExecutorWaitReason({
|
||||||
|
name: 'project1',
|
||||||
|
blockedBy: ['project2']
|
||||||
|
});
|
||||||
|
expect(waitReason).eql(
|
||||||
|
'executor1: blocked by currently running "project2"'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be blocked by project when executing blocks it', function() {
|
||||||
|
var waitReason = createNodeMock({
|
||||||
|
maxExecutorsCount: 2,
|
||||||
|
executors: {project2: {project: {
|
||||||
|
name: 'project2',
|
||||||
|
blocks: ['project1']
|
||||||
|
}}}
|
||||||
|
}).getExecutorWaitReason({
|
||||||
|
name: 'project1'
|
||||||
|
});
|
||||||
|
expect(waitReason).eql(
|
||||||
|
'executor1: blocked by currently running "project2"'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
var expectNodeHasFreeExecutor = function(project, value) {
|
var expectNodeHasFreeExecutor = function(project, value) {
|
||||||
it('should' + (value ? ' ' : ' not ') + 'has free executors for ' +
|
it('should' + (value ? ' ' : ' not ') + 'has free executors for ' +
|
||||||
project.name, function() {
|
project.name, function() {
|
||||||
@ -19,7 +128,7 @@ describe('Node', function() {
|
|||||||
|
|
||||||
describe('basic', function() {
|
describe('basic', function() {
|
||||||
it('instance should be created without errors', function() {
|
it('instance should be created without errors', function() {
|
||||||
node = new Node({
|
node = createNode({
|
||||||
type: 'local',
|
type: 'local',
|
||||||
maxExecutorsCount: 1
|
maxExecutorsCount: 1
|
||||||
});
|
});
|
||||||
|
@ -42,7 +42,8 @@ var expect = require('expect.js'),
|
|||||||
it('create scm instance attached to new repository without errors', function() {
|
it('create scm instance attached to new repository without errors', function() {
|
||||||
scm = createScm({
|
scm = createScm({
|
||||||
type: type,
|
type: type,
|
||||||
repository: originalRepositoryPath
|
repository: originalRepositoryPath,
|
||||||
|
command: new SpawnCommand()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -129,7 +130,11 @@ var expect = require('expect.js'),
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('create scm instance attached to existing `cwd` without errors', function() {
|
it('create scm instance attached to existing `cwd` without errors', function() {
|
||||||
scm = createScm({type: type, cwd: repositoryPath});
|
scm = createScm({
|
||||||
|
type: type,
|
||||||
|
cwd: repositoryPath,
|
||||||
|
command: new SpawnCommand()
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('expect repository log from rev0 to default revision equals to ' +
|
it('expect repository log from rev0 to default revision equals to ' +
|
||||||
|
Loading…
Reference in New Issue
Block a user