Skip to content

Instantly share code, notes, and snippets.

@SydneyUni-Jim
Last active July 6, 2022 00:25
Show Gist options
  • Save SydneyUni-Jim/7a427203b64e013af331883f7bb59bb0 to your computer and use it in GitHub Desktop.
Save SydneyUni-Jim/7a427203b64e013af331883f7bb59bb0 to your computer and use it in GitHub Desktop.
Custom logical ids for CodeBuild projects
import * as cdk from 'aws-cdk-lib'
import * as codebuild from 'aws-cdk-lib/aws-codebuild'
import * as pipelines from 'aws-cdk-lib/pipelines'
import { Construct } from 'constructs'
export class PipelineStack extends cdk.Stack {
public readonly pipeline: pipelines.CodePipeline
constructor(scope: Construct, id: string, props: cdk.StackProps) {
super(scope, id, props)
this.pipeline = new pipelines.CodePipeline(this, 'CdkPipeline', {
synth: new pipelines.ShellStep('CdkSynth', {
// ………
}),
})
}
protected allocateLogicalId(cfnElement: cdk.CfnElement): string {
const logicalId = super.allocateLogicalId(cfnElement)
if (cfnElement instanceof codebuild.CfnProject) {
const hash = logicalId.slice(-8)
const idStack = (
cfnElement.node.scopes
.slice(cfnElement.node.scopes.indexOf(cfnElement.stack) + 1)
.map(x => x.node.id)
)
let id = idStack.pop()
while (id && (id === 'Resource' || id === 'CdkBuildProject')) {
id = idStack.pop()
}
id ??= cfnElement.node.id
id = id.replace(/[^A-Za-z0-9]/g, '')
return `${this.stackName}${id}${hash}`
} else {
return logicalId
}
}
}
@SydneyUni-Jim
Copy link
Author

What does this do?

It customises how CDK allocates logical IDs for CodeBuild projects.

Normally the CDK allocates logical IDs by concatenating all the Construct / CfnElement ids from one past the stack down to the particular node.

In this example, the ShellStep id is CdkSynth. Normally the CDK would allocate an ID like CdkPipelineBuildCdkSynthCdkBuildProjectA713CFA7. This is because the hierarchy of ids would have been CdkPipeline, Build, CdkSynth, CdkBuildProject, Resource. The physical ID ends up being something like CdkPipelineBuildCdkSynthCdk-x7qn180HcLtp.

With this, for CodeBuild projects only, it finds the deepest id that is not Resource or CdkBuildProject and assigns that as the logical ID, prefixing it with the name of the stack. It also suffixes it with the hash as normal to ensure the logical IDs are unique in the stack.

Instead of CdkPipelineBuildCdkSynthCdkBuildProjectA713CFA7, the CDK allocates an ID like demoSynthCdkA713CFA7, assuming the stack's name is demo. This ends up being a physical ID like demoCdkSynthA713CFA7-X3vCwqQ9mxIZ.

Why do I want to do this?

By default, CloudFormation does not prefix the physical ID of CodeBuild projects with the name of the stack they came from. Also the physical IDs of CodeBuild projects are relatively short. On top of the, the CDK creates long logical IDs were the useful part towards the end is truncated to form the physical ID. This means you end up with a bunch of CodeBuild projects with unhelpful physical IDs.

In this example — if the CDK app builds two Docker images — without this you would end up with these CodeBuild projects.

  • CdkPipelineBuildCdkSynthCdk-x7qn180HcLtp
  • CdkPipelineUpdatePipelineSe-GafqYqhvIruH
  • CdkPipelineAssetsDockerAsse-oej5f6FyUDti
  • CdkPipelineAssetsDockerAsse-X3vCwqQ9mxIZ

You can see the problem particularly with the two CodeBuild projects for the Docker images.

With this, you instead end up with these CodeBuild projects, assuming the stack is called demo.

  • demoCdkSynthA713CFA7-X3vCwqQ9mxIZ
  • demoSelfMutation81360810-TKH4to7LpGEg
  • demoDockerAsset1ABECB7E0-Y91THm7cnyvs
  • demoDockerAsset26799E66E-wMsTZmoxtBEt

Much more helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment