From af0b68fdecb5d95b78e8522cee6fbc3ff97d9834 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Tue, 1 Sep 2026 15:59:47 -0700 Subject: [PATCH] ci: run the cockpit shell control-plane e2e, which nothing invoked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #921 added apps/cockpit/e2e/control-plane.spec.ts — 7 Playwright tests over the operational sidebar: the real Angular handshake without blank or unresponsive states, operational controls reachable at four viewports, forced colors preserving control boundaries and keyboard focus, and reduced motion disabling loader and drawer animation. Nothing ever ran it. The suite sits behind `nx e2e cockpit`, and the cockpit-e2e matrix only dispatches caps derived from walking cockpit/** — apps/cockpit is never a candidate. No other job named the target either: grepping every workflow for `nx e2e` returns examples-chat-angular, examples-ag-ui-angular, the cap matrix, and website. So this has been dead coverage for its whole life. Verified it actually passes before wiring it up — 7/7 in 24s locally. It goes in the existing `cockpit` job rather than a new one because it is cheap, it reuses that job's `npm ci`, the `cockpit` scope already gates the shell, and required-pr-checks already aggregates the job — so it becomes merge-blocking with no gate change. The playwright config already sets retries: 2 on CI. Found while auditing the tags I removed from apps/cockpit in #939. Co-Authored-By: Claude Opus 5 --- .github/workflows/ci.yml | 17 +++++++++++++++++ scripts/ci-workflow.spec.mjs | 25 ++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 22d1e3ce9..91df669b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -232,6 +232,23 @@ jobs: # actually execute. All three share the `scope:cockpit` tag, so ci-scope # already gates this job correctly for changes under either library. - run: npx nx run-many -t test --projects=cockpit,cockpit-docs,cockpit-registry --skip-nx-cache + # apps/cockpit owns a real Playwright suite (e2e/control-plane.spec.ts) + # behind `nx e2e cockpit` that nothing invoked: the cockpit-e2e matrix + # only dispatches caps derived from cockpit/**, and no other job named + # the target — so it had never run in CI since #921 added it. It lives + # here rather than in its own job because it is cheap (7 tests, ~25s + # once the dev servers are up) and reuses this job's `npm ci`; the + # `cockpit` scope already gates the shell, and required-pr-checks + # already aggregates this job. + - name: Cache Playwright browsers + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: ~/.cache/ms-playwright + key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }} + restore-keys: | + playwright-${{ runner.os }}- + - run: npx playwright install --with-deps chromium + - run: npx nx e2e cockpit --skip-nx-cache cockpit-examples-build: name: Cockpit — build all examples diff --git a/scripts/ci-workflow.spec.mjs b/scripts/ci-workflow.spec.mjs index d4a9ecabb..5112716ed 100644 --- a/scripts/ci-workflow.spec.mjs +++ b/scripts/ci-workflow.spec.mjs @@ -373,7 +373,9 @@ describe('CI workflow', () => { // hardcoded LIBS list that excludes both of these. If they are dropped // from this run-many their specs stop executing silently. const cockpitJob = readJobBlock(await readWorkflow(), 'cockpit'); - const runMany = cockpitJob.match(/npx nx run-many -t test --projects=(\S+)/); + const runMany = cockpitJob.match( + /npx nx run-many -t test --projects=(\S+)/ + ); assert.ok(runMany, 'cockpit job should run tests via nx run-many'); @@ -386,6 +388,27 @@ describe('CI workflow', () => { } }); + it('runs the cockpit shell control-plane e2e', async () => { + // apps/cockpit owns a real Playwright suite (e2e/control-plane.spec.ts, + // 7 tests, added by #921) behind `nx e2e cockpit`. Nothing invoked that + // target: the cockpit-e2e matrix only dispatches caps derived from + // cockpit/**, and no other job named it — so the suite had never run in + // CI. It belongs in the `cockpit` job, whose `cockpit` scope already + // gates the shell and is already aggregated by required-pr-checks. + const cockpitJob = readJobBlock(await readWorkflow(), 'cockpit'); + + assert.match( + cockpitJob, + /npx nx e2e cockpit\b/, + 'cockpit job should run the shell control-plane e2e' + ); + assert.match( + cockpitJob, + /npx playwright install/, + 'the control-plane e2e needs a browser installed' + ); + }); + it('lets the cockpit e2e summary inspect CI scope outputs', async () => { const cockpitE2eSummaryJob = await readCockpitE2eSummaryJob();