11name : Integration Test deployment (Auto)
22
3- # This workflow automatically runs integration tests when a PR with snapshot changes
4- # is approved by a CDK team member. No manual approval required.
3+ # Privileged workflow that runs integration tests when triggered by the
4+ # "Integration Test Auto Trigger" workflow. Uses workflow_run to run in the
5+ # base repo context with access to secrets, vars, and OIDC.
56#
6- # SHADOW MODE: This workflow is in shadow mode - failures don't block PR merges.
7+ # SHADOW MODE: Failures don't block PR merges.
78# Once validated, this will replace the label-based workflow (integration-test-deployment.yml).
89
910on :
10- pull_request_review :
11- types : [submitted]
11+ workflow_run :
12+ workflows : ["Integration Test Auto Trigger"]
13+ types :
14+ - completed
1215
13- concurrency :
14- group : ${{ github.workflow }}-${{ github.event.pull_request.number }}
15- cancel-in-progress : true
16+ permissions :
17+ actions : read # Required to download artifacts from the trigger workflow run
1618
1719jobs :
18- # Early validation: Check if approver is a CDK team member and PR has snapshot changes
19- validate_approver :
20- if : github.event.review.state == 'approved'
20+ pr_info :
21+ if : github.event.workflow_run.conclusion == 'success'
2122 runs-on : ubuntu-latest
2223 outputs :
23- should_run : ${{ steps.check_team.outputs.is_member == 'true' && steps.check_snapshots.outputs.has_snapshots == 'true' }}
24- permissions :
25- contents : read
26- pull-requests : read
24+ pr_number : ${{ steps.pr_output.outputs.pr_number }}
25+ head_sha : ${{ steps.pr_output.outputs.head_sha }}
26+ base_sha : ${{ steps.pr_output.outputs.base_sha }}
27+ reviewer : ${{ steps.pr_output.outputs.reviewer }}
28+ has_context : ${{ steps.download.outcome == 'success' }}
2729 steps :
28- - name : Checkout for path filtering
29- uses : actions/checkout@v6
30- with :
31- ref : ${{ github.event.pull_request.head.sha }}
32- fetch-depth : 0
33-
34- - name : Setup Node.js
35- uses : actions/setup-node@v6
30+ - name : Download trigger context
31+ id : download
32+ uses : actions/download-artifact@v8
33+ continue-on-error : true
3634 with :
37- node-version : " lts/*"
38-
39- - name : Install dependencies
40- run : yarn install --frozen-lockfile
41-
42- - name : Build deployment-integ
43- run : yarn --cwd tools/@aws-cdk/integration-test-deployment build
44-
45- - name : Check for snapshot changes
46- id : check_snapshots
47- env :
48- TARGET_BRANCH_COMMIT : ${{ github.event.pull_request.base.sha }}
49- SOURCE_BRANCH_COMMIT : ${{ github.event.pull_request.head.sha }}
35+ name : integ-test-trigger-context
36+ path : trigger-context/
37+ github-token : ${{ secrets.GITHUB_TOKEN }}
38+ run-id : ${{ github.event.workflow_run.id }}
39+
40+ - name : Parse trigger context
41+ if : steps.download.outcome == 'success'
42+ id : pr_output
5043 run : |
51- # Reuses getChangedSnapshots() from utils.ts — single source of truth
52- if yarn --cwd tools/@aws-cdk/integration-test-deployment check-snapshots; then
53- echo "has_snapshots=true" >> $GITHUB_OUTPUT
54- else
55- echo "has_snapshots=false" >> $GITHUB_OUTPUT
56- fi
44+ echo "pr_number=$(cat trigger-context/pr_number)" >> "$GITHUB_OUTPUT"
45+ echo "head_sha=$(cat trigger-context/head_sha)" >> "$GITHUB_OUTPUT"
46+ echo "base_sha=$(cat trigger-context/base_sha)" >> "$GITHUB_OUTPUT"
47+ echo "reviewer=$(cat trigger-context/reviewer)" >> "$GITHUB_OUTPUT"
5748
49+ validate_approver :
50+ needs : pr_info
51+ if : needs.pr_info.outputs.has_context == 'true'
52+ runs-on : ubuntu-latest
53+ outputs :
54+ is_member : ${{ steps.check_team.outputs.is_member }}
55+ steps :
5856 - name : Check if approver is CDK team member
5957 id : check_team
60- if : steps.check_snapshots.outputs.has_snapshots == 'true'
6158 env :
6259 GITHUB_TOKEN : ${{ secrets.PROJEN_GITHUB_TOKEN }}
63- APPROVER : ${{ github.event.review.user.login }}
60+ APPROVER : ${{ needs.pr_info.outputs.reviewer }}
6461 run : |
65- # Use gh CLI to check team membership (pre-installed in GitHub Actions runners)
66- # https://docs.github.com/en/rest/teams/members#get-team-membership-for-a-user
6762 if gh api "orgs/aws/teams/aws-cdk-team/memberships/${APPROVER}" --jq '.state' 2>/dev/null | grep -q "active"; then
6863 echo "${APPROVER} is an active CDK team member"
6964 echo "is_member=true" >> $GITHUB_OUTPUT
@@ -73,29 +68,49 @@ jobs:
7368 fi
7469
7570 integration_test_deployment_auto :
76- needs : validate_approver
77- # Only run if approver is a CDK team member AND PR has snapshot changes
78- if : needs.validate_approver.outputs.should_run == 'true'
71+ needs : [pr_info, validate_approver]
72+ if : needs.validate_approver.outputs.is_member == 'true'
7973 runs-on : codebuild-aws-cdk-github-actions-deployment-integ-runner-${{ github.run_id }}-${{ github.run_attempt }}
80- # No environment - runs automatically without manual approval
74+ timeout-minutes : 7200 # Maximum limit for self-hosted runners, job can still be limited by our runner timeout (which is set at 36 hours).
8175 # Shadow mode: workflow reports success even if tests fail
8276 continue-on-error : true
8377 name : ' Deploy integration test snapshots (Auto)'
78+ # Cancel previous deployment for the same PR (uses artifact-sourced PR number, works for fork PRs)
79+ concurrency :
80+ group : integ-test-auto-${{ needs.pr_info.outputs.pr_number }}
81+ cancel-in-progress : true
8482
85- # Job-level permissions for least privilege
8683 permissions :
8784 id-token : write # Required for OIDC authentication with AWS Atmosphere
88- pull-requests : read # Required to check PR reviews and labels
89- contents : read # Required to checkout code
85+ contents : read
86+ checks : write # Required to report status back to PR via Checks API
9087
9188 env :
9289 PR_BUILD : true
9390
9491 steps :
92+ - name : Create check run
93+ id : create_check
94+ env :
95+ GH_TOKEN : ${{ github.token }}
96+ HEAD_SHA : ${{ needs.pr_info.outputs.head_sha }}
97+ run : |
98+ CHECK_ID=$(gh api -X POST \
99+ -H "Accept: application/vnd.github+json" \
100+ -f name="Integration Tests (Auto)" \
101+ -f head_sha="${HEAD_SHA}" \
102+ -f status="in_progress" \
103+ -f 'output[title]=Integration tests running' \
104+ -f 'output[summary]=Running integration tests for snapshot changes...' \
105+ -f "details_url=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
106+ --jq '.id' \
107+ /repos/${{ github.repository }}/check-runs)
108+ echo "check_id=$CHECK_ID" >> "$GITHUB_OUTPUT"
109+
95110 - name : Checkout HEAD
96111 uses : actions/checkout@v6
97112 with :
98- ref : ${{ github.event.pull_request.head.sha }}
113+ ref : ${{ needs.pr_info.outputs.head_sha }}
99114 fetch-depth : 0
100115
101116 - name : Setup Node.js
@@ -143,15 +158,41 @@ jobs:
143158 run : npx lerna run build --scope="{@aws-cdk/*,@aws-cdk-testing/framework-integ}"
144159
145160 - name : Run integration tests
161+ id : run_tests
146162 run : yarn run atmosphere-integ-test
147163 env :
148164 CDK_ATMOSPHERE_ENDPOINT : ${{ vars.CDK_ATMOSPHERE_ENDPOINT }}
149165 CDK_ATMOSPHERE_POOL : ${{ vars.CDK_ATMOSPHERE_POOL }}
150166 CDK_ATMOSPHERE_OIDC_ROLE : ${{ vars.CDK_ATMOSPHERE_OIDC_ROLE }}
151167 CDK_ATMOSPHERE_BATCH_SIZE : ${{ vars.CDK_ATMOSPHERE_BATCH_SIZE }}
152- TARGET_BRANCH_COMMIT : ${{ github.event.pull_request.base.sha }}
153- SOURCE_BRANCH_COMMIT : ${{ github.event.pull_request.head.sha }}
154- # GitHub context for preflight check (validates CDK team membership)
168+ TARGET_BRANCH_COMMIT : ${{ needs.pr_info.outputs.base_sha }}
169+ SOURCE_BRANCH_COMMIT : ${{ needs.pr_info.outputs.head_sha }}
155170 GITHUB_TOKEN : ${{ secrets.PROJEN_GITHUB_TOKEN }}
156171 GITHUB_REPOSITORY : ${{ github.repository }}
157- PR_NUMBER : ${{ github.event.pull_request.number }}
172+ PR_NUMBER : ${{ needs.pr_info.outputs.pr_number }}
173+
174+ - name : Update check run
175+ if : always() && steps.create_check.outputs.check_id
176+ env :
177+ GH_TOKEN : ${{ github.token }}
178+ CHECK_ID : ${{ steps.create_check.outputs.check_id }}
179+ TEST_OUTCOME : ${{ steps.run_tests.outcome }}
180+ PR_NUMBER : ${{ needs.pr_info.outputs.pr_number }}
181+ RUN_URL : ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
182+ run : |
183+ if [ "$TEST_OUTCOME" = "success" ]; then
184+ CONCLUSION="success"
185+ TITLE="Integration tests passed"
186+ SUMMARY="All integration tests passed for PR #${PR_NUMBER}."
187+ else
188+ CONCLUSION="failure"
189+ TITLE="Integration tests failed"
190+ SUMMARY="Integration tests failed for PR #${PR_NUMBER}. See [workflow run](${RUN_URL}) for details."
191+ fi
192+ gh api -X PATCH \
193+ -H "Accept: application/vnd.github+json" \
194+ -f status="completed" \
195+ -f conclusion="$CONCLUSION" \
196+ -f "output[title]=$TITLE" \
197+ -f "output[summary]=$SUMMARY" \
198+ /repos/${{ github.repository }}/check-runs/${CHECK_ID}
0 commit comments