先ほどの記事に引き続き。
GitHubからAmazon SNSでLambdaにイベント飛ばせば簡易CIができそうだだったので作ってみた。
処理の概要
- GitHubにpush→Amazon SNS→Lambdaにイベント
- Lambdaがイベントをフック→cfnスタックを作成
- cfnスタックがEC2インスタンスを起動→git clone
- bundle exec rspec
- cfnスタックは処理完了後に自動的に削除
Lambda Function
こんな感じ。
var Promise = require('bluebird'); var AWS = require("aws-sdk"); AWS.config.update({region: 'ap-northeast-1'}); var cloudformation = Promise.promisifyAll(new AWS.CloudFormation()); var fs = Promise.promisifyAll(require('fs')); exports.handler = function(event, context) { var message = JSON.parse(event.Records[0].Sns.Message); var repo_url = message.repository.url; var stackName = 'my-stack-' + new Date().getTime(); fs.readFileAsync('template.json', 'utf8').then(function(data) { return cloudformation.createStackAsync({ StackName: stackName, Parameters: [ { ParameterKey: 'Repository', ParameterValue: repo_url } ], TemplateBody: data }); }).then(function(data) { console.log(data); }).then(function() { context.succeed('OK'); }).catch(function(err) { context.fail(err); }); };
roleにはcfnスタックを作成できる適切な権限を付与しておく。
cfn template
こんな感じ。
{ "Parameters": { "Repository": { "Type": "String" } }, "Resources": { "MyInstance": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId": "ami-cbf90ecb", "InstanceType": "t2.micro", "SubnetId": "subnet-XXXXXXXX", "IamInstanceProfile": "my_role", "Tags": [ { "Key": "Name", "Value": {"Ref": "AWS::StackId"} } ], "UserData": { "Fn::Base64": { "Fn::Join": [ "", [ "#!/bin/bash\n", "export PATH=/usr/local/bin:$PATH\n", "yum install -y git\n", "yum install -y rubygem-io-console\n", "gem install bundler\n", "git clone ", {"Ref": "Repository"}, " myrepo\n", "cd myrepo\n", "bundle install\n", "bundle exec rspec\n", "aws cloudformation delete-stack --stack-name ", {"Ref": "AWS::StackName"}, " --region ", {"Ref": "AWS::Region"}, "\n" ] ] } } } } } }
やってることは、見たとおり。
/usr/local/bin
にパスを通す必要があった。
Amazon SNS
Lambdaにイベントを飛ばすトピックを作成。
GitHubリポジトリ
https://github.com/winebarrel/gh-lambda
SNSとの連携を設定しておく。
使ってみる
上記のリポジトリで適当にコミットすると
$ git commit --allow-empty -m 'XXX'; git push [master 1d03048] XXX Counting objects: 1, done. Writing objects: 100% (1/1), 189 bytes | 0 bytes/s, done. Total 1 (delta 0), reused 0 (delta 0) To git@github.com:winebarrel/gh-lambda.git 765ff58..1d03048 master -> master
Lambdaにイベントが飛んで
START RequestId: d7f6bdab-3da8-11e5-82cf-81454d6df691 END RequestId: d7f6bdab-3da8-11e5-82cf-81454d6df691 2015-08-08T08:38:30.060Z d7f6bdab-3da8-11e5-82cf-81454d6df691 { ResponseMetadata: { RequestId: 'd8206580-3da8-11e5-84e4-e722a24172c9' }, StackId: 'arn:aws:cloudformation:ap-northeast-1:123456789012:stack/my-stack-1439023109307/d8343b90-3da8-11e5-8e97-5001aba754a8' } REPORT RequestId: d7f6bdab-3da8-11e5-82cf-81454d6df691 Duration: 768.96 ms Billed Duration: 800 ms Memory Size: 128 MB Max Memory Used: 16 MB
インスタンスが起動して
rspecが実行されて
インスタンスは削除される。