Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(codepipeline): GitPullRequestFilter for pipeline trigger #29128

Merged
merged 22 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 138 additions & 2 deletions packages/aws-cdk-lib/aws-codepipeline/lib/trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,91 @@ export interface GitPushFilter {
readonly tagsIncludes?: string[];
}

/**
* Git pull request filter for trigger.
*/
export interface GitPullRequestFilter {
/**
* The list of patterns of Git branches that, when pull request events occurs, are
* to be excluded from starting the pipeline.
*
* You can filter with glob patterns. The `branchesExcludes` takes priority
* over the `branchesIncludes`.
*
* Maximum length of this array is 8.
*
* @default - no branches.
*/
readonly branchesExcludes?: string[];

/**
* The list of patterns of Git branches that, when pull request events occurs, are
* to be included as criteria that starts the pipeline.
*
* You can filter with glob patterns. The `branchesExcludes` takes priority
* over the `branchesIncludes`.
*
* Maximum length of this array is 8.
*
* @default - no branches.
*/
readonly branchesIncludes?: string[];

/**
* The list of patterns of Git repository file paths that, when pull request events occurs,
* are to be excluded from starting the pipeline.
*
* You can filter with glob patterns. The `filePathsExcludes` takes priority
* over the `filePathsIncludes`.
*
* Maximum length of this array is 8.
*
* @default - no filePaths.
*/
readonly filePathsExcludes?: string[];

/**
* The list of patterns of Git repository file paths that, when pull request events occurs,
* are to be included as criteria that starts the pipeline.
*
* You can filter with glob patterns. The `filePathsExcludes` takes priority
* over the `filePathsIncludes`.
*
* Maximum length of this array is 8.
*
* @default - no filePaths.
*/
readonly filePathsIncludes?: string[];

/**
* The field that specifies which pull request events to filter on (opened, updated, closed)
* for the trigger configuration.
*
* Maximum length of this array is 3.
*
* @default - no events.
*/
readonly events?: GitPullRequestEvent[];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please verify if specifying duplicate events is allowed?
Eg, [GitPullRequestEvent.OPEN, GitPullRequestEvent.OPEN]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

/**
* Event for trigger with pull request filter.
*/
export enum GitPullRequestEvent {
/**
* OPEN
*/
OPEN = 'OPEN',
go-to-k marked this conversation as resolved.
Show resolved Hide resolved
/**
* UPDATED
*/
UPDATED = 'UPDATED',
/**
* CLOSED
*/
CLOSED = 'CLOSED',
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


/**
* Git configuration for trigger.
*/
Expand All @@ -58,6 +143,16 @@ export interface GitConfiguration {
* @default - no filter.
*/
readonly pushFilter?: GitPushFilter[];

/**
* The field where the repository event that will start the pipeline
* is specified as pull requests.
*
* The length must be less than or equal to 3.
*
* @default - no filter.
*/
readonly pullRequestFilter?: GitPullRequestFilter[];
}

/**
Expand Down Expand Up @@ -117,10 +212,33 @@ export class Trigger {

pushFilter?.forEach(filter => {
if (filter.tagsExcludes && filter.tagsExcludes.length > 8) {
throw new Error(`maximum length of tagsExcludes for sourceAction with name '${sourceAction.actionProperties.actionName}' is 8, got ${filter.tagsExcludes.length}`);
throw new Error(`maximum length of tagsExcludes in pushFilter for sourceAction with name '${sourceAction.actionProperties.actionName}' is 8, got ${filter.tagsExcludes.length}`);
}
if (filter.tagsIncludes && filter.tagsIncludes.length > 8) {
throw new Error(`maximum length of tagsIncludes for sourceAction with name '${sourceAction.actionProperties.actionName}' is 8, got ${filter.tagsIncludes.length}`);
throw new Error(`maximum length of tagsIncludes in pushFilter for sourceAction with name '${sourceAction.actionProperties.actionName}' is 8, got ${filter.tagsIncludes.length}`);
}
});

const pullRequestFilter = this.props.gitConfiguration.pullRequestFilter;
if (pullRequestFilter !== undefined && pullRequestFilter.length > 3) {
throw new Error(`length of pullRequestFilter for sourceAction with name '${sourceAction.actionProperties.actionName}' must be less than or equal to 3, got ${pullRequestFilter.length}`);
}

pullRequestFilter?.forEach(filter => {
if (filter.branchesExcludes && filter.branchesExcludes.length > 8) {
throw new Error(`maximum length of branchesExcludes in pullRequestFilter for sourceAction with name '${sourceAction.actionProperties.actionName}' is 8, got ${filter.branchesExcludes.length}`);
}
if (filter.branchesIncludes && filter.branchesIncludes.length > 8) {
throw new Error(`maximum length of branchesIncludes in pullRequestFilter for sourceAction with name '${sourceAction.actionProperties.actionName}' is 8, got ${filter.branchesIncludes.length}`);
}
if (filter.filePathsExcludes && filter.filePathsExcludes.length > 8) {
throw new Error(`maximum length of filePathsExcludes in pullRequestFilter for sourceAction with name '${sourceAction.actionProperties.actionName}' is 8, got ${filter.filePathsExcludes.length}`);
}
if (filter.filePathsIncludes && filter.filePathsIncludes.length > 8) {
throw new Error(`maximum length of filePathsIncludes in pullRequestFilter for sourceAction with name '${sourceAction.actionProperties.actionName}' is 8, got ${filter.filePathsIncludes.length}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're missing validation for filter.events to contain 1 to 3 items if specified.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If none are included, all events are automatically set. Also, any duplicates will be eliminated.
So I don't think validation is necessary. What do you think?

https://github.com/go-to-k/aws-cdk/blob/7891faa1ae26b91e01f14b87ab4b8a783f4b0ee5/packages/aws-cdk-lib/aws-codepipeline/lib/trigger.ts#L284

}
if (filter.events && filter.events.length > 3) {
throw new Error(`maximum length of events in pullRequestFilter for sourceAction with name '${sourceAction.actionProperties.actionName}' is 3, got ${filter.events.length}`);
}
});
}
Expand All @@ -136,6 +254,7 @@ export class Trigger {
if (this.props.gitConfiguration) {
const sourceAction = this.props.gitConfiguration.sourceAction;
const pushFilter = this.props.gitConfiguration.pushFilter;
const pullRequestFilter = this.props.gitConfiguration.pullRequestFilter;
go-to-k marked this conversation as resolved.
Show resolved Hide resolved

const push: CfnPipeline.GitPushFilterProperty[] | undefined = pushFilter?.map(filter => {
const tags: CfnPipeline.GitTagFilterCriteriaProperty | undefined = {
Expand All @@ -145,10 +264,27 @@ export class Trigger {
};
return { tags };
});
const pullRequest: CfnPipeline.GitPullRequestFilterProperty[] | undefined = pullRequestFilter?.map(filter => {
go-to-k marked this conversation as resolved.
Show resolved Hide resolved
const branches: CfnPipeline.GitBranchFilterCriteriaProperty | undefined = {
// set to undefined if empty array because CloudFormation does not accept empty array
excludes: filter.branchesExcludes?.length ? filter.branchesExcludes : undefined,
includes: filter.branchesIncludes?.length ? filter.branchesIncludes : undefined,
};
const filePaths: CfnPipeline.GitFilePathFilterCriteriaProperty | undefined = {
// set to undefined if empty array because CloudFormation does not accept empty array
excludes: filter.filePathsExcludes?.length ? filter.filePathsExcludes : undefined,
includes: filter.filePathsIncludes?.length ? filter.filePathsIncludes : undefined,
};
// set to undefined if empty array because CloudFormation does not accept empty array
const events: string[] | undefined = filter.events?.length ? filter.events : undefined;
return { branches, filePaths, events };
});

gitConfiguration = {
// set to undefined if empty array because CloudFormation does not accept empty array
push: push?.length ? push : undefined,
// set to undefined if empty array because CloudFormation does not accept empty array
pullRequest: pullRequest?.length ? pullRequest : undefined,
sourceActionName: sourceAction.actionProperties.actionName,
};
}
Expand Down
4 changes: 2 additions & 2 deletions packages/aws-cdk-lib/aws-codepipeline/test/triggers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ describe('triggers', () => {
},
}],
});
}).toThrow(/maximum length of tagsExcludes for sourceAction with name 'CodeStarConnectionsSourceAction' is 8, got 9/);
}).toThrow(/maximum length of tagsExcludes in pushFilter for sourceAction with name 'CodeStarConnectionsSourceAction' is 8, got 9/);
});

test('throw if length of excludes is greater than 8', () => {
Expand All @@ -265,7 +265,7 @@ describe('triggers', () => {
},
}],
});
}).toThrow(/maximum length of tagsIncludes for sourceAction with name 'CodeStarConnectionsSourceAction' is 8, got 9/);
}).toThrow(/maximum length of tagsIncludes in pushFilter for sourceAction with name 'CodeStarConnectionsSourceAction' is 8, got 9/);
});

test('empty pushFilter for trigger is set to undefined', () => {
Expand Down
Loading