From 2ca20578403b56ae91a36caae62256e1e1566c50 Mon Sep 17 00:00:00 2001 From: Punk 6529 <108035228+punk6529@users.noreply.github.com> Date: Tue, 7 Jul 2026 23:05:19 +0000 Subject: [PATCH] ci(e2e): add daily production read-only canary workflow Production has no scheduled E2E: the prod deploy workflow runs no post-deploy packs, and backend releases, data issues or third-party changes can break the user experience without any frontend deploy at all (see the 2026-07-07 wave-crash incident). Add a daily cron that runs the manifest-resolved production canary packs (10 read-only packs, desktop chromium) via scripts/e2e-packs.cjs against 6529.io, with artifact upload and a Discord alert on scheduled failure. Read-only is enforced by the readonly mutation guard at the network layer; no secrets are needed because production is public. Merge order: requires #3190 (pack manifest + runner) on main first. Co-Authored-By: Claude Opus 4.8 Signed-off-by: Punk 6529 <108035228+punk6529@users.noreply.github.com> --- .github/workflows/prod-canary.yml | 91 +++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 .github/workflows/prod-canary.yml diff --git a/.github/workflows/prod-canary.yml b/.github/workflows/prod-canary.yml new file mode 100644 index 0000000000..116915fc24 --- /dev/null +++ b/.github/workflows/prod-canary.yml @@ -0,0 +1,91 @@ +name: Production E2E Canary + +# Daily read-only synthetic check that production works for users right now, +# regardless of whose deploy broke it: backend releases, data issues and +# third-party changes never trigger the frontend deploy gates, and the prod +# deploy workflow has no post-deploy E2E of its own. +# +# Runs the manifest-resolved production canary packs (safety: readonly, +# trigger: cron in tests/packs.manifest.ts) through scripts/e2e-packs.cjs. +# Read-only is enforced at the network layer by the readonly mutation guard +# (PLAYWRIGHT_READONLY / production base URL), not by convention. +# +# No secrets are required: production is publicly reachable and the packs +# are unauthenticated. + +on: + workflow_dispatch: {} + schedule: + # Daily, offset from the 04:00 Device Farm crons so scheduled QA + # failures arrive as distinct signals. + - cron: "30 5 * * *" + +permissions: + contents: read + +concurrency: + group: prod-e2e-canary + cancel-in-progress: false + +jobs: + canary-packs: + name: Production canary packs + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - name: Checkout code + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false + + - name: Install Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "22" + + - name: Activate pinned pnpm + run: | + corepack enable pnpm + corepack prepare "$(node -p 'require("./package.json").packageManager')" --activate + pnpm --version + + - name: Install Socket Firewall + id: socket_firewall + uses: SocketDev/action@2d3f25590c6ed6ba11a9a14c064d962a3a04698f # v1.3.1 + with: + mode: firewall + + - name: Assert npm lockfile is absent + run: ./bin/6529 guard:no-package-lock + + - name: Install dependencies + env: + SFW_BIN: ${{ steps.socket_firewall.outputs.firewall-path-binary }} + run: ./bin/6529 install:frozen + + - name: Install Playwright browser + run: ./bin/6529 exec playwright install --with-deps chromium + + - name: Run production canary packs against 6529.io + run: ./bin/6529 run e2e:packs -- --env production --trigger cron + + - name: Upload Playwright artifacts on failure + if: failure() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: prod-canary-artifacts + path: | + test-results/ + playwright-report/ + retention-days: 7 + if-no-files-found: ignore + + - name: Notify about scheduled failure + uses: sarisia/actions-status-discord@eb045afee445dc055c18d3d90bd0f244fd062708 # v1.16.0 + if: failure() && github.event_name == 'schedule' + env: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} + with: + title: "Production E2E Canary: daily read-only pack failed" + description: "Production may be broken for users. Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + color: 0xff0000