diff options
author | Kenny Ballou <kballou@devnulllabs.io> | 2020-01-28 21:49:30 -0700 |
---|---|---|
committer | Kenny Ballou <kballou@devnulllabs.io> | 2020-02-05 17:33:12 -0700 |
commit | 0eea4a0abfdbf1225abd148eac0a7f151c1144b3 (patch) | |
tree | 7572d62e5a9260c2b755d6c085769f2dcab5e8b0 /stacks | |
parent | 1bb882edd5c1745d1a1bd4cc12e30fcbd8f81be9 (diff) | |
download | kennyballou.com-0eea4a0abfdbf1225abd148eac0a7f151c1144b3.tar.gz kennyballou.com-0eea4a0abfdbf1225abd148eac0a7f151c1144b3.tar.xz |
code-{build,commit} auto build and deploy blog
Create codecommit and codebuild resources to store and build web/blog
content. Add in a lambda function to trigger the builds automatically
to futher automate deployment and publishing of content.
Signed-off-by: Kenny Ballou <kballou@devnulllabs.io>
Diffstat (limited to 'stacks')
-rw-r--r-- | stacks/blog.tpl | 150 | ||||
-rw-r--r-- | stacks/codebuild-service-role.json.in | 49 | ||||
-rw-r--r-- | stacks/codecommit-build-policy.json.in | 33 | ||||
-rwxr-xr-x | stacks/codecommit-build.py | 76 |
4 files changed, 308 insertions, 0 deletions
diff --git a/stacks/blog.tpl b/stacks/blog.tpl index 454540c..3a6cd7f 100644 --- a/stacks/blog.tpl +++ b/stacks/blog.tpl @@ -230,6 +230,156 @@ "URIRewriteLambdaFunction", "Arn"]}, "Description": "Lambda Function performing URI rewriting" } + }, + "BlogContentRepository": { + "Type": "AWS::CodeCommit::Repository", + "Properties": { + "RepositoryDescription": "Blog Content Repository", + "RepositoryName": {"Ref": "BlogBucketName"}, + "Triggers": [ + { + "Name": "Build and Deploy", + "Branches": ["master"], + "DestinationArn": {"Ref": "CodeCommitEventsSnsTopic"}, + "Events": ["all"] + } + ] + } + }, + "BlogCodeBuildLogGroup": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": {"Fn::Join": ["-", [ + "/aws/codebuild/CodeBuild", + {"Ref": "BlogBucketName"}]]}, + "RetentionInDays": 14 + } + }, + "BlogCodeBuild": { + "Type": "AWS::CodeBuild::Project", + "Properties": { + "Name": "BlogCI", + "Description": "Blog Build Project", + "Artifacts": { + "Type": "NO_ARTIFACTS" + }, + "Environment": { + "ComputeType": "BUILD_GENERAL1_SMALL", + "Image": "kennyballou/debian-pandoc:latest", + "Type": "LINUX_CONTAINER" + }, + "LogsConfig": { + "CloudWatchLogs": { + "GroupName": {"Fn::Join": ["-", [ + "/aws/codebuild/CodeBuild", + {"Ref": "BlogBucketName"} + ]]}, + "Status": "ENABLED" + } + }, + "ServiceRole": {"Ref": "CodeBuildIamServiceRole"}, + "Source": { + "Type": "CODECOMMIT", + "Location": {"Fn::GetAtt": ["BlogContentRepository", + "CloneUrlHttp"]} + } + } + }, + "CodeCommitEventsSnsTopic": { + "Type": "AWS::SNS::Topic", + "Properties": { + "DisplayName": "CodeCommit Events", + "TopicName": "codecommit-events" + } + }, + "CodeBuildIamManagedPolicy": { + "Type": "AWS::IAM::ManagedPolicy", + "Properties": { + "Description": "CodeBuild Service Policy", + "PolicyDocument": [+ INCLUDE "codebuild-service-role.json.in" +] + } + }, + "CodeBuildIamServiceRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Principal": { + "Service": "codebuild.amazonaws.com" + }, + "Effect": "Allow" + } + ] + }, + "ManagedPolicyArns": [ + {"Ref": "CodeBuildIamManagedPolicy"} + ] + } + }, + "LambdaCodeCommitBuildIamManagedPolicy": { + "Type": "AWS::IAM::ManagedPolicy", + "Properties": { + "Description": "Lambda CodeCommit-Build Execution Policy", + "PolicyDocument": [+ INCLUDE "codecommit-build-policy.json.in" +] + } + }, + "LambdaCodeCommitBuildIamServiceRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Principal": { + "Service": "lambda.amazonaws.com" + }, + "Effect": "Allow" + } + ] + }, + "ManagedPolicyArns": [ + {"Ref": "LambdaCodeCommitBuildIamManagedPolicy"} + ] + } + }, + "CodeCommitBuildLambdaPermission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "FunctionName": {"Fn::GetAtt": [ + "CodeCommitBuildLambdaFunction", "Arn"]}, + "Action": "lambda:InvokeFunction", + "Principal": "sns.amazonaws.com", + "SourceArn": {"Ref": "CodeCommitEventsSnsTopic"} + } + }, + "CodeCommitBuildLambdaFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "FunctionName": "codecommit-build-bae089e8-3871-4067-9a3d-bac114f08438", + "Code": { + "ZipFile": [+ INCLUDE "codecommit-build.py.in" +] + }, + "Description": "Start builds on commit events", + "Handler": "index.handler", + "MemorySize": 128, + "Timeout": 3, + "Role": {"Fn::GetAtt": [ + "LambdaCodeCommitBuildIamServiceRole", "Arn"]}, + "Runtime": "python3.7" + } + }, + "CodeCommitBuildSnsSubscription": { + "Type": "AWS::SNS::Subscription", + "Properties": { + "Protocol": "lambda", + "Endpoint": {"Fn::GetAtt": [ + "CodeCommitBuildLambdaFunction", "Arn"]}, + "TopicArn": {"Ref": "CodeCommitEventsSnsTopic"} + } } } } diff --git a/stacks/codebuild-service-role.json.in b/stacks/codebuild-service-role.json.in new file mode 100644 index 0000000..abcb514 --- /dev/null +++ b/stacks/codebuild-service-role.json.in @@ -0,0 +1,49 @@ +[+ autogen5 template -*- mode: json -*- +] +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Resource": [ + {"Fn::Join": [":", [ + "arn:aws:logs", + {"Ref": "AWS::Region"}, + {"Ref": "AWS::AccountId"}, + "log-group:/aws/codebuild/CodeBuild*"]]}, + {"Fn::Join": [":", [ + "arn:aws:logs", + {"Ref": "AWS::Region"}, + {"Ref": "AWS::AccountId"}, + "log-group:/aws/codebuild/CodeBuild*", + "log-stream:*"]]} + ] + }, { + "Effect": "Allow", + "Action": [ + "codecommit:GitPull" + ], + "Resource": [ + {"Fn::Join": [":", [ + "arn:aws:codecommit", + {"Ref": "AWS::Region"}, + {"Ref": "AWS::AccountId"}, + "*"]]} + ] + }, { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:Get*", + "s3:List" + ], + "Resource": [ + {"Fn::GetAtt": ["BlogContentBucket", "Arn"]}, + {"Fn::Join": ["", [{"Fn::GetAtt": ["BlogContentBucket", "Arn"]}, "/*"]]} + ] + } + ] +} diff --git a/stacks/codecommit-build-policy.json.in b/stacks/codecommit-build-policy.json.in new file mode 100644 index 0000000..634acb2 --- /dev/null +++ b/stacks/codecommit-build-policy.json.in @@ -0,0 +1,33 @@ +[+ autogen5 template -*- mode: json -*- +] +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Resource": [ + {"Fn::Join": [":", [ + "arn:aws:logs", + {"Ref": "AWS::Region"}, + {"Ref": "AWS::AccountId"}, + "log-group:/aws/lambda/codecommit-build-bae089e8-3871-4067-9a3d-bac114f08438:*" + ]]} + ] + }, { + "Effect": "Allow", + "Action": [ + "codebuild:StartBuild" + ], + "Resource": [ + {"Fn::Join": [":", [ + "arn:aws:codebuild", + {"Ref": "AWS::Region"}, + {"Ref": "AWS::AccountId"}, + "project/*"]]} + ] + } + ] +} diff --git a/stacks/codecommit-build.py b/stacks/codecommit-build.py new file mode 100755 index 0000000..9c8d3ce --- /dev/null +++ b/stacks/codecommit-build.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +''' +CodeCommit to CodeBuild Integration + +Start CodeBuild jobs based on CodeCommit events. +''' + + +import json +import logging +import boto3 + +LOG = logging.getLogger() +LOG.setLevel(logging.INFO) + +PROJECT_NAME = 'BlogCI' + + +def get_is_tag(ref): + return 'tags' in ref + + +def submit_build(reference, project_name, region): + '''Submit codebuild job for reference''' + client = boto3.client('codebuild', region_name=region) + + response = client.start_build( + projectName=project_name, + sourceVersion=reference, + ) + LOG.info(response['build']) + + +def debug_handler(detail): + '''Log details and exit''' + LOG.warn(detail) + return True + + +def reference_change_handler(detail): + '''handle reference change events, submitting code build jobs if needed''' + references = detail['codecommit']['references'] + region = detail['awsRegion'] + for reference in references: + is_deleted = reference.get('deleted', False) + if is_deleted: + continue + if 'tags' in reference['ref']: + submit_build(reference['ref'], PROJECT_NAME, region) + else: + submit_build(reference['commit'], PROJECT_NAME, region) + + +EVENT_HANDLERS = { + 'TriggerEventTest': False, + 'ReferenceChanges': reference_change_handler, +} + + +def handler(event, _context): + '''Main Event Handler''' + for message_record in event['Records']: + records = json.loads(message_record['Sns']['Message']) + for record in records['Records']: + name = record['eventName'] + event_handler = EVENT_HANDLERS.get(name) + if event_handler is False: + return True + elif event_handler is None: + event_handler = debug_handler + try: + event_handler(record) + except Exception as ex: + LOG.error('Runtime exception occurred: %s', ex) + + return True |