From e900e15d1cdf3a7b0abea89bc76b95909b76683f Mon Sep 17 00:00:00 2001 From: James Kent Date: Tue, 31 Mar 2026 20:50:29 -0500 Subject: [PATCH 1/2] refactor aws stack - move to cold storage for results - explicitly name and control the lambda and ecs images - lower storage to 20gb --- .github/workflows/deploy.yml | 63 +++++++++- Dockerfile | 3 + infra/cdk/app.py | 24 ++-- infra/cdk/stacks/__init__.py | 3 +- infra/cdk/stacks/compose_runner_stack.py | 122 +++++++++++-------- infra/cdk/stacks/image_repositories_stack.py | 61 ++++++++++ infra/cdk/tests/test_compose_runner_stack.py | 47 +++++++ 7 files changed, 260 insertions(+), 63 deletions(-) create mode 100644 infra/cdk/stacks/image_repositories_stack.py create mode 100644 infra/cdk/tests/test_compose_runner_stack.py diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2152923..0ba5cc1 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -11,6 +11,9 @@ permissions: jobs: deploy: runs-on: ubuntu-latest + env: + ECS_IMAGE_REPOSITORY: compose-runner-ecs + LAMBDA_IMAGE_REPOSITORY: compose-runner-lambda steps: - name: Checkout @@ -35,7 +38,7 @@ jobs: pip install -r requirements.txt - name: Install AWS CDK CLI - run: npm install -g aws-cdk@2.130.0 --registry=https://registry.npmjs.org + run: npm install -g aws-cdk@2.1107.0 --registry=https://registry.npmjs.org - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 @@ -43,6 +46,47 @@ jobs: role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} aws-region: ${{ secrets.AWS_REGION }} + - name: Deploy image repository stack + working-directory: infra/cdk + run: | + source .venv/bin/activate + cdk deploy \ + ComposeRunnerImageRepositoriesStack \ + --require-approval never + + - name: Log in to Amazon ECR + run: | + AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) + ECR_REGISTRY="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com" + echo "ECR_REGISTRY=${ECR_REGISTRY}" >> "$GITHUB_ENV" + aws ecr get-login-password | docker login --username AWS --password-stdin "$ECR_REGISTRY" + + - name: Build and push release images + env: + VERSION: ${{ github.event.release.tag_name }} + run: | + if [ -z "$VERSION" ]; then + echo "Release tag name is required to publish ECR images" + exit 1 + fi + + ECS_IMAGE_URI="${ECR_REGISTRY}/${ECS_IMAGE_REPOSITORY}:${VERSION}" + LAMBDA_IMAGE_URI="${ECR_REGISTRY}/${LAMBDA_IMAGE_REPOSITORY}:${VERSION}" + + docker build \ + --file Dockerfile \ + --build-arg COMPOSE_RUNNER_VERSION="${VERSION}" \ + --tag "${ECS_IMAGE_URI}" \ + . + docker push "${ECS_IMAGE_URI}" + + docker build \ + --file aws_lambda/Dockerfile \ + --build-arg COMPOSE_RUNNER_VERSION="${VERSION}" \ + --tag "${LAMBDA_IMAGE_URI}" \ + . + docker push "${LAMBDA_IMAGE_URI}" + - name: Deploy CDK stack working-directory: infra/cdk env: @@ -50,10 +94,11 @@ jobs: TASK_CPU: 4096 TASK_MEMORY_MIB: 30720 STATE_MACHINE_TIMEOUT_SECONDS: 7200 + VERSION: ${{ github.event.release.tag_name }} run: | source .venv/bin/activate - VERSION=${GITHUB_REF_NAME} cdk deploy \ + ComposeRunnerStack \ --require-approval never \ --outputs-file cdk-outputs.json \ -c composeRunnerVersion=${VERSION} \ @@ -112,3 +157,17 @@ jobs: echo "Status response missing status: $status_json" exit 1 fi + + - name: Garbage collect unused CDK bootstrap S3 assets + working-directory: infra/cdk + run: | + source .venv/bin/activate + AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) + cdk gc \ + "aws://${AWS_ACCOUNT_ID}/${AWS_REGION}" \ + --unstable=gc \ + --type=s3 \ + --action=full \ + --created-buffer-days=7 \ + --rollback-buffer-days=30 \ + --confirm false diff --git a/Dockerfile b/Dockerfile index 6947c2e..fe876a1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,9 @@ FROM public.ecr.aws/docker/library/python:3.13-slim ARG COMPOSE_RUNNER_VERSION ENV COMPOSE_RUNNER_VERSION=${COMPOSE_RUNNER_VERSION} +ENV HATCH_BUILD_VERSION=${COMPOSE_RUNNER_VERSION} +ENV SETUPTOOLS_SCM_PRETEND_VERSION=${COMPOSE_RUNNER_VERSION} +ENV SETUPTOOLS_SCM_PRETEND_VERSION_FOR_COMPOSE_RUNNER=${COMPOSE_RUNNER_VERSION} LABEL org.opencontainers.image.title="compose-runner ecs task" LABEL org.opencontainers.image.version=${COMPOSE_RUNNER_VERSION} diff --git a/infra/cdk/app.py b/infra/cdk/app.py index e4e3c8f..af2d176 100644 --- a/infra/cdk/app.py +++ b/infra/cdk/app.py @@ -6,21 +6,31 @@ import aws_cdk as cdk -from stacks.compose_runner_stack import ComposeRunnerStack +from stacks import ComposeRunnerImageRepositoriesStack, ComposeRunnerStack def main() -> None: app = cdk.App() + env = cdk.Environment( + account=os.getenv("CDK_DEFAULT_ACCOUNT"), + region=os.getenv("CDK_DEFAULT_REGION"), + ) - ComposeRunnerStack( + image_repositories_stack = ComposeRunnerImageRepositoriesStack( app, - "ComposeRunnerStack", - env=cdk.Environment( - account=os.getenv("CDK_DEFAULT_ACCOUNT"), - region=os.getenv("CDK_DEFAULT_REGION"), - ), + "ComposeRunnerImageRepositoriesStack", + env=env, ) + if app.node.try_get_context("composeRunnerVersion"): + ComposeRunnerStack( + app, + "ComposeRunnerStack", + ecs_image_repository=image_repositories_stack.ecs_image_repository, + lambda_image_repository=image_repositories_stack.lambda_image_repository, + env=env, + ) + app.synth() diff --git a/infra/cdk/stacks/__init__.py b/infra/cdk/stacks/__init__.py index feab5c0..1175460 100644 --- a/infra/cdk/stacks/__init__.py +++ b/infra/cdk/stacks/__init__.py @@ -1,3 +1,4 @@ +from .image_repositories_stack import ComposeRunnerImageRepositoriesStack from .compose_runner_stack import ComposeRunnerStack -__all__ = ["ComposeRunnerStack"] +__all__ = ["ComposeRunnerImageRepositoriesStack", "ComposeRunnerStack"] diff --git a/infra/cdk/stacks/compose_runner_stack.py b/infra/cdk/stacks/compose_runner_stack.py index 3cc99ee..649bf26 100644 --- a/infra/cdk/stacks/compose_runner_stack.py +++ b/infra/cdk/stacks/compose_runner_stack.py @@ -1,14 +1,12 @@ from __future__ import annotations -from pathlib import Path - import aws_cdk as cdk from aws_cdk import ( Duration, RemovalPolicy, Stack, aws_ec2 as ec2, - aws_ecr_assets as ecr_assets, + aws_ecr as ecr, aws_ecs as ecs, aws_iam as iam, aws_lambda as lambda_, @@ -23,7 +21,15 @@ class ComposeRunnerStack(Stack): """Provision Step Functions + ECS infrastructure for compose-runner workflows.""" - def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> None: + def __init__( + self, + scope: Construct, + construct_id: str, + *, + ecs_image_repository: ecr.IRepository, + lambda_image_repository: ecr.IRepository, + **kwargs: object, + ) -> None: super().__init__(scope, construct_id, **kwargs) # Context configuration with sensible defaults. @@ -40,7 +46,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> Non task_cpu = int(self.node.try_get_context("taskCpu") or 4096) task_memory_mib = int(self.node.try_get_context("taskMemoryMiB") or 30720) - task_ephemeral_storage_gib = int(self.node.try_get_context("taskEphemeralStorageGiB") or 21) + task_ephemeral_storage_gib = int(self.node.try_get_context("taskEphemeralStorageGiB") or 20) task_cpu_large = int(self.node.try_get_context("taskCpuLarge") or 16384) task_memory_large_mib = int(self.node.try_get_context("taskMemoryLargeMiB") or 65536) state_machine_timeout_seconds = int(self.node.try_get_context("stateMachineTimeoutSeconds") or 32400) @@ -48,7 +54,6 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> Non if task_cpu_large >= 16384 and task_memory_large_mib < 32768: raise ValueError("taskMemoryLargeMiB must be at least 32768 MiB for 16 vCPU tasks.") - project_root = Path(__file__).resolve().parents[3] project_version = self.node.try_get_context("composeRunnerVersion") if not project_version: raise ValueError( @@ -60,7 +65,6 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> Non "submitMemorySize cannot exceed 3008 MB when using the Python 3.13 Lambda runtime. " "Pass a smaller value via `-c submitMemorySize=` or adjust the default." ) - build_args = {"COMPOSE_RUNNER_VERSION": project_version} # Bucket for storing workflow artifacts. if results_bucket_name: @@ -74,19 +78,21 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> Non block_public_access=s3.BlockPublicAccess.BLOCK_ALL, encryption=s3.BucketEncryption.S3_MANAGED, enforce_ssl=True, + lifecycle_rules=[ + s3.LifecycleRule( + id="TransitionResultsToIntelligentTiering", + transitions=[ + s3.Transition( + storage_class=s3.StorageClass.INTELLIGENT_TIERING, + transition_after=Duration.days(0), + ) + ], + ) + ], versioned=True, removal_policy=RemovalPolicy.RETAIN, ) - # Build Docker image for ECS Fargate task. - fargate_asset = ecr_assets.DockerImageAsset( - self, - "ComposeRunnerFargateImage", - directory=str(project_root), - file="Dockerfile", - build_args=build_args, - ) - # Networking for ECS tasks (public subnets with internet access). vpc = ec2.Vpc( self, @@ -119,20 +125,28 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> Non removal_policy=RemovalPolicy.RETAIN, ) + task_definition_kwargs: dict[str, object] = { + "cpu": task_cpu, + "memory_limit_mib": task_memory_mib, + } + task_definition_large_kwargs: dict[str, object] = { + "cpu": task_cpu_large, + "memory_limit_mib": task_memory_large_mib, + } + if task_ephemeral_storage_gib > 20: + task_definition_kwargs["ephemeral_storage_gib"] = task_ephemeral_storage_gib + task_definition_large_kwargs["ephemeral_storage_gib"] = task_ephemeral_storage_gib + task_definition = ecs.FargateTaskDefinition( self, "ComposeRunnerTaskDefinition", - cpu=task_cpu, - memory_limit_mib=task_memory_mib, - ephemeral_storage_gib=task_ephemeral_storage_gib, + **task_definition_kwargs, ) task_definition_large = ecs.FargateTaskDefinition( self, "ComposeRunnerLargeTaskDefinition", - cpu=task_cpu_large, - memory_limit_mib=task_memory_large_mib, - ephemeral_storage_gib=task_ephemeral_storage_gib, + **task_definition_large_kwargs, ) container_environment = { @@ -143,7 +157,10 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> Non container = task_definition.add_container( "ComposeRunnerContainer", - image=ecs.ContainerImage.from_docker_image_asset(fargate_asset), + image=ecs.ContainerImage.from_ecr_repository( + ecs_image_repository, + tag=project_version, + ), entry_point=["python", "-m", "compose_runner.ecs_task"], logging=ecs.LogDriver.aws_logs( log_group=task_log_group, @@ -154,7 +171,10 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> Non container_large = task_definition_large.add_container( "ComposeRunnerLargeContainer", - image=ecs.ContainerImage.from_docker_image_asset(fargate_asset), + image=ecs.ContainerImage.from_ecr_repository( + ecs_image_repository, + tag=project_version, + ), entry_point=["python", "-m", "compose_runner.ecs_task"], logging=ecs.LogDriver.aws_logs( log_group=task_log_group, @@ -244,12 +264,16 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> Non max_attempts=2, ) - cost_check_code = lambda_.DockerImageCode.from_image_asset( - str(project_root), - file="aws_lambda/Dockerfile", - cmd=["compose_runner.aws_lambda.cost_check_handler.handler"], - build_args=build_args, - ) + def lambda_image_code(handler: str | None = None) -> lambda_.DockerImageCode: + kwargs: dict[str, object] = { + "repository": lambda_image_repository, + "tag_or_digest": project_version, + } + if handler is not None: + kwargs["cmd"] = [handler] + return lambda_.DockerImageCode.from_ecr(**kwargs) + + cost_check_code = lambda_image_code("compose_runner.aws_lambda.cost_check_handler.handler") cost_check_function = lambda_.DockerImageFunction( self, @@ -322,11 +346,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> Non ) # Lambda image shared across handlers. - lambda_code = lambda_.DockerImageCode.from_image_asset( - str(project_root), - file="aws_lambda/Dockerfile", - build_args=build_args, - ) + lambda_code = lambda_image_code() submit_function = lambda_.DockerImageFunction( self, @@ -347,12 +367,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> Non auth_type=lambda_.FunctionUrlAuthType.NONE, ) - status_code = lambda_.DockerImageCode.from_image_asset( - str(project_root), - file="aws_lambda/Dockerfile", - cmd=["compose_runner.aws_lambda.status_handler.handler"], - build_args=build_args, - ) + status_code = lambda_image_code("compose_runner.aws_lambda.status_handler.handler") status_function = lambda_.DockerImageFunction( self, @@ -373,12 +388,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> Non auth_type=lambda_.FunctionUrlAuthType.NONE, ) - poll_code = lambda_.DockerImageCode.from_image_asset( - str(project_root), - file="aws_lambda/Dockerfile", - cmd=["compose_runner.aws_lambda.log_poll_handler.handler"], - build_args=build_args, - ) + poll_code = lambda_image_code("compose_runner.aws_lambda.log_poll_handler.handler") poll_function = lambda_.DockerImageFunction( self, @@ -405,12 +415,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> Non auth_type=lambda_.FunctionUrlAuthType.NONE, ) - results_code = lambda_.DockerImageCode.from_image_asset( - str(project_root), - file="aws_lambda/Dockerfile", - cmd=["compose_runner.aws_lambda.results_handler.handler"], - build_args=build_args, - ) + results_code = lambda_image_code("compose_runner.aws_lambda.results_handler.handler") results_function = lambda_.DockerImageFunction( self, @@ -441,5 +446,16 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> Non cdk.CfnOutput(self, "ComposeRunnerResultsFunctionName", value=results_function.function_name) cdk.CfnOutput(self, "ComposeRunnerResultsFunctionUrl", value=results_function_url.url) cdk.CfnOutput(self, "ComposeRunnerResultsBucketName", value=results_bucket.bucket_name) + cdk.CfnOutput( + self, + "ComposeRunnerEcsImageRepositoryName", + value=ecs_image_repository.repository_name, + ) + cdk.CfnOutput( + self, + "ComposeRunnerLambdaImageRepositoryName", + value=lambda_image_repository.repository_name, + ) + cdk.CfnOutput(self, "ComposeRunnerImageTag", value=project_version) cdk.CfnOutput(self, "ComposeRunnerStateMachineArn", value=state_machine.state_machine_arn) cdk.CfnOutput(self, "ComposeRunnerTaskLogGroupName", value=task_log_group.log_group_name) diff --git a/infra/cdk/stacks/image_repositories_stack.py b/infra/cdk/stacks/image_repositories_stack.py new file mode 100644 index 0000000..5545a97 --- /dev/null +++ b/infra/cdk/stacks/image_repositories_stack.py @@ -0,0 +1,61 @@ +from __future__ import annotations + +import aws_cdk as cdk +from aws_cdk import RemovalPolicy, Stack, aws_ecr as ecr, aws_iam as iam +from constructs import Construct + + +class ComposeRunnerImageRepositoriesStack(Stack): + """Provision ECR repositories used by compose-runner runtime images.""" + + def __init__(self, scope: Construct, construct_id: str, **kwargs: object) -> None: + super().__init__(scope, construct_id, **kwargs) + + lifecycle_rules = [ + ecr.LifecycleRule( + description="Keep only the latest 2 tagged images.", + max_image_count=2, + tag_status=ecr.TagStatus.TAGGED, + tag_pattern_list=["*"], + ) + ] + + self.ecs_image_repository = ecr.Repository( + self, + "ComposeRunnerEcsImageRepository", + repository_name="compose-runner-ecs", + image_scan_on_push=True, + lifecycle_rules=lifecycle_rules, + removal_policy=RemovalPolicy.RETAIN, + ) + + self.lambda_image_repository = ecr.Repository( + self, + "ComposeRunnerLambdaImageRepository", + repository_name="compose-runner-lambda", + image_scan_on_push=True, + lifecycle_rules=lifecycle_rules, + removal_policy=RemovalPolicy.RETAIN, + ) + self.lambda_image_repository.add_to_resource_policy( + iam.PolicyStatement( + sid="LambdaECRImageRetrievalPolicy", + effect=iam.Effect.ALLOW, + principals=[iam.ServicePrincipal("lambda.amazonaws.com")], + actions=[ + "ecr:BatchGetImage", + "ecr:GetDownloadUrlForLayer", + ], + ) + ) + + cdk.CfnOutput( + self, + "ComposeRunnerEcsImageRepositoryName", + value=self.ecs_image_repository.repository_name, + ) + cdk.CfnOutput( + self, + "ComposeRunnerLambdaImageRepositoryName", + value=self.lambda_image_repository.repository_name, + ) diff --git a/infra/cdk/tests/test_compose_runner_stack.py b/infra/cdk/tests/test_compose_runner_stack.py new file mode 100644 index 0000000..dfe5c1f --- /dev/null +++ b/infra/cdk/tests/test_compose_runner_stack.py @@ -0,0 +1,47 @@ +from __future__ import annotations + +import json +import unittest + +import aws_cdk as cdk +from aws_cdk.assertions import Template + +from stacks import ComposeRunnerImageRepositoriesStack, ComposeRunnerStack + + +class ComposeRunnerStackImageConfigTest(unittest.TestCase): + def test_stack_uses_explicit_ecr_repositories(self) -> None: + app = cdk.App(context={"composeRunnerVersion": "0.7.8"}) + + image_repositories_stack = ComposeRunnerImageRepositoriesStack( + app, + "ComposeRunnerImageRepositoriesStack", + env=cdk.Environment(account="631329474511", region="us-east-1"), + ) + + stack = ComposeRunnerStack( + app, + "ComposeRunnerStack", + ecs_image_repository=image_repositories_stack.ecs_image_repository, + lambda_image_repository=image_repositories_stack.lambda_image_repository, + env=cdk.Environment(account="631329474511", region="us-east-1"), + ) + + repositories_template_json = json.dumps(Template.from_stack(image_repositories_stack).to_json()) + app_template_json = json.dumps(Template.from_stack(stack).to_json()) + + self.assertIn("compose-runner-ecs", repositories_template_json) + self.assertIn("compose-runner-lambda", repositories_template_json) + self.assertIn("Keep only the latest 2 tagged images.", repositories_template_json) + self.assertIn("LambdaECRImageRetrievalPolicy", repositories_template_json) + + self.assertIn("0.7.8", app_template_json) + self.assertIn("ComposeRunnerImageRepositoriesStack:ExportsOutputRef", app_template_json) + self.assertIn("TransitionResultsToIntelligentTiering", app_template_json) + self.assertIn("INTELLIGENT_TIERING", app_template_json) + self.assertNotIn("cdk-hnb659fds-container-assets", app_template_json) + self.assertNotIn("AssetParameters", app_template_json) + + +if __name__ == "__main__": + unittest.main() From fd45d5d8f24f6d1bf34045330a064f2d4ff6b2c1 Mon Sep 17 00:00:00 2001 From: James Kent Date: Thu, 2 Apr 2026 20:33:15 -0500 Subject: [PATCH 2/2] fix stack --- .github/workflows/deploy.yml | 18 ++++++++ infra/cdk/tests/test_compose_runner_stack.py | 45 ++++++++++++++++++-- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0ba5cc1..1ae84ec 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -54,6 +54,24 @@ jobs: ComposeRunnerImageRepositoriesStack \ --require-approval never + - name: Verify ComposeRunnerStack does not synthesize CDK Docker assets + working-directory: infra/cdk + env: + VERSION: ${{ github.event.release.tag_name }} + run: | + source .venv/bin/activate + rm -rf /tmp/compose-runner-cdk-verify + cdk synth \ + ComposeRunnerStack \ + --output /tmp/compose-runner-cdk-verify \ + -c composeRunnerVersion=${VERSION} >/dev/null + jq -e '(.dockerImages // {}) | length == 0' \ + /tmp/compose-runner-cdk-verify/ComposeRunnerStack.assets.json >/dev/null || { + echo "ComposeRunnerStack synthesized Docker image assets; deployment would require the CDK bootstrap ECR repository." + cat /tmp/compose-runner-cdk-verify/ComposeRunnerStack.assets.json + exit 1 + } + - name: Log in to Amazon ECR run: | AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) diff --git a/infra/cdk/tests/test_compose_runner_stack.py b/infra/cdk/tests/test_compose_runner_stack.py index dfe5c1f..debadb7 100644 --- a/infra/cdk/tests/test_compose_runner_stack.py +++ b/infra/cdk/tests/test_compose_runner_stack.py @@ -1,14 +1,25 @@ from __future__ import annotations import json +import sys +import tempfile import unittest +from pathlib import Path -import aws_cdk as cdk -from aws_cdk.assertions import Template +try: + import aws_cdk as cdk + from aws_cdk.assertions import Template +except ModuleNotFoundError: + cdk = None + Template = None -from stacks import ComposeRunnerImageRepositoriesStack, ComposeRunnerStack +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +if cdk is not None: + from stacks import ComposeRunnerImageRepositoriesStack, ComposeRunnerStack + +@unittest.skipIf(cdk is None, "aws_cdk is not installed in this test environment") class ComposeRunnerStackImageConfigTest(unittest.TestCase): def test_stack_uses_explicit_ecr_repositories(self) -> None: app = cdk.App(context={"composeRunnerVersion": "0.7.8"}) @@ -42,6 +53,34 @@ def test_stack_uses_explicit_ecr_repositories(self) -> None: self.assertNotIn("cdk-hnb659fds-container-assets", app_template_json) self.assertNotIn("AssetParameters", app_template_json) + def test_cloud_assembly_does_not_include_docker_image_assets(self) -> None: + with tempfile.TemporaryDirectory() as output_dir: + app = cdk.App( + context={"composeRunnerVersion": "0.7.8"}, + outdir=output_dir, + ) + + image_repositories_stack = ComposeRunnerImageRepositoriesStack( + app, + "ComposeRunnerImageRepositoriesStack", + env=cdk.Environment(account="631329474511", region="us-east-1"), + ) + + ComposeRunnerStack( + app, + "ComposeRunnerStack", + ecs_image_repository=image_repositories_stack.ecs_image_repository, + lambda_image_repository=image_repositories_stack.lambda_image_repository, + env=cdk.Environment(account="631329474511", region="us-east-1"), + ) + + app.synth() + + with open(f"{output_dir}/ComposeRunnerStack.assets.json", encoding="utf-8") as manifest_file: + assets_manifest = json.load(manifest_file) + + self.assertEqual(assets_manifest.get("dockerImages", {}), {}) + if __name__ == "__main__": unittest.main()