mirror of
https://gitlab.silvrtree.co.uk/martind2000/nci.git
synced 2025-01-11 07:45:09 +00:00
merge and bootstrap added
This commit is contained in:
commit
1a91f9cb27
@ -5,6 +5,7 @@ var EventEmitter = require('events').EventEmitter,
|
|||||||
|
|
||||||
function Command(params) {
|
function Command(params) {
|
||||||
params = params || {};
|
params = params || {};
|
||||||
|
this.emitIn = params.emitIn;
|
||||||
this.emitOut = params.emitOut;
|
this.emitOut = params.emitOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
var spawn = require('child_process').spawn,
|
var spawn = require('child_process').spawn,
|
||||||
ParentCommand = require('./base').Command,
|
ParentCommand = require('./base').Command,
|
||||||
inherits = require('util').inherits,
|
inherits = require('util').inherits,
|
||||||
utils = require('../utils');
|
_ = require('underscore');
|
||||||
|
|
||||||
function Command(params) {
|
function Command(params) {
|
||||||
params = params || {};
|
params = params || {};
|
||||||
@ -21,20 +21,29 @@ inherits(Command, ParentCommand);
|
|||||||
Command.prototype.run = function(params, callback) {
|
Command.prototype.run = function(params, callback) {
|
||||||
var self = this,
|
var self = this,
|
||||||
stdout = self.collectOut ? '' : null;
|
stdout = self.collectOut ? '' : null;
|
||||||
|
|
||||||
if (!params.cmd) return callback(new Error('`cmd` is not set'));
|
if (!params.cmd) return callback(new Error('`cmd` is not set'));
|
||||||
if (!params.args) return callback(new Error('`args` is not set'));
|
if (!params.args) return callback(new Error('`args` is not set'));
|
||||||
callback = utils.once(callback);
|
callback = _(callback).once();
|
||||||
params.options = params.options || {};
|
params.options = params.options || {};
|
||||||
params.options.cwd = params.options.cwd || this.cwd;
|
params.options.cwd = params.options.cwd || this.cwd;
|
||||||
|
|
||||||
var cmd = spawn(params.cmd, params.args, params.options);
|
var cmd = spawn(params.cmd, params.args, params.options);
|
||||||
|
|
||||||
|
if (self.emitIn) {
|
||||||
|
self.emit('stdin', params.cmd + ' ' + params.args.join(' '));
|
||||||
|
}
|
||||||
|
|
||||||
cmd.stdout.on('data', function(data) {
|
cmd.stdout.on('data', function(data) {
|
||||||
if (self.emitOut) self.emit('stdout', data);
|
if (self.emitOut) self.emit('stdout', data);
|
||||||
if (self.collectOut) stdout += data;
|
if (self.collectOut) stdout += data;
|
||||||
});
|
});
|
||||||
|
|
||||||
cmd.stderr.on('data', function(data) {
|
cmd.stderr.on('data', function(data) {
|
||||||
callback(new Error('Spawned command outputs to stderr: ' + data));
|
callback(new Error('Spawned command outputs to stderr: ' + data));
|
||||||
cmd.kill();
|
cmd.kill();
|
||||||
});
|
});
|
||||||
|
|
||||||
cmd.on('close', function(code) {
|
cmd.on('close', function(code) {
|
||||||
var err = null;
|
var err = null;
|
||||||
if (code !== 0) err = new Error(
|
if (code !== 0) err = new Error(
|
||||||
@ -42,5 +51,6 @@ Command.prototype.run = function(params, callback) {
|
|||||||
);
|
);
|
||||||
callback(err, stdout);
|
callback(err, stdout);
|
||||||
});
|
});
|
||||||
|
|
||||||
return cmd;
|
return cmd;
|
||||||
};
|
};
|
||||||
|
@ -17,6 +17,9 @@ function Distributor(params) {
|
|||||||
self.onBuildUpdate = params.onBuildUpdate || function(build, callback) {
|
self.onBuildUpdate = params.onBuildUpdate || function(build, callback) {
|
||||||
callback(null, build);
|
callback(null, build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.onBuildData = params.onBuildData || function(build, data) {
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.Distributor = Distributor;
|
exports.Distributor = Distributor;
|
||||||
@ -55,10 +58,22 @@ Distributor.prototype._runNext = function(callback) {
|
|||||||
self.queue.splice(queueItemIndex, 1);
|
self.queue.splice(queueItemIndex, 1);
|
||||||
|
|
||||||
var stepCallback = this.slot();
|
var stepCallback = this.slot();
|
||||||
node.run(queueItem.project, build.params, function(err) {
|
var executor = node.run(queueItem.project, build.params, function(err) {
|
||||||
build.status = err ? 'error' : 'done';
|
build.status = err ? 'error' : 'done';
|
||||||
build.error = err;
|
build.error = err;
|
||||||
self._updateBuild(build, stepCallback);
|
self._updateBuild(build, function(err, build) {
|
||||||
|
// try to run next project from the queue
|
||||||
|
self._runNext(stepCallback);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
executor.on('currentStep', function(stepLabel) {
|
||||||
|
build.currentStep = stepLabel;
|
||||||
|
self._updateBuild(build);
|
||||||
|
});
|
||||||
|
|
||||||
|
executor.on('data', function(data) {
|
||||||
|
self.onBuildData(build, data);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
callback
|
callback
|
||||||
@ -66,6 +81,7 @@ Distributor.prototype._runNext = function(callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Distributor.prototype._updateBuild = function(build, callback) {
|
Distributor.prototype._updateBuild = function(build, callback) {
|
||||||
|
callback = callback || _.noop;
|
||||||
this.onBuildUpdate(build, callback);
|
this.onBuildUpdate(build, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -76,7 +92,7 @@ Distributor.prototype.run = function(project, params, callback) {
|
|||||||
self._updateBuild({
|
self._updateBuild({
|
||||||
project: project,
|
project: project,
|
||||||
params: params,
|
params: params,
|
||||||
status: 'waiting'
|
status: 'queued'
|
||||||
}, this.slot());
|
}, this.slot());
|
||||||
},
|
},
|
||||||
function(err, build) {
|
function(err, build) {
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
var Steppy = require('twostep').Steppy,
|
var Steppy = require('twostep').Steppy,
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
_ = require('underscore');
|
_ = require('underscore'),
|
||||||
|
EventEmitter = require('events').EventEmitter,
|
||||||
|
inherits = require('util').inherits,
|
||||||
|
utils = require('../utils');
|
||||||
|
|
||||||
function Executor(params) {
|
function Executor(params) {
|
||||||
this.project = params.project;
|
this.project = params.project;
|
||||||
@ -11,6 +14,8 @@ function Executor(params) {
|
|||||||
|
|
||||||
exports.Executor = Executor;
|
exports.Executor = Executor;
|
||||||
|
|
||||||
|
inherits(Executor, EventEmitter);
|
||||||
|
|
||||||
Executor.prototype._getSources = function(params, callback) {
|
Executor.prototype._getSources = function(params, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -23,11 +28,14 @@ Executor.prototype.run = function(params, callback) {
|
|||||||
project = _({}).extend(self.project, params);
|
project = _({}).extend(self.project, params);
|
||||||
Steppy(
|
Steppy(
|
||||||
function() {
|
function() {
|
||||||
|
self.emit('currentStep', 'get sources');
|
||||||
self._getSources(project.scm, this.slot());
|
self._getSources(project.scm, this.slot());
|
||||||
},
|
},
|
||||||
function() {
|
function() {
|
||||||
var funcs = project.steps.map(function(step) {
|
var funcs = project.steps.map(function(step, index) {
|
||||||
return function() {
|
return function() {
|
||||||
|
var stepLabel = step.name || utils.prune(step.cmd, 15);
|
||||||
|
self.emit('currentStep', stepLabel);
|
||||||
self._runStep(step, this.slot());
|
self._runStep(step, this.slot());
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,8 @@ var Steppy = require('twostep').Steppy,
|
|||||||
ParentExecutor = require('./base').Executor,
|
ParentExecutor = require('./base').Executor,
|
||||||
createScm = require('../scm').createScm,
|
createScm = require('../scm').createScm,
|
||||||
createCommand = require('../command').createCommand,
|
createCommand = require('../command').createCommand,
|
||||||
fs = require('fs');
|
fs = require('fs'),
|
||||||
|
_ = require('underscore');
|
||||||
|
|
||||||
function Executor(params) {
|
function Executor(params) {
|
||||||
ParentExecutor.call(this, params);
|
ParentExecutor.call(this, params);
|
||||||
@ -61,7 +62,21 @@ Executor.prototype._runStep = function(params, callback) {
|
|||||||
}
|
}
|
||||||
// set command cwd to executor cwd
|
// set command cwd to executor cwd
|
||||||
params.cwd = self.cwd;
|
params.cwd = self.cwd;
|
||||||
var command = createCommand(params);
|
var command = createCommand(
|
||||||
|
_({
|
||||||
|
emitIn: true,
|
||||||
|
emitOut: true
|
||||||
|
}).extend(params)
|
||||||
|
);
|
||||||
|
|
||||||
|
command.on('stdin', function(data) {
|
||||||
|
self.emit('data', '> ' + String(data));
|
||||||
|
});
|
||||||
|
|
||||||
|
command.on('stdout', function(data) {
|
||||||
|
self.emit('data', String(data));
|
||||||
|
});
|
||||||
|
|
||||||
command.run(params, this.slot())
|
command.run(params, this.slot())
|
||||||
},
|
},
|
||||||
callback
|
callback
|
||||||
|
@ -39,4 +39,6 @@ Node.prototype.run = function(project, params, callback) {
|
|||||||
delete self.executors[project.name];
|
delete self.executors[project.name];
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return this.executors[project.name];
|
||||||
};
|
};
|
||||||
|
28
lib/utils.js
28
lib/utils.js
@ -1,24 +1,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
['Function', 'String', 'Number', 'Date', 'RegExp'].forEach(function(name) {
|
exports.prune = function(str, length) {
|
||||||
exports['is' + name] = function(obj) {
|
var result = '',
|
||||||
return toString.call(obj) == '[object ' + name + ']';
|
words = str.split(' ');
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
exports.isObject = function(obj) {
|
do {
|
||||||
return obj === Object(obj);
|
result += words.shift() + ' ';
|
||||||
};
|
} while (words.length && result.length < length);
|
||||||
|
|
||||||
exports.noop = function() {};
|
return result.replace(/ $/, result.length <= length ? '' : '...');
|
||||||
|
|
||||||
exports.slice = Array.prototype.slice;
|
|
||||||
|
|
||||||
exports.once = function(func) {
|
|
||||||
var isCalled = false;
|
|
||||||
return function() {
|
|
||||||
if (isCalled) return;
|
|
||||||
func.apply(this, arguments);
|
|
||||||
isCalled = true;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,11 @@
|
|||||||
"rev": "default"
|
"rev": "default"
|
||||||
},
|
},
|
||||||
"steps": [
|
"steps": [
|
||||||
|
{"type": "shell", "cmd": "sleep 2 && echo \"hello, cur dir is `pwd`\""},
|
||||||
|
{"type": "shell", "name": "sleep", "cmd": "sleep 4"},
|
||||||
{"type": "shell", "cmd": "echo 1 > 1.txt"},
|
{"type": "shell", "cmd": "echo 1 > 1.txt"},
|
||||||
{"type": "shell", "cmd": "echo 2 > 2.txt"}
|
{"type": "shell", "cmd": "sleep 4"},
|
||||||
|
{"type": "shell", "cmd": "echo 2 > 2.txt"},
|
||||||
|
{"type": "shell", "cmd": "cat 1.txt 2.txt"}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -7,6 +7,8 @@
|
|||||||
},
|
},
|
||||||
"steps": [
|
"steps": [
|
||||||
{"type": "shell", "cmd": "echo 11 > 11.txt"},
|
{"type": "shell", "cmd": "echo 11 > 11.txt"},
|
||||||
{"type": "shell", "cmd": "echo 22 > 22.txt"}
|
{"type": "shell", "cmd": "sleep 4"},
|
||||||
|
{"type": "shell", "cmd": "echo 22 > 22.txt"},
|
||||||
|
{"type": "shell", "cmd": "cat 11.txt 22.txt"}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -19,16 +19,28 @@ project.loadAll('projects', function(err, loadedProjects) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
module.exports = function(app) {
|
module.exports = function(app) {
|
||||||
|
var buildsSequnce = 0;
|
||||||
|
|
||||||
var distributor = new Distributor({
|
var distributor = new Distributor({
|
||||||
nodes: [{type: 'local', maxExecutorsCount: 1}],
|
nodes: [{type: 'local', maxExecutorsCount: 1}],
|
||||||
onBuildUpdate: function(build, callback) {
|
onBuildUpdate: function(build, callback) {
|
||||||
var buildsResource = app.dataio.resource('builds');
|
var buildsResource = app.dataio.resource('builds');
|
||||||
|
if (build.status === 'queued') {
|
||||||
|
build.id = ++buildsSequnce;
|
||||||
|
// create resource for build data
|
||||||
|
var buildDataResource = app.dataio.resource('build' + build.id);
|
||||||
|
buildDataResource.on('connection', function(client) {
|
||||||
|
client.emit('sync', 'data', '< collected data >');
|
||||||
|
});
|
||||||
|
}
|
||||||
buildsResource.clientEmitSync(
|
buildsResource.clientEmitSync(
|
||||||
build.status === 'waiting' ? 'create' : 'update',
|
build.status === 'queued' ? 'create' : 'update',
|
||||||
build
|
build
|
||||||
);
|
);
|
||||||
callback(null, build);
|
callback(null, build);
|
||||||
|
},
|
||||||
|
onBuildData: function(build, data) {
|
||||||
|
app.dataio.resource('build' + build.id).clientEmitSync('data', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
10
static/js/app/actions/build.js
Normal file
10
static/js/app/actions/build.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define(['reflux'], function(Reflux) {
|
||||||
|
var Actions = Reflux.createActions([
|
||||||
|
'readConsoleOutput',
|
||||||
|
'readAll'
|
||||||
|
]);
|
||||||
|
|
||||||
|
return Actions;
|
||||||
|
});
|
@ -6,31 +6,9 @@ define([
|
|||||||
], function(
|
], function(
|
||||||
React, template, Components, ProjectActions
|
React, template, Components, ProjectActions
|
||||||
) {
|
) {
|
||||||
//var projectsTemplate = _($('#projects-template').html()).template();
|
|
||||||
//$('#content').on('click', '.js-projects .js-run', function() {
|
|
||||||
//var projectName = $(this).parent('.js-project').data('name');
|
|
||||||
//projects.sync('run', {projectName: projectName}, function(err, result) {
|
|
||||||
//$('#content').append(
|
|
||||||
//(err && err.message)
|
|
||||||
//);
|
|
||||||
//});
|
|
||||||
//});
|
|
||||||
|
|
||||||
//projects.sync('read', function(err, projects) {
|
|
||||||
//console.log('read complete');
|
|
||||||
////$('#content').html(
|
|
||||||
////(err && err.message) ||
|
|
||||||
////projectsTemplate({projects: projects})
|
|
||||||
////);
|
|
||||||
//});
|
|
||||||
|
|
||||||
//builds.subscribe(function(data, action) {
|
|
||||||
//$('#content').append(action.action + ': ' + JSON.stringify(data));
|
|
||||||
//});
|
|
||||||
|
|
||||||
React.render(template({
|
React.render(template({
|
||||||
App: Components.App
|
App: Components.App
|
||||||
}), document.getElementById('react-content'));
|
}), document.getElementById('content'));
|
||||||
|
|
||||||
ProjectActions.readAll();
|
ProjectActions.readAll();
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
div
|
h1 nci
|
||||||
h1 application
|
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-md-4
|
||||||
ProjectsList()
|
ProjectsList()
|
||||||
|
|
||||||
|
.col-md-4
|
||||||
|
BuildsList()
|
||||||
|
|
||||||
|
.col-md-4
|
||||||
|
Console()
|
||||||
|
@ -3,12 +3,16 @@
|
|||||||
define([
|
define([
|
||||||
'react',
|
'react',
|
||||||
'app/components/projects/index',
|
'app/components/projects/index',
|
||||||
|
'app/components/builds/index',
|
||||||
|
'app/components/console/index',
|
||||||
'templates/app/components/app'
|
'templates/app/components/app'
|
||||||
], function(React, Projects, template) {
|
], function(React, Projects, Builds, Console, template) {
|
||||||
var Component = React.createClass({
|
var Component = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
return template({
|
return template({
|
||||||
ProjectsList: Projects.List
|
ProjectsList: Projects.List,
|
||||||
|
BuildsList: Builds.List,
|
||||||
|
Console: Console.Console
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
11
static/js/app/components/builds/index.js
Normal file
11
static/js/app/components/builds/index.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define([
|
||||||
|
'app/components/builds/item',
|
||||||
|
'app/components/builds/list'
|
||||||
|
], function(Item, List) {
|
||||||
|
return {
|
||||||
|
Item: Item,
|
||||||
|
List: List
|
||||||
|
};
|
||||||
|
});
|
5
static/js/app/components/builds/item.jade
Normal file
5
static/js/app/components/builds/item.jade
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
li.list-group-item
|
||||||
|
span.badge= item.status
|
||||||
|
a.pull-right(href="javascript:void(0);", onClick=onBuildSelect(item.id), style={marginRight: '5px'}) show console output
|
||||||
|
span Build #
|
||||||
|
span= item.id
|
20
static/js/app/components/builds/item.js
Normal file
20
static/js/app/components/builds/item.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define([
|
||||||
|
'react', 'app/actions/build', 'templates/app/components/builds/item'
|
||||||
|
], function(React, BuildActions, template) {
|
||||||
|
var Component = React.createClass({
|
||||||
|
onBuildSelect: function(buildId) {
|
||||||
|
console.log('on build select');
|
||||||
|
BuildActions.readConsoleOutput(buildId);
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
return template({
|
||||||
|
item: this.props.item,
|
||||||
|
onBuildSelect: this.onBuildSelect
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Component;
|
||||||
|
});
|
6
static/js/app/components/builds/list.jade
Normal file
6
static/js/app/components/builds/list.jade
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
div
|
||||||
|
h2 builds list
|
||||||
|
- console.log(items)
|
||||||
|
ul.list-group
|
||||||
|
each build, index in items
|
||||||
|
Item(item=build, key=build.id)
|
32
static/js/app/components/builds/list.js
Normal file
32
static/js/app/components/builds/list.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define([
|
||||||
|
'react',
|
||||||
|
'reflux',
|
||||||
|
'./item',
|
||||||
|
'app/stores/builds',
|
||||||
|
'templates/app/components/builds/list'
|
||||||
|
], function(React, Reflux, Item, buildsStore, template) {
|
||||||
|
var Component = React.createClass({
|
||||||
|
mixins: [Reflux.ListenerMixin],
|
||||||
|
componentDidMount: function() {
|
||||||
|
this.listenTo(buildsStore, this.updateItems);
|
||||||
|
},
|
||||||
|
updateItems: function(items) {
|
||||||
|
this.setState({items: items});
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
return template({
|
||||||
|
Item: Item,
|
||||||
|
items: this.state.items
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
items: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Component;
|
||||||
|
});
|
3
static/js/app/components/console/console.jade
Normal file
3
static/js/app/components/console/console.jade
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
if name
|
||||||
|
h2= name
|
||||||
|
pre= data
|
29
static/js/app/components/console/console.js
Normal file
29
static/js/app/components/console/console.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define([
|
||||||
|
'react',
|
||||||
|
'reflux',
|
||||||
|
'app/stores/console',
|
||||||
|
'templates/app/components/console/console'
|
||||||
|
], function(React, Reflux, consoleStore, template) {
|
||||||
|
var Component = React.createClass({
|
||||||
|
mixins: [Reflux.ListenerMixin],
|
||||||
|
componentDidMount: function() {
|
||||||
|
this.listenTo(consoleStore, this.updateItems);
|
||||||
|
},
|
||||||
|
updateItems: function(data) {
|
||||||
|
this.setState({data: data});
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
return template(this.state.data);
|
||||||
|
},
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
name: '',
|
||||||
|
data: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Component;
|
||||||
|
});
|
9
static/js/app/components/console/index.js
Normal file
9
static/js/app/components/console/index.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define([
|
||||||
|
'app/components/console/console',
|
||||||
|
], function(Console) {
|
||||||
|
return {
|
||||||
|
Console: Console
|
||||||
|
};
|
||||||
|
});
|
@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
define([
|
define([
|
||||||
'app/components/projects/index',
|
'app/components/projects/index',
|
||||||
|
'app/components/builds/index',
|
||||||
'app/components/app',
|
'app/components/app',
|
||||||
], function(ProjectsComponents, App) {
|
], function(ProjectsComponents, BuildsComponents, App) {
|
||||||
return {
|
return {
|
||||||
App: App,
|
App: App,
|
||||||
ProjectsComponents: ProjectsComponents
|
ProjectsComponents: ProjectsComponents,
|
||||||
|
BuildsComponents: BuildsComponents
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -1 +1,3 @@
|
|||||||
h1(onClick=onProjectSelect(item.name))= item.name
|
li.list-group-item
|
||||||
|
a.pull-right(href="javascript:void(0);", onClick=onProjectSelect(item.name)) start build
|
||||||
|
span= item.name
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
div
|
h2 projects list
|
||||||
h2 projects list
|
ul.list-group
|
||||||
each project, index in items
|
each project, index in items
|
||||||
Item(item=project, key=project.name)
|
Item(item=project, key=project.name)
|
||||||
|
8
static/js/app/connect.js
Normal file
8
static/js/app/connect.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define([
|
||||||
|
'socketio', 'dataio'
|
||||||
|
], function(socketio, dataio) {
|
||||||
|
// Do it because we use connect in console store
|
||||||
|
return dataio(socketio.connect());
|
||||||
|
});
|
@ -1,2 +1,2 @@
|
|||||||
div
|
.container-fluid
|
||||||
App()
|
App()
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
define([
|
define(['app/connect'], function(connect) {
|
||||||
'socketio', 'dataio'
|
|
||||||
], function(socketio, dataio) {
|
|
||||||
var connect = dataio(socketio.connect());
|
|
||||||
|
|
||||||
var projects = connect.resource('projects');
|
var projects = connect.resource('projects');
|
||||||
var builds = connect.resource('builds');
|
var builds = connect.resource('builds');
|
||||||
|
|
||||||
|
37
static/js/app/stores/builds.js
Normal file
37
static/js/app/stores/builds.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define([
|
||||||
|
'underscore',
|
||||||
|
'reflux', 'app/actions/build', 'app/resources'
|
||||||
|
], function(_, Reflux, BuildActions, resources) {
|
||||||
|
var resource = resources.builds;
|
||||||
|
|
||||||
|
var Store = Reflux.createStore({
|
||||||
|
listenables: BuildActions,
|
||||||
|
builds: [],
|
||||||
|
|
||||||
|
_onAction: function(build, action) {
|
||||||
|
var oldBuild = _(this.builds).findWhere({id: build.id});
|
||||||
|
if (oldBuild) {
|
||||||
|
_(oldBuild).extend(build);
|
||||||
|
} else {
|
||||||
|
this.builds.unshift(build);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trigger(this.builds);
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
resource.subscribe(this._onAction);
|
||||||
|
},
|
||||||
|
|
||||||
|
onReadAll: function() {
|
||||||
|
var self = this;
|
||||||
|
resource.sync('read', function(err, builds) {
|
||||||
|
self.trigger(builds);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Store;
|
||||||
|
});
|
34
static/js/app/stores/console.js
Normal file
34
static/js/app/stores/console.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define([
|
||||||
|
'underscore',
|
||||||
|
'reflux', 'app/actions/build', 'app/connect'
|
||||||
|
], function(_, Reflux, BuildActions, connect) {
|
||||||
|
var Store = Reflux.createStore({
|
||||||
|
listenables: BuildActions,
|
||||||
|
|
||||||
|
output: '',
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
console.log('init builds console output');
|
||||||
|
},
|
||||||
|
|
||||||
|
onReadConsoleOutput: function(buildId) {
|
||||||
|
this.output = ''
|
||||||
|
|
||||||
|
var resourceName = 'build' + buildId,
|
||||||
|
self = this;
|
||||||
|
|
||||||
|
connect.resource(resourceName).unsubscribeAll();
|
||||||
|
connect.resource(resourceName).subscribe(function(data) {
|
||||||
|
self.output += data;
|
||||||
|
self.trigger({
|
||||||
|
name: 'Console for build #' + buildId,
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Store;
|
||||||
|
});
|
19
static/js/dataio.js
Normal file
19
static/js/dataio.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define(['_dataio'], function(dataio) {
|
||||||
|
return function(socket) {
|
||||||
|
var connect = dataio(socket);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extend Resource
|
||||||
|
*/
|
||||||
|
var resource = connect.resource('__someResource__'),
|
||||||
|
resourcePrototype = Object.getPrototypeOf(resource);
|
||||||
|
|
||||||
|
resourcePrototype.unsubscribeAll = function() {
|
||||||
|
this.socket.removeAllListeners();
|
||||||
|
};
|
||||||
|
|
||||||
|
return connect;
|
||||||
|
};
|
||||||
|
});
|
@ -6,7 +6,7 @@ require.config({
|
|||||||
underscore: 'libs/underscore/underscore',
|
underscore: 'libs/underscore/underscore',
|
||||||
react: 'libs/react/react-with-addons',
|
react: 'libs/react/react-with-addons',
|
||||||
reflux: 'libs/reflux/dist/reflux',
|
reflux: 'libs/reflux/dist/reflux',
|
||||||
dataio: '/data.io',
|
_dataio: '/data.io',
|
||||||
socketio: '/socket.io/socket.io.js',
|
socketio: '/socket.io/socket.io.js',
|
||||||
jquery: 'libs/jquery/jquery'
|
jquery: 'libs/jquery/jquery'
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
var Distributor = require('../lib/distributor').Distributor,
|
var Distributor = require('../lib/distributor').Distributor,
|
||||||
Node = require('../lib/node').Node,
|
Node = require('../lib/node').Node,
|
||||||
expect = require('expect.js');
|
expect = require('expect.js'),
|
||||||
|
EventEmitter = require('events').EventEmitter;
|
||||||
|
|
||||||
|
|
||||||
describe('Distributor', function() {
|
describe('Distributor', function() {
|
||||||
@ -13,7 +14,9 @@ describe('Distributor', function() {
|
|||||||
return function(params) {
|
return function(params) {
|
||||||
var node = new Node(params);
|
var node = new Node(params);
|
||||||
node._createExecutor = function() {
|
node._createExecutor = function() {
|
||||||
return {run: executorRun};
|
var executor = new EventEmitter();
|
||||||
|
executor.run = executorRun;
|
||||||
|
return executor;
|
||||||
};
|
};
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
@ -43,7 +46,7 @@ describe('Distributor', function() {
|
|||||||
it('instance should be created without errors', function() {
|
it('instance should be created without errors', function() {
|
||||||
var number = 1;
|
var number = 1;
|
||||||
var conditionsHash = {
|
var conditionsHash = {
|
||||||
1: {queue: {length: 0}, build: {status: 'waiting'}},
|
1: {queue: {length: 0}, build: {status: 'queued'}},
|
||||||
2: {queue: {length: 1}, build: {status: 'in-progress'}},
|
2: {queue: {length: 1}, build: {status: 'in-progress'}},
|
||||||
3: {queue: {length: 0}, build: {status: 'done'}},
|
3: {queue: {length: 0}, build: {status: 'done'}},
|
||||||
4: 'Should never happend'
|
4: 'Should never happend'
|
||||||
@ -92,7 +95,7 @@ describe('Distributor', function() {
|
|||||||
it('instance should be created without errors', function() {
|
it('instance should be created without errors', function() {
|
||||||
var number = 1;
|
var number = 1;
|
||||||
var conditionsHash = {
|
var conditionsHash = {
|
||||||
1: {queue: {length: 0}, build: {status: 'waiting'}},
|
1: {queue: {length: 0}, build: {status: 'queued'}},
|
||||||
2: {queue: {length: 1}, build: {status: 'in-progress'}},
|
2: {queue: {length: 1}, build: {status: 'in-progress'}},
|
||||||
3: {
|
3: {
|
||||||
queue: {length: 0},
|
queue: {length: 0},
|
||||||
|
@ -1,26 +1,14 @@
|
|||||||
doctype html
|
doctype html
|
||||||
html
|
html
|
||||||
head
|
head
|
||||||
title test
|
title nci
|
||||||
|
|
||||||
|
// do it temporary
|
||||||
|
link(href="/js/libs/bootstrap/dist/css/bootstrap.css", rel="stylesheet", type="text/css")
|
||||||
|
|
||||||
script(data-main="/js/main" src="/js/libs/requirejs/require.js")
|
script(data-main="/js/main" src="/js/libs/requirejs/require.js")
|
||||||
script(type="text/javascript").
|
script(type="text/javascript").
|
||||||
require(['app/app']);
|
require(['app/app']);
|
||||||
|
|
||||||
body
|
body
|
||||||
h1 hello world
|
|
||||||
|
|
||||||
|
|
||||||
script#projects-template(type="text/template")
|
|
||||||
| <div class="js-projects">
|
|
||||||
| <% _(projects).each(function(project) { %>
|
|
||||||
| <div class="js-project" data-name="<%= project.name %>">
|
|
||||||
| <span><%= project.name %></span>
|
|
||||||
| <span class="js-run">→</span>
|
|
||||||
| </div>
|
|
||||||
| <% }); %>
|
|
||||||
| </div>
|
|
||||||
|
|
||||||
|
|
||||||
#content
|
#content
|
||||||
|
|
||||||
#react-content
|
|
||||||
|
Loading…
Reference in New Issue
Block a user