Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .github/workflows/integration-test-deployment-auto-trigger.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Unprivileged workflow that runs in the context of the PR when a review is submitted.
# Saves PR metadata and snapshot check result as artifacts for the privileged
# integration-test-deployment-auto.yml workflow (triggered via workflow_run).
#
# This two-stage pattern is required because pull_request_review has no access to
# repository secrets for fork PRs. See pr-linter-review-trigger.yml for precedent.
name: Integration Test Auto Trigger

on:
pull_request_review:
types: [submitted]

permissions:
contents: read

jobs:
save-pr-info:
if: github.event.review.state == 'approved'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "lts/*"

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Build deployment-integ
run: yarn --cwd tools/@aws-cdk/integration-test-deployment build

- name: Check for snapshot changes
id: check_snapshots
env:
TARGET_BRANCH_COMMIT: ${{ github.event.pull_request.base.sha }}
SOURCE_BRANCH_COMMIT: ${{ github.event.pull_request.head.sha }}
run: |
if yarn --cwd tools/@aws-cdk/integration-test-deployment check-snapshots; then
echo "has_snapshots=true" >> $GITHUB_OUTPUT
else
echo "has_snapshots=false" >> $GITHUB_OUTPUT
fi

- name: Save PR info
if: steps.check_snapshots.outputs.has_snapshots == 'true'
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
REVIEWER: ${{ github.event.review.user.login }}
run: |
mkdir -p ./trigger-context
echo "$PR_NUMBER" > ./trigger-context/pr_number
echo "$HEAD_SHA" > ./trigger-context/head_sha
echo "$BASE_SHA" > ./trigger-context/base_sha
echo "$REVIEWER" > ./trigger-context/reviewer

- uses: actions/upload-artifact@v7
if: steps.check_snapshots.outputs.has_snapshots == 'true'
with:
name: integ-test-trigger-context
path: trigger-context/
157 changes: 99 additions & 58 deletions .github/workflows/integration-test-deployment-auto.yml
Original file line number Diff line number Diff line change
@@ -1,69 +1,64 @@
name: Integration Test deployment (Auto)

# This workflow automatically runs integration tests when a PR with snapshot changes
# is approved by a CDK team member. No manual approval required.
# Privileged workflow that runs integration tests when triggered by the
# "Integration Test Auto Trigger" workflow. Uses workflow_run to run in the
# base repo context with access to secrets, vars, and OIDC.
#
# SHADOW MODE: This workflow is in shadow mode - failures don't block PR merges.
# SHADOW MODE: Failures don't block PR merges.
# Once validated, this will replace the label-based workflow (integration-test-deployment.yml).

on:
pull_request_review:
types: [submitted]
workflow_run:
workflows: ["Integration Test Auto Trigger"]
types:
- completed

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
permissions:
actions: read # Required to download artifacts from the trigger workflow run

jobs:
# Early validation: Check if approver is a CDK team member and PR has snapshot changes
validate_approver:
if: github.event.review.state == 'approved'
pr_info:
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
outputs:
should_run: ${{ steps.check_team.outputs.is_member == 'true' && steps.check_snapshots.outputs.has_snapshots == 'true' }}
permissions:
contents: read
pull-requests: read
pr_number: ${{ steps.pr_output.outputs.pr_number }}
head_sha: ${{ steps.pr_output.outputs.head_sha }}
base_sha: ${{ steps.pr_output.outputs.base_sha }}
reviewer: ${{ steps.pr_output.outputs.reviewer }}
has_context: ${{ steps.download.outcome == 'success' }}
steps:
- name: Checkout for path filtering
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v6
- name: Download trigger context
id: download
uses: actions/download-artifact@v8
continue-on-error: true
with:
node-version: "lts/*"

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Build deployment-integ
run: yarn --cwd tools/@aws-cdk/integration-test-deployment build

- name: Check for snapshot changes
id: check_snapshots
env:
TARGET_BRANCH_COMMIT: ${{ github.event.pull_request.base.sha }}
SOURCE_BRANCH_COMMIT: ${{ github.event.pull_request.head.sha }}
name: integ-test-trigger-context
path: trigger-context/
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}

- name: Parse trigger context
if: steps.download.outcome == 'success'
id: pr_output
run: |
# Reuses getChangedSnapshots() from utils.ts — single source of truth
if yarn --cwd tools/@aws-cdk/integration-test-deployment check-snapshots; then
echo "has_snapshots=true" >> $GITHUB_OUTPUT
else
echo "has_snapshots=false" >> $GITHUB_OUTPUT
fi
echo "pr_number=$(cat trigger-context/pr_number)" >> "$GITHUB_OUTPUT"
echo "head_sha=$(cat trigger-context/head_sha)" >> "$GITHUB_OUTPUT"
echo "base_sha=$(cat trigger-context/base_sha)" >> "$GITHUB_OUTPUT"
echo "reviewer=$(cat trigger-context/reviewer)" >> "$GITHUB_OUTPUT"

validate_approver:
needs: pr_info
if: needs.pr_info.outputs.has_context == 'true'
runs-on: ubuntu-latest
outputs:
is_member: ${{ steps.check_team.outputs.is_member }}
steps:
- name: Check if approver is CDK team member
id: check_team
if: steps.check_snapshots.outputs.has_snapshots == 'true'
env:
GITHUB_TOKEN: ${{ secrets.PROJEN_GITHUB_TOKEN }}
APPROVER: ${{ github.event.review.user.login }}
APPROVER: ${{ needs.pr_info.outputs.reviewer }}
run: |
# Use gh CLI to check team membership (pre-installed in GitHub Actions runners)
# https://docs.github.com/en/rest/teams/members#get-team-membership-for-a-user
if gh api "orgs/aws/teams/aws-cdk-team/memberships/${APPROVER}" --jq '.state' 2>/dev/null | grep -q "active"; then
echo "${APPROVER} is an active CDK team member"
echo "is_member=true" >> $GITHUB_OUTPUT
Expand All @@ -73,40 +68,60 @@
fi

integration_test_deployment_auto:
needs: validate_approver
# Only run if approver is a CDK team member AND PR has snapshot changes
if: needs.validate_approver.outputs.should_run == 'true'
needs: [pr_info, validate_approver]
if: needs.validate_approver.outputs.is_member == 'true'
runs-on: codebuild-aws-cdk-github-actions-deployment-integ-runner-${{ github.run_id }}-${{ github.run_attempt }}
# No environment - runs automatically without manual approval
timeout-minutes: 7200 # Maximum limit for self-hosted runners, job can still be limited by our runner timeout (which is set at 36 hours).
# Shadow mode: workflow reports success even if tests fail
continue-on-error: true
name: 'Deploy integration test snapshots (Auto)'
# Cancel previous deployment for the same PR (uses artifact-sourced PR number, works for fork PRs)
concurrency:
group: integ-test-auto-${{ needs.pr_info.outputs.pr_number }}
cancel-in-progress: true

# Job-level permissions for least privilege
permissions:
id-token: write # Required for OIDC authentication with AWS Atmosphere
pull-requests: read # Required to check PR reviews and labels
contents: read # Required to checkout code
contents: read
checks: write # Required to report status back to PR via Checks API

env:
PR_BUILD: true

steps:
- name: Create check run
id: create_check
env:
GH_TOKEN: ${{ github.token }}
HEAD_SHA: ${{ needs.pr_info.outputs.head_sha }}
run: |
CHECK_ID=$(gh api -X POST \
-H "Accept: application/vnd.github+json" \
-f name="Integration Tests (Auto)" \
-f head_sha="${HEAD_SHA}" \
-f status="in_progress" \
-f 'output[title]=Integration tests running' \
-f 'output[summary]=Running integration tests for snapshot changes...' \
-f "details_url=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
--jq '.id' \
/repos/${{ github.repository }}/check-runs)
echo "check_id=$CHECK_ID" >> "$GITHUB_OUTPUT"

- name: Checkout HEAD
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
ref: ${{ needs.pr_info.outputs.head_sha }}
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "lts/*"
cache: "yarn"
cache-dependency-path: |
yarn.lock

- name: Set up Docker

Check failure

Code scanning / CodeQL

Checkout of untrusted code in a privileged context Critical

Potential execution of untrusted code on a privileged workflow (
workflow_run
)
uses: docker/setup-buildx-action@v4

- name: Load Docker images
Expand All @@ -133,25 +148,51 @@
(command -v sysctl || sudo apt-get update && sudo apt-get install -y procps) && \
sudo sysctl -w vm.max_map_count=2251954

- name: Install dependencies for Integration Tests
run: yarn install --frozen-lockfile

- name: Build deployment-integ

Check failure

Code scanning / CodeQL

Checkout of untrusted code in a privileged context Critical

Potential execution of untrusted code on a privileged workflow (
workflow_run
)
run: yarn --cwd tools/@aws-cdk/integration-test-deployment build

- name: Build Integration Test packages

Check failure

Code scanning / CodeQL

Checkout of untrusted code in a privileged context Critical

Potential execution of untrusted code on a privileged workflow (
workflow_run
)
run: npx lerna run build --scope="{@aws-cdk/*,@aws-cdk-testing/framework-integ}"

- name: Run integration tests
id: run_tests
run: yarn run atmosphere-integ-test
env:
CDK_ATMOSPHERE_ENDPOINT: ${{ vars.CDK_ATMOSPHERE_ENDPOINT }}
CDK_ATMOSPHERE_POOL: ${{ vars.CDK_ATMOSPHERE_POOL }}
CDK_ATMOSPHERE_OIDC_ROLE: ${{ vars.CDK_ATMOSPHERE_OIDC_ROLE }}
CDK_ATMOSPHERE_BATCH_SIZE: ${{ vars.CDK_ATMOSPHERE_BATCH_SIZE }}
TARGET_BRANCH_COMMIT: ${{ github.event.pull_request.base.sha }}
SOURCE_BRANCH_COMMIT: ${{ github.event.pull_request.head.sha }}
# GitHub context for preflight check (validates CDK team membership)
TARGET_BRANCH_COMMIT: ${{ needs.pr_info.outputs.base_sha }}
SOURCE_BRANCH_COMMIT: ${{ needs.pr_info.outputs.head_sha }}
GITHUB_TOKEN: ${{ secrets.PROJEN_GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_NUMBER: ${{ needs.pr_info.outputs.pr_number }}

- name: Update check run
if: always() && steps.create_check.outputs.check_id
env:
GH_TOKEN: ${{ github.token }}
CHECK_ID: ${{ steps.create_check.outputs.check_id }}
TEST_OUTCOME: ${{ steps.run_tests.outcome }}
PR_NUMBER: ${{ needs.pr_info.outputs.pr_number }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
if [ "$TEST_OUTCOME" = "success" ]; then
CONCLUSION="success"
TITLE="Integration tests passed"
SUMMARY="All integration tests passed for PR #${PR_NUMBER}."
else
CONCLUSION="failure"
TITLE="Integration tests failed"
SUMMARY="Integration tests failed for PR #${PR_NUMBER}. See [workflow run](${RUN_URL}) for details."
fi
gh api -X PATCH \
-H "Accept: application/vnd.github+json" \
-f status="completed" \
-f conclusion="$CONCLUSION" \
-f "output[title]=$TITLE" \
-f "output[summary]=$SUMMARY" \
/repos/${{ github.repository }}/check-runs/${CHECK_ID}
Loading