From f618ff6713d55fab9074f838f91c33bcb7d66224 Mon Sep 17 00:00:00 2001 From: oleg Date: Fri, 12 Jun 2015 16:26:34 +0300 Subject: [PATCH] notify on change --- data/projects/project1/config.yaml | 5 +- db.js | 14 +++-- lib/notifier/index.js | 36 ++++++++++++- test/notifier.js | 86 +++++++++++++++++++++++++++++- 4 files changed, 134 insertions(+), 7 deletions(-) diff --git a/data/projects/project1/config.yaml b/data/projects/project1/config.yaml index d3eb448..65114f5 100644 --- a/data/projects/project1/config.yaml +++ b/data/projects/project1/config.yaml @@ -8,8 +8,9 @@ scm: notify: on: - - success - - fail + # - success + # - fail + - change to: console: # email: diff --git a/db.js b/db.js index 0cb261e..f714b98 100644 --- a/db.js +++ b/db.js @@ -13,15 +13,23 @@ exports.builds = new nlevel.DocsSection(ldb, 'builds', { {key: {createDate: 1}, value: pickId}, {key: {descCreateDate: descCreateDate, id: 1}}, {key: { - projectName: function(build) { - return build.project.name; - }, + projectName: pickProjectName, descCreateDate: descCreateDate, id: 1 + }}, + // note that's unordered projection (coz number is numeric) + {key: { + projectName: pickProjectName, + number: 1, + id: 1 }} ] }); +function pickProjectName(build) { + return build.project.name; +} + exports.builds._beforePut = function(builds, callback) { var self = this, build; diff --git a/lib/notifier/index.js b/lib/notifier/index.js index d83a126..11d47a9 100644 --- a/lib/notifier/index.js +++ b/lib/notifier/index.js @@ -2,7 +2,8 @@ var Steppy = require('twostep').Steppy, _ = require('underscore'), - utils = require('../utils'); + utils = require('../utils'), + db = require('../../db'); var constructors = {}, instances = {}; @@ -24,6 +25,25 @@ exports.init = function(params, callback) { ); }; +// Returns previous (by number) build from the same project +exports._getPrevBuild = function(build, callback) { + Steppy( + function() { + db.builds.find({ + start: { + projectName: build.project.name, + number: build.number - 1 + }, + limit: 1 + }, this.slot()); + }, + function(err, builds) { + this.pass(builds[0]); + }, + callback + ); +}; + /* * Check if that's completed build should be notified, then notify */ @@ -42,11 +62,25 @@ exports.send = function(build, callback) { return callback(); } + this.pass(notify); + + // get previous build (for some strategies) + if ( + build.number > 1 && + _(notify.on).intersection(['change']).length + ) { + exports._getPrevBuild(build, this.slot()); + } + }, + function(err, notify, prevBuild) { var strategy = _(notify.on).find(function(strategy) { if (strategy === 'success') { return build.status === 'done'; } else if (strategy === 'fail') { return build.status === 'error'; + } else if (strategy === 'change') { + // notify on status change or about first build + return prevBuild ? build.status !== prevBuild.status: true; } }); diff --git a/test/notifier.js b/test/notifier.js index 3562f4c..ecd6b15 100644 --- a/test/notifier.js +++ b/test/notifier.js @@ -2,7 +2,8 @@ var notifier = require('../lib/notifier'), expect = require('expect.js'), - sinon = require('sinon'); + sinon = require('sinon'), + _ = require('underscore'); describe('notifier module', function() { @@ -147,4 +148,87 @@ describe('notifier module', function() { }); }); + var secondBuild; + + // for all previos build related strategies + describe('Stub getting of previos build', function() { + it('', function() { + sinon.stub(notifier, '_getPrevBuild').callsArgWith(1, null, build); + }); + }); + + describe('notify on change', function() { + it('set build info', function() { + build = { + completed: true, + status: 'done', + number: 1, + project: { + name: 'project1', + notify: { + on: ['change'], + to: {test: ['recipient1', 'recipient2']} + } + } + }; + sendSpy.reset(); + }); + + it('should notify for the first build', function(done) { + notifier.send(build, function(err) { + expect(err).not.ok(); + expect(sendSpy.calledOnce).equal(true); + done(); + }); + }); + + it('should be notified with right params', function() { + expect(sendSpy.calledWith({ + notifyReason: {strategy: 'change'}, + build: build + })).equal(true); + }); + + it('set second build info (same status)', function() { + secondBuild = _(build).clone(); + secondBuild.number = 2; + sendSpy.reset(); + }); + + it('should not notify when same second build status', function(done) { + notifier.send(secondBuild, function(err) { + expect(err).not.ok(); + expect(sendSpy.calledOnce).equal(false); + done(); + }); + }); + + it('set second build info (changed status)', function() { + secondBuild.status = 'error'; + sendSpy.reset(); + }); + + it('should notify when status is changed', function(done) { + notifier.send(secondBuild, function(err) { + expect(err).not.ok(); + expect(sendSpy.calledOnce).equal(true); + done(); + }); + }); + + it('should be notified with right params', function() { + expect(sendSpy.calledWith({ + notifyReason: {strategy: 'change'}, + build: secondBuild + })).equal(true); + }); + + }); + + describe('Restore getting of previos build', function() { + it('', function() { + notifier._getPrevBuild.restore(); + }); + }); + });