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
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 }}
HAS_SNAPSHOTS: ${{ steps.check_snapshots.outputs.has_snapshots }}
run: |
mkdir -p ./pr
echo "$PR_NUMBER" > ./pr/pr_number
echo "$HEAD_SHA" > ./pr/head_sha
echo "$BASE_SHA" > ./pr/base_sha
echo "$REVIEWER" > ./pr/reviewer
echo "$HAS_SNAPSHOTS" > ./pr/has_snapshots

- uses: actions/upload-artifact@v7
with:
name: integ_test_pr_info
path: pr/
194 changes: 60 additions & 134 deletions .github/workflows/integration-test-deployment-auto.yml
Original file line number Diff line number Diff line change
@@ -1,157 +1,83 @@
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.
#
# SHADOW MODE: This workflow is in shadow mode - failures don't block PR merges.
# Once validated, this will replace the label-based workflow (integration-test-deployment.yml).
# ⚠️ FORK TEST VERSION — DO NOT MERGE
# Stubbed for testing the workflow_run artifact handoff on a fork.
# Real version: see commit 49066b8463

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

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch }}
cancel-in-progress: true

jobs:
# Early validation: Check if approver is a CDK team member and PR has snapshot changes
validate_approver:
if: github.event.review.state == 'approved'
download-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_snapshots: ${{ steps.pr_output.outputs.has_snapshots }}
steps:
- name: Checkout for path filtering
uses: actions/checkout@v6
- name: Download artifact
uses: dawidd6/action-download-artifact@v19
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
run_id: ${{ github.event.workflow_run.id }}
name: integ_test_pr_info
path: pr/
search_artifacts: true

- 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 }}
- name: Read PR info
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

- name: Check if approver is CDK team member
echo "pr_number=$(cat pr/pr_number)" >> "$GITHUB_OUTPUT"
echo "head_sha=$(cat pr/head_sha)" >> "$GITHUB_OUTPUT"
echo "base_sha=$(cat pr/base_sha)" >> "$GITHUB_OUTPUT"
echo "reviewer=$(cat pr/reviewer)" >> "$GITHUB_OUTPUT"
echo "has_snapshots=$(cat pr/has_snapshots)" >> "$GITHUB_OUTPUT"
echo "::notice::PR #$(cat pr/pr_number) | head=$(cat pr/head_sha) | base=$(cat pr/base_sha) | reviewer=$(cat pr/reviewer) | snapshots=$(cat pr/has_snapshots)"

# FORK TEST: Skip real team check, just validate the handoff worked
validate-approver:
needs: download-pr-info
if: needs.download-pr-info.outputs.has_snapshots == 'true'
runs-on: ubuntu-latest
outputs:
is_member: ${{ steps.check_team.outputs.is_member }}
steps:
- name: "FORK TEST: Stub team check"
id: check_team
if: steps.check_snapshots.outputs.has_snapshots == 'true'
env:
GITHUB_TOKEN: ${{ secrets.PROJEN_GITHUB_TOKEN }}
APPROVER: ${{ github.event.review.user.login }}
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
else
echo "${APPROVER} is not a CDK team member or membership is not active"
echo "is_member=false" >> $GITHUB_OUTPUT
fi
echo "::notice::FORK TEST — skipping real team check for reviewer: ${{ needs.download-pr-info.outputs.reviewer }}"
echo "is_member=true" >> $GITHUB_OUTPUT

# FORK TEST: Replace deployment with a summary of what would run
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'
runs-on: codebuild-aws-cdk-github-actions-deployment-integ-runner-${{ github.run_id }}-${{ github.run_attempt }}
# No environment - runs automatically without manual approval
# Shadow mode: workflow reports success even if tests fail
needs: [download-pr-info, validate-approver]
if: needs.validate-approver.outputs.is_member == 'true'
runs-on: ubuntu-latest
continue-on-error: true
name: 'Deploy integration test snapshots (Auto)'

# 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

env:
PR_BUILD: true

steps:
- name: Checkout HEAD
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/*"
cache: "yarn"
cache-dependency-path: |
yarn.lock

- name: Set up Docker
uses: docker/setup-buildx-action@v4

- name: Load Docker images
id: docker-cache
uses: actions/cache/restore@v5
with:
path: |
~/.docker-images.tar
key: docker-cache-${{ runner.os }}

- name: Restore Docker images
if: ${{ steps.docker-cache.outputs.cache-hit }}
run: docker image load --input ~/.docker-images.tar

- name: Cache build artifacts
uses: actions/cache@v5
with:
path: |
~/.s3buildcache
key: s3buildcache-${{ runner.os }}

- name: Configure system settings
- name: "FORK TEST: Deployment stub"
run: |
(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
run: yarn --cwd tools/@aws-cdk/integration-test-deployment build

- name: Build Integration Test packages
run: npx lerna run build --scope="{@aws-cdk/*,@aws-cdk-testing/framework-integ}"

- name: Run integration 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)
GITHUB_TOKEN: ${{ secrets.PROJEN_GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
echo "========================================="
echo " FORK TEST — Full chain validated! ✅"
echo "========================================="
echo ""
echo "PR Number: ${{ needs.download-pr-info.outputs.pr_number }}"
echo "Head SHA: ${{ needs.download-pr-info.outputs.head_sha }}"
echo "Base SHA: ${{ needs.download-pr-info.outputs.base_sha }}"
echo "Reviewer: ${{ needs.download-pr-info.outputs.reviewer }}"
echo "Snapshots: ${{ needs.download-pr-info.outputs.has_snapshots }}"
echo ""
echo "In production, this job would:"
echo " 1. Run on codebuild runner"
echo " 2. Authenticate via OIDC to AWS Atmosphere"
echo " 3. Build and deploy integration tests"
42 changes: 42 additions & 0 deletions docs/integration-test-deployment-task.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
## Motivation / Problem Statement
Right now to deploy the integration tests you need to do multiple manual steps stated below. We want to have way more simplified steps but keeping the output the same deploying the integration tests. Beside that we want to deploy the integration test that changed on every PR deployed not only the one that has specific label.

1. add label `pr/needs-integration-tests-deployment`
2. approve the workflow
3. approve the PR
4. when the mergify merge to main you need to approve again the workflow

## Proposed Solution
Modify the existing workflow to deploy the integration tests after the the PR get approved and before the Mergify merge to main. **For now make this workflow as shadow mode so even if it failed it will merge to main.** That's only temporary until we're sure that's not making a lot of pain because false positive in the future it will block merging the PR if failed.

---

## Task 1: Enable Integration Test Deployment in Shadow Mode

### Acceptance Criteria
- [ ] PRs with integration test changes and `pr/needs-integration-tests-deployment` label run the workflow
- [ ] Workflow only runs after approval from a maintainer group member
- [ ] Workflow only runs once on approval (not after merge to main)
- [ ] Workflow runs in shadow mode (failures don't block PR merge)
- [ ] PRs without integration test changes have no new behaviour
- [ ] **Keep** the label `pr/needs-integration-tests-deployment` so we can review workflow results and give feedback

### Why Keep the Label During Shadow Mode
With shadow mode enabled, we must **keep** the `pr/needs-integration-tests-deployment` label. This is because:
- Shadow mode doesn't block PRs on failure, so PRs will merge regardless of workflow result
- Without the label, there's no way to know if the integration test was successful before the PR merges
- The label triggers the workflow, allowing us to review results and give feedback

---

## Task 2: Enforce Integration Test Deployment (Disable Shadow Mode)

### Description
After validating Task 1 is working correctly and we're confident in the workflow, disable shadow mode and remove the label requirement.

### Acceptance Criteria
- [ ] Disable shadow mode in the workflow
- [ ] Remove the `pr/needs-integration-tests-deployment` label requirement
- [ ] PRs with integration test changes automatically run the workflow (no label needed)
- [ ] PRs with integration test changes are blocked from merging if the workflow fails
- [ ] PRs without integration test changes have no new behaviour
Loading
Loading