AWS CDK pass branch name from Event to CodeBuild project

In AWS CDK, I would like to define a CodeBuild project that will run every time a pull request is opened or updated in CodeCommit. I am doing this to be able to have my tests and build validated prior to merging to the main branch.

How do I have this CodeBuild project run for the branch that is associated with the pull request?

Below is my code:

import { Repository } from 'aws-cdk-lib/aws-codecommit';
import { BuildSpec, Project, Source } from 'aws-cdk-lib/aws-codebuild';
import { CodeBuildProject } from 'aws-cdk-lib/aws-events-targets';

const repo = Repository.fromRepositoryName(this, 'MyRepo', 'my-repo');

const project = new Project(this, 'MyCodeBuildProject', {
  source: Source.codeCommit({ repository: repo }),
  buildSpec: BuildSpec.fromObject({
    version: '0.2',
    phases: {
      build: {
        commands: [ 'npm run build' ],
      },
    },
  }),
});

const myRule = repo.onPullRequestStateChange('MyRule', {
  target: new targets.CodeBuildProject(project),
});

I have tried providing it to the project source this way:

import { ReferenceEvent } from 'aws-cdk-lib/aws-codecommit';
...
  source: Source.codeCommit({ repository: repo, branchOrRef: ReferenceEvent.name }),

But I receive this error: reference not found for primary source and source version $.detail.referenceName

CodeCommit -> Open pull request -> CloudWatch event (EventBridge) -> CodeBuild
AWS CDK v2.5.0
TypeScript


Solution 1:

I was able to solve this by extracting the branch from the event and then passing that to the target.

import { EventField, RuleTargetInput } from 'aws-cdk-lib/aws-events';

const myRule = repo.onPullRequestStateChange('MyRule', {
  target: new targets.CodeBuildProject(project, {
    event: RuleTargetInput.fromObject({
      sourceVersion: EventField.fromPath('$.detail.sourceReference'),
    }),
  }),
});

This works because targets.CodeBuildProject() will call the CodeBuild StartBuild API. The event key in CodeBuildProjectProps specifies the payload that will be sent to the StartBuild API. by default, the entire Event is sent, but this is not in the format expected by CodeBuild. The StartBuild API payload allows a branch, commit, or tag to be specified using sourceVersion. We can extract data from the event using EventField. Events from CodeCommit have the reference nested under detail.sourceReference. This will be something like 'refs/heads/my-branch'. Using Eventfield.fromPath() we can use the $. syntax to access the event that triggered this rule, and then provide a dot-notation string for the JSON path to access the data we need.