Integration Tests (PR) #47
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Integration tests for PRs (including forks). | |
| # Uses workflow_run to safely access secrets without checking out untrusted PR code. | |
| # Security model: | |
| # - ci.yml builds the PR's code in an unprivileged context and uploads binary artifacts | |
| # - This workflow downloads those artifacts and runs tests from the DEFAULT BRANCH (main) | |
| # - PR code is never checked out in a privileged context | |
| # - Fork PRs require manual environment approval before tests run (security gate) | |
| # - Internal PRs (same repo) skip the approval gate — contributors already have write access | |
| name: Integration Tests (PR) | |
| env: | |
| PYTHON_VERSION: '3.12' | |
| on: | |
| workflow_run: | |
| workflows: ["CI"] | |
| types: [completed] | |
| permissions: | |
| contents: read | |
| actions: read | |
| statuses: write | |
| jobs: | |
| # Fork PRs: require manual approval via environment protection rules. | |
| # A maintainer must review the fork's code before secrets are exposed to its artifacts. | |
| approve-fork: | |
| if: > | |
| github.event.workflow_run.conclusion == 'success' && | |
| github.event.workflow_run.event == 'pull_request' && | |
| github.event.workflow_run.head_repository.full_name != github.repository | |
| runs-on: ubuntu-latest | |
| environment: integration-tests | |
| steps: | |
| - run: echo "Fork PR approved for ${{ github.event.workflow_run.head_branch }} from ${{ github.event.workflow_run.head_repository.full_name }}" | |
| # Internal PRs: skip approval gate — contributors already have write access to the repo. | |
| approve-internal: | |
| if: > | |
| github.event.workflow_run.conclusion == 'success' && | |
| github.event.workflow_run.event == 'pull_request' && | |
| github.event.workflow_run.head_repository.full_name == github.repository | |
| runs-on: ubuntu-latest | |
| steps: | |
| - run: echo "Internal PR auto-approved for ${{ github.event.workflow_run.head_branch }}" | |
| # Linux-only for fast PR feedback. Full platform smoke tests run post-merge. | |
| smoke-test: | |
| needs: [approve-fork, approve-internal] | |
| # Run if either approval job succeeded (the other will be skipped) | |
| if: always() && (needs.approve-fork.result == 'success' || needs.approve-internal.result == 'success') | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| actions: read | |
| steps: | |
| # Checkout default branch (main) — never PR code | |
| - uses: actions/checkout@v4 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '24' | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install uv | |
| run: | | |
| curl -LsSf https://astral.sh/uv/install.sh | sh | |
| echo "$HOME/.cargo/bin" >> $GITHUB_PATH | |
| - name: Cache uv environments | |
| uses: actions/cache@v3 | |
| with: | |
| path: | | |
| ~/.cache/uv | |
| ~/.local/share/uv | |
| key: ${{ runner.os }}-uv-${{ hashFiles('**/pyproject.toml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-uv- | |
| - name: Install dependencies | |
| run: uv sync --extra dev | |
| - name: Run smoke tests | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GH_MODELS_PAT }} | |
| GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} | |
| run: uv run pytest tests/integration/test_runtime_smoke.py -v | |
| # Linux-only — downloads the single Linux binary artifact from ci.yml. | |
| integration-tests: | |
| name: Integration Tests | |
| needs: [smoke-test] | |
| if: always() && needs.smoke-test.result == 'success' | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| actions: read | |
| models: read | |
| steps: | |
| # Checkout default branch (main) for test scripts — never PR code | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| # Download binary artifact built from PR code by ci.yml | |
| - name: Download APM binary from CI workflow | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: apm-linux-x86_64 | |
| run-id: ${{ github.event.workflow_run.id }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '24' | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install uv | |
| run: | | |
| curl -LsSf https://astral.sh/uv/install.sh | sh | |
| echo "$HOME/.cargo/bin" >> $GITHUB_PATH | |
| - name: Install test dependencies | |
| run: uv sync --extra dev | |
| - name: Run integration tests | |
| env: | |
| APM_E2E_TESTS: "1" | |
| GITHUB_TOKEN: ${{ secrets.GH_MODELS_PAT }} | |
| GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} | |
| ADO_APM_PAT: ${{ secrets.ADO_APM_PAT }} | |
| run: | | |
| chmod +x scripts/test-integration.sh | |
| uv run ./scripts/test-integration.sh | |
| timeout-minutes: 20 | |
| # Linux-only — validates the Linux binary in isolation. Full platform validation runs post-merge. | |
| release-validation: | |
| name: Release Validation | |
| needs: [integration-tests] | |
| if: always() && needs.integration-tests.result == 'success' | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| actions: read | |
| models: read | |
| steps: | |
| # Checkout default branch for test scripts — never PR code | |
| - name: Checkout test scripts | |
| uses: actions/checkout@v4 | |
| with: | |
| sparse-checkout: scripts | |
| path: repo | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '24' | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| # Download binary artifact to isolated test directory | |
| - name: Download APM binary from CI workflow | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: apm-linux-x86_64 | |
| run-id: ${{ github.event.workflow_run.id }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| path: /tmp/apm-isolated-test/ | |
| - name: Make binary executable and verify isolation | |
| run: | | |
| cd /tmp/apm-isolated-test | |
| echo "Downloaded structure:" | |
| find . -name "apm" -type f | |
| ls -la ./dist/ | |
| chmod +x ./dist/apm-linux-x86_64/apm | |
| - name: Create APM symlink for testing | |
| run: | | |
| cd /tmp/apm-isolated-test | |
| ln -s "$(pwd)/dist/apm-linux-x86_64/apm" "$(pwd)/apm" | |
| echo "/tmp/apm-isolated-test" >> $GITHUB_PATH | |
| - name: Prepare test scripts from default branch | |
| run: | | |
| # Copy test scripts from main branch checkout into isolated test dir | |
| cp -r repo/scripts /tmp/apm-isolated-test/scripts | |
| - name: Run release validation tests | |
| env: | |
| APM_E2E_TESTS: "1" | |
| GITHUB_TOKEN: ${{ secrets.GH_MODELS_PAT }} | |
| GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} | |
| ADO_APM_PAT: ${{ secrets.ADO_APM_PAT }} | |
| run: | | |
| cd /tmp/apm-isolated-test | |
| chmod +x scripts/test-release-validation.sh | |
| ./scripts/test-release-validation.sh | |
| timeout-minutes: 20 | |
| # Report integration test results back to the PR as a commit status | |
| report-status: | |
| needs: [smoke-test, integration-tests, release-validation] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| permissions: | |
| statuses: write | |
| steps: | |
| - name: Report status to PR | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const success = '${{ needs.release-validation.result }}' === 'success' | |
| && '${{ needs.integration-tests.result }}' === 'success' | |
| && '${{ needs.smoke-test.result }}' === 'success'; | |
| await github.rest.repos.createCommitStatus({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| sha: context.payload.workflow_run.head_sha, | |
| state: success ? 'success' : 'failure', | |
| target_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, | |
| context: 'Integration Tests (PR)', | |
| description: success ? 'All integration tests passed' : 'Integration tests failed' | |
| }); | |