Skip to content

Commit c9c2771

Browse files
authored
Merge pull request #28 from thesuavehog/CodePipeline
Initial Code Pipeline event support
2 parents 5d92e13 + d900bd1 commit c9c2771

5 files changed

+227
-0
lines changed

src/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ function processIncoming(event) {
1515
require("./parsers/codebuild"),
1616
require("./parsers/codedeployCloudWatch"),
1717
require("./parsers/codedeploySns"),
18+
require("./parsers/codepipeline"),
19+
require("./parsers/codepipeline-approval"),
1820
require("./parsers/ses-received"),
1921
require("./parsers/codecommit/pullrequest"),
2022
require("./parsers/codecommit/repository"),

src/parsers/codepipeline-approval.js

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"use strict";
2+
3+
const BbPromise = require("bluebird"),
4+
_ = require("lodash"),
5+
Slack = require("../slack");
6+
7+
class CodePipelineApprovalParser {
8+
9+
parse(event) {
10+
//console.log("CodePipeline.Approval :: start...");
11+
//console.log(_.get(event, "Records[0].Sns.Message", "{}"));
12+
return BbPromise.try(() =>
13+
JSON.parse(_.get(event, "Records[0].Sns.Message", "{}")))
14+
.catch(_.noop) // ignore JSON errors
15+
.then(message => {
16+
17+
// Check that this is a CodePipeline APPROVAL message
18+
if (!_.has(message, "approval") || !_.has(message, "consoleLink")) {
19+
return BbPromise.resolve(false);
20+
}
21+
22+
console.log(" this IS an APPROVAL message");
23+
24+
//const detailType = message.detail-type;
25+
const pipeline = message.approval.pipelineName;
26+
const stage = message.approval.stageName;
27+
const action = message.approval.actionName;
28+
const expires = new Date(message.approval.expires);
29+
const reviewLink = message.approval.externalEntityLink;
30+
const approveLink = message.approval.approvalReviewLink;
31+
const customMsg = message.approval.customData;
32+
const time = new Date(_.get(event, "Records[0].Sns.Timestamp"));
33+
34+
var slackTitle = pipeline + " >> APPROVAL REQUIRED for " + stage;
35+
36+
const slackMessage = {
37+
attachments: [{
38+
fallback: `${pipeline} >> APPROVAL REQUIRED: ${approveLink}`,
39+
color: Slack.COLORS.warning,
40+
author_name: "AWS CodePipeline :: APPROVAL REQUIRED",
41+
title: slackTitle,
42+
text: customMsg,
43+
fields: [{
44+
title: "Review Link",
45+
value: reviewLink,
46+
short: true
47+
}, {
48+
title: "Approval Link",
49+
value: approveLink,
50+
short: true
51+
}
52+
/*
53+
, {
54+
title: "Approve By",
55+
value: expires,
56+
short: true
57+
}
58+
*/],
59+
ts: Slack.toEpochTime(time)
60+
}]
61+
};
62+
63+
return slackMessage;
64+
65+
});
66+
}
67+
}
68+
69+
module.exports = CodePipelineApprovalParser;

src/parsers/codepipeline.js

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
"use strict";
2+
3+
const BbPromise = require("bluebird"),
4+
_ = require("lodash"),
5+
Slack = require("../slack");
6+
7+
class CodePipelineParser {
8+
9+
parse(event) {
10+
//console.log("CodePipeline :: start...");
11+
//console.log(_.get(event, "Records[0].Sns.Message", "{}"));
12+
return BbPromise.try(() =>
13+
JSON.parse(_.get(event, "Records[0].Sns.Message", "{}")))
14+
.catch(_.noop) // ignore JSON errors
15+
.then(message => {
16+
17+
// Check that this is a CodePipeline message
18+
if (!_.has(message, "source") || message.source != "aws.codepipeline") {
19+
return BbPromise.resolve(false);
20+
}
21+
22+
const source = message.source;
23+
24+
// Check that this is NOT an approval message (there is a separate handler for those...)
25+
// NOTE: CodePipeline Action Execution State Changes that are APPROVALs are handled here,
26+
// only ignore the dedicated Approval request notifications
27+
if (_.has(message, "approval") && _.has(message, "consoleLink")) {
28+
return BbPromise.resolve(false);
29+
}
30+
31+
const typeProvider = message.detail.type.provider;
32+
const typeCategory = message.detail.type.category;
33+
const pipeline = message.detail.pipeline;
34+
const stage = message.detail.stage;
35+
const action = message.detail.action;
36+
const state = message.detail.state;
37+
const time = new Date(message.time);
38+
39+
// Compose the title based upon the best "one line" summary of the state
40+
var slackTitle = pipeline + " >> ";
41+
if(typeProvider == "Manual" && typeCategory == "Approval") {
42+
slackTitle += "APPROVAL REQUIRED for " + stage;
43+
}
44+
45+
46+
let color = Slack.COLORS.neutral;
47+
switch(state) {
48+
//case "RESUMED":
49+
//case "SUPERSEDED":
50+
case "STARTED":
51+
color = Slack.COLORS.accent;
52+
break;
53+
case "SUCCEEDED":
54+
color = Slack.COLORS.ok;
55+
break;
56+
case "FAILED":
57+
color = Slack.COLORS.critical;
58+
break;
59+
case "CANCELLED":
60+
color = Slack.COLORS.warning;
61+
break;
62+
}
63+
64+
const slackMessage = {
65+
attachments: [{
66+
fallback: `${pipeline} >> ${stage} is ${state}`,
67+
color: color,
68+
author_name: "AWS CodePipeline",
69+
title: slackTitle,
70+
text: message,
71+
fields: [{
72+
title: "Stage",
73+
value: stage,
74+
short: true
75+
}, {
76+
title: "Action",
77+
value: action,
78+
short: true
79+
}, {
80+
title: "State",
81+
value: state,
82+
short: true
83+
}],
84+
ts: Slack.toEpochTime(time)
85+
}]
86+
};
87+
88+
return slackMessage;
89+
90+
});
91+
}
92+
}
93+
94+
module.exports = CodePipelineParser;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"Records": [
3+
{
4+
"EventSource": "aws:sns",
5+
"EventVersion": "1.0",
6+
"EventSubscriptionArn": "arn:aws:sns:us-east-1:{{accountId}}:ExampleTopic",
7+
"Sns": {
8+
"Type": "Notification",
9+
"MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
10+
"TopicArn": "arn:aws:sns:us-east-1:123456789012:ExampleTopic",
11+
"Subject": "example subject",
12+
"Message": "{\"region\":\"us-east-1\",\"consoleLink\":\"https://console.aws.amazon.com/codepipeline/home?region=us-east-1#/view/mypipeline.name\",\"approval\":{\"pipelineName\":\"mypipeline.name\",\"stageName\":\"Deploy\",\"actionName\":\"Deploy_Approval\",\"token\":\"abcdefgh-b2fb-1234-a00a-31a03b998faa\",\"expires\":\"2018-11-13T21:36Z\",\"externalEntityLink\":\"https://my.reviewwebsite.com\",\"approvalReviewLink\":\"https://console.aws.amazon.com/codepipeline/home?region=us-east-1#/view/mypipeline.name/Deploy/Deploy_Approval/approve/abcdefgh-b2fb-1234-a00a-31a03b998faa\",\"customData\":\"TESTING :: Manual approval for a deployment to mypipeline.name\"}}",
13+
"Timestamp": "1970-01-01T00:00:00.000Z",
14+
"SignatureVersion": "1",
15+
"Signature": "EXAMPLE",
16+
"SigningCertUrl": "EXAMPLE",
17+
"UnsubscribeUrl": "EXAMPLE",
18+
"MessageAttributes": {
19+
"Test": {
20+
"Type": "String",
21+
"Value": "TestString"
22+
},
23+
"TestBinary": {
24+
"Type": "Binary",
25+
"Value": "TestBinary"
26+
}
27+
}
28+
}
29+
}
30+
]
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"Records": [
3+
{
4+
"EventSource": "aws:sns",
5+
"EventVersion": "1.0",
6+
"EventSubscriptionArn": "arn:aws:sns:us-east-1:{{accountId}}:ExampleTopic",
7+
"Sns": {
8+
"Type": "Notification",
9+
"MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
10+
"TopicArn": "arn:aws:sns:us-east-1:123456789012:ExampleTopic",
11+
"Subject": "example subject",
12+
"Message": "{\"version\":\"0\",\"id\":\"abcdefgh-ee18-1111-3fc1-951f022567a1\",\"detail-type\":\"CodePipeline Action Execution State Change\",\"source\":\"aws.codepipeline\",\"account\":\"123456789012\",\"time\":\"2018-11-06T21:36:10Z\",\"region\":\"us-east-1\",\"resources\":[\"arn:aws:codepipeline:us-east-1:123456789012:mypipeline\"],\"detail\":{\"pipeline\":\"mypipeline\",\"execution-id\":\"abcdefgh-ce35-1111-a123-c501546c9cdb\",\"stage\":\"Deploy\",\"action\":\"Deploy_Approval\",\"state\":\"STARTED\",\"region\":\"us-east-1\",\"type\":{\"owner\":\"AWS\",\"provider\":\"Manual\",\"category\":\"Approval\",\"version\":\"1\"},\"version\":4.0}}",
13+
"Timestamp": "1970-01-01T00:00:00.000Z",
14+
"SignatureVersion": "1",
15+
"Signature": "EXAMPLE",
16+
"SigningCertUrl": "EXAMPLE",
17+
"UnsubscribeUrl": "EXAMPLE",
18+
"MessageAttributes": {
19+
"Test": {
20+
"Type": "String",
21+
"Value": "TestString"
22+
},
23+
"TestBinary": {
24+
"Type": "Binary",
25+
"Value": "TestBinary"
26+
}
27+
}
28+
}
29+
}
30+
]
31+
}

0 commit comments

Comments
 (0)