55# render the same versions as the workflows built here.
66GITHUB_ACTIONS = {
77 "checkout" : "actions/checkout@v7" ,
8+ "cache_restore" : "actions/cache/restore@v6" ,
9+ "cache_save" : "actions/cache/save@v6" ,
810 "configure_aws_credentials" : "aws-actions/configure-aws-credentials@v6" ,
911 "semantic_pull_request" : "amannn/action-semantic-pull-request@v6" ,
1012 "setup_python" : "actions/setup-python@v7" ,
@@ -18,7 +20,7 @@ def pin_github_actions(gh):
1820 gh .actions .set (action .split ("@" )[0 ], action )
1921
2022
21- def cdk_environment_steps (python_version , cdk_cli_version ):
23+ def cdk_environment_steps (python_version , cdk_cli_version , aws_credentials = None ):
2224 """Checkout, Python, uv, project dependencies and the CDK CLI."""
2325 return [
2426 {
@@ -38,19 +40,85 @@ def cdk_environment_steps(python_version, cdk_cli_version):
3840 "name" : "Setup uv" ,
3941 "uses" : GITHUB_ACTIONS ["setup_uv" ],
4042 },
43+ * ([aws_credentials ] if aws_credentials else []),
4144 {
4245 "name" : "Install dependencies" ,
43- "run" : "uv sync" ,
46+ "run" : "uv sync --frozen " ,
4447 },
4548 {
4649 "name" : "Install cdk cli" ,
4750 "run" : f"npm install -g aws-cdk@{ cdk_cli_version } " ,
4851 },
52+ * (
53+ [
54+ {
55+ "name" : "Wait for AWS authentication" ,
56+ "wait" : ["configure_aws_credentials" ],
57+ }
58+ ]
59+ if aws_credentials
60+ else []
61+ ),
4962 ]
5063
5164
52- def cdk_validate_workflow (gh , python_version , cdk_cli_version ):
65+ def docker_asset_cache_steps ():
66+ """Restore content-addressed bundling images; skip uploads for apps without Docker assets."""
67+ cache_path = "${{ runner.temp }}/docker-assets"
68+ cache_prefix = "docker-assets-v2-${{ runner.os }}-${{ runner.arch }}-${{ steps.docker_cache_epoch.outputs.week }}-"
69+ restore = [
70+ {
71+ "name" : "Choose Docker cache refresh week" ,
72+ "id" : "docker_cache_epoch" ,
73+ "run" : 'echo "week=$(date -u +%G-%V)" >> "$GITHUB_OUTPUT"\n echo "source=$(git rev-parse "HEAD^{tree}")" >> "$GITHUB_OUTPUT"' ,
74+ },
75+ {
76+ "name" : "Restore Docker asset images" ,
77+ "id" : "docker_cache" ,
78+ "uses" : GITHUB_ACTIONS ["cache_restore" ],
79+ "with" : {
80+ "path" : cache_path ,
81+ "key" : cache_prefix + "${{ steps.docker_cache_epoch.outputs.source }}" ,
82+ "restore-keys" : cache_prefix ,
83+ },
84+ },
85+ {
86+ "name" : "Load Docker asset images" ,
87+ "run" : 'if [ -f "$RUNNER_TEMP/docker-assets/images.tar" ]; then docker load --input "$RUNNER_TEMP/docker-assets/images.tar"; fi' ,
88+ },
89+ ]
90+ save = [
91+ {
92+ "name" : "Export Docker asset images" ,
93+ "id" : "export_docker_images" ,
94+ "if" : "steps.docker_cache.outputs.cache-hit != 'true'" ,
95+ "shell" : "bash" ,
96+ "run" : (
97+ "images=()\n "
98+ 'while IFS= read -r image; do images+=("$image"); done < <(docker image ls --filter "reference=cdk-*" --format "{{.Repository}}:{{.Tag}}")\n '
99+ 'if [ "${#images[@]}" -gt 0 ]; then\n '
100+ ' mkdir -p "$RUNNER_TEMP/docker-assets"\n '
101+ ' docker save --output "$RUNNER_TEMP/docker-assets/images.tar" "${images[@]}"\n '
102+ ' echo "has-images=true" >> "$GITHUB_OUTPUT"\n '
103+ "fi"
104+ ),
105+ },
106+ {
107+ "name" : "Save Docker asset images" ,
108+ "if" : "steps.export_docker_images.outputs.has-images == 'true'" ,
109+ "uses" : GITHUB_ACTIONS ["cache_save" ],
110+ "with" : {
111+ "path" : cache_path ,
112+ "key" : "${{ steps.docker_cache.outputs.cache-primary-key }}" ,
113+ },
114+ },
115+ ]
116+ return restore , save
117+
118+
119+ def cdk_validate_workflow (gh , python_version , cdk_cli_version , environments ):
53120 """Validate the CDK app offline on pull requests, without AWS credentials."""
121+ restore_cache , save_cache = docker_asset_cache_steps ()
54122 workflow = github .GithubWorkflow (gh , "cdk-validate" )
55123 workflow .on (pull_request = {}, workflow_dispatch = {})
56124 workflow .add_jobs (
@@ -63,10 +131,30 @@ def cdk_validate_workflow(gh, python_version, cdk_cli_version):
63131 },
64132 "steps" : [
65133 * cdk_environment_steps (python_version , cdk_cli_version ),
134+ * restore_cache ,
135+ * [
136+ {
137+ "id" : f"validate_{ env } " ,
138+ "name" : f"Validate { env } offline" ,
139+ "background" : True ,
140+ "run" : f'uv run projen { env } :validate --no-online --output "${{{{ runner.temp }}}}/cdk-assemblies/{ env } "' ,
141+ }
142+ for env in environments
143+ ],
66144 {
67- "name" : "Validate CDK app against the default rule set" ,
68- "run" : "uv run projen validate" ,
145+ "id" : "unit_tests" ,
146+ "name" : "Run tests" ,
147+ "background" : True ,
148+ "run" : "uv run projen test" ,
69149 },
150+ {
151+ "name" : "Wait for validation and tests" ,
152+ "wait" : [
153+ * [f"validate_{ env } " for env in environments ],
154+ "unit_tests" ,
155+ ],
156+ },
157+ * save_cache ,
70158 ],
71159 },
72160 }
@@ -93,15 +181,20 @@ def github_cicd(gh, account, env, python_version, aws_region, cdk_cli_version):
93181 "idToken" : github .workflows .JobPermission .WRITE ,
94182 },
95183 "steps" : [
96- * cdk_environment_steps (python_version , cdk_cli_version ),
97- {
98- "name" : "Configure AWS credentials" ,
99- "uses" : GITHUB_ACTIONS ["configure_aws_credentials" ],
100- "with" : {
101- "role-to-assume" : f"arn:aws:iam::{ account } :role/GitHubDeployRole" ,
102- "aws-region" : aws_region ,
184+ * cdk_environment_steps (
185+ python_version ,
186+ cdk_cli_version ,
187+ aws_credentials = {
188+ "id" : "configure_aws_credentials" ,
189+ "name" : "Configure AWS credentials" ,
190+ "background" : True ,
191+ "uses" : GITHUB_ACTIONS ["configure_aws_credentials" ],
192+ "with" : {
193+ "role-to-assume" : f"arn:aws:iam::{ account } :role/GitHubDeployRole" ,
194+ "aws-region" : aws_region ,
195+ },
103196 },
104- } ,
197+ ) ,
105198 {
106199 "name" : f"Validate CDK for the { env .upper ()} environment" ,
107200 "run" : f"uv run projen { env } :validate" ,
0 commit comments