Created
November 17, 2017 09:22
-
-
Save vvondra/945c7d2c25f01ba9ead374b7da52cd6a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"AWSTemplateFormatVersion" : "2010-09-09", | |
"Resources" : { | |
"GithubServiceTopic" : { | |
"Type" : "AWS::SNS::Topic", | |
"Properties" : { | |
"DisplayName" : "Topic for Github pull request integration", | |
"Subscription" : [ | |
{ | |
"Endpoint" : { "Fn::GetAtt" : [ "GithubValidatePullRequest", "Arn" ] }, | |
"Protocol" : "lambda" | |
} | |
], | |
"TopicName" : "GithubServiceTopic" | |
}, | |
"DependsOn" : [ "InvokeGithubValidationLambdaFn" ] | |
}, | |
"InvokeGithubValidationLambdaFn" : { | |
"Type" : "AWS::Lambda::Permission", | |
"Properties" : { | |
"Action" : "lambda:InvokeFunction", | |
"FunctionName" : { "Fn::GetAtt" : [ "GithubValidatePullRequest", "Arn" ] }, | |
"Principal" : "sns.amazonaws.com" | |
} | |
}, | |
"GithubServiceUser" : { | |
"Type" : "AWS::IAM::User", | |
"Properties" : { | |
"Path" : "/", | |
"Policies" : [ | |
{ | |
"PolicyName" : "PublishGithubSnsEvents", | |
"PolicyDocument" : { | |
"Version" : "2012-10-17", | |
"Statement" : [ | |
{ | |
"Action" : [ | |
"sns:Publish" | |
], | |
"Resource" : [ | |
{ "Ref" : "GithubServiceTopic" } | |
], | |
"Effect" : "Allow" | |
} | |
] | |
} | |
} | |
] | |
} | |
}, | |
"GithubServiceUserKey" : { | |
"Type" : "AWS::IAM::AccessKey", | |
"Properties" : { | |
"Status" : "Active", | |
"UserName" : { "Ref" : "GithubServiceUser" } | |
} | |
}, | |
"DevToolLambdaExecutor" : { | |
"Type" : "AWS::IAM::Role", | |
"Properties" : { | |
"Path" : "/lambda/", | |
"Policies" : [ { | |
"PolicyName" : "DevToolLambdaExecutor", | |
"PolicyDocument" : { | |
"Version" : "2012-10-17", | |
"Statement" : [ | |
{ | |
"Effect" : "Allow", | |
"Action" : [ | |
"logs:CreateLogGroup", | |
"logs:CreateLogStream", | |
"logs:PutLogEvents" | |
], | |
"Resource" : "arn:aws:logs:*:*:*" | |
} | |
] | |
} | |
} ], | |
"AssumeRolePolicyDocument" : { | |
"Version" : "2012-10-17", | |
"Statement" : [ { | |
"Sid" : "", | |
"Effect" : "Allow", | |
"Principal" : { | |
"Service" : "lambda.amazonaws.com" | |
}, | |
"Action" : "sts:AssumeRole" | |
} ] | |
} | |
} | |
}, | |
"GithubValidatePullRequest" : { | |
"Type" : "AWS::Lambda::Function", | |
"Properties" : { | |
"Code" : { | |
"S3Bucket" : "%TEMPLATES-BUCKET%", | |
"S3Key" : { "Fn::Join" : [ "/", [ | |
"%TEMPLATE-VERSION%", | |
"githubValidatePullRequest.zip" | |
] ] } | |
}, | |
"Description" : "Creates to validate pull requests reacting on events coming from Github", | |
"Handler" : "validatePullRequest.handler", | |
"MemorySize" : "128", | |
"Role" : { "Fn::GetAtt" : [ "DevToolLambdaExecutor", "Arn" ] }, | |
"Runtime" : "nodejs4.3", | |
"Timeout" : "60" | |
} | |
} | |
}, | |
"Outputs" : { | |
"GithubServiceUser" : { | |
"Description" : "Github service user", | |
"Value" : { "Ref" : "GithubServiceUser" } | |
}, | |
"GithubServiceUserKeyId" : { | |
"Description" : "Github user access key ID", | |
"Value" : { "Ref" : "GithubServiceUserKey" } | |
}, | |
"GithubServiceUserSecretAccessKey" : { | |
"Description" : "Github user secret access key", | |
"Value" : { | |
"Fn::GetAtt" : ["GithubServiceUserKey", "SecretAccessKey"] | |
} | |
}, | |
"GithubSNSTopicARN" : { | |
"Description" : "SNS topic for Github notifications ARN", | |
"Value" : { "Ref" : "GithubServiceTopic" } | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var GitHubApi = require('github'); | |
var github = new GitHubApi({ | |
version: '3.0.0' | |
}); | |
/* | |
Adding to github | |
Under Repository admin, add as new *Service*, type *Amazon SNS* | |
All configuration (access key, secret, and SNS ARN come from CloudFormation) | |
The only catch is events have by default only "push" event enabled, so you need to do this API trickery: | |
curl -H "Authorization: token <oauthtoken>" https://api.github.com/repos/company/repo/hooks | |
curl -X PATCH -d '{"add_events": ["pull_request"]}' -H "Authorization: token <oauthtoken>" https://api.github.com/repos/company/repo/hooks/<id from first request> | |
curl -X PATCH -d '{"remove_events": ["push"]}' -H "Authorization: token <oauthtoken>" https://api.github.com/repos/company/repo/hooks/<id from first request> | |
curl -H "Authorization: token <oauthtoken>" https://api.github.com/repos/company/repo/hooks | |
*/ | |
exports.handler = function(event, context) { | |
var githubEvent = event.Records[0].Sns.Message; | |
var eventAttributes = event.Records[0].Sns.MessageAttributes; | |
console.log('Received GitHub event:', githubEvent); | |
console.log('Received GitHub event attributes:', eventAttributes); | |
if (!eventAttributes.hasOwnProperty('X-Github-Event') || | |
eventAttributes['X-Github-Event']['Value'] !== 'pull_request') { | |
console.log("Not a pull_request event"); | |
// Not a pull request event | |
context.succeed("Not pull_request event"); | |
return; | |
} | |
githubEvent = JSON.parse(githubEvent); | |
if ( | |
githubEvent.action !== 'opened' && | |
githubEvent.action !== 'synchronize' | |
) { | |
console.log("Event action not opened or synchronize"); | |
context.succeed("Event action not opened or synchronize"); | |
return; | |
} | |
if (githubEvent.pull_request.state !== 'open') { | |
console.log("PR is already closed"); | |
context.succeed("PR is already closed"); | |
return; | |
} | |
// Authenticate to comment on the issue | |
github.authenticate({ | |
type: 'oauth', | |
token: 'mytoken' // can only change PR statuses, no point in trying to abuse | |
}); | |
var prData = githubEvent.pull_request; | |
// Let's do the validations | |
var isValid = true; | |
var isAwesome = true; | |
var description = []; | |
if (prData.additions > 900) { | |
isValid = false; | |
description.push("This is a big PR, what about splitting it up?"); | |
} | |
if (prData.title.toUpperCase().indexOf('NO_TICKET') !== 0) { | |
if (!prData.body || prData.body.indexOf("maycompany.atlassian") == -1) { | |
isAwesome = false; | |
description.push("I could use that link to JIRA."); | |
} | |
if (prData.title.indexOf("LOGI-") !== 0) { | |
isValid = false; | |
description.push("I can't see the ticket ID in the title."); | |
} | |
} | |
if (isValid) { | |
if (prData.deletions > 1500) { | |
description.push("Do they call you code slayer?"); | |
} else if (prData.additions - prData.deletions < -500) { | |
description.push("I thought you're paid for writing code, not deleting it.") | |
} | |
} | |
if (isValid && description.length == 0) { | |
console.log("PR is valid"); | |
if (isAwesome) { | |
description.push('Your pull request is awesome!'); | |
} else { | |
description.push('Looks alright.'); | |
} | |
} | |
var statusMessage = description.join(" "); | |
console.log("Posting status message " + statusMessage); | |
github.statuses.create({ | |
user: githubEvent.repository.owner.login, | |
repo: githubEvent.repository.name, | |
sha: prData.head.sha, | |
state: isValid ? 'success' : 'failure', | |
description: statusMessage, | |
context: "Tip of the Day™" | |
}, context.done); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment