Skip to content

Commit

Permalink
🔩
Browse files Browse the repository at this point in the history
added  time ago
fix bug space closes #1
add possibility to recognize not complete slug closes #3
add more info built status message closes #4
  • Loading branch information
eromano committed Apr 8, 2016
1 parent 50679fe commit d4712c5
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 27 deletions.
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,37 @@
## About Ci-alarm
Ci-alarm is a simple node.js slack bot to help to turn on a light alarm through GPIO of the Raspberry Pi when your Travis or Jenkins build fail

### Contributors
## Development

* To test ci-alarm

```$ npm run-script test```

* To debug ci-alarm

```$ npm run-script debug```

* To see the test coverage ci-alarm

```$ npm run-script coverage```

* To run ci-alarm on your machine

```$ npm run-script start```

## Contributing

1. Fork it!
2. Create your feature branch: `git checkout -b ci-alarm`
3. Commit your changes: `git commit -a `
4. Push to the branch: `git push origin ci-alarm`
5. Submit a pull request

## History

For detailed changelog, check [Releases](https://github.com/eromano/ci-alarm/releases).

### Contributors

Contributor | GitHub profile | Twitter profile |
--- | --- | ---
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,7 @@
"contributors": [
"Eugenio Romano <> (http://eromano.github.io/)"
],
"dependencies": {}
"dependencies": {
"moment": "^2.12.0"
}
}
44 changes: 29 additions & 15 deletions src/slackMessageInterface.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

var Bot = require('slackbots');
var moment = require('moment');

class slackMessageInterface {

Expand Down Expand Up @@ -54,14 +55,15 @@ class slackMessageInterface {

listenerRequestStatusBuild() {
this.bot.on('message', ((message) => {
if (!this.isFromCiAlarmBotMessage(message) && this.isChatMessage(message) &&
this.isMentioningCiAlarm(message) && this.isStatusRequest(message)) {
if (this.isValidCiMentionMessage(message) && this.isStatusRequest(message)) {
var repoName = this.getRepositoriesNameInMessage(message);

if (repoName) {
this.ciService.getLastBuildStatusByRepository(repoName).then((statusBuild)=> {
statusBuild = statusBuild ? statusBuild : 'unknown';
this.postSlackMessageToChannel('Hi <@' + message.user + '> the build Status is ' + statusBuild + '!', 'Ci status', this.colorByStatus(statusBuild));
var fields = this._createFieldsAdditionInformationMessage(statusBuild);
var lastBuildState = statusBuild.last_build_state ? statusBuild.last_build_state : 'unknown';

this.postSlackMessageToChannel('Hi <@' + message.user + '> the build Status was ' + lastBuildState + ' ' + moment(statusBuild.last_build_finished_at).fromNow(), 'Ci status', this.colorByStatus(lastBuildState), fields); // jscs:ignore maximumLineLength
}, (error)=> {
this.postSlackMessageToChannel(error.toString(), 'Ci status', this.failColor);
});
Expand All @@ -77,8 +79,7 @@ class slackMessageInterface {
*/
listenerRepositoryListMessage() {
this.bot.on('message', ((message) => {
if (!this.isFromCiAlarmBotMessage(message) && this.isChatMessage(message) &&
this.isMentioningCiAlarm(message) && this.isListRepositoryRequest(message)) {
if (this.isValidCiMentionMessage(message) && this.isListRepositoryRequest(message)) {

this.ciService.getUserRepositoriesSlugList().then((repositories)=> {
this.postSlackMessageToChannel('Hi <@' + message.user + '> this is the repository list: \n • ' +
Expand All @@ -93,10 +94,8 @@ class slackMessageInterface {
*/
listenerCommandListMessage() {
this.bot.on('message', ((message) => {
if (!this.isFromCiAlarmBotMessage(message) && this.isChatMessage(message) &&
this.isMentioningCiAlarm(message) && this.isCommandListRequest(message)) {

this.postSlackMessageToChannel('Command list: \n • Repository list \n • build status username/example-project');
if (this.isValidCiMentionMessage(message) && this.isCommandListRequest(message)) {
this.postSlackMessageToChannel('Command list: \n • repository list \n • status username/example-project');
}
}));
}
Expand All @@ -107,8 +106,9 @@ class slackMessageInterface {
* @param {String} message
* @param {String} fallback
* @param {successColor|failColor|infoColor} color of the vertical line before the message default infoColor yellow
* @param {Array} fields is an Array of messages { 'title': 'Project', 'value': 'Awesome Project','short': true},
*/
postSlackMessageToChannel(message, fallback, color) {
postSlackMessageToChannel(message, fallback, color, fields) {
var params = {
icon_emoji: ':robot_face:',
attachments: [
Expand All @@ -117,7 +117,8 @@ class slackMessageInterface {
'color': color || this.infoColor,
'author_name': 'Ci Alarm',
'author_link': 'https://github.com/eromano/ci-alarm',
'text': message
'text': message,
'fields': fields
}
]
};
Expand All @@ -130,13 +131,22 @@ class slackMessageInterface {

getRepositoriesNameInMessage(message) {
var statusPos = message.text.toLowerCase().indexOf('status');
var afterStatus = message.text.toLowerCase().substr(statusPos + 6, message.length);
var afterStatus = message.text.toLowerCase().substr(statusPos + 6, message.length).trim();

var allPhrasesSeparateBySpace = afterStatus.split(' ');
if (allPhrasesSeparateBySpace && allPhrasesSeparateBySpace.length > 1) {
return allPhrasesSeparateBySpace[1].trim();

if (allPhrasesSeparateBySpace && allPhrasesSeparateBySpace.length > 0) {
return allPhrasesSeparateBySpace[0].trim();
}
}

_createFieldsAdditionInformationMessage(statusBuild) {
return [
{'title': 'Elapsed time', 'value': (statusBuild.last_build_duration + ' sec'), 'short': true},
{'title': 'Build Number', 'value': ('#' + statusBuild.last_build_number), 'short': true}
];
}

isChatMessage(message) {
return message.type === 'message' && Boolean(message.text);
}
Expand All @@ -157,6 +167,10 @@ class slackMessageInterface {
return message.text && message.text.toLowerCase().indexOf('command list') > -1;
}

isValidCiMentionMessage(message) {
return !this.isFromCiAlarmBotMessage(message) && this.isChatMessage(message) && this.isMentioningCiAlarm(message);
}

colorByStatus(status) {
var color = this.infoColor;

Expand Down
13 changes: 10 additions & 3 deletions src/travisService.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,18 @@ class travisInterface {
*/
getLastBuildStatusByRepository(repositoryName) {
return new Promise((resolve, reject) => {

this.getUserRepositoriesList().then((repositoriesList)=> {
var slugRepository = _.find(repositoriesList, ['slug', repositoryName]);

var slugRepository = _.find(repositoriesList, (repository)=> {
if (repository.slug.indexOf(repositoryName) > -1) {
return repository.slug;
}
});

if (slugRepository) {
resolve(slugRepository.last_build_state);
}else {
resolve(slugRepository);
} else {
reject(new Error(('This repositories dosen\'t exixst')));
}
});
Expand Down
59 changes: 55 additions & 4 deletions test/slackMessageInterfaceBotStatusNotify.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ describe('Bot CI build communication', function () {
this.slackbotStub = sinon.stub(Bot.prototype, '_post', (function (type, name, text, message) {
this.textCheck = message.attachments[0].text;
this.colorMessage = message.attachments[0].color;
this.fields = message.attachments[0].fields;
}).bind(this));

this.loginStub = sinon.stub(Bot.prototype, 'login', function () {});
Expand Down Expand Up @@ -87,8 +88,10 @@ describe('Bot CI build communication', function () {
});

setTimeout(()=> {
expect(this.textCheck).to.be.equal('Hi <@C3P0> the build Status is passed!');
expect(this.textCheck).to.be.equal('Hi <@C3P0> the build Status was passed a few seconds ago');
expect(this.colorMessage).to.be.equal(this.slackMessageInterface.successColor);
expect(JSON.stringify(this.fields[0])).to.be.equal('{"title":"Elapsed time","value":"52 sec","short":true}');
expect(JSON.stringify(this.fields[1])).to.be.equal('{"title":"Build Number","value":"#37","short":true}');
done();
}, 50);
});
Expand All @@ -107,14 +110,16 @@ describe('Bot CI build communication', function () {
});

setTimeout(()=> {
expect(this.textCheck).to.be.equal('Hi <@C3P0> the build Status is failed!');
expect(this.textCheck).to.be.equal('Hi <@C3P0> the build Status was failed a few seconds ago');
expect(this.colorMessage).to.be.equal(this.slackMessageInterface.failColor);
expect(JSON.stringify(this.fields[0])).to.be.equal('{"title":"Elapsed time","value":"52 sec","short":true}');
expect(JSON.stringify(this.fields[1])).to.be.equal('{"title":"Build Number","value":"#37","short":true}');
done();
}, 50);

});

it('should the bot respond with the Unknown Build status if asked "build status" and travis not ha this repo in the CI', function (done) {
it('should the bot respond with the Unknown Build status if asked "build status" and travis not has this repo in the CI', function (done) {
var repos = Repository.createRepositoriesList();
nock('https://api.travis-ci.org:443')
.get('/repos/mbros')
Expand All @@ -128,11 +133,57 @@ describe('Bot CI build communication', function () {
});

setTimeout(()=> {
expect(this.textCheck).to.be.equal('Hi <@C3P0> the build Status is unknown!');
expect(this.textCheck).to.be.equal('Hi <@C3P0> the build Status was unknown a few seconds ago');
expect(this.colorMessage).to.be.equal(this.slackMessageInterface.infoColor);
expect(JSON.stringify(this.fields[0])).to.be.equal('{"title":"Elapsed time","value":"52 sec","short":true}');
expect(JSON.stringify(this.fields[1])).to.be.equal('{"title":"Build Number","value":"#37","short":true}');
done();
}, 50);
});

it('should the bot respond with the Build status also if there are spaces before and after the slug repository name', function (done) {
var repos = Repository.createRepositoriesList();
nock('https://api.travis-ci.org:443')
.get('/repos/mbros')
.reply(200, {repos});

this.slackMessageInterface.bot.emit('message', {
username: 'Sonikku',
user: 'C3P0',
type: 'message',
text: '<@' + this.slackMessageInterface.bot.self.id + '>: status fakeuser/fake-project3 '
});

setTimeout(()=> {
expect(this.textCheck).to.be.equal('Hi <@C3P0> the build Status was unknown a few seconds ago');
expect(this.colorMessage).to.be.equal(this.slackMessageInterface.infoColor);
expect(JSON.stringify(this.fields[0])).to.be.equal('{"title":"Elapsed time","value":"52 sec","short":true}');
expect(JSON.stringify(this.fields[1])).to.be.equal('{"title":"Build Number","value":"#37","short":true}');
done();
}, 50);

});

it('should the bot respond with the Build status also if the slug is not complete', function (done) {
var repos = Repository.createRepositoriesList();
nock('https://api.travis-ci.org:443')
.get('/repos/mbros')
.reply(200, {repos});

this.slackMessageInterface.bot.emit('message', {
username: 'Sonikku',
user: 'C3P0',
type: 'message',
text: '<@' + this.slackMessageInterface.bot.self.id + '>: status fake-project2'
});

setTimeout(()=> {
expect(this.textCheck).to.be.equal('Hi <@C3P0> the build Status was failed a few seconds ago');
expect(this.colorMessage).to.be.equal(this.slackMessageInterface.failColor);
expect(JSON.stringify(this.fields[0])).to.be.equal('{"title":"Elapsed time","value":"52 sec","short":true}');
expect(JSON.stringify(this.fields[1])).to.be.equal('{"title":"Build Number","value":"#37","short":true}');
done();
}, 50);

});
});
2 changes: 1 addition & 1 deletion test/slackMessageInterfaceGeneralInfo.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ describe('Bot CI General Travis info communication', function () {
});

setTimeout(()=> {
expect(this.textCheck).to.be.equal('Command list: \n • Repository list \n • build status username/example-project');// jscs:ignore maximumLineLength
expect(this.textCheck).to.be.equal('Command list: \n • repository list \n • status username/example-project');// jscs:ignore maximumLineLength
expect(this.colorMessage).to.be.equal(this.slackMessageInterface.infoColor);
done();
}, 50);
Expand Down
4 changes: 2 additions & 2 deletions test/travisService.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,11 @@ describe('Travis Service', function () {

var buildStatusResponse;
this.travisService.getLastBuildStatusByRepository('fakeuser/fake-project2').then((status)=> {
buildStatusResponse = status.toString();
buildStatusResponse = status;
});

setTimeout(()=> {
expect(buildStatusResponse).equals('failed');
expect(buildStatusResponse.last_build_state).equals('failed');
done();
}, 50);

Expand Down

0 comments on commit d4712c5

Please sign in to comment.