Skip to content

Commit 85495b9

Browse files
feat(codepipeline): add filters for CodeStarSourceConnection action
This change deprecates the old filters and re-scopes adding them to the only action where they are valid. This also adds classes for simplifying the input of filters for all filter types
1 parent 5114955 commit 85495b9

File tree

9 files changed

+998
-291
lines changed

9 files changed

+998
-291
lines changed

packages/aws-cdk-lib/aws-codepipeline-actions/lib/codestar-connections/source-action.ts

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { Construct } from 'constructs';
2+
import { Trigger } from './trigger';
23
import * as codepipeline from '../../../aws-codepipeline';
34
import * as iam from '../../../aws-iam';
45
import { Action } from '../action';
56
import { sourceArtifactBounds } from '../common';
67

8+
const ACTION_PROVIDER = 'CodeStarSourceConnection';
9+
710
/**
811
* The CodePipeline variables emitted by CodeStar source Action.
912
*/
@@ -83,8 +86,23 @@ export interface CodeStarConnectionsSourceActionProps extends codepipeline.Commo
8386
*
8487
* @default true
8588
* @see https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodestarConnectionSource.html
89+
*
90+
* @deprecated - use `trigger` instead.
8691
*/
8792
readonly triggerOnPush?: boolean;
93+
94+
/**
95+
* The trigger configuration for this action.
96+
*
97+
* In a V1 pipeline, only `Trigger.ALL` or `Trigger.NONE` may be used.
98+
*
99+
* In a V2 pipeline, a trigger may have up to three of each type of filter
100+
* (Pull Request or Push) or may trigger on every change to the default branch
101+
* if no filters are provided.
102+
*
103+
* @default - The pipeline is triggered on all changes to the default branch.
104+
*/
105+
readonly trigger?: Trigger;
88106
}
89107

90108
/**
@@ -107,7 +125,7 @@ export class CodeStarConnectionsSourceAction extends Action {
107125
...props,
108126
category: codepipeline.ActionCategory.SOURCE,
109127
owner: 'AWS', // because props also has a (different!) owner property!
110-
provider: 'CodeStarSourceConnection',
128+
provider: ACTION_PROVIDER,
111129
artifactBounds: sourceArtifactBounds(),
112130
outputs: [props.output],
113131
});
@@ -158,8 +176,41 @@ export class CodeStarConnectionsSourceAction extends Action {
158176
OutputArtifactFormat: this.props.codeBuildCloneOutput === true
159177
? 'CODEBUILD_CLONE_REF'
160178
: undefined,
161-
DetectChanges: this.props.triggerOnPush,
179+
// For a v2 pipeline, if `trigger` is set this configuration property is disabled
180+
// and the trigger setting is used. For a v1 pipeline, `trigger` can still be used to
181+
// turn on/off `DetectChanges`.
182+
//
183+
// __attachActionToPipeline() will update this value so that it is handled correctly depending
184+
// on the pipeline version.
185+
DetectChanges: this.props.trigger ? this.renderDetectChanges(this.props.trigger) : this.props.triggerOnPush,
162186
},
163187
};
164188
}
189+
190+
private renderTriggerGitConfiguration(trigger: Trigger): codepipeline.CfnPipeline.PipelineTriggerDeclarationProperty {
191+
const providerType = ACTION_PROVIDER;
192+
const push: codepipeline.CfnPipeline.GitPushFilterProperty[] = trigger._filters.map((_filter) =>
193+
_filter._push).filter(item => item) as codepipeline.CfnPipeline.GitPushFilterProperty[];
194+
195+
const pullRequest: codepipeline.CfnPipeline.GitPullRequestFilterProperty[] = trigger._filters.map((_filter) =>
196+
_filter._pullRequest).filter(item => item) as codepipeline.CfnPipeline.GitPullRequestFilterProperty[];
197+
198+
return (push.length === 0 && pullRequest.length === 0) ? {
199+
providerType,
200+
} : {
201+
providerType,
202+
gitConfiguration: {
203+
push: push.length > 0 ? push : undefined,
204+
pullRequest: pullRequest.length > 0 ? pullRequest : undefined,
205+
sourceActionName: this.actionProperties.actionName,
206+
},
207+
};
208+
}
209+
210+
private renderDetectChanges(trigger: Trigger): boolean | codepipeline.CfnPipeline.PipelineTriggerDeclarationProperty {
211+
// No trigger or change detection
212+
if (!trigger._enabled) return false;
213+
214+
return this.renderTriggerGitConfiguration(trigger);
215+
}
165216
}
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
import { CfnPipeline } from '../../../aws-codepipeline/lib';
2+
3+
/**
4+
* The patterns used for filtering criteria.
5+
*/
6+
export interface FilterPattern {
7+
/**
8+
* The excludes patterns to use. If any pattern are included in both includes and excludes,
9+
* excludes take precedence.
10+
*
11+
* @default - No patterns are excluded in this filter.
12+
*/
13+
readonly excludes?: string[];
14+
15+
/**
16+
* The includes patterns to use. If any pattern are included in both includes and excludes,
17+
* excludes take precedence.
18+
*
19+
* @default - No patterns are included in this filter.
20+
*/
21+
readonly includes?: string[];
22+
}
23+
24+
/**
25+
* Filtering options for filtering on a branch.
26+
*/
27+
export interface BranchFilterOptions {
28+
/**
29+
* The list of branches to filter on.
30+
*/
31+
readonly branches: FilterPattern;
32+
/**
33+
* The list of filepaths to filter on.
34+
*
35+
* @default - No filtering for filepaths.
36+
*/
37+
readonly filePaths?: FilterPattern;
38+
}
39+
40+
/**
41+
* Filtering options for pull requests
42+
*/
43+
export interface PullRequestFilterOptions extends BranchFilterOptions { }
44+
45+
/**
46+
* Filtering options for filtering on a tag,
47+
*/
48+
export interface TagFilterOptions extends FilterPattern { }
49+
50+
enum Events {
51+
OPENED = 'OPENED',
52+
UPDATED = 'UPDATED',
53+
CLOSED = 'CLOSED',
54+
};
55+
56+
/**
57+
* Adds a filter to the trigger.
58+
*/
59+
export class Filter {
60+
/**
61+
* Triggers on all pull request events. These include: OPENED, UPDATED, and CLOSED.
62+
* @param filter The filters to use to limit which pull requests are included in the trigger
63+
*/
64+
public static pullRequestEvents(filter: PullRequestFilterOptions) {
65+
return Filter._pullRequest([Events.OPENED, Events.UPDATED, Events.CLOSED], filter);
66+
}
67+
68+
/**
69+
* Triggers on OPENED pull request events.
70+
* @param filter The filters to use to limit which pull requests are included in the trigger
71+
*/
72+
public static pullRequestOpened(filter: PullRequestFilterOptions) {
73+
return Filter._pullRequest([Events.OPENED], filter);
74+
}
75+
76+
/**
77+
* Triggers on UPDATED pull request events.
78+
* @param filter The filters to use to limit which pull requests are included in the trigger
79+
*/
80+
public static pullRequestUpdated(filter: PullRequestFilterOptions) {
81+
return Filter._pullRequest([Events.UPDATED], filter);
82+
}
83+
84+
/**
85+
* Triggers on CLOSED pull request events.
86+
* @param filter The filters to use to limit which pull requests are included in the trigger
87+
*/
88+
public static pullRequestClosed(filter: PullRequestFilterOptions) {
89+
return Filter._pullRequest([Events.CLOSED], filter);
90+
}
91+
92+
/**
93+
* Triggers on OPENED or UPDATED pull request events.
94+
* @param filter The filters to use to limit which pull requests are included in the trigger
95+
*/
96+
public static pullRequestOpenedOrUpdated(filter: PullRequestFilterOptions) {
97+
return Filter._pullRequest([Events.OPENED, Events.UPDATED], filter);
98+
}
99+
100+
/**
101+
* Triggers on OPENED or CLOSED pull request events.
102+
* @param filter The filters to use to limit which pull requests are included in the trigger
103+
*/
104+
public static pullRequestOpenedOrClosed(filter: PullRequestFilterOptions) {
105+
return Filter._pullRequest([Events.OPENED, Events.CLOSED], filter);
106+
}
107+
108+
/**
109+
* Triggers on UPDATED or CLOSED pull request events.
110+
* @param filter The filters to use to limit which pull requests are included in the trigger
111+
*/
112+
public static pullRequestUpdatedOrClosed(filter: PullRequestFilterOptions) {
113+
return Filter._pullRequest([Events.UPDATED, Events.CLOSED], filter);
114+
}
115+
116+
/**
117+
* Trigger on push events.
118+
* @param filter The filters to use to limit which push events are included in the trigger
119+
*/
120+
public static push(filter: PushFilter) {
121+
return new Filter(undefined, { tags: filter._tags, branches: filter._branches, filePaths: filter._filePaths });
122+
}
123+
124+
private static _pullRequest(events: Events[], filter: PullRequestFilterOptions) {
125+
mustContainValue('Functions filtering on a pull request', filter.branches, ' on the \'branches\' field');
126+
return new Filter({ events, branches: filter.branches, filePaths: filter.filePaths }, undefined);
127+
}
128+
129+
/**
130+
* @internal
131+
*/
132+
public readonly _pullRequest?: CfnPipeline.GitPullRequestFilterProperty;
133+
134+
/**
135+
* @internal
136+
*/
137+
public readonly _push?: CfnPipeline.GitPushFilterProperty;
138+
139+
constructor(
140+
pullRequest?: CfnPipeline.GitPullRequestFilterProperty,
141+
push?: CfnPipeline.GitPushFilterProperty,
142+
) {
143+
this._pullRequest = pullRequest;
144+
this._push = push;
145+
}
146+
}
147+
148+
/**
149+
* Represents a CodePipeline V2 Pipeline trigger. Each trigger may include filters to limit the
150+
* circumstances in which the pipeline will trigger.
151+
*/
152+
export class Trigger {
153+
/**
154+
* Trigger on all code pushes to the default branch.
155+
*/
156+
public static readonly ENABLED = new Trigger(true);
157+
158+
/**
159+
* Disables triggers for the pipeline.
160+
*/
161+
public static readonly DISABLED = new Trigger(false);
162+
163+
/**
164+
* Enables a trigger for the pipeline, filtering for specific events.
165+
* Requires at least one filter.
166+
* @param filters Additional filters for this trigger
167+
*/
168+
public static withFilters(filter: Filter, ...filters: Filter[]) {
169+
const trigger = new Trigger(true);
170+
trigger._filters.push(filter, ...filters);
171+
return trigger;
172+
}
173+
174+
/**
175+
* @internal
176+
*/
177+
public _filters: Filter[] = [];
178+
179+
/**
180+
* @internal
181+
*/
182+
public _enabled: boolean;
183+
184+
constructor(enabled: boolean) {
185+
this._enabled = enabled;
186+
}
187+
}
188+
189+
/**
190+
* Filters specific to push triggers.
191+
*/
192+
export class PushFilter {
193+
/**
194+
* Filter on tags
195+
* @param options The filtering options for tags
196+
*/
197+
public static onTags(options: TagFilterOptions) {
198+
mustContainValue('PushFilter.onTags()', options);
199+
return new PushFilter(options);
200+
}
201+
202+
/**
203+
* Filter on branches
204+
* @param options The filtering options for branches
205+
*/
206+
public static onBranches(options: BranchFilterOptions) {
207+
mustContainValue('PushFilter.onBranches()', options.branches, ' on the \'branches\' field');
208+
return new PushFilter(undefined, options.branches, options.filePaths);
209+
}
210+
211+
/**
212+
* @internal
213+
*/
214+
public readonly _tags?: CfnPipeline.GitTagFilterCriteriaProperty;
215+
216+
/**
217+
* @internal
218+
*/
219+
public readonly _branches?: CfnPipeline.GitBranchFilterCriteriaProperty;
220+
221+
/**
222+
* @internal
223+
*/
224+
public readonly _filePaths?: CfnPipeline.GitFilePathFilterCriteriaProperty;
225+
226+
constructor(
227+
tags?: CfnPipeline.GitTagFilterCriteriaProperty,
228+
branches?: CfnPipeline.GitBranchFilterCriteriaProperty,
229+
filePaths?: CfnPipeline.GitFilePathFilterCriteriaProperty,
230+
) {
231+
this._tags = maybeUndefined(tags);
232+
this._branches = maybeUndefined(branches);
233+
this._filePaths = maybeUndefined(filePaths);
234+
}
235+
}
236+
237+
function maybeUndefined(input?: FilterPattern) {
238+
return (input?.excludes || input?.includes) ?
239+
(input?.excludes?.length == 0 && input.includes?.length == 0 ? undefined : input) :
240+
undefined;
241+
}
242+
243+
function mustContainValue(type: string, input?: FilterPattern, additionalDetails?: string) {
244+
if (!maybeUndefined(input)) {
245+
throw new Error(`${type} must contain at least one 'includes' or 'excludes' pattern${additionalDetails ?? ''}.`);
246+
}
247+
}

packages/aws-cdk-lib/aws-codepipeline-actions/lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from './alexa-ask/deploy-action';
22
export * from './bitbucket/source-action';
33
export * from './codestar-connections/source-action';
4+
export * from './codestar-connections/trigger';
45
export * from './cloudformation';
56
export * from './codebuild/build-action';
67
export * from './codecommit/source-action';

0 commit comments

Comments
 (0)