Skip to content

CodebuildBuilder

Bases: AbstractAWSResourceBuilder['CodebuildBuilder', CodebuildConfig]

Builder for creating AWS CodeBuild projects with organizational standards.

Creates CodeBuild projects for CI/CD pipelines with support for different project types (standalone projects and pipeline projects), ECR integration, scheduled builds, and comprehensive logging. Handles both container image builds and AMI builds.

Source code in mare_aws_common_lib/builders/codebuild_builder.py
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
class CodebuildBuilder(AbstractAWSResourceBuilder["CodebuildBuilder", CodebuildConfig]):
    """Builder for creating AWS CodeBuild projects with organizational standards.

    Creates CodeBuild projects for CI/CD pipelines with support for different project
    types (standalone projects and pipeline projects), ECR integration, scheduled builds,
    and comprehensive logging. Handles both container image builds and AMI builds.
    """

    _resource_type: AWSResourceType = AWSResourceType.CODEBUILD
    _requires_usage: bool = True

    def reset(self) -> None:
        """Reset the builder to its initial state.

        Clears all internal state including project type and CodeBuild project instance.
        Called internally to prepare for a new build.
        """
        super().reset()
        self._codebuild_type: CodebuildType = None
        self._codebuild_project: codebuild.IProject = None

    def set_codebuild_type(self, codebuild_type: CodebuildType) -> 'CodebuildBuilder': 
        """Set the CodeBuild project type.

        Args:
            codebuild_type: Type of CodeBuild project (PROJECT or PIPELINE_PROJECT)

        Returns:
            Self for method chaining
        """
        self._codebuild_type = codebuild_type
        return self

    def build(self, scope : Construct) -> codebuild.IProject:
        """Build and return the configured CodeBuild project.

        Creates a CodeBuild project with the specified configuration, sets up
        permissions, configures optional features like scheduling and immediate builds.

        Args:
            scope: CDK construct scope where the project will be created

        Returns:
            Configured CodeBuild Project instance

        Raises:
            ValidationError: If project configuration validation fails
            ValueError: If codebuild_type is not set
        """
        super().build()

        self._codebuild_project = self._create_codebuild_project(scope)
        self._configure_optional_features(scope)
        self._tag_resource(self._codebuild_project)

        return self._codebuild_project

    def _create_codebuild_project(self, scope: Construct) -> codebuild.IProject:
        """Create the appropriate CodeBuild project based on configuration type.

        Args:
            scope: CDK construct scope

        Returns:
            CodeBuild Project or PipelineProject instance
        """
        if self._config.codebuild_type == CodebuildType.PROJECT:
            return self._create_project(scope)
        else:
            return self._create_pipeline_project(scope)

    def _create_project(self, scope: Construct) -> codebuild.IProject:
        """Create a standalone CodeBuild project with git source and ECR integration.

        Args:
            scope: CDK construct scope

        Returns:
            Configured CodeBuild Project instance

        Side Effects:
            Creates CodeBuild Project in AWS
            Configures ECR and cross-account IAM permissions
        """
        project_name, logical_id = self._generate_project_identifiers(CodebuildType.PROJECT)

        codebuild_project = codebuild.Project(
            scope, logical_id,
            vpc=self._config.vpc,
            role=self._config.role,
            project_name=project_name,
            source=self._create_source(),
            environment=self._get_build_environment(),
            environment_variables={
                "ECR_REPO_URI": codebuild.BuildEnvironmentVariable(value=self._config.typed.ecr_repo.repository_uri),
                "AWS_ACCOUNT_ID": codebuild.BuildEnvironmentVariable(value=Aws.ACCOUNT_ID),
                "AWS_REGION": codebuild.BuildEnvironmentVariable(value=Aws.REGION),
                "PROJECT_NAME": codebuild.BuildEnvironmentVariable(value=self._application_helper.get_project().upper())
            },
            build_spec=codebuild.BuildSpec.from_source_filename(self._config.buildspec_path),
            logging=self._get_logging_options(),
            security_groups=self._config.security_groups
        )

        self._configure_project_permissions(codebuild_project)

        return codebuild_project

    def _create_source(self) -> codebuild.Source:
        """Create CodeBuild source configuration based on git provider (currently only supports CODECOMMIT).

        Returns:
            CodeBuild Source configuration

        Raises:
            ValueError: If git provider is not supported
        """
        match self._config.git_provider:
            case GitProvider.CODECOMMIT:
                return codebuild.Source.code_commit(
                    repository=self._config.git_repo,
                    branch_or_ref=self._config.git_branch
                )
            case _:
                raise ValueError(f"Unsupported git provider: {self._config.git_provider}. "
                               f"Supported providers: {', '.join([p.value for p in GitProvider])}")
            # case GitProvider.GITHUB:
            #     return codebuild.Source.git_hub(
            #         owner=self._config.git_repo_owner,
            #         repo=self._config.git_repo,
            #         branch_or_ref=self._config.git_branch,
            #         webhook=self._config.enable_webhook if hasattr(self._config, 'enable_webhook') else False,
            #         webhook_filters=self._config.webhook_filters if hasattr(self._config, 'webhook_filters') else None
            #     )
        # TODO: implement other git providers

    def _create_pipeline_project(self, scope: Construct) -> codebuild.PipelineProject:
        """Create a pipeline-integrated CodeBuild project for CI/CD workflows.

        Args:
            scope: CDK construct scope

        Returns:
            Configured CodeBuild PipelineProject instance

        Side Effects:
            Creates CodeBuild PipelineProject in AWS
            Configures S3 logging permissions if logs bucket specified
        """
        use_ami = self._config.ami_ecr_repo is not None
        project_name, logical_id = self._generate_project_identifiers(
            CodebuildType.PIPELINE_PROJECT, 
            suffix=self._config.pipeline_type.value
        )

        build_spec = codebuild.BuildSpec.from_source_filename(self._config.buildspec_path) if self._config.buildspec_path else None

        codebuild_pipeline_project = codebuild.PipelineProject(
            scope, logical_id,
            vpc=self._config.vpc,
            role=self._config.role,
            project_name= project_name,
            build_spec=build_spec,
            environment=self._get_build_environment(use_ami),
            environment_variables=self._config.env_vars,
            logging=self._get_logging_options(),
            security_groups=self._config.security_groups
        )

        self._configure_logs_permissions()

        return codebuild_pipeline_project

    def _generate_project_identifiers(self, project_type: CodebuildType, suffix: str = None) -> tuple[str, str]:
        """Generate project name and logical ID following organizational patterns.

        Args:
            project_type: Type of CodeBuild project
            suffix: Optional suffix for project naming

        Returns:
            Tuple of (project_name, logical_id)
        """
        resource_name = project_type.name
        base_logical_id = project_type.name

        if suffix:
            resource_name = f"{resource_name}-{suffix}"
            base_logical_id = f"{base_logical_id}-{suffix}"

        if self._config.usage_context:
            resource_name = f"{resource_name}-{self._config.usage_context}"
            base_logical_id = f"{base_logical_id}-{self._config.usage_context}"

        project_name = self._get_name_for_resource(
            resource_name, 
            max_length=AWSResourceNameLength.CODEBUILD_PIPELINE_PROJECT.value
        )
        logical_id = self._get_cfn_logical_id(base_logical_id)

        return project_name, logical_id

    def _configure_project_permissions(self, codebuild_project: codebuild.Project) -> None:
        """Configure IAM permissions for ECR access and cross-account roles.

        Args:
            codebuild_project: CodeBuild project to configure permissions for

        Side Effects:
            Grants ECR pull/push permissions to CodeBuild project
            Adds cross-account role assumption policy to project role
            Configures S3 logging permissions if applicable
        """
        # Grant CodeBuild permissions to interact with ECR
        self._config.ecr_repo.grant_pull_push(codebuild_project)

        # Add cross-account role assumption policy
        codebuild_project.add_to_role_policy(
            iam.PolicyStatement(
                actions=["sts:AssumeRole"],
                resources=[
                    f"arn:aws:iam::{Aws.ACCOUNT_ID}:role/"
                    f"{self._application_helper.get_from_common('cross_account_role')}"
                ]
            )
        )

        self._configure_logs_permissions()

    def _configure_logs_permissions(self) -> None:
        """Grant S3 write permissions for log storage if logs bucket is configured."""
        if self._config.logs_bucket and self._config.role:
            self._config.typed.logs_bucket.grant_write(self._config.role)

    def _get_build_environment(self, use_ami: bool = False) -> codebuild.BuildEnvironment:
        """Create build environment configuration with proper image and compute settings.

        Args:
            use_ami: Whether to use AMI from ECR repository

        Returns:
            Configured CodeBuild BuildEnvironment
        """
        codebuild_env: codebuild.BuildEnvironment = None
        if use_ami:
            codebuild_env = codebuild.BuildEnvironment(
                build_image=codebuild.LinuxBuildImage.from_ecr_repository(
                    self._config.ami_ecr_repo,
                    tag_or_digest="latest"
                ),
                compute_type=self._config.compute_type,
                privileged=self._config.privileged
            )
        else:
            codebuild_env = codebuild.BuildEnvironment(
                build_image=self._config.build_image,
                compute_type=self._config.compute_type,
                privileged=self._config.privileged
            )

        return codebuild_env

    def _add_start_build_api_dependency(self, scope: Construct) -> None:
        """Create custom resource to trigger build immediately after deployment.

        Args:
            scope: CDK construct scope

        Side Effects:
            Creates AwsCustomResource that calls CodeBuild StartBuild API
            Adds dependency to ensure build triggers after project creation
        """
        resource_id = self._get_cfn_logical_id('build-after-deployment')

        # Use AwsCustomResource to invoke the CodeBuild StartBuild API
        start_build = cr.AwsCustomResource(
            scope, resource_id,
            policy=cr.AwsCustomResourcePolicy.from_statements([
                iam.PolicyStatement(
                    actions=["codebuild:StartBuild"],
                    resources=[self._codebuild_project.project_arn]
                )
            ]),
            on_create=cr.AwsSdkCall(
                service="CodeBuild",
                action="startBuild",
                parameters={
                    "projectName": self._codebuild_project.project_name
                },
                physical_resource_id=cr.PhysicalResourceId.of(resource_id)
            )
        )

        # Ensure that the build is triggered after the project is deployed
        start_build.node.add_dependency(self._codebuild_project)

    def _create_build_trigger_on_schedule(self, scope: Construct) -> None:
        """Create EventBridge rule to trigger builds on a weekly schedule.

        Args:
            scope: CDK construct scope

        Side Effects:
            Creates EventBridge Rule that triggers builds every Monday at 00:30 UTC
            Adds CodeBuild project as target for the rule
        """
        # EventBridge Rule to trigger build every Monday
        rule = events.Rule(
            scope, self._get_cfn_logical_id("scheduler-rule"),
            schedule=events.Schedule.cron(minute="30", hour="0", week_day="MON")  # Runs every Monday at 00:30 UTC
        )
        rule.add_target(targets.CodeBuildProject(self._codebuild_project))

    def _get_logging_options(self) -> codebuild.LoggingOptions:
        """Configure logging options for S3 or default CloudWatch logging.

        Returns:
            LoggingOptions if S3 bucket configured, None for default CloudWatch logging
        """
        if self._config.logs_bucket is not None:
            return codebuild.LoggingOptions(
                s3=codebuild.S3LoggingOptions(
                    bucket=self._config.logs_bucket,
                    enabled=True
                ),
                cloud_watch=codebuild.CloudWatchLoggingOptions(
                    enabled=False
                )
            )
        return None # AWS will by default enable CloudWatch logs and create the LogGroup automatically

    def _configure_optional_features(self, scope: Construct) -> None:
        """Configure optional features like scheduling and immediate builds.

        Args:
            scope: CDK construct scope

        Side Effects:
            Creates EventBridge rule if create_build_scheduler is enabled
            Creates custom resource for immediate build if build_after_deployment is enabled
        """
        if self._config.create_build_scheduler:
            self._create_build_trigger_on_schedule(scope)

        if self._config.build_after_deployment:
            self._add_start_build_api_dependency(scope)

    def _set_config(self) -> None:
        """Create and validate the CodeBuild project configuration.

        Merges builder configuration with project type to create a validated
        CodebuildConfig object for project creation.

        Raises:
            ValidationError: If the CodebuildConfig validation fails
        """
        try:
            self._config = CodebuildConfig(**{
                **self._builder_config,
                "codebuild_type": self._codebuild_type
            })
        except ValidationError as e:
            self._log_validation_error(e, CodebuildConfig)
            raise

    def _control_consistency(self) -> None:
        """Validate builder configuration and internal state consistency.

        Ensures codebuild_type is set and validates the complete
        configuration using the CodebuildConfig model.

        Raises:
            ValueError: If codebuild_type is not set
            ValidationError: If configuration validation fails
        """
        super()._control_consistency()

        if not self._codebuild_type:
            raise ValueError("Codebuild Type must be set before building.")

        self._set_config()

Attributes

_requires_usage = True class-attribute instance-attribute

_resource_type = AWSResourceType.CODEBUILD class-attribute instance-attribute

Functions

_add_start_build_api_dependency(scope)

Create custom resource to trigger build immediately after deployment.

Parameters:

Name Type Description Default
scope Construct

CDK construct scope

required
Side Effects

Creates AwsCustomResource that calls CodeBuild StartBuild API Adds dependency to ensure build triggers after project creation

Source code in mare_aws_common_lib/builders/codebuild_builder.py
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
def _add_start_build_api_dependency(self, scope: Construct) -> None:
    """Create custom resource to trigger build immediately after deployment.

    Args:
        scope: CDK construct scope

    Side Effects:
        Creates AwsCustomResource that calls CodeBuild StartBuild API
        Adds dependency to ensure build triggers after project creation
    """
    resource_id = self._get_cfn_logical_id('build-after-deployment')

    # Use AwsCustomResource to invoke the CodeBuild StartBuild API
    start_build = cr.AwsCustomResource(
        scope, resource_id,
        policy=cr.AwsCustomResourcePolicy.from_statements([
            iam.PolicyStatement(
                actions=["codebuild:StartBuild"],
                resources=[self._codebuild_project.project_arn]
            )
        ]),
        on_create=cr.AwsSdkCall(
            service="CodeBuild",
            action="startBuild",
            parameters={
                "projectName": self._codebuild_project.project_name
            },
            physical_resource_id=cr.PhysicalResourceId.of(resource_id)
        )
    )

    # Ensure that the build is triggered after the project is deployed
    start_build.node.add_dependency(self._codebuild_project)

_configure_logs_permissions()

Grant S3 write permissions for log storage if logs bucket is configured.

Source code in mare_aws_common_lib/builders/codebuild_builder.py
245
246
247
248
def _configure_logs_permissions(self) -> None:
    """Grant S3 write permissions for log storage if logs bucket is configured."""
    if self._config.logs_bucket and self._config.role:
        self._config.typed.logs_bucket.grant_write(self._config.role)

_configure_optional_features(scope)

Configure optional features like scheduling and immediate builds.

Parameters:

Name Type Description Default
scope Construct

CDK construct scope

required
Side Effects

Creates EventBridge rule if create_build_scheduler is enabled Creates custom resource for immediate build if build_after_deployment is enabled

Source code in mare_aws_common_lib/builders/codebuild_builder.py
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
def _configure_optional_features(self, scope: Construct) -> None:
    """Configure optional features like scheduling and immediate builds.

    Args:
        scope: CDK construct scope

    Side Effects:
        Creates EventBridge rule if create_build_scheduler is enabled
        Creates custom resource for immediate build if build_after_deployment is enabled
    """
    if self._config.create_build_scheduler:
        self._create_build_trigger_on_schedule(scope)

    if self._config.build_after_deployment:
        self._add_start_build_api_dependency(scope)

_configure_project_permissions(codebuild_project)

Configure IAM permissions for ECR access and cross-account roles.

Parameters:

Name Type Description Default
codebuild_project Project

CodeBuild project to configure permissions for

required
Side Effects

Grants ECR pull/push permissions to CodeBuild project Adds cross-account role assumption policy to project role Configures S3 logging permissions if applicable

Source code in mare_aws_common_lib/builders/codebuild_builder.py
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
def _configure_project_permissions(self, codebuild_project: codebuild.Project) -> None:
    """Configure IAM permissions for ECR access and cross-account roles.

    Args:
        codebuild_project: CodeBuild project to configure permissions for

    Side Effects:
        Grants ECR pull/push permissions to CodeBuild project
        Adds cross-account role assumption policy to project role
        Configures S3 logging permissions if applicable
    """
    # Grant CodeBuild permissions to interact with ECR
    self._config.ecr_repo.grant_pull_push(codebuild_project)

    # Add cross-account role assumption policy
    codebuild_project.add_to_role_policy(
        iam.PolicyStatement(
            actions=["sts:AssumeRole"],
            resources=[
                f"arn:aws:iam::{Aws.ACCOUNT_ID}:role/"
                f"{self._application_helper.get_from_common('cross_account_role')}"
            ]
        )
    )

    self._configure_logs_permissions()

_control_consistency()

Validate builder configuration and internal state consistency.

Ensures codebuild_type is set and validates the complete configuration using the CodebuildConfig model.

Raises:

Type Description
ValueError

If codebuild_type is not set

ValidationError

If configuration validation fails

Source code in mare_aws_common_lib/builders/codebuild_builder.py
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
def _control_consistency(self) -> None:
    """Validate builder configuration and internal state consistency.

    Ensures codebuild_type is set and validates the complete
    configuration using the CodebuildConfig model.

    Raises:
        ValueError: If codebuild_type is not set
        ValidationError: If configuration validation fails
    """
    super()._control_consistency()

    if not self._codebuild_type:
        raise ValueError("Codebuild Type must be set before building.")

    self._set_config()

_create_build_trigger_on_schedule(scope)

Create EventBridge rule to trigger builds on a weekly schedule.

Parameters:

Name Type Description Default
scope Construct

CDK construct scope

required
Side Effects

Creates EventBridge Rule that triggers builds every Monday at 00:30 UTC Adds CodeBuild project as target for the rule

Source code in mare_aws_common_lib/builders/codebuild_builder.py
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
def _create_build_trigger_on_schedule(self, scope: Construct) -> None:
    """Create EventBridge rule to trigger builds on a weekly schedule.

    Args:
        scope: CDK construct scope

    Side Effects:
        Creates EventBridge Rule that triggers builds every Monday at 00:30 UTC
        Adds CodeBuild project as target for the rule
    """
    # EventBridge Rule to trigger build every Monday
    rule = events.Rule(
        scope, self._get_cfn_logical_id("scheduler-rule"),
        schedule=events.Schedule.cron(minute="30", hour="0", week_day="MON")  # Runs every Monday at 00:30 UTC
    )
    rule.add_target(targets.CodeBuildProject(self._codebuild_project))

_create_codebuild_project(scope)

Create the appropriate CodeBuild project based on configuration type.

Parameters:

Name Type Description Default
scope Construct

CDK construct scope

required

Returns:

Type Description
IProject

CodeBuild Project or PipelineProject instance

Source code in mare_aws_common_lib/builders/codebuild_builder.py
73
74
75
76
77
78
79
80
81
82
83
84
85
def _create_codebuild_project(self, scope: Construct) -> codebuild.IProject:
    """Create the appropriate CodeBuild project based on configuration type.

    Args:
        scope: CDK construct scope

    Returns:
        CodeBuild Project or PipelineProject instance
    """
    if self._config.codebuild_type == CodebuildType.PROJECT:
        return self._create_project(scope)
    else:
        return self._create_pipeline_project(scope)

_create_pipeline_project(scope)

Create a pipeline-integrated CodeBuild project for CI/CD workflows.

Parameters:

Name Type Description Default
scope Construct

CDK construct scope

required

Returns:

Type Description
PipelineProject

Configured CodeBuild PipelineProject instance

Side Effects

Creates CodeBuild PipelineProject in AWS Configures S3 logging permissions if logs bucket specified

Source code in mare_aws_common_lib/builders/codebuild_builder.py
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
def _create_pipeline_project(self, scope: Construct) -> codebuild.PipelineProject:
    """Create a pipeline-integrated CodeBuild project for CI/CD workflows.

    Args:
        scope: CDK construct scope

    Returns:
        Configured CodeBuild PipelineProject instance

    Side Effects:
        Creates CodeBuild PipelineProject in AWS
        Configures S3 logging permissions if logs bucket specified
    """
    use_ami = self._config.ami_ecr_repo is not None
    project_name, logical_id = self._generate_project_identifiers(
        CodebuildType.PIPELINE_PROJECT, 
        suffix=self._config.pipeline_type.value
    )

    build_spec = codebuild.BuildSpec.from_source_filename(self._config.buildspec_path) if self._config.buildspec_path else None

    codebuild_pipeline_project = codebuild.PipelineProject(
        scope, logical_id,
        vpc=self._config.vpc,
        role=self._config.role,
        project_name= project_name,
        build_spec=build_spec,
        environment=self._get_build_environment(use_ami),
        environment_variables=self._config.env_vars,
        logging=self._get_logging_options(),
        security_groups=self._config.security_groups
    )

    self._configure_logs_permissions()

    return codebuild_pipeline_project

_create_project(scope)

Create a standalone CodeBuild project with git source and ECR integration.

Parameters:

Name Type Description Default
scope Construct

CDK construct scope

required

Returns:

Type Description
IProject

Configured CodeBuild Project instance

Side Effects

Creates CodeBuild Project in AWS Configures ECR and cross-account IAM permissions

Source code in mare_aws_common_lib/builders/codebuild_builder.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
def _create_project(self, scope: Construct) -> codebuild.IProject:
    """Create a standalone CodeBuild project with git source and ECR integration.

    Args:
        scope: CDK construct scope

    Returns:
        Configured CodeBuild Project instance

    Side Effects:
        Creates CodeBuild Project in AWS
        Configures ECR and cross-account IAM permissions
    """
    project_name, logical_id = self._generate_project_identifiers(CodebuildType.PROJECT)

    codebuild_project = codebuild.Project(
        scope, logical_id,
        vpc=self._config.vpc,
        role=self._config.role,
        project_name=project_name,
        source=self._create_source(),
        environment=self._get_build_environment(),
        environment_variables={
            "ECR_REPO_URI": codebuild.BuildEnvironmentVariable(value=self._config.typed.ecr_repo.repository_uri),
            "AWS_ACCOUNT_ID": codebuild.BuildEnvironmentVariable(value=Aws.ACCOUNT_ID),
            "AWS_REGION": codebuild.BuildEnvironmentVariable(value=Aws.REGION),
            "PROJECT_NAME": codebuild.BuildEnvironmentVariable(value=self._application_helper.get_project().upper())
        },
        build_spec=codebuild.BuildSpec.from_source_filename(self._config.buildspec_path),
        logging=self._get_logging_options(),
        security_groups=self._config.security_groups
    )

    self._configure_project_permissions(codebuild_project)

    return codebuild_project

_create_source()

Create CodeBuild source configuration based on git provider (currently only supports CODECOMMIT).

Returns:

Type Description
Source

CodeBuild Source configuration

Raises:

Type Description
ValueError

If git provider is not supported

Source code in mare_aws_common_lib/builders/codebuild_builder.py
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
def _create_source(self) -> codebuild.Source:
    """Create CodeBuild source configuration based on git provider (currently only supports CODECOMMIT).

    Returns:
        CodeBuild Source configuration

    Raises:
        ValueError: If git provider is not supported
    """
    match self._config.git_provider:
        case GitProvider.CODECOMMIT:
            return codebuild.Source.code_commit(
                repository=self._config.git_repo,
                branch_or_ref=self._config.git_branch
            )
        case _:
            raise ValueError(f"Unsupported git provider: {self._config.git_provider}. "
                           f"Supported providers: {', '.join([p.value for p in GitProvider])}")

_generate_project_identifiers(project_type, suffix=None)

Generate project name and logical ID following organizational patterns.

Parameters:

Name Type Description Default
project_type CodebuildType

Type of CodeBuild project

required
suffix str

Optional suffix for project naming

None

Returns:

Type Description
tuple[str, str]

Tuple of (project_name, logical_id)

Source code in mare_aws_common_lib/builders/codebuild_builder.py
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
def _generate_project_identifiers(self, project_type: CodebuildType, suffix: str = None) -> tuple[str, str]:
    """Generate project name and logical ID following organizational patterns.

    Args:
        project_type: Type of CodeBuild project
        suffix: Optional suffix for project naming

    Returns:
        Tuple of (project_name, logical_id)
    """
    resource_name = project_type.name
    base_logical_id = project_type.name

    if suffix:
        resource_name = f"{resource_name}-{suffix}"
        base_logical_id = f"{base_logical_id}-{suffix}"

    if self._config.usage_context:
        resource_name = f"{resource_name}-{self._config.usage_context}"
        base_logical_id = f"{base_logical_id}-{self._config.usage_context}"

    project_name = self._get_name_for_resource(
        resource_name, 
        max_length=AWSResourceNameLength.CODEBUILD_PIPELINE_PROJECT.value
    )
    logical_id = self._get_cfn_logical_id(base_logical_id)

    return project_name, logical_id

_get_build_environment(use_ami=False)

Create build environment configuration with proper image and compute settings.

Parameters:

Name Type Description Default
use_ami bool

Whether to use AMI from ECR repository

False

Returns:

Type Description
BuildEnvironment

Configured CodeBuild BuildEnvironment

Source code in mare_aws_common_lib/builders/codebuild_builder.py
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
def _get_build_environment(self, use_ami: bool = False) -> codebuild.BuildEnvironment:
    """Create build environment configuration with proper image and compute settings.

    Args:
        use_ami: Whether to use AMI from ECR repository

    Returns:
        Configured CodeBuild BuildEnvironment
    """
    codebuild_env: codebuild.BuildEnvironment = None
    if use_ami:
        codebuild_env = codebuild.BuildEnvironment(
            build_image=codebuild.LinuxBuildImage.from_ecr_repository(
                self._config.ami_ecr_repo,
                tag_or_digest="latest"
            ),
            compute_type=self._config.compute_type,
            privileged=self._config.privileged
        )
    else:
        codebuild_env = codebuild.BuildEnvironment(
            build_image=self._config.build_image,
            compute_type=self._config.compute_type,
            privileged=self._config.privileged
        )

    return codebuild_env

_get_logging_options()

Configure logging options for S3 or default CloudWatch logging.

Returns:

Type Description
LoggingOptions

LoggingOptions if S3 bucket configured, None for default CloudWatch logging

Source code in mare_aws_common_lib/builders/codebuild_builder.py
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
def _get_logging_options(self) -> codebuild.LoggingOptions:
    """Configure logging options for S3 or default CloudWatch logging.

    Returns:
        LoggingOptions if S3 bucket configured, None for default CloudWatch logging
    """
    if self._config.logs_bucket is not None:
        return codebuild.LoggingOptions(
            s3=codebuild.S3LoggingOptions(
                bucket=self._config.logs_bucket,
                enabled=True
            ),
            cloud_watch=codebuild.CloudWatchLoggingOptions(
                enabled=False
            )
        )
    return None # AWS will by default enable CloudWatch logs and create the LogGroup automatically

_set_config()

Create and validate the CodeBuild project configuration.

Merges builder configuration with project type to create a validated CodebuildConfig object for project creation.

Raises:

Type Description
ValidationError

If the CodebuildConfig validation fails

Source code in mare_aws_common_lib/builders/codebuild_builder.py
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
def _set_config(self) -> None:
    """Create and validate the CodeBuild project configuration.

    Merges builder configuration with project type to create a validated
    CodebuildConfig object for project creation.

    Raises:
        ValidationError: If the CodebuildConfig validation fails
    """
    try:
        self._config = CodebuildConfig(**{
            **self._builder_config,
            "codebuild_type": self._codebuild_type
        })
    except ValidationError as e:
        self._log_validation_error(e, CodebuildConfig)
        raise

build(scope)

Build and return the configured CodeBuild project.

Creates a CodeBuild project with the specified configuration, sets up permissions, configures optional features like scheduling and immediate builds.

Parameters:

Name Type Description Default
scope Construct

CDK construct scope where the project will be created

required

Returns:

Type Description
IProject

Configured CodeBuild Project instance

Raises:

Type Description
ValidationError

If project configuration validation fails

ValueError

If codebuild_type is not set

Source code in mare_aws_common_lib/builders/codebuild_builder.py
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
def build(self, scope : Construct) -> codebuild.IProject:
    """Build and return the configured CodeBuild project.

    Creates a CodeBuild project with the specified configuration, sets up
    permissions, configures optional features like scheduling and immediate builds.

    Args:
        scope: CDK construct scope where the project will be created

    Returns:
        Configured CodeBuild Project instance

    Raises:
        ValidationError: If project configuration validation fails
        ValueError: If codebuild_type is not set
    """
    super().build()

    self._codebuild_project = self._create_codebuild_project(scope)
    self._configure_optional_features(scope)
    self._tag_resource(self._codebuild_project)

    return self._codebuild_project

reset()

Reset the builder to its initial state.

Clears all internal state including project type and CodeBuild project instance. Called internally to prepare for a new build.

Source code in mare_aws_common_lib/builders/codebuild_builder.py
27
28
29
30
31
32
33
34
35
def reset(self) -> None:
    """Reset the builder to its initial state.

    Clears all internal state including project type and CodeBuild project instance.
    Called internally to prepare for a new build.
    """
    super().reset()
    self._codebuild_type: CodebuildType = None
    self._codebuild_project: codebuild.IProject = None

set_codebuild_type(codebuild_type)

Set the CodeBuild project type.

Parameters:

Name Type Description Default
codebuild_type CodebuildType

Type of CodeBuild project (PROJECT or PIPELINE_PROJECT)

required

Returns:

Type Description
CodebuildBuilder

Self for method chaining

Source code in mare_aws_common_lib/builders/codebuild_builder.py
37
38
39
40
41
42
43
44
45
46
47
def set_codebuild_type(self, codebuild_type: CodebuildType) -> 'CodebuildBuilder': 
    """Set the CodeBuild project type.

    Args:
        codebuild_type: Type of CodeBuild project (PROJECT or PIPELINE_PROJECT)

    Returns:
        Self for method chaining
    """
    self._codebuild_type = codebuild_type
    return self