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(pipelines): add variable namespace support for CodeBuildStep #18893

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/@aws-cdk/pipelines/README.md
Expand Up @@ -696,6 +696,9 @@ new pipelines.CodeBuildStep('Synth', {
subnetSelection: { subnetType: ec2.SubnetType.PRIVATE },
securityGroups: [mySecurityGroup],

// You can customize the variable namespace of exported variables if needed
variablesNamespace: 'MyNamespace',

// Additional policy statements for the execution role
rolePolicyStatements: [
new iam.PolicyStatement({ /* ... */ }),
Expand Down
25 changes: 25 additions & 0 deletions packages/@aws-cdk/pipelines/lib/blueprint/shell-step.ts
Expand Up @@ -88,6 +88,12 @@ export interface ShellStepProps {
*/
readonly primaryOutputDirectory?: string;

/**
* The name of the namespace to use for variables emitted by this action.
*
* @default No namespace.
*/
readonly variablesNamespace?: string;
}

/**
Expand Down Expand Up @@ -140,6 +146,13 @@ export class ShellStep extends Step {
*/
public readonly outputs: FileSetLocation[] = [];

/**
* The name of the namespace to use for variables emitted by this action.
*
* @default Id of the step.
*/
public readonly variablesNamespace: string;

private readonly _additionalOutputs: Record<string, FileSet> = {};

private _primaryOutputDirectory?: string;
Expand All @@ -151,6 +164,7 @@ export class ShellStep extends Step {
this.installCommands = props.installCommands ?? [];
this.env = props.env ?? {};
this.envFromCfnOutputs = mapValues(props.envFromCfnOutputs ?? {}, StackOutputReference.fromCfnOutput);
this.variablesNamespace = props.variablesNamespace ?? id;

// Inputs
if (props.input) {
Expand Down Expand Up @@ -229,6 +243,17 @@ export class ShellStep extends Step {
}
return fileSet;
}

/**
* Reference a CodePipeline variable defined by the ShellStep.
*
* Variables in CodeBuild actions are defined using the 'exported-variables' subsection of the 'env' section of the buildspec.
*
* @param variableName the name of the variable for reference.
*/
public variable(variableName: string): string {
return `#{${this.variablesNamespace}.${variableName}}`;
}
}

/**
Expand Down
Expand Up @@ -98,6 +98,7 @@ export interface CodeBuildFactoryProps {

readonly env?: Record<string, string>;
readonly envFromCfnOutputs?: Record<string, StackOutputReference>;
readonly variablesNamespace?: string;

/**
* If given, override the scope from the produce call with this scope.
Expand Down Expand Up @@ -128,6 +129,7 @@ export class CodeBuildFactory implements ICodePipelineActionFactory {
inputs: shellStep.inputs,
outputs: shellStep.outputs,
stepId: shellStep.id,
variablesNamespace: shellStep.variablesNamespace,
installCommands: shellStep.installCommands,
...additional,
});
Expand All @@ -145,6 +147,7 @@ export class CodeBuildFactory implements ICodePipelineActionFactory {
partialBuildSpec: step.partialBuildSpec,
vpc: step.vpc,
subnetSelection: step.subnetSelection,
variablesNamespace: step.variablesNamespace,
timeout: step.timeout,
}),
});
Expand Down Expand Up @@ -314,6 +317,7 @@ export class CodeBuildFactory implements ICodePipelineActionFactory {
outputs: outputArtifacts,
project,
runOrder: options.runOrder,
variablesNamespace: this.props.variablesNamespace,

// Inclusion of the hash here will lead to the pipeline structure for any changes
// made the config of the underlying CodeBuild Project.
Expand Down
@@ -1,7 +1,7 @@
import { Duration } from '@aws-cdk/core';
import * as codebuild from '@aws-cdk/aws-codebuild';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as iam from '@aws-cdk/aws-iam';
import { Duration } from '@aws-cdk/core';
import { ShellStep, ShellStepProps } from '../blueprint';

/**
Expand Down
7 changes: 7 additions & 0 deletions packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts
Expand Up @@ -225,6 +225,13 @@ export interface CodeBuildOptions {
*/
readonly rolePolicy?: iam.PolicyStatement[];

/**
* The name of the namespace to use for variables emitted by this action.
*
* @default The projectName will be used if it is defined. Otherwise, the construct ID will be used.
*/
readonly variablesNamespace?: string;

/**
* Partial buildspec, will be combined with other buildspecs that apply
*
Expand Down
Expand Up @@ -141,4 +141,28 @@ test('envFromOutputs works even with very long stage and stack names', () => {
});

// THEN - did not throw an error about identifier lengths
});
});

test('variable namespace is set in CodeBuildStep', () => {
// WHEN
const pipeline = new ModernTestGitHubNpmPipeline(pipelineStack, 'Cdk');
const myApp = new AppWithOutput(app, 'VariableNamespaceApp');

const step1 = new cdkp.CodeBuildStep('Synth', {
commands: ['/bin/true'],
input: cdkp.CodePipelineSource.gitHub('test/test', 'main'),
variablesNamespace: 'CodeBuildStep-namespace',
});
const step2 = new cdkp.ShellStep('Approve', {
commands: ['/bin/true'],
variablesNamespace: 'ShellStep-namespace',
});
pipeline.addStage(myApp, {
pre: [step1],
post: [step2],
});

// THEN
expect(step1.variable('test')).toEqual('#{CodeBuildStep-namespace.test}');
expect(step2.variable('test')).toEqual('#{ShellStep-namespace.test}');
});
Expand Up @@ -833,6 +833,7 @@
}
],
"Name": "Synth",
"Namespace": "Synth",
"OutputArtifacts": [
{
"Name": "Synth_Output"
Expand Down Expand Up @@ -870,6 +871,7 @@
}
],
"Name": "SelfMutate",
"Namespace": "SelfMutate",
"RoleArn": {
"Fn::GetAtt": [
"PipelineUpdatePipelineSelfMutateCodePipelineActionRoleD6D4E5CF",
Expand Down Expand Up @@ -901,6 +903,7 @@
}
],
"Name": "FileAsset1",
"Namespace": "FileAsset1",
"RoleArn": {
"Fn::GetAtt": [
"PipelineAssetsFileAsset1CodePipelineActionRoleC0EC649A",
Expand All @@ -927,6 +930,7 @@
}
],
"Name": "FileAsset2",
"Namespace": "FileAsset2",
"RoleArn": {
"Fn::GetAtt": [
"PipelineAssetsFileAsset2CodePipelineActionRole06965A59",
Expand Down
Expand Up @@ -299,6 +299,7 @@
}
],
"Name": "Synth",
"Namespace": "Synth",
"OutputArtifacts": [
{
"Name": "Synth_Output"
Expand Down Expand Up @@ -336,6 +337,7 @@
}
],
"Name": "SelfMutate",
"Namespace": "SelfMutate",
"RoleArn": {
"Fn::GetAtt": [
"PipelineUpdatePipelineSelfMutateCodePipelineActionRoleD6D4E5CF",
Expand Down