aws-codepipeline-actions: CodeStarConnectionsSourceAction.variables inaccurate
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
If you try to use `CodeStarConnectionsSourceAction.variables.branchName` on an execution triggered by a pull request, your build will fail with:
> An action in this pipeline failed because one or more variables could not be resolved: Action name=XYZ. This can result when a variable is referenced that does not exist. Validate the configuration for this action.
### Detail
#5604 added a `.variables` getter to a number of `codepipeline.Action` subclasses including `CodeStarConnectionsSourceAction`. It's hardcoded to return a particular set of variables, and seems to be the only public way to get at the action's variables.
https://github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-codepipeline-actions/lib/codestar-connections/source-action.ts#L119-L128
These variables are correct in some cases, but aren't correct if the execution was triggered by a pull request (see screenshots below.)
With a `pullRequestFilter` in place, `BranchName` will be unavailable, but four additional variables will be set: `DestinationBranchName`, `PullRequestId`, `PullRequestTitle`, `SourceBranchName`. There's no good way to get at these right now.
### Expected Behavior
One of the below:
a. `variables` should return the variables that the source action actually exports (likely impossible to implement at CDK level.)
b. `variables` should return only variables that are always safe to use. I'm not sure if there's a public spec indicating what variables are returned under what circumstances. But `BranchName` is not always defined by the source action and therefore isn't safe to us.
More importantly, since the CDK doesn't/can't know what the possible variables are, I'd expect the underlying `variableExpression(variableName: string)` should be publicly accessible, like it is on some of the other actions:
https://github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-codepipeline-actions/lib/codebuild/build-action.ts#L145-L147
https://github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-codepipeline/lib/action.ts#L428-L431
### Current Behavior
The cdk-provided `variables` getter misses some variables and returns others that may not exist. It doesn't provide any way to get at the missing ones.
For missed variables, a workaround is to call the protected `variableExpression` method via `action["variableExpression"]("DestinationBranchName")` or similar.
For returned variables that don't exist (`BranchName`), workaround is not to use it.
### Reproduction Steps
Below is a construct that will reproduce the issue. Unfortunately, due to the way CodePipeline works, the minimal reproduction is not especially concise.
To use it, you'll need a CDK stack with a VPC and a CodeConnection to a git repo (I used a Github repo.)
Once you've got the stack deployed, open a pull request in the repo. It should trigger an execution. The `UsesBranchName` build action will fail, because the source action doesn't export the `BranchName` variable.
Now try manually triggering a execution with the "Release Change" button in the console. Here, the `UsesBranchName` build action will succeed, but the `UsesDestinationBranchName` will fail, because the `DestinationBranchName` won't have been defined (this will also happen when the pipeline is first created.)
Reproduction: https://gist.github.com/dleavitt/7950f5073bb0ebe2f3fa5049a2f44ab8
### Possible Solution
1. Add a public `variable(variableName: string): string` method to `CodeStarConnectionsSourceAction`, with the same implementation like this:
https://github.com/aws/aws-cdk/blob/9295a85a8fb893d7f5eae06108b68df864096c4c/packages/aws-cdk-lib/aws-codepipeline-actions/lib/codebuild/build-action.ts#L145-L147
Maybe add it directly to `Action` (or make `variableExpression` public) if there are other actions where the list of variables could be dynamic.
2. (breaking) Consider removing `BranchName` from `CodeStarConnectionsSourceAction.variables()`, since it's not always present and if missing attempting to use it will cause the build to fail.
### Additional Information/Context
From what I can tell, there's an underlying issue with the implementation of the CodeStarSourceConnection Action provider in CodePipeline. For a given pipeline and action:
- Different output variables will be available depending on how the build was triggered.
- There's no way for subsequent stages to determine what variables are available.
- Attempting to use a missing variable causes an unrecoverable failure of the pipeline.
Therefore the only variables that can be safely used are ones available in _all_ cases (which `BranchName` is not.)
I would love to be wrong about this, let me know if there's a workaround!
**Variables from a non-pr trigger**

**Variables from a pull request trigger**

### CDK CLI Version
2.150.0 (build 3f93027)
### Framework Version
_No response_
### Node.js Version
v20.11.1
### OS
MacOS 14.3 (23D56)
### Language
TypeScript
### Language Version
Typescript (5.4.5)
### Other information
_No response_
Contributor guide
Research direction
Start with packages/aws-cdk-lib/aws-codepipeline-actions/lib/codestar-connections/source-action.ts and compare its variables getter with variableExpression in packages/aws-cdk-lib/aws-codepipeline-actions/lib/codebuild/build-action.ts and packages/aws-cdk-lib/aws-codepipeline/lib/action.ts. Use the linked reproduction to observe pull-request and manual executions. Done means the action exposes an appropriate way to reference available variables without advertising variables that are unavailable in a trigger context.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- cloud, devops
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100