There's the following buildspec that runs some commands and exports a variable in the end:
env:
exported-variables:
- PROPERTY_FROM_BUILD
I'd like to use this variable inside a custom pipeline stage, but I have no idea how to get it here:
import { Stage, StageProps } from 'aws-cdk-lib';
class MyStage extends Stage {
constructor(scope: Construct, id: string, props: StageProps) {
new Stack(this, 'MyStack', {
PROPERTY_FROM_BUILD: '???'
});
}
}
Let me post more details just in case. My code pipeline looks like this:
const codePipeline = new cdk.pipelines.CodePipeline(this, 'MyPipeline', {...});
codePipeline.addStage(new MyStage(this, 'MyStage', {...})
codePipeline.buildPipeline();
As you can see, I just create a pipeline, add my stage and build it. After that is done, I make a codebuild project and action to run my buildspec:
const project = new cdk.aws_codebuild.PipelineProject(this, 'MyProject', {
buildSpec: cdk.aws_codebuild.BuildSpec.fromSourceFilename(`buildspec.yml`),
});
const action = new cdk.aws_codepipeline_actions.CodeBuildAction({
actionName: 'MyAction',
project: project,
});
codePipeline.pipeline.addStage({
stageName: 'MyActionStage',
actions: [action],
placement: {
rightBefore: codePipeline.pipeline.stage('MyStage')
}
});
It works and generates a nice pipeline. Is there any way I can pass my PROPERTY_FROM_BUILD
from variable and use it in my stack?
While it took me about a week to figure this out, I've managed to make it work after all. Let me leave the solution here, in case someone else encounters the issue:
Before even starting, extend your CodeBuildAction
with a custom namespace, like:
const action = new cdk.aws_codepipeline_actions.CodeBuildAction({
actionName: 'MyAction',
project: project,
variablesNamespace: 'my_action_namespace',
});
First of all, you've got to figure out the index of your deployment stage, like:
const deployIdx = codePipeline.pipeline.stages.indexOf(codePipeline.pipeline.stage('Deploy'));
Then, find all actions of type "changeset replace":
const actionsIdxs = codePipeline.pipeline.stage('Deploy').actions.filter(x => x.actionProperties.category === 'Deploy').map((x,i)=>i);
Next, use this Escape Hatches feature to edit the generated template and attach the pipeline variable as ParameterOverrides
to all deployment actions:
const cfnPipeline = codePipeline.pipeline.node.findChild('Resource') as cdk.aws_codepipeline.CfnPipeline;
for(const i of actionsIdxs){
cfnPipeline.addOverride(
`Properties.Stages.${deployIdx}.Actions.${i}.Configuration.ParameterOverrides`,
JSON.stringify({
// Use lowercase-only here to match the autogenerated name of the CfnParameter.
propertyfrombuild: "#{my_action_namespace.PROPERTY_FROM_BUILD}"
}));
}
And then, finally, in my stack, I can access the value like this:
const PROPERTY_FROM_BUILD = new cdk.CfnParameter(this, 'propertyfrombuild').valueAsString;
Make sure you name the variable all-lowercase with no special characters, and place it in your stack (not in a child construct).