woodpecker/static/scripts/build.js
2016-05-11 00:36:01 -07:00

200 lines
4.3 KiB
JavaScript

function JobViewModel(repo, build, job, status) {
var self = this;
self.status = status;
self.stream = function() {
$("#output").html("");
$("#restart").hide();
$("#cancel").show();
var buf = new Drone.Buffer();
buf.start(document.getElementById("output"));
$( "#tail" ).show();
$( "#tail" ).click(function() {
buf.autoFollow = !buf.autoFollow;
if (buf.autoFollow) {
$( "#tail i" ).text("pause");
$( "#tail" ).show();
// scroll to the bottom of the page
window.scrollTo(0, document.body.scrollHeight);
} else {
$( "#tail i" ).text("expand_more");
$( "#tail" ).show();
}
})
Stream(repo, build, job, function(out){
buf.write(out);
});
};
if (status !== "running" && status !== "pending") {
Logs(repo, build, job);
$("#restart").show();
}
if (status === "running") {
self.stream();
}
$("#restart").click(function() {
$("#restart").hide();
$("#output").html("");
$(".status").attr("class", "status pending").text("pending");
$.ajax({
url: "/api/repos/"+repo+"/builds/"+build,
type: "POST",
success: function( data ) { },
error: function( data ) {
console.log(data);
}
});
})
$("#cancel").click(function() {
$("#cancel").hide();
$.ajax({
url: "/api/repos/"+repo+"/builds/"+build+"/"+job,
type: "DELETE",
success: function( data ) { },
error: function( data ) {
console.log(data);
}
});
})
Subscribe(repo, function(data){
if (!data.jobs) {
return;
}
if (data.number !== build) {
return;
}
var before = self.status;
self.status = data.jobs[job-1].status;
// update the status for each job in the view
for (var i=0;i<data.jobs.length;i++) {
var job_ = data.jobs[i];
var el = $("[data-job="+job_.number+"]");
el.find(".status")
.attr("class", "status "+job_.status).text(job_.status);
switch (job_.status) {
case "running":
el.find(".msg-running").find("span").attr("data-livestamp", job_.started_at);
el.find(".msg-pending").hide();
el.find(".msg-running").show();
el.find(".msg-finished").hide();
el.find(".msg-exited").hide();
break;
case "pending":
el.find(".msg-pending").show();
el.find(".msg-running").hide();
el.find(".msg-finished").hide();
el.find(".msg-exited").hide();
break;
default:
el.find(".msg-finished").find("span").attr("data-livestamp", job_.finished_at);
el.find(".msg-exited").find("span").text(job_.exit_code);
el.find(".msg-pending").hide();
el.find(".msg-running").hide();
el.find(".msg-finished").show();
el.find(".msg-exited").show();
break;
}
}
var after = self.status;
// if the status has changed we should start
// streaming the build contents.
if (before !== after && after === "running") {
self.stream();
}
// if the status is changes to complete, we can show
// the restart button and hide the tail button.
if (after !== "pending" && after !== "running") {
$("#restart").show();
$("#cancel").hide();
$("#tail").hide();
}
}.bind(this));
}
function Logs(repo, build, job) {
$.get( "/api/repos/"+repo+"/logs/"+build+"/"+job, function( data ) {
var lines = JSON.parse(data);
var groups = {}
for (var i=0; i<lines.length; i++) {
var line = lines[i];
if (!line.proc) {
continue
}
var group = groups[line.proc];
if (!group) {
// create an element to hold the group of output
var pre = $("<pre>").attr("data-title", line.proc);
$("#output").append(pre);
// create the buffer for the group of output
var buf = new Drone.Buffer();
buf.start(pre[0]);
// add items to the group
group = {
pre: pre,
buf: buf,
};
groups[line.proc]=group;
}
group.buf.write(line.out+"\n");
}
for (var i=0; i<groups.length; i++) {
groups[i].buf.stop();
}
});
}
function Stream(repo, build, job, _callback) {
var callback = _callback;
var events = new EventSource("/api/stream/" + repo + "/" + build + "/" + job, {withCredentials: true});
events.onmessage = function (event) {
if (callback !== undefined) {
callback(event.data);
}
};
events.onerror = function (event) {
callback = undefined;
if (events !== undefined) {
events.close();
events = undefined;
}
console.log('user event stream closed due to error.', event);
};
};