mirror of
https://gitlab.silvrtree.co.uk/martind2000/nci.git
synced 2025-02-11 03:29:17 +00:00
merge
This commit is contained in:
commit
4366105cf8
@ -3,6 +3,7 @@
|
|||||||
var Steppy = require('twostep').Steppy,
|
var Steppy = require('twostep').Steppy,
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
Node = require('./node').Node,
|
Node = require('./node').Node,
|
||||||
|
getAvgProjectBuildDuration = require('./project').getAvgProjectBuildDuration,
|
||||||
EventEmitter = require('events').EventEmitter,
|
EventEmitter = require('events').EventEmitter,
|
||||||
inherits = require('util').inherits,
|
inherits = require('util').inherits,
|
||||||
notifier = require('./notifier'),
|
notifier = require('./notifier'),
|
||||||
@ -226,8 +227,10 @@ Distributor.prototype.run = function(params, callback) {
|
|||||||
} else {
|
} else {
|
||||||
this.pass(null);
|
this.pass(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAvgProjectBuildDuration(params.projectName, this.slot());
|
||||||
},
|
},
|
||||||
function(err, hasScmChanges) {
|
function(err, hasScmChanges, avgProjectBuildDuration) {
|
||||||
if (params.withScmChangesOnly && !hasScmChanges) {
|
if (params.withScmChangesOnly && !hasScmChanges) {
|
||||||
logger.log(
|
logger.log(
|
||||||
'Building of "%s" skipped coz no scm changes',
|
'Building of "%s" skipped coz no scm changes',
|
||||||
@ -236,6 +239,8 @@ Distributor.prototype.run = function(params, callback) {
|
|||||||
return callback();
|
return callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
project.avgBuildDuration = avgProjectBuildDuration;
|
||||||
|
|
||||||
self._updateBuild({}, {
|
self._updateBuild({}, {
|
||||||
project: project,
|
project: project,
|
||||||
initiator: params.initiator,
|
initiator: params.initiator,
|
||||||
|
@ -5,6 +5,7 @@ var Steppy = require('twostep').Steppy,
|
|||||||
path = require('path'),
|
path = require('path'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
reader = require('./reader'),
|
reader = require('./reader'),
|
||||||
|
db = require('../db'),
|
||||||
utils = require('./utils');
|
utils = require('./utils');
|
||||||
|
|
||||||
|
|
||||||
@ -99,3 +100,27 @@ exports.create = function(baseDir, config, callback) {
|
|||||||
callback
|
callback
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.getAvgProjectBuildDuration = function(projectName, callback) {
|
||||||
|
Steppy(
|
||||||
|
function() {
|
||||||
|
// get last done builds to calc avg build time
|
||||||
|
db.builds.find({
|
||||||
|
start: {
|
||||||
|
projectName: projectName,
|
||||||
|
status: 'done',
|
||||||
|
descCreateDate: ''
|
||||||
|
},
|
||||||
|
limit: 10
|
||||||
|
}, this.slot());
|
||||||
|
},
|
||||||
|
function(err, doneBuilds) {
|
||||||
|
var durationsSum = _(doneBuilds).reduce(function(memo, build) {
|
||||||
|
return memo + (build.endDate - build.startDate);
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
this.pass(Math.round(durationsSum / doneBuilds.length));
|
||||||
|
},
|
||||||
|
callback
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -30,7 +30,9 @@ module.exports = function(app) {
|
|||||||
_(builds).each(function(build) {
|
_(builds).each(function(build) {
|
||||||
delete build.stepTimings;
|
delete build.stepTimings;
|
||||||
delete build.scm.changes;
|
delete build.scm.changes;
|
||||||
build.project = _(build.project).pick('name', 'scm');
|
build.project = _(build.project).pick(
|
||||||
|
'name', 'scm', 'avgBuildDuration'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
res.send(builds);
|
res.send(builds);
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
var Steppy = require('twostep').Steppy,
|
var Steppy = require('twostep').Steppy,
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
|
getAvgProjectBuildDuration =
|
||||||
|
require('../lib/project').getAvgProjectBuildDuration,
|
||||||
createBuildDataResource = require('../distributor').createBuildDataResource,
|
createBuildDataResource = require('../distributor').createBuildDataResource,
|
||||||
logger = require('../lib/logger')('projects resource'),
|
logger = require('../lib/logger')('projects resource'),
|
||||||
db = require('../db');
|
db = require('../db');
|
||||||
@ -26,14 +28,16 @@ module.exports = function(app) {
|
|||||||
function() {
|
function() {
|
||||||
project = _(app.projects).findWhere(req.data);
|
project = _(app.projects).findWhere(req.data);
|
||||||
|
|
||||||
// get last done builds to calc avg build time
|
getAvgProjectBuildDuration(project.name, this.slot());
|
||||||
|
|
||||||
|
// get last done build
|
||||||
db.builds.find({
|
db.builds.find({
|
||||||
start: {
|
start: {
|
||||||
projectName: project.name,
|
projectName: project.name,
|
||||||
status: 'done',
|
status: 'done',
|
||||||
descCreateDate: ''
|
descCreateDate: ''
|
||||||
},
|
},
|
||||||
limit: 10
|
limit: 1
|
||||||
}, this.slot());
|
}, this.slot());
|
||||||
|
|
||||||
// tricky but effective streak counting inside filter goes below
|
// tricky but effective streak counting inside filter goes below
|
||||||
@ -60,17 +64,9 @@ module.exports = function(app) {
|
|||||||
doneBuildsStreakCallback(err, doneBuildsStreak);
|
doneBuildsStreakCallback(err, doneBuildsStreak);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function(err, doneBuilds, doneBuildsStreak) {
|
function(err, avgProjectBuildDuration, lastDoneBuilds, doneBuildsStreak) {
|
||||||
project.lastDoneBuild = doneBuilds[0];
|
project.lastDoneBuild = lastDoneBuilds[0];
|
||||||
|
project.avgBuildDuration = avgProjectBuildDuration;
|
||||||
var durationsSum = _(doneBuilds).reduce(function(memo, build) {
|
|
||||||
return memo + (build.endDate - build.startDate);
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
project.avgBuildDuration = Math.round(
|
|
||||||
durationsSum / doneBuilds.length
|
|
||||||
);
|
|
||||||
|
|
||||||
project.doneBuildsStreak = doneBuildsStreak;
|
project.doneBuildsStreak = doneBuildsStreak;
|
||||||
|
|
||||||
res.send(project);
|
res.send(project);
|
||||||
|
@ -14,15 +14,12 @@
|
|||||||
.row();
|
.row();
|
||||||
padding: 15px 0;
|
padding: 15px 0;
|
||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
|
background: lighten(@well-bg, 3%);
|
||||||
|
|
||||||
&__in-progress {
|
&_status {
|
||||||
background: lighten(@brand-info, 40%);
|
float: left;
|
||||||
}
|
padding-top: 14px;
|
||||||
&__done {
|
margin-right: 13px;
|
||||||
background: lighten(@brand-success, 50%);
|
|
||||||
}
|
|
||||||
&__error {
|
|
||||||
background: lighten(@brand-danger, 30%);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&_info {
|
&_info {
|
||||||
@ -34,8 +31,21 @@
|
|||||||
.make-md-column(3);
|
.make-md-column(3);
|
||||||
.make-xs-column(3);
|
.make-xs-column(3);
|
||||||
.text-right;
|
.text-right;
|
||||||
margin-top: 8px;
|
|
||||||
|
&_buttons {
|
||||||
|
margin-top: 8px;
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_progress {
|
||||||
|
padding-top: 14px;
|
||||||
|
.progress {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&_content {
|
&_content {
|
||||||
.make-md-column(9);
|
.make-md-column(9);
|
||||||
.make-xs-column(9);
|
.make-xs-column(9);
|
||||||
@ -48,4 +58,72 @@
|
|||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.build_controls_buttons {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@animation-duration: 1.5s;
|
||||||
|
|
||||||
|
.status {
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
&__in-progress {
|
||||||
|
background: @brand-info;
|
||||||
|
|
||||||
|
-webkit-animation: pulsate @animation-duration ease-out;
|
||||||
|
-webkit-animation-iteration-count: infinite;
|
||||||
|
-moz-animation: pulsate @animation-duration ease-out;
|
||||||
|
-moz-animation-iteration-count: infinite;
|
||||||
|
-o-animation: pulsate @animation-duration ease-out;
|
||||||
|
-o-animation-iteration-count: infinite;
|
||||||
|
animation: pulsate @animation-duration ease-out;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
}
|
||||||
|
&__done {
|
||||||
|
background: @link-color;
|
||||||
|
}
|
||||||
|
&__error {
|
||||||
|
background: @brand-danger;
|
||||||
|
}
|
||||||
|
&__queued {
|
||||||
|
background: @brand-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pulsate-frames() {
|
||||||
|
.transform(@scaleX, @scaleY) {
|
||||||
|
-webkit-transform: scale(@scaleX, @scaleY); opacity: 1;
|
||||||
|
-moz-transform: scale(@scaleX, @scaleY); opacity: 1;
|
||||||
|
-ms-transform: scale(@scaleX, @scaleY); opacity: 1;
|
||||||
|
-o-transform: scale(@scaleX, @scaleY); opacity: 1;
|
||||||
|
transform: scale(@scaleX, @scaleY); opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
0% {
|
||||||
|
.transform(1.0, 1.0);
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
opacity: 1.0;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
.transform(0.75, 0.75);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 1.0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
.transform(1.0, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes pulsate {.pulsate-frames}
|
||||||
|
@-moz-keyframes pulsate {.pulsate-frames}
|
||||||
|
@-ms-keyframes pulsate {.pulsate-frames}
|
||||||
|
@-o-keyframes pulsate {.pulsate-frames}
|
||||||
|
@keyframes pulsate {.pulsate-frames}
|
||||||
|
@ -13,16 +13,27 @@ mixin statusText(build)
|
|||||||
|
|
||||||
- var build = this.props.build;
|
- var build = this.props.build;
|
||||||
|
|
||||||
.build(class="build__#{build.status}")
|
.build(class="")
|
||||||
.build_content
|
.build_content
|
||||||
|
.build_status
|
||||||
|
.status(class="status__#{build.status}")
|
||||||
div.build_header
|
div.build_header
|
||||||
|
if build.project
|
||||||
|
span
|
||||||
|
Scm(scm=build.project.scm.type)
|
||||||
|
|
|
||||||
|
Link(to="project", params={name: build.project.name})
|
||||||
|
span= build.project.name
|
||||||
|
|
|
||||||
if build.number
|
if build.number
|
||||||
|
span(style={fontSize: '15px', color: '#a6a6a6'}) build
|
||||||
|
|
|
||||||
if build.status !== 'queued'
|
if build.status !== 'queued'
|
||||||
Link(to="build", params={id: build.id})
|
Link(to="build", params={id: build.id})
|
||||||
span Build #
|
span #
|
||||||
span= build.number
|
span= build.number
|
||||||
else
|
else
|
||||||
span Build #
|
span #
|
||||||
span= build.number
|
span= build.number
|
||||||
|
|
||||||
if build.waitReason
|
if build.waitReason
|
||||||
@ -36,12 +47,6 @@ mixin statusText(build)
|
|||||||
span )
|
span )
|
||||||
|
|
||||||
div
|
div
|
||||||
if build.project
|
|
||||||
span.build_info
|
|
||||||
Scm(scm=build.project.scm.type)
|
|
||||||
|
|
|
||||||
Link(to="project", params={name: build.project.name})
|
|
||||||
span= build.project.name
|
|
||||||
if build.endDate
|
if build.endDate
|
||||||
span.build_info
|
span.build_info
|
||||||
i.fa.fa-fw.fa-clock-o
|
i.fa.fa-fw.fa-clock-o
|
||||||
@ -69,11 +74,13 @@ mixin statusText(build)
|
|||||||
|
|
||||||
.build_controls
|
.build_controls
|
||||||
if build.completed
|
if build.completed
|
||||||
a.btn.btn-sm.btn-default(href="javascript:void(0);", onClick=this.onRebuildProject(build.project.name))
|
.build_controls_buttons
|
||||||
i.fa.fa-fw.fa-repeat(title="Rebuild")
|
a.btn.btn-sm.btn-default(href="javascript:void(0);", onClick=this.onRebuildProject(build.project.name))
|
||||||
|
|
i.fa.fa-fw.fa-repeat(title="Rebuild")
|
||||||
| Build again
|
|
|
||||||
else
|
| Build again
|
||||||
//-.progress
|
if build.status === 'in-progress'
|
||||||
//-.progress-bar.progress-bar-success(style={width: '60%'})
|
.build_controls_progress
|
||||||
|
if build.project.avgBuildDuration
|
||||||
|
Progress(build=build)
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ define([
|
|||||||
template = template.locals({
|
template = template.locals({
|
||||||
DateTime: CommonComponents.DateTime,
|
DateTime: CommonComponents.DateTime,
|
||||||
Duration: CommonComponents.Duration,
|
Duration: CommonComponents.Duration,
|
||||||
|
Progress: CommonComponents.Progress,
|
||||||
Scm: CommonComponents.Scm,
|
Scm: CommonComponents.Scm,
|
||||||
Terminal: TerminalComponent,
|
Terminal: TerminalComponent,
|
||||||
Link: Router.Link
|
Link: Router.Link
|
||||||
@ -24,7 +25,6 @@ define([
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
onRebuildProject: function(projectName) {
|
onRebuildProject: function(projectName) {
|
||||||
console.log('onRebuildProject');
|
|
||||||
ProjectActions.run(projectName)
|
ProjectActions.run(projectName)
|
||||||
},
|
},
|
||||||
onShowTerminal: function(build) {
|
onShowTerminal: function(build) {
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
span
|
span
|
||||||
span= this.props.duration / 1000
|
if this.props.minutes
|
||||||
|
span= this.props.minutes
|
||||||
|
|
|
||||||
|
span min
|
||||||
|
|
|
||||||
|
span= this.state.seconds
|
||||||
|
|
|
|
||||||
span sec
|
span sec
|
||||||
|
@ -4,6 +4,14 @@ define([
|
|||||||
'react', 'templates/app/components/common/duration/index'
|
'react', 'templates/app/components/common/duration/index'
|
||||||
], function(React, template) {
|
], function(React, template) {
|
||||||
return React.createClass({
|
return React.createClass({
|
||||||
render: template
|
render: template,
|
||||||
|
getInitialState: function() {
|
||||||
|
var seconds = Math.round(this.props.duration / 1000);
|
||||||
|
|
||||||
|
return {
|
||||||
|
minutes: null,
|
||||||
|
seconds: seconds
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
define([
|
define([
|
||||||
'./dateTime/index',
|
'./dateTime/index',
|
||||||
'./scm/index',
|
'./scm/index',
|
||||||
'./duration/index'
|
'./duration/index',
|
||||||
], function(DateTime, Scm, Duration) {
|
'./progress/index'
|
||||||
|
], function(DateTime, Scm, Duration, Progress) {
|
||||||
return {
|
return {
|
||||||
DateTime: DateTime,
|
DateTime: DateTime,
|
||||||
Scm: Scm,
|
Scm: Scm,
|
||||||
Duration: Duration
|
Duration: Duration,
|
||||||
|
Progress: Progress
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
2
static/js/app/components/common/progress/index.jade
Normal file
2
static/js/app/components/common/progress/index.jade
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.progress
|
||||||
|
.progress-bar.progress-bar-success(style={width: this.state.percent + '%'})
|
31
static/js/app/components/common/progress/index.js
Normal file
31
static/js/app/components/common/progress/index.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define([
|
||||||
|
'underscore',
|
||||||
|
'react',
|
||||||
|
'templates/app/components/common/progress/index'
|
||||||
|
], function(_, React, template) {
|
||||||
|
return React.createClass({
|
||||||
|
render: template,
|
||||||
|
_computePercent: function() {
|
||||||
|
var build = this.props.build;
|
||||||
|
return Math.round((Date.now() - build.startDate) /
|
||||||
|
build.project.avgBuildDuration * 100);
|
||||||
|
},
|
||||||
|
componentDidMount: function() {
|
||||||
|
var self = this,
|
||||||
|
updateCallback = function() {
|
||||||
|
if (self.props.build.status === 'in-progress') {
|
||||||
|
self.setState({percent: self._computePercent()});
|
||||||
|
_.delay(updateCallback, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateCallback();
|
||||||
|
},
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
percent: this._computePercent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user