From 0c7e0962313051e5de255abbe006c404cd6231fd Mon Sep 17 00:00:00 2001 From: Hugh Hackman Date: Tue, 24 Mar 2026 23:05:32 +0000 Subject: [PATCH] ci: add E2E workflow for Playwright smoke tests Adds `.github/workflows/e2e.yaml` to run Playwright E2E smoke tests against a deployed Headlamp instance in `privilegedescalation-dev`. Follows the headlamp-polaris-plugin pattern: - Builds the plugin, deploys via scripts/deploy-e2e-headlamp.sh - Runs tests with `npm run e2e` (intel-gpu uses npm, not pnpm) - Uploads Playwright report and test results on failure - Cleans up via scripts/teardown-e2e-headlamp.sh (if: always()) - Concurrency group prevents concurrent runs sharing E2E resources - Uses runs-on: runners-privilegedescalation (self-hosted ARC) Depends on Gandalf's E2E test implementation in PR #25. Co-Authored-By: Paperclip --- .github/workflows/e2e.yaml | 103 +++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 .github/workflows/e2e.yaml diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml new file mode 100644 index 0000000..37f33a9 --- /dev/null +++ b/.github/workflows/e2e.yaml @@ -0,0 +1,103 @@ +name: E2E Tests + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +# Only one E2E run at a time: the shared E2E_RELEASE (headlamp-e2e) in +# privilegedescalation-dev cannot be shared across concurrent runs. +# cancel-in-progress: false (queue, don't cancel) — cancelling in-flight +# runs may skip the if: always() teardown, leaving dangling cluster resources. +concurrency: + group: e2e-${{ github.repository }} + cancel-in-progress: false + +env: + E2E_NAMESPACE: privilegedescalation-dev + E2E_RELEASE: headlamp-e2e + # Pin to a known-good Headlamp version. Using :latest is risky because + # the tag can change between CI runs, causing flaky failures when a newer + # image is pulled on some nodes but not others (IfNotPresent pull policy). + # Update this when Headlamp is upgraded in production (kube-system). + HEADLAMP_VERSION: v0.40.1 + +jobs: + e2e: + runs-on: runners-privilegedescalation + timeout-minutes: 15 + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '22' + cache: 'npm' + + - name: Setup kubectl + uses: azure/setup-kubectl@v4 + + - name: Install dependencies + run: npm ci + + - name: Build plugin + run: npx @kinvolk/headlamp-plugin build + + - name: Deploy E2E Headlamp instance + run: scripts/deploy-e2e-headlamp.sh + + - name: Load E2E environment + run: | + if [ -f .env.e2e ]; then + cat .env.e2e >> "$GITHUB_ENV" + else + echo "::error::deploy-e2e-headlamp.sh did not produce .env.e2e" + exit 1 + fi + + - name: Install Playwright browsers + run: npx playwright install --with-deps chromium + + - name: Run E2E tests + run: npm run e2e + env: + HEADLAMP_URL: ${{ env.HEADLAMP_URL }} + HEADLAMP_TOKEN: ${{ env.HEADLAMP_TOKEN }} + + - name: Collect deployment diagnostics on failure + if: failure() + run: | + echo "=== Pod state ===" + kubectl get pods -n "$E2E_NAMESPACE" -l "app.kubernetes.io/instance=$E2E_RELEASE" 2>&1 || true + echo "=== Pod describe ===" + kubectl describe pods -n "$E2E_NAMESPACE" -l "app.kubernetes.io/instance=$E2E_RELEASE" 2>&1 || true + echo "=== Recent namespace events ===" + kubectl get events -n "$E2E_NAMESPACE" --sort-by='.lastTimestamp' 2>&1 | tail -20 || true + + - name: Teardown E2E instance + if: always() + run: scripts/teardown-e2e-headlamp.sh + + - name: Upload Playwright report + uses: actions/upload-artifact@v7 + if: failure() + with: + name: playwright-report + path: playwright-report/ + retention-days: 7 + + - name: Upload test results + uses: actions/upload-artifact@v7 + if: failure() + with: + name: test-results + path: test-results/ + retention-days: 7 -- 2.52.0