UNPKG

15.7 kBMarkdownView Raw
1# AWS CodePipeline Construct Library
2<!--BEGIN STABILITY BANNER-->
3
4---
5
6![End-of-Support](https://img.shields.io/badge/End--of--Support-critical.svg?style=for-the-badge)
7
8> AWS CDK v1 has reached End-of-Support on 2023-06-01.
9> This package is no longer being updated, and users should migrate to AWS CDK v2.
10>
11> For more information on how to migrate, see the [_Migrating to AWS CDK v2_ guide][doc].
12>
13> [doc]: https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html
14
15---
16
17<!--END STABILITY BANNER-->
18
19## Pipeline
20
21To construct an empty Pipeline:
22
23```ts
24// Construct an empty Pipeline
25const pipeline = new codepipeline.Pipeline(this, 'MyFirstPipeline');
26```
27
28To give the Pipeline a nice, human-readable name:
29
30```ts
31// Give the Pipeline a nice, human-readable name
32const pipeline = new codepipeline.Pipeline(this, 'MyFirstPipeline', {
33 pipelineName: 'MyPipeline',
34});
35```
36
37Be aware that in the default configuration, the `Pipeline` construct creates
38an AWS Key Management Service (AWS KMS) Customer Master Key (CMK) for you to
39encrypt the artifacts in the artifact bucket, which incurs a cost of
40**$1/month**. This default configuration is necessary to allow cross-account
41actions.
42
43If you do not intend to perform cross-account deployments, you can disable
44the creation of the Customer Master Keys by passing `crossAccountKeys: false`
45when defining the Pipeline:
46
47```ts
48// Don't create Customer Master Keys
49const pipeline = new codepipeline.Pipeline(this, 'MyFirstPipeline', {
50 crossAccountKeys: false,
51});
52```
53
54If you want to enable key rotation for the generated KMS keys,
55you can configure it by passing `enableKeyRotation: true` when creating the pipeline.
56Note that key rotation will incur an additional cost of **$1/month**.
57
58```ts
59// Enable key rotation for the generated KMS key
60const pipeline = new codepipeline.Pipeline(this, 'MyFirstPipeline', {
61 // ...
62 enableKeyRotation: true,
63});
64```
65
66## Stages
67
68You can provide Stages when creating the Pipeline:
69
70```ts
71// Provide a Stage when creating a pipeline
72const pipeline = new codepipeline.Pipeline(this, 'MyFirstPipeline', {
73 stages: [
74 {
75 stageName: 'Source',
76 actions: [
77 // see below...
78 ],
79 },
80 ],
81});
82```
83
84Or append a Stage to an existing Pipeline:
85
86```ts
87// Append a Stage to an existing Pipeline
88declare const pipeline: codepipeline.Pipeline;
89const sourceStage = pipeline.addStage({
90 stageName: 'Source',
91 actions: [ // optional property
92 // see below...
93 ],
94});
95```
96
97You can insert the new Stage at an arbitrary point in the Pipeline:
98
99```ts
100// Insert a new Stage at an arbitrary point
101declare const pipeline: codepipeline.Pipeline;
102declare const anotherStage: codepipeline.IStage;
103declare const yetAnotherStage: codepipeline.IStage;
104
105const someStage = pipeline.addStage({
106 stageName: 'SomeStage',
107 placement: {
108 // note: you can only specify one of the below properties
109 rightBefore: anotherStage,
110 justAfter: yetAnotherStage,
111 }
112});
113```
114
115You can disable transition to a Stage:
116
117```ts
118// Disable transition to a stage
119declare const pipeline: codepipeline.Pipeline;
120
121const someStage = pipeline.addStage({
122 stageName: 'SomeStage',
123 transitionToEnabled: false,
124 transitionDisabledReason: 'Manual transition only', // optional reason
125})
126```
127
128This is useful if you don't want every executions of the pipeline to flow into
129this stage automatically. The transition can then be "manually" enabled later on.
130
131## Actions
132
133Actions live in a separate package, `@aws-cdk/aws-codepipeline-actions`.
134
135To add an Action to a Stage, you can provide it when creating the Stage,
136in the `actions` property,
137or you can use the `IStage.addAction()` method to mutate an existing Stage:
138
139```ts
140// Use the `IStage.addAction()` method to mutate an existing Stage.
141declare const sourceStage: codepipeline.IStage;
142declare const someAction: codepipeline.Action;
143sourceStage.addAction(someAction);
144```
145
146## Custom Action Registration
147
148To make your own custom CodePipeline Action requires registering the action provider. Look to the `JenkinsProvider` in `@aws-cdk/aws-codepipeline-actions` for an implementation example.
149
150```ts
151// Make a custom CodePipeline Action
152new codepipeline.CustomActionRegistration(this, 'GenericGitSourceProviderResource', {
153 category: codepipeline.ActionCategory.SOURCE,
154 artifactBounds: { minInputs: 0, maxInputs: 0, minOutputs: 1, maxOutputs: 1 },
155 provider: 'GenericGitSource',
156 version: '1',
157 entityUrl: 'https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-create-custom-action.html',
158 executionUrl: 'https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-create-custom-action.html',
159 actionProperties: [
160 {
161 name: 'Branch',
162 required: true,
163 key: false,
164 secret: false,
165 queryable: false,
166 description: 'Git branch to pull',
167 type: 'String',
168 },
169 {
170 name: 'GitUrl',
171 required: true,
172 key: false,
173 secret: false,
174 queryable: false,
175 description: 'SSH git clone URL',
176 type: 'String',
177 },
178 ],
179});
180```
181
182## Cross-account CodePipelines
183
184> Cross-account Pipeline actions require that the Pipeline has *not* been
185> created with `crossAccountKeys: false`.
186
187Most pipeline Actions accept an AWS resource object to operate on. For example:
188
189* `S3DeployAction` accepts an `s3.IBucket`.
190* `CodeBuildAction` accepts a `codebuild.IProject`.
191* etc.
192
193These resources can be either newly defined (`new s3.Bucket(...)`) or imported
194(`s3.Bucket.fromBucketAttributes(...)`) and identify the resource that should
195be changed.
196
197These resources can be in different accounts than the pipeline itself. For
198example, the following action deploys to an imported S3 bucket from a
199different account:
200
201```ts
202// Deploy an imported S3 bucket from a different account
203declare const stage: codepipeline.IStage;
204declare const input: codepipeline.Artifact;
205stage.addAction(new codepipeline_actions.S3DeployAction({
206 bucket: s3.Bucket.fromBucketAttributes(this, 'Bucket', {
207 account: '123456789012',
208 // ...
209 }),
210 input: input,
211 actionName: 's3-deploy-action',
212 // ...
213}));
214```
215
216Actions that don't accept a resource object accept an explicit `account` parameter:
217
218```ts
219// Actions that don't accept a resource objet accept an explicit `account` parameter
220declare const stage: codepipeline.IStage;
221declare const templatePath: codepipeline.ArtifactPath;
222stage.addAction(new codepipeline_actions.CloudFormationCreateUpdateStackAction({
223 account: '123456789012',
224 templatePath,
225 adminPermissions: false,
226 stackName: Stack.of(this).stackName,
227 actionName: 'cloudformation-create-update',
228 // ...
229}));
230```
231
232The `Pipeline` construct automatically defines an **IAM Role** for you in the
233target account which the pipeline will assume to perform that action. This
234Role will be defined in a **support stack** named
235`<PipelineStackName>-support-<account>`, that will automatically be deployed
236before the stack containing the pipeline.
237
238If you do not want to use the generated role, you can also explicitly pass a
239`role` when creating the action. In that case, the action will operate in the
240account the role belongs to:
241
242```ts
243// Explicitly pass in a `role` when creating an action.
244declare const stage: codepipeline.IStage;
245declare const templatePath: codepipeline.ArtifactPath;
246stage.addAction(new codepipeline_actions.CloudFormationCreateUpdateStackAction({
247 templatePath,
248 adminPermissions: false,
249 stackName: Stack.of(this).stackName,
250 actionName: 'cloudformation-create-update',
251 // ...
252 role: iam.Role.fromRoleArn(this, 'ActionRole', '...'),
253}));
254```
255
256## Cross-region CodePipelines
257
258Similar to how you set up a cross-account Action, the AWS resource object you
259pass to actions can also be in different *Regions*. For example, the
260following Action deploys to an imported S3 bucket from a different Region:
261
262```ts
263// Deploy to an imported S3 bucket from a different Region.
264declare const stage: codepipeline.IStage;
265declare const input: codepipeline.Artifact;
266stage.addAction(new codepipeline_actions.S3DeployAction({
267 bucket: s3.Bucket.fromBucketAttributes(this, 'Bucket', {
268 region: 'us-west-1',
269 // ...
270 }),
271 input: input,
272 actionName: 's3-deploy-action',
273 // ...
274}));
275```
276
277Actions that don't take an AWS resource will accept an explicit `region`
278parameter:
279
280```ts
281// Actions that don't take an AWS resource will accept an explicit `region` parameter.
282declare const stage: codepipeline.IStage;
283declare const templatePath: codepipeline.ArtifactPath;
284stage.addAction(new codepipeline_actions.CloudFormationCreateUpdateStackAction({
285 templatePath,
286 adminPermissions: false,
287 stackName: Stack.of(this).stackName,
288 actionName: 'cloudformation-create-update',
289 // ...
290 region: 'us-west-1',
291}));
292```
293
294The `Pipeline` construct automatically defines a **replication bucket** for
295you in the target region, which the pipeline will replicate artifacts to and
296from. This Bucket will be defined in a **support stack** named
297`<PipelineStackName>-support-<region>`, that will automatically be deployed
298before the stack containing the pipeline.
299
300If you don't want to use these support stacks, and already have buckets in
301place to serve as replication buckets, you can supply these at Pipeline definition
302time using the `crossRegionReplicationBuckets` parameter. Example:
303
304```ts
305// Supply replication buckets for the Pipeline instead of using the generated support stack
306const pipeline = new codepipeline.Pipeline(this, 'MyFirstPipeline', {
307 // ...
308
309 crossRegionReplicationBuckets: {
310 // note that a physical name of the replication Bucket must be known at synthesis time
311 'us-west-1': s3.Bucket.fromBucketAttributes(this, 'UsWest1ReplicationBucket', {
312 bucketName: 'my-us-west-1-replication-bucket',
313 // optional KMS key
314 encryptionKey: kms.Key.fromKeyArn(this, 'UsWest1ReplicationKey',
315 'arn:aws:kms:us-west-1:123456789012:key/1234-5678-9012'
316 ),
317 }),
318 },
319});
320```
321
322See [the AWS docs here](https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-create-cross-region.html)
323for more information on cross-region CodePipelines.
324
325### Creating an encrypted replication bucket
326
327If you're passing a replication bucket created in a different stack,
328like this:
329
330```ts
331// Passing a replication bucket created in a different stack.
332const app = new App();
333const replicationStack = new Stack(app, 'ReplicationStack', {
334 env: {
335 region: 'us-west-1',
336 },
337});
338const key = new kms.Key(replicationStack, 'ReplicationKey');
339const replicationBucket = new s3.Bucket(replicationStack, 'ReplicationBucket', {
340 // like was said above - replication buckets need a set physical name
341 bucketName: PhysicalName.GENERATE_IF_NEEDED,
342 encryptionKey: key, // does not work!
343});
344
345// later...
346new codepipeline.Pipeline(replicationStack, 'Pipeline', {
347 crossRegionReplicationBuckets: {
348 'us-west-1': replicationBucket,
349 },
350});
351```
352
353When trying to encrypt it
354(and note that if any of the cross-region actions happen to be cross-account as well,
355the bucket *has to* be encrypted - otherwise the pipeline will fail at runtime),
356you cannot use a key directly - KMS keys don't have physical names,
357and so you can't reference them across environments.
358
359In this case, you need to use an alias in place of the key when creating the bucket:
360
361```ts
362// Passing an encrypted replication bucket created in a different stack.
363const app = new App();
364const replicationStack = new Stack(app, 'ReplicationStack', {
365 env: {
366 region: 'us-west-1',
367 },
368});
369const key = new kms.Key(replicationStack, 'ReplicationKey');
370const alias = new kms.Alias(replicationStack, 'ReplicationAlias', {
371 // aliasName is required
372 aliasName: PhysicalName.GENERATE_IF_NEEDED,
373 targetKey: key,
374});
375const replicationBucket = new s3.Bucket(replicationStack, 'ReplicationBucket', {
376 bucketName: PhysicalName.GENERATE_IF_NEEDED,
377 encryptionKey: alias,
378});
379```
380
381## Variables
382
383The library supports the CodePipeline Variables feature.
384Each action class that emits variables has a separate variables interface,
385accessed as a property of the action instance called `variables`.
386You instantiate the action class and assign it to a local variable;
387when you want to use a variable in the configuration of a different action,
388you access the appropriate property of the interface returned from `variables`,
389which represents a single variable.
390Example:
391
392```ts fixture=action
393// MyAction is some action type that produces variables, like EcrSourceAction
394const myAction = new MyAction({
395 // ...
396 actionName: 'myAction',
397});
398new OtherAction({
399 // ...
400 config: myAction.variables.myVariable,
401 actionName: 'otherAction',
402});
403```
404
405The namespace name that will be used will be automatically generated by the pipeline construct,
406based on the stage and action name;
407you can pass a custom name when creating the action instance:
408
409```ts fixture=action
410// MyAction is some action type that produces variables, like EcrSourceAction
411const myAction = new MyAction({
412 // ...
413 variablesNamespace: 'MyNamespace',
414 actionName: 'myAction',
415});
416```
417
418There are also global variables available,
419not tied to any action;
420these are accessed through static properties of the `GlobalVariables` class:
421
422```ts fixture=action
423// OtherAction is some action type that produces variables, like EcrSourceAction
424new OtherAction({
425 // ...
426 config: codepipeline.GlobalVariables.executionId,
427 actionName: 'otherAction',
428});
429```
430
431Check the documentation of the `@aws-cdk/aws-codepipeline-actions`
432for details on how to use the variables for each action class.
433
434See the [CodePipeline documentation](https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-variables.html)
435for more details on how to use the variables feature.
436
437## Events
438
439### Using a pipeline as an event target
440
441A pipeline can be used as a target for a CloudWatch event rule:
442
443```ts
444// A pipeline being used as a target for a CloudWatch event rule.
445import * as targets from '@aws-cdk/aws-events-targets';
446import * as events from '@aws-cdk/aws-events';
447
448// kick off the pipeline every day
449const rule = new events.Rule(this, 'Daily', {
450 schedule: events.Schedule.rate(Duration.days(1)),
451});
452
453declare const pipeline: codepipeline.Pipeline;
454rule.addTarget(new targets.CodePipeline(pipeline));
455```
456
457When a pipeline is used as an event target, the
458"codepipeline:StartPipelineExecution" permission is granted to the AWS
459CloudWatch Events service.
460
461### Event sources
462
463Pipelines emit CloudWatch events. To define event rules for events emitted by
464the pipeline, stages or action, use the `onXxx` methods on the respective
465construct:
466
467```ts
468// Define event rules for events emitted by the pipeline
469import * as events from '@aws-cdk/aws-events';
470
471declare const myPipeline: codepipeline.Pipeline;
472declare const myStage: codepipeline.IStage;
473declare const myAction: codepipeline.Action;
474declare const target: events.IRuleTarget;
475myPipeline.onStateChange('MyPipelineStateChange', { target: target } );
476myStage.onStateChange('MyStageStateChange', target);
477myAction.onStateChange('MyActionStateChange', target);
478```
479
480## CodeStar Notifications
481
482To define CodeStar Notification rules for Pipelines, use one of the `notifyOnXxx()` methods.
483They are very similar to `onXxx()` methods for CloudWatch events:
484
485```ts
486// Define CodeStar Notification rules for Pipelines
487import * as chatbot from '@aws-cdk/aws-chatbot';
488const target = new chatbot.SlackChannelConfiguration(this, 'MySlackChannel', {
489 slackChannelConfigurationName: 'YOUR_CHANNEL_NAME',
490 slackWorkspaceId: 'YOUR_SLACK_WORKSPACE_ID',
491 slackChannelId: 'YOUR_SLACK_CHANNEL_ID',
492});
493
494declare const pipeline: codepipeline.Pipeline;
495const rule = pipeline.notifyOnExecutionStateChange('NotifyOnExecutionStateChange', target);
496```