Skip to content

Commit 81f96b2

Browse files
authored
feat: add mac instances in codebuild project (#979)
Signed-off-by: Arjun Raja Yogidas <arjunry@amazon.com>
1 parent 8740261 commit 81f96b2

6 files changed

Lines changed: 117 additions & 39 deletions

File tree

lib/codebuild-stack.ts

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ const githHubSource = codebuild.Source.gitHub({
3131
cloneDepth: 0,
3232
});
3333

34+
const githHubSourceDaemon = codebuild.Source.gitHub({
35+
owner: 'runfinch',
36+
repo: 'finch-daemon',
37+
webhook: true,
38+
webhookFilters: webhookFiltersArr,
39+
fetchSubmodules: true,
40+
cloneDepth: 0,
41+
});
42+
3443
interface ImageFilterProps {
3544
'virtualization-type': string[];
3645
'root-device-type': string[];
@@ -59,6 +68,7 @@ class CodeBuildStackDefaultProps {
5968
}
6069

6170
class CodeBuildStackProps {
71+
repo: string;
6272
env: cdk.Environment | undefined;
6373
projectName: string;
6474
region: string;
@@ -72,6 +82,7 @@ class CodeBuildStackProps {
7282
computeType: codebuild.FleetComputeType;
7383
baseCapacity: number;
7484
};
85+
buildImageString?: codebuild.IBuildImage;
7586
projectEnvironmentProps?: {
7687
computeType: codebuild.ComputeType;
7788
};
@@ -96,15 +107,6 @@ export class CodeBuildStack extends cdk.Stack {
96107
arnFormat: cdk.ArnFormat.COLON_RESOURCE_NAME
97108
});
98109

99-
const machineImageProps = {
100-
name: props.amiSearchString,
101-
filters: {
102-
...(props.imageFilterProps || CodeBuildStackDefaultProps.imageFilterProps),
103-
architecture: [props.arch]
104-
}
105-
};
106-
const machineImage = new ec2.LookupMachineImage(machineImageProps);
107-
108110
const fleetServiceRole = new iam.Role(this, `FleetServiceRole-${platformId}`, {
109111
assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com'),
110112
managedPolicies: [
@@ -118,19 +120,47 @@ export class CodeBuildStack extends cdk.Stack {
118120
environmentType: props.environmentType
119121
});
120122

121-
const imageId: string = machineImage.getImage(this).imageId;
123+
let buildImage: codebuild.IBuildImage;
124+
let imageId: string;
125+
let githubSource: codebuild.ISource;
126+
127+
if (!props.amiSearchString) {
128+
// For finch-daemon (macOS), use the buildImageString directly
129+
buildImage = props.buildImageString!;
130+
// Empty string for macOS since we don't need an ImageId
131+
imageId = "";
132+
} else {
133+
// For all other projects, look up the AMI
134+
const machineImageProps = {
135+
name: props.amiSearchString,
136+
filters: {
137+
...(props.imageFilterProps || CodeBuildStackDefaultProps.imageFilterProps),
138+
architecture: [props.arch]
139+
}
140+
};
141+
const machineImage = new ec2.LookupMachineImage(machineImageProps);
142+
imageId = machineImage.getImage(this).imageId;
143+
buildImage = this.getBuildImageByOS(props.buildImageOS, props.environmentType, imageId);
144+
}
145+
146+
githubSource = props.repo == "finch-daemon" ? githHubSourceDaemon : githHubSource;
122147

123148
const cfnFleet = fleet.node.defaultChild as cdk.CfnResource;
124-
cfnFleet.addPropertyOverride('ImageId', imageId);
149+
150+
// Only set ImageId if it's not empty (skip for macOS)
151+
if (imageId) {
152+
cfnFleet.addPropertyOverride('ImageId', imageId);
153+
}
154+
125155
cfnFleet.addPropertyOverride('FleetServiceRole', fleetServiceRole.roleArn);
126156

127157
const codebuildProject = new codebuild.Project(this, id, {
128158
projectName: props.projectName,
129-
source: githHubSource,
159+
source: githubSource,
130160
environment: {
131161
...(props.projectEnvironmentProps || CodeBuildStackDefaultProps.projectEnvironmentProps),
132162
fleet: fleet,
133-
buildImage: this.getBuildImageByOS(props.buildImageOS, props.environmentType, imageId)
163+
buildImage: buildImage
134164
},
135165
encryptionKey: new Key(this, `codebuild-${platformId}-key-${props.region}`, {
136166
description: 'Kms Key to encrypt data-at-rest',

lib/finch-pipeline-app-stage.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,22 @@ export class FinchPipelineAppStage extends cdk.Stage {
101101
}
102102
})(this, 'CodeBuildStack-credentials');
103103

104-
for (const { arch, operatingSystem, amiSearchString, environmentType, buildImageOS } of CODEBUILD_STACKS) {
105-
const codeBuildStack = new CodeBuildStack(this, `CodeBuildStack-${operatingSystem}-${toStackName(arch)}`, {
104+
for (const { project, arch, operatingSystem, amiSearchString, environmentType, buildImageOS, buildImageString, fleetProps, projectEnvironmentProps } of CODEBUILD_STACKS) {
105+
let codeBuildStack;
106+
codeBuildStack = new CodeBuildStack(this, `CodeBuildStack-${operatingSystem}-${toStackName(arch)}`, {
107+
repo: project,
106108
env: props.env,
107-
projectName: `finch-${arch}-${props.environmentStage}-instance`,
109+
projectName: `${project}-${arch}-${props.environmentStage}-instance`,
108110
region: 'us-west-2',
109111
arch,
110112
amiSearchString,
111113
operatingSystem,
112114
buildImageOS: buildImageOS,
113-
environmentType: environmentType
115+
environmentType: environmentType,
116+
buildImageString,
117+
fleetProps,
118+
projectEnvironmentProps
114119
});
115-
116120
codeBuildStack.addDependency(codebuildCredsStack);
117121
}
118122
}

lib/utils.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,47 @@ export enum BuildImageOS {
77
}
88

99
export interface CodeBuildStackArgs {
10+
project: string;
1011
operatingSystem: string;
1112
arch: string;
1213
amiSearchString: string;
1314
environmentType: codebuild.EnvironmentType;
1415
buildImageOS: BuildImageOS;
16+
fleetProps?: {
17+
computeType: codebuild.FleetComputeType;
18+
baseCapacity: number;
19+
};
20+
buildImageString?: codebuild.IBuildImage,
21+
projectEnvironmentProps?: {
22+
computeType: codebuild.ComputeType;
23+
};
1524
}
1625

1726
export const CODEBUILD_STACKS: CodeBuildStackArgs[] = [
1827
{
28+
project: 'finch',
1929
operatingSystem: 'ubuntu',
2030
arch: 'x86_64',
2131
amiSearchString: 'ubuntu/images/hvm-ssd/ubuntu*22.04*',
2232
environmentType: codebuild.EnvironmentType.LINUX_EC2,
2333
buildImageOS: BuildImageOS.LINUX
2434
},
2535
{
36+
project: 'finch',
2637
operatingSystem: 'ubuntu',
2738
arch: 'arm64',
2839
amiSearchString: 'ubuntu/images/hvm-ssd/ubuntu*22.04*',
2940
environmentType: codebuild.EnvironmentType.ARM_EC2,
3041
buildImageOS: BuildImageOS.LINUX
42+
},
43+
{
44+
project: 'finch-daemon',
45+
operatingSystem: 'macOS',
46+
arch: 'arm64',
47+
amiSearchString: "", // Empty string since we're using buildImageString directly
48+
environmentType: codebuild.EnvironmentType.MAC_ARM,
49+
buildImageOS: BuildImageOS.MAC,
50+
buildImageString: codebuild.MacBuildImage.BASE_14
3151
}
3252
];
3353

package-lock.json

Lines changed: 7 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"@types/jest": "^29.5.14",
1818
"@types/node": "^22.15.30",
1919
"@types/prettier": "3.0.0",
20-
"aws-cdk": "^2.1018.1",
20+
"aws-cdk": "^2.1020.2",
2121
"jest": "^29.7.0",
2222
"prettier": "^3.5.3",
2323
"ts-jest": "^29.4.0",

test/codebuild-stack.test.ts

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ describe('CodeBuildStack', () => {
99
test('synthesizes the way we expect', () => {
1010
const app = new cdk.App();
1111
const codebuildStackArgs: CodeBuildStackArgs = {
12+
project: 'finch',
1213
operatingSystem: 'ubuntu',
1314
arch: 'x86_64',
1415
amiSearchString: 'ubuntu*22.04*',
@@ -21,7 +22,8 @@ describe('CodeBuildStack', () => {
2122
account: '123456789012',
2223
region: 'us-east-1'
2324
},
24-
projectName: 'test-project',
25+
projectName: codebuildStackArgs.project,
26+
repo: codebuildStackArgs.project,
2527
region: 'us-west-2',
2628
...codebuildStackArgs
2729
});
@@ -38,7 +40,8 @@ describe('CodeBuildStack', () => {
3840
account: '123456789012',
3941
region: 'us-east-1'
4042
},
41-
projectName: 'test-project',
43+
projectName: codebuildStackArgs.project,
44+
repo: codebuildStackArgs.project,
4245
region: 'us-west-2',
4346
...codebuildStackArgs
4447
});
@@ -50,27 +53,49 @@ describe('CodeBuildStack', () => {
5053
});
5154

5255
const validateTemplate = (codebuildStack: CodeBuildStackArgs, template: Template) => {
53-
// Assert that the stack creates a Fleet
56+
let imageMatcher;
57+
if (codebuildStack.amiSearchString === "") {
58+
// For macOS builds, match only the base image versions (14 or 15)
59+
imageMatcher = Match.stringLikeRegexp('aws/codebuild/macos-arm-base:1[45]$');
60+
} else {
61+
// For regular builds, expect an AMI ID
62+
imageMatcher = Match.stringLikeRegexp('ami-1234');
63+
}
64+
65+
// Assert that the stack creates a Project
5466
template.hasResourceProperties('AWS::CodeBuild::Project', {
55-
Name: 'test-project',
67+
Name: codebuildStack.project,
5668
Environment: {
5769
Type: codebuildStack.environmentType,
58-
ComputeType: 'BUILD_GENERAL1_MEDIUM',
59-
Image: Match.stringLikeRegexp('ami-1234'),
70+
ComputeType: codebuildStack.projectEnvironmentProps?.computeType || 'BUILD_GENERAL1_MEDIUM',
71+
Image: imageMatcher,
6072
},
6173
Source: {
6274
Type: 'GITHUB',
63-
Location: 'https://github.com/runfinch/finch.git',
75+
Location: codebuildStack.project === 'finch-daemon'
76+
? 'https://github.com/runfinch/finch-daemon.git'
77+
: 'https://github.com/runfinch/finch.git',
6478
ReportBuildStatus: true
6579
}
6680
});
6781

6882
// Assert that the stack creates a Fleet
69-
template.hasResourceProperties('AWS::CodeBuild::Fleet', {
70-
BaseCapacity: 1,
71-
ComputeType: 'BUILD_GENERAL1_MEDIUM',
72-
EnvironmentType: codebuildStack.environmentType
73-
});
83+
if (codebuildStack.amiSearchString !== "") {
84+
// For non-macOS builds, expect ImageId property
85+
template.hasResourceProperties('AWS::CodeBuild::Fleet', {
86+
BaseCapacity: codebuildStack.fleetProps?.baseCapacity || 1,
87+
ComputeType: codebuildStack.fleetProps?.computeType || 'BUILD_GENERAL1_MEDIUM',
88+
EnvironmentType: codebuildStack.environmentType,
89+
ImageId: Match.anyValue()
90+
});
91+
} else {
92+
// For macOS builds, ImageId property should not be present
93+
template.hasResourceProperties('AWS::CodeBuild::Fleet', {
94+
BaseCapacity: codebuildStack.fleetProps?.baseCapacity || 1,
95+
ComputeType: codebuildStack.fleetProps?.computeType || 'BUILD_GENERAL1_MEDIUM',
96+
EnvironmentType: codebuildStack.environmentType
97+
});
98+
}
7499

75100
// Assert that the stack creates a Fleet service role
76101
template.hasResourceProperties('AWS::IAM::Role', {

0 commit comments

Comments
 (0)