diff --git a/lib/app.js b/lib/app.js index fed85c66e..2d0b67ca1 100644 --- a/lib/app.js +++ b/lib/app.js @@ -146,6 +146,9 @@ var init = exports.init = function (config) { app.get('/:org/:repo/', auth.requireReadAccess, routes_jobs.latest_build); app.get('/:org/:repo/job/:job_id', auth.requireReadAccess, routes_jobs.job); + // todo: make a config option to make this private? + app.get('/:user/:org/:repo/badge', routes_jobs.badge); + /* Requires admin access to the repository in the path */ app.get('/:org/:repo/config', auth.requireUser, auth.requireRepoAdmin, routes.config); diff --git a/public/images/badges/build-passing.png b/public/images/badges/build_passing.png similarity index 100% rename from public/images/badges/build-passing.png rename to public/images/badges/build_passing.png diff --git a/routes/index.js b/routes/index.js index 5bd7ad547..d0df4402c 100644 --- a/routes/index.js +++ b/routes/index.js @@ -7,6 +7,7 @@ var BASE_PATH = "../lib/" var _ = require('underscore') , Step = require('step') , common = require(BASE_PATH + 'common') + , config = require(BASE_PATH + 'config') , fs = require('fs') , gh = require(BASE_PATH + 'github') , jobs = require(BASE_PATH + 'jobs') @@ -148,6 +149,7 @@ exports.config = function(req, res) var r = { // May be undefined if not configured display_name: wrepo_config.display_name, + badge_url: config.strider_server_name + '/' + req.user.id + '/' + req.params.org + '/' + req.params.repo + '/badge', repo_org: req.params.org, repo_name: req.params.repo, apresController: "/javascripts/apres/controller/project_config.js", diff --git a/routes/jobs/index.js b/routes/jobs/index.js index 0a893d43e..56882ebef 100644 --- a/routes/jobs/index.js +++ b/routes/jobs/index.js @@ -113,6 +113,48 @@ exports.latest_build = function(req, res) }); }; +/* + * index.badge - redirect to the right badge + */ +exports.badge = function(req, res) { + res.statusCode = 200; + var user = req.params.user; + var org = req.params.org; + var repo = req.params.repo; + var repo_url = "https://github.com/" + org + "/" + repo; + + function sendBadge(name) { + return res.redirect('/images/badges/build_' + name + '.png'); + } + + // Ignore if can't parse as ObjectID + try { + user = new mongoose.Types.ObjectId(user); + } catch(e) { + console.debug('[badge] invalid user ObjectID', user); + return sendBadge('unknown'); + } + + Job.findOne() + .sort({'finished_timestamp': -1}) + .where('finished_timestamp').ne(null) + .where('archived_timestamp', null) + // FIXME: is it always lowercase? + .where('repo_url', repo_url.toLowerCase()) + .where('_owner', user) + .where('type').in(['TEST_ONLY','TEST_AND_DEPLOY']) + .exec(function(err, job) { + if (err || !job) { + if (err) { + console.debug('[badge] error looking for latest build', err.message); + } + return sendBadge('unknown'); + } + if (job.test_exitcode === 0) return sendBadge('passing'); + return sendBadge('failing'); + }); +}; + /* * index.job - build the job detail page */ diff --git a/views/base.html b/views/base.html index 891f3c459..94607efba 100644 --- a/views/base.html +++ b/views/base.html @@ -9,6 +9,7 @@ {% pluginblock title %}Strider: Brilliant Continuous Deployment{% endpluginblock %} {% include "bootstrap.html" %} + {% pluginblock AfterHead %}{% endpluginblock %} {% pluginblock ExtraStyles %}{% endpluginblock %} @@ -90,7 +91,6 @@ {% block footerScripts %} - {% endblock %} {% block pageScripts %} diff --git a/views/bootstrap.html b/views/bootstrap.html index 5d1311eb6..4def1d4ca 100644 --- a/views/bootstrap.html +++ b/views/bootstrap.html @@ -1,7 +1,10 @@ +{% if (!apres) %} +{% endif %} + diff --git a/views/project_config.html b/views/project_config.html index 24cca7266..12044ee2e 100644 --- a/views/project_config.html +++ b/views/project_config.html @@ -1,7 +1,26 @@ {% extends "base.html" %} - +{% set apres = true %} {% block bodyContent %} +
+ Build Badge

Configuration - {{display_name}}