-
Notifications
You must be signed in to change notification settings - Fork 0
/
cdk-codepipeline-github.ts
executable file
·137 lines (126 loc) · 3.81 KB
/
cdk-codepipeline-github.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { IStage, Pipeline } from '@aws-cdk/aws-codepipeline';
import { LambdaFunction } from '@aws-cdk/aws-events-targets';
import { PolicyStatement } from '@aws-cdk/aws-iam';
import { Code, Function, Runtime } from '@aws-cdk/aws-lambda';
import { Construct, Duration, SecretValue } from '@aws-cdk/core';
import { join } from 'path';
export interface ICdkCodepipelineGithubProps {
/**
* The Codepipeline stage publishing status events
*/
readonly stage?: IStage;
/**
* The Codepipeline publishing status events
*/
readonly pipeline?: Pipeline;
/**
* The arn of a secret in the Secrets Manager with
* a github token value.
*/
readonly gitHubSecretArn: string;
}
/**
* Publishes status events from a stage in Codepipeline
* to a Github repo using webhooks.
*
* SAM template conversion by Julia Jacobs
* {@see {@link https://github.com/jewelsjacobs}}
*
* SAM template created by Jens Eickmeyer
* {@see {@link https://github.com/jenseickmeyer/github-commit-status-bot}}
* {@see {@link https://scratchpad.blog/devops/howto/send-commit-status-from-codepipeline-to-github/}}
*
* @example <caption>Example usage of construct in pipeline.</caption>
* // One possible way to get an existing secret's arn - using AwsCustomResource
* // and AWS SecretsManager SDK
* const getGithubSecret = new AwsCustomResource(this, 'GetGithubSecret', {
* onUpdate: {
* service: 'SecretsManager',
* action: 'describeSecret',
* parameters: {
* SecretId: 'TOKENS/PIPELINE/GithubToken' // ID of secret
* }
* }
* });
* // ARN is a property in the describeSecret SDK response
* const gitHubSecretArn = `${getGithubSecret.getData("ARN")}` as string;
*
* // pipeline
* const pipeline = new codepipeline.Pipeline(this, 'Pipeline', {
* restartExecutionOnUpdate: true
* });
*
* // source stage
* pipeline.addStage({
* stageName: 'Source',
* actions: [sourceAction]
* });
*
* // build stage
* const buildStage = pipeline.addStage({
* stageName: 'Build',
* actions: [buildAction]
* });
*
* // Github status checks based on status of the build stage
* new CdkCodepipelineGithub(this, 'GithubCodepipeline', {
* stage: buildStage,
* gitHubSecretArn
* });
*
* // deploy stage
* pipeline.addStage({
* stageName: 'Deploy',
* actions: [deployAction]
* });
*
* // or check status of pipeline itself:
* new CdkCodepipelineGithub(this, 'GithubCodepipeline', {
* pipeline,
* gitHubSecretArn
* });
*/
export class CdkCodepipelineGithub extends Construct {
constructor(scope: Construct, id: string, props: ICdkCodepipelineGithubProps) {
super(scope, id);
const { stage, pipeline, gitHubSecretArn } = props;
const statusLambda = new Function(this, 'StatusLambda', {
code: Code.asset(join(__dirname, '..', 'lambda_packages', 'package.zip')),
environment: {
ACCESS_TOKEN: SecretValue.secretsManager(gitHubSecretArn).toString(), // github token passed to Lambda
},
handler: 'index.handler',
runtime: Runtime.NODEJS_10_X,
timeout: Duration.seconds(300),
});
const lambdaTarget = new LambdaFunction(statusLambda);
if (stage) {
stage.onStateChange('StageOnStateChange', lambdaTarget, {
eventPattern: {
detail: {
state: ['STARTED', 'SUCCEEDED', 'FAILED'],
},
},
});
}
if (pipeline) {
pipeline.onStateChange('StageOnStateChange', {
eventPattern: {
detail: {
state: ['STARTED', 'SUCCEEDED', 'FAILED'],
},
},
target: lambdaTarget,
});
}
if (!stage && !pipeline) {
throw Error('Choose a pipeline or stage to send event status messages from');
}
statusLambda.addToRolePolicy(
new PolicyStatement({
actions: ['*'],
resources: ['*'],
}),
);
}
}