From ce3b7ca5585a329bda1509f147ee4c01ef48f0cc Mon Sep 17 00:00:00 2001 From: Kyle Huntsman Date: Tue, 21 Jun 2016 13:56:47 -0700 Subject: [PATCH 1/2] Added SlackNotifier. Still need to test. --- lib/factory.js | 13 +- lib/notification/slack.js | 97 ++++++++++ npm-shrinkwrap.json | 380 +++++++++++++++++++++++++++++++++++++- package.json | 25 +-- 4 files changed, 498 insertions(+), 17 deletions(-) create mode 100644 lib/notification/slack.js diff --git a/lib/factory.js b/lib/factory.js index 18c4b95..b186657 100644 --- a/lib/factory.js +++ b/lib/factory.js @@ -23,6 +23,7 @@ var winston = require('winston'), path = require('path'), PostHookNotifier = require('./notification/posthook'), HipchatNotifier = require('./notification/hipchat'), + SlackNotifier = require('./notification/slack') nunjucks = require('nunjucks'), _ = require('lodash'); @@ -72,6 +73,10 @@ var DEFAULT_CONFIG = { token: process.env.HIPCHAT_TOKEN, room: process.env.HIPCHAT_ROOM }, + slack: { + url: process.env.SLACK_URL, + room: process.env.SLACK_ROOM + } baseUrl: process.env.BASE_URL || 'http://localhost:8080', env: process.env.TOTEM_ENV || 'local' }; @@ -86,7 +91,7 @@ function Factory(config) { // Merge in custom config with defaults _.defaults(config, DEFAULT_CONFIG); - + // Store reference to current object var _this = this; @@ -118,14 +123,15 @@ function Factory(config) { _.forEach(_this.notifiers, function(notifier) { notifier.notify(isSuccessful, notifyCtx, image); }); - + }); }, this.config.concurrentJobs); // Limit the number of concurrent jobs // Notification for job this.notifiers = [ new PostHookNotifier(config.hook), - new HipchatNotifier(config.hipchat) + new HipchatNotifier(config.hipchat), + new SlackNotifier(config.slack) ]; // Initialize the API @@ -424,4 +430,3 @@ Factory.prototype.createJob = function createJob(req, res, context, next) { return next(new restify.InternalError(e.message)); } }; - diff --git a/lib/notification/slack.js b/lib/notification/slack.js new file mode 100644 index 0000000..4534e20 --- /dev/null +++ b/lib/notification/slack.js @@ -0,0 +1,97 @@ +/*! + * Docker Image Factory - Notification module + * + */ + +'use strict'; + +var winston = require('winston'), + Slack = require('node-slack'), + nunjucks = require('nunjucks'); + +module.exports = SlackNotifier; + +function SlackNotifier(cfg, slack) { + this.cfg = cfg || {}; + this.slack = new Slack(cfg.url); +} + +/** + * Returns true if notification is enabled. + * @returns {boolean} + */ +SlackNotifier.prototype.isEnabled = function () { + return (this.cfg.url) ? true : false; +}; + +SlackNotifier.prototype.notify = function (isSuccessful, context) { + var _this = this; + var cfg = _this.cfg; + if (_this.isEnabled()) { + if (!isSuccessful) { + + // The owner of the repo + var ownerUrl = ctx.owner; + if(ctx.github) { + ownerUrl = "https://github.com/" + ctx.owner; + } + + // The repo + var repoUrl = ctx.repo; + if(ctx.github) { + repoUrl = "https://github.com/" + ctx.owner + "/" + ctx.repo; + } + + // The branch + var branchUrl = ctx.ref; + if(ctx.github) { + branchUrl = "https://github.com/" + "/" + ctx.owner + "/" + ctx.repo + "/tree/" + ctx.ref; + } + + // The commit + var commitUrl = ctx.commit; + if(ctx.github) { + commitUrl = "https://github.com/" + ctx.owner + "/" + ctx.repo + "/commit/" + ctx.commit; + } + var shortCommit = ctx.commit + + // The job + var jobUrl = ctx.baseUrl + "/job/" + ctx.id; + var jobLogUrl = jobUrl + "/log"; + + var channels = cfg.rooms.split(','); + channels.forEach(function(channel) { + _this.slack.send({ + text: " ", + username: "Totem Bot", + channel: channel, + attachments: [{ + title: "Image Factory ( " + ctx.env + " )", + text: link(ownerUrl, ctx.owner) + " / " + link(repoUrl, ctx.repo) + " / " + link(branchUrl, ctx.ref) + " / " + link(commitUrl, ctx.commit.substr(0, 7)), + color: "danger", + + fields: [ + { + title: "Job", + value: link(jobUrl, ctx.id) + " ( " + link(jobLogUrl, "logs") + " )", + short: true + }, + { + title: "Message", + value: message, + short: true + } + ], + + footer: "Image Factory", + ts: Date.now() / 1000 + }] + }); + }); + } + } +}; + +function link(url, text) { + return "<" + url + "|" + text + ">"; +} diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 7665d04..29684fc 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "image-factory", - "version": "0.6.8", + "version": "0.7.1", "dependencies": { "abbrev": { "version": "1.0.7", @@ -119,6 +119,11 @@ } } }, + "aws4": { + "version": "1.4.1", + "from": "aws4@>=1.2.1 <2.0.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz" + }, "backoff": { "version": "2.4.1", "from": "https://registry.npmjs.org/backoff/-/backoff-2.4.1.tgz", @@ -136,6 +141,23 @@ "from": "balanced-match@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.3.0.tgz" }, + "bl": { + "version": "1.1.2", + "from": "bl@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "dependencies": { + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "readable-stream": { + "version": "2.0.6", + "from": "readable-stream@>=2.0.5 <2.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz" + } + } + }, "blanket": { "version": "1.1.6", "from": "blanket@1.1.6", @@ -151,6 +173,11 @@ "from": "brace-expansion@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.3.tgz" }, + "caseless": { + "version": "0.11.0", + "from": "caseless@>=0.11.0 <0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz" + }, "chalk": { "version": "1.1.1", "from": "chalk@>=1.1.1 <2.0.0", @@ -245,6 +272,23 @@ "from": "ctype@0.5.3", "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" }, + "d": { + "version": "0.1.1", + "from": "d@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz" + }, + "dashdash": { + "version": "1.14.0", + "from": "dashdash@>=1.12.0 <2.0.0", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "from": "assert-plus@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + } + } + }, "date-now": { "version": "0.1.4", "from": "date-now@>=0.1.4 <0.2.0", @@ -265,6 +309,11 @@ "from": "deep-eql@0.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz" }, + "deferred": { + "version": "0.7.1", + "from": "deferred@0.7.1", + "resolved": "https://registry.npmjs.org/deferred/-/deferred-0.7.1.tgz" + }, "delayed-stream": { "version": "0.0.5", "from": "delayed-stream@0.0.5", @@ -307,11 +356,31 @@ "from": "domutils@>=1.5.0 <1.6.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz" }, + "ecc-jsbn": { + "version": "0.1.1", + "from": "ecc-jsbn@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz" + }, "entities": { "version": "1.0.0", "from": "entities@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz" }, + "es5-ext": { + "version": "0.10.11", + "from": "es5-ext@>=0.10.2 <0.11.0", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.11.tgz" + }, + "es6-iterator": { + "version": "2.0.0", + "from": "es6-iterator@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.0.tgz" + }, + "es6-symbol": { + "version": "3.0.2", + "from": "es6-symbol@>=3.0.2 <3.1.0", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.0.2.tgz" + }, "escape-string-regexp": { "version": "1.0.5", "from": "escape-string-regexp@>=1.0.2 <2.0.0", @@ -322,6 +391,11 @@ "from": "esprima@>=1.0.2 <1.1.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz" }, + "event-emitter": { + "version": "0.3.4", + "from": "event-emitter@>=0.3.1 <0.4.0", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.4.tgz" + }, "eventemitter2": { "version": "0.4.14", "from": "eventemitter2@>=0.4.13 <0.5.0", @@ -337,6 +411,16 @@ "from": "exit@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" }, + "extend": { + "version": "3.0.0", + "from": "extend@>=3.0.0 <3.1.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" + }, + "extsprintf": { + "version": "1.0.2", + "from": "extsprintf@1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz" + }, "falafel": { "version": "0.1.6", "from": "falafel@>=0.1.6 <0.2.0", @@ -396,11 +480,33 @@ "from": "fsevents@>=0.3.1 <0.4.0", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-0.3.8.tgz" }, + "generate-function": { + "version": "2.0.0", + "from": "generate-function@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" + }, + "generate-object-property": { + "version": "1.2.0", + "from": "generate-object-property@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz" + }, "getobject": { "version": "0.1.0", "from": "getobject@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz" }, + "getpass": { + "version": "0.1.6", + "from": "getpass@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "from": "assert-plus@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + } + } + }, "glob": { "version": "3.1.21", "from": "glob@>=3.1.21 <3.2.0", @@ -418,6 +524,11 @@ "from": "graceful-fs@>=1.2.0 <1.3.0", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" }, + "graceful-readlink": { + "version": "1.0.1", + "from": "graceful-readlink@>=1.0.0", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" + }, "growl": { "version": "1.8.1", "from": "growl@1.8.1", @@ -476,6 +587,18 @@ } } }, + "har-validator": { + "version": "2.0.6", + "from": "har-validator@>=2.0.6 <2.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "dependencies": { + "commander": { + "version": "2.9.0", + "from": "commander@>=2.9.0 <3.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz" + } + } + }, "has-ansi": { "version": "2.0.0", "from": "has-ansi@>=2.0.0 <3.0.0", @@ -535,6 +658,18 @@ "from": "http-signature@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz" }, + "httpplease": { + "version": "0.16.4", + "from": "httpplease@>=0.16.4 <0.17.0", + "resolved": "https://registry.npmjs.org/httpplease/-/httpplease-0.16.4.tgz", + "dependencies": { + "xtend": { + "version": "3.0.0", + "from": "xtend@>=3.0.0 <3.1.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz" + } + } + }, "iconv-lite": { "version": "0.2.11", "from": "iconv-lite@>=0.2.11 <0.3.0", @@ -545,11 +680,38 @@ "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, + "is-my-json-valid": { + "version": "2.13.1", + "from": "is-my-json-valid@>=2.12.4 <3.0.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz", + "dependencies": { + "xtend": { + "version": "4.0.1", + "from": "xtend@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + } + }, + "is-property": { + "version": "1.0.2", + "from": "is-property@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" + }, + "is-typedarray": { + "version": "1.0.0", + "from": "is-typedarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + }, "isarray": { "version": "0.0.1", "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, + "isstream": { + "version": "0.1.2", + "from": "isstream@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" + }, "jade": { "version": "0.26.3", "from": "jade@0.26.3", @@ -567,11 +729,21 @@ } } }, + "jodid25519": { + "version": "1.0.2", + "from": "jodid25519@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz" + }, "js-yaml": { "version": "2.0.5", "from": "js-yaml@>=2.0.5 <2.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz" }, + "jsbn": { + "version": "0.1.0", + "from": "jsbn@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz" + }, "jshint": { "version": "2.9.1", "from": "jshint@>=2.9.1 <2.10.0", @@ -589,11 +761,26 @@ } } }, + "json-schema": { + "version": "0.2.2", + "from": "json-schema@0.2.2", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz" + }, "json-stringify-safe": { "version": "5.0.1", "from": "json-stringify-safe@>=5.0.0 <5.1.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" }, + "jsonpointer": { + "version": "2.0.0", + "from": "jsonpointer@2.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz" + }, + "jsprim": { + "version": "1.2.2", + "from": "jsprim@>=1.2.2 <2.0.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.2.2.tgz" + }, "lcov-parse": { "version": "0.0.9", "from": "lcov-parse@0.0.9", @@ -689,6 +876,11 @@ "from": "mime@>=1.2.11 <1.3.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, + "mime-db": { + "version": "1.23.0", + "from": "mime-db@>=1.23.0 <1.24.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz" + }, "mime-types": { "version": "1.0.2", "from": "mime-types@>=1.0.1 <1.1.0", @@ -751,6 +943,16 @@ "from": "nan@>=2.0.2 <3.0.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.2.0.tgz" }, + "next-tick": { + "version": "0.2.2", + "from": "next-tick@>=0.2.2 <0.3.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz" + }, + "node-slack": { + "version": "0.0.7", + "from": "node-slack@latest", + "resolved": "https://registry.npmjs.org/node-slack/-/node-slack-0.0.7.tgz" + }, "node-uuid": { "version": "1.4.7", "from": "node-uuid@>=1.4.0 <1.5.0", @@ -863,11 +1065,36 @@ } } }, + "options": { + "version": "0.0.6", + "from": "options@>=0.0.5", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz" + }, + "pinkie": { + "version": "2.0.4", + "from": "pinkie@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + }, + "pinkie-promise": { + "version": "2.0.1", + "from": "pinkie-promise@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, "qs": { "version": "1.0.2", "from": "qs@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/qs/-/qs-1.0.2.tgz" }, + "query-string": { + "version": "3.0.3", + "from": "query-string@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-3.0.3.tgz" + }, "readable-stream": { "version": "1.1.13", "from": "readable-stream@>=1.1.0 <1.2.0", @@ -1222,11 +1449,120 @@ "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" }, + "slack": { + "version": "7.3.0", + "from": "slack@latest", + "resolved": "https://registry.npmjs.org/slack/-/slack-7.3.0.tgz", + "dependencies": { + "assert-plus": { + "version": "0.2.0", + "from": "assert-plus@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz" + }, + "aws-sign2": { + "version": "0.6.0", + "from": "aws-sign2@>=0.6.0 <0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz" + }, + "boom": { + "version": "2.10.1", + "from": "boom@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" + }, + "combined-stream": { + "version": "1.0.5", + "from": "combined-stream@>=1.0.5 <1.1.0", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz" + }, + "cryptiles": { + "version": "2.0.5", + "from": "cryptiles@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz" + }, + "delayed-stream": { + "version": "1.0.0", + "from": "delayed-stream@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + }, + "forever-agent": { + "version": "0.6.1", + "from": "forever-agent@>=0.6.1 <0.7.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" + }, + "form-data": { + "version": "1.0.0-rc4", + "from": "form-data@>=1.0.0-rc3 <1.1.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz" + }, + "hawk": { + "version": "3.1.3", + "from": "hawk@>=3.1.3 <3.2.0", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz" + }, + "hoek": { + "version": "2.16.3", + "from": "hoek@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + }, + "http-signature": { + "version": "1.1.1", + "from": "http-signature@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz" + }, + "mime-types": { + "version": "2.1.11", + "from": "mime-types@>=2.1.7 <2.2.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz" + }, + "oauth-sign": { + "version": "0.8.2", + "from": "oauth-sign@>=0.8.1 <0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz" + }, + "qs": { + "version": "6.1.0", + "from": "qs@>=6.1.0 <6.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.1.0.tgz" + }, + "request": { + "version": "2.72.0", + "from": "request@>=2.67.0 <3.0.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.72.0.tgz" + }, + "sntp": { + "version": "1.0.9", + "from": "sntp@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" + } + } + }, "sntp": { "version": "0.2.4", "from": "sntp@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" }, + "sshpk": { + "version": "1.8.3", + "from": "sshpk@>=1.7.0 <2.0.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.8.3.tgz", + "dependencies": { + "asn1": { + "version": "0.2.3", + "from": "asn1@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz" + }, + "assert-plus": { + "version": "1.0.0", + "from": "assert-plus@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + } + } + }, + "strict-uri-encode": { + "version": "1.1.0", + "from": "strict-uri-encode@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz" + }, "string_decoder": { "version": "0.10.31", "from": "string_decoder@>=0.10.0 <0.11.0", @@ -1262,11 +1598,21 @@ "from": "tunnel-agent@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.2.tgz" }, + "tweetnacl": { + "version": "0.13.3", + "from": "tweetnacl@>=0.13.0 <0.14.0", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz" + }, "type-detect": { "version": "0.1.1", "from": "type-detect@0.1.1", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz" }, + "ultron": { + "version": "1.0.2", + "from": "ultron@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz" + }, "underscore": { "version": "1.7.0", "from": "underscore@>=1.7.0 <1.8.0", @@ -1277,11 +1623,33 @@ "from": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.0.3.tgz", "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.0.3.tgz" }, + "urllite": { + "version": "0.5.0", + "from": "urllite@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/urllite/-/urllite-0.5.0.tgz", + "dependencies": { + "xtend": { + "version": "4.0.1", + "from": "xtend@>=4.0.0 <4.1.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + } + }, "util": { "version": "0.10.3", "from": "util@>=0.10.3 <1.0.0", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz" }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + }, + "verror": { + "version": "1.3.6", + "from": "verror@1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz" + }, "which": { "version": "1.0.9", "from": "which@>=1.0.5 <1.1.0", @@ -1334,6 +1702,16 @@ "from": "https://registry.npmjs.org/wrench/-/wrench-1.5.8.tgz", "resolved": "https://registry.npmjs.org/wrench/-/wrench-1.5.8.tgz" }, + "ws": { + "version": "1.1.0", + "from": "ws@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.0.tgz" + }, + "xmlhttprequest": { + "version": "1.8.0", + "from": "xmlhttprequest@*", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz" + }, "xtend": { "version": "2.1.2", "from": "xtend@>=2.1.1 <2.2.0", diff --git a/package.json b/package.json index 499f9e8..d6b3bf7 100644 --- a/package.json +++ b/package.json @@ -16,22 +16,23 @@ }, "dependencies": { "async": "*", - "winston": "*", - "restify": "~2.7.0", - "wrench": "*", - "optimist": "*", - "shortid": "*", - "lodash": "*", - "formatter": "*", - "z-schema": "2.4.6", - "underscore.string": "*", "aws-sdk": "2.0.0-rc13", - "events": "~1.0.0", - "backoff": "*", "aws-swf": "4.0.0", + "backoff": "*", + "events": "~1.0.0", + "formatter": "*", "hipchatter": "~0.2.0", + "lodash": "*", + "node-slack": "0.0.7", "nunjucks": "*", - "request": "~2.53.0" + "optimist": "*", + "request": "~2.53.0", + "restify": "~2.7.0", + "shortid": "*", + "underscore.string": "*", + "winston": "*", + "wrench": "*", + "z-schema": "2.4.6" }, "devDependencies": { "chai": "~1.10.0", From dc14e19e330aebe9d14203de036b5beb20983681 Mon Sep 17 00:00:00 2001 From: Kyle Huntsman Date: Mon, 18 Jul 2016 17:30:53 -0700 Subject: [PATCH 2/2] Added slack templates --- lib/factory.js | 6 ++- lib/notification/slack.js | 104 ++++++++++++-------------------------- templates/slack.json | 17 +++++++ 3 files changed, 54 insertions(+), 73 deletions(-) create mode 100644 templates/slack.json diff --git a/lib/factory.js b/lib/factory.js index b186657..27baccf 100644 --- a/lib/factory.js +++ b/lib/factory.js @@ -23,7 +23,7 @@ var winston = require('winston'), path = require('path'), PostHookNotifier = require('./notification/posthook'), HipchatNotifier = require('./notification/hipchat'), - SlackNotifier = require('./notification/slack') + SlackNotifier = require('./notification/slack'), nunjucks = require('nunjucks'), _ = require('lodash'); @@ -76,7 +76,7 @@ var DEFAULT_CONFIG = { slack: { url: process.env.SLACK_URL, room: process.env.SLACK_ROOM - } + }, baseUrl: process.env.BASE_URL || 'http://localhost:8080', env: process.env.TOTEM_ENV || 'local' }; @@ -120,6 +120,8 @@ function Factory(config) { env: _this.config.env, id: job.id }); + notifyCtx.shortCommit = notifyCtx.commit.substring(0, 7); + _.forEach(_this.notifiers, function(notifier) { notifier.notify(isSuccessful, notifyCtx, image); }); diff --git a/lib/notification/slack.js b/lib/notification/slack.js index 4534e20..01a93e9 100644 --- a/lib/notification/slack.js +++ b/lib/notification/slack.js @@ -11,87 +11,49 @@ var winston = require('winston'), module.exports = SlackNotifier; -function SlackNotifier(cfg, slack) { +function SlackNotifier(cfg) { this.cfg = cfg || {}; this.slack = new Slack(cfg.url); } /** - * Returns true if notification is enabled. - * @returns {boolean} + * Returns true if notification is enabled */ SlackNotifier.prototype.isEnabled = function () { return (this.cfg.url) ? true : false; }; -SlackNotifier.prototype.notify = function (isSuccessful, context) { - var _this = this; - var cfg = _this.cfg; - if (_this.isEnabled()) { - if (!isSuccessful) { - - // The owner of the repo - var ownerUrl = ctx.owner; - if(ctx.github) { - ownerUrl = "https://github.com/" + ctx.owner; - } - - // The repo - var repoUrl = ctx.repo; - if(ctx.github) { - repoUrl = "https://github.com/" + ctx.owner + "/" + ctx.repo; - } - - // The branch - var branchUrl = ctx.ref; - if(ctx.github) { - branchUrl = "https://github.com/" + "/" + ctx.owner + "/" + ctx.repo + "/tree/" + ctx.ref; - } - - // The commit - var commitUrl = ctx.commit; - if(ctx.github) { - commitUrl = "https://github.com/" + ctx.owner + "/" + ctx.repo + "/commit/" + ctx.commit; - } - var shortCommit = ctx.commit - - // The job - var jobUrl = ctx.baseUrl + "/job/" + ctx.id; - var jobLogUrl = jobUrl + "/log"; - - var channels = cfg.rooms.split(','); - channels.forEach(function(channel) { - _this.slack.send({ - text: " ", - username: "Totem Bot", - channel: channel, - attachments: [{ - title: "Image Factory ( " + ctx.env + " )", - text: link(ownerUrl, ctx.owner) + " / " + link(repoUrl, ctx.repo) + " / " + link(branchUrl, ctx.ref) + " / " + link(commitUrl, ctx.commit.substr(0, 7)), - color: "danger", - - fields: [ - { - title: "Job", - value: link(jobUrl, ctx.id) + " ( " + link(jobLogUrl, "logs") + " )", - short: true - }, - { - title: "Message", - value: message, - short: true - } - ], - - footer: "Image Factory", - ts: Date.now() / 1000 - }] - }); - }); - } +SlackNotifier.prototype.notify = function (isSuccessful, ctx) { + var cfg = this.cfg; + if (this.isEnabled() && !isSuccessful) { + var channel = cfg.room; + this.sendMessage('slack.json', ctx, channel); } }; -function link(url, text) { - return "<" + url + "|" + text + ">"; -} +/** + * Creates the context object to send the + * template engine and then renders the template + */ +SlackNotifier.prototype.sendMessage = function(templateName, ctx, channel) { + var _this = this; + winston.debug('Posting slack message to ' + channel + ' channel'); + + // Context object with any addition notification details + var obj = { + ctx: ctx, + notification: { + channel: channel, + date: Date.now() / 1000 + } + }; + + // Render the template and send the message + nunjucks.render(templateName, obj, function(err, resp) { + if(!err) { + _this.slack.send(JSON.parse(resp)); + } else { + winston.error('Failed to render template. Reason: ' + err.message); + } + }); +}; diff --git a/templates/slack.json b/templates/slack.json new file mode 100644 index 0000000..79b42b9 --- /dev/null +++ b/templates/slack.json @@ -0,0 +1,17 @@ +{ + "text": " ", + "username": "Image Factory", + "channel": "{{ channel }}", + "attachments": [{ + "text": "A *{{ ctx.env }}* build for *{{ ctx.repo }}* has failed!\nFor more details, view the <{{ ctx.baseUrl }}/job/{{ ctx.id }}/log|logs>.", + "color": "danger", + "mrkdwn_in": ["text"], + "footer": + {% if ctx.github %} + " / / / \n" + {% else %} + "{{ctx.owner or 'NA'}}/{{ctx.repo or 'NA'}}/{{ctx.branch or 'NA'}}/{{ctx.shortCommit or 'NA'}}" + {% endif %}, + "ts": "{{ notification.date }}" + }] +} \ No newline at end of file