chore(ci): drop auto screenshot refresh job, switch to manual capture (#884)

The release-only `update-screenshots` job opened a `chore/refresh-screenshots`
PR and immediately tried to squash-merge it. Branch protection (1 review,
6 status checks) rejected the merge on every release, leaving an open PR
behind. Screenshots will instead be refreshed manually after UI changes.

Removed:
- The `update-screenshots` job from ci.yml (~57 lines).
- The `paths-ignore: docs/images/**` push trigger filter; its sole purpose
  was to break the auto-merge re-trigger cascade. Its absence also fixes a
  latent bug where docs-only pushes to main would have skipped sync-docs.
- Four `head_ref != 'chore/refresh-screenshots'` guards in other jobs.
- The "doc screenshots" mention in the skip-bot-PRs comment.

Reworked the screenshot capture spec to be opt-in:
- playwright.config.ts now defines two projects. The default `chromium`
  project ignores screenshots.spec.ts; a separate `screenshots` project
  matches it and is invoked manually.
- The e2e CI job runs `--project=chromium` so the screenshots project
  cannot accidentally run in CI.
- Updated the spec's module comment with the new manual invocation.

Net: 86 lines removed, 27 added.
This commit is contained in:
Anso
2026-05-02 15:57:45 -04:00
committed by GitHub
parent 87abfc2ec0
commit 1115650e78
4 changed files with 30 additions and 86 deletions
+2 -2
View File
@@ -19,8 +19,8 @@ inputs:
When 'true', skip running `npm run build` in backend/ and assume the When 'true', skip running `npm run build` in backend/ and assume the
caller has already materialized backend/dist (e.g. via download-artifact caller has already materialized backend/dist (e.g. via download-artifact
from an upstream job that already built and verified it). Leave 'false' from an upstream job that already built and verified it). Leave 'false'
for standalone invocations like the update-screenshots job that do not for standalone invocations that do not run in a job graph with a
run in a job graph with a prior build step. prior build step.
required: false required: false
default: 'false' default: 'false'
+9 -79
View File
@@ -5,20 +5,13 @@ on:
branches: [main] branches: [main]
push: push:
branches: [main] branches: [main]
# Screenshot auto-merge commits only touch docs/images/.
# Ignoring this path breaks the cascade:
# merge PR → screenshots PR auto-merges → would re-trigger CI → now skipped.
# The next real merge will sync everything (rsync --delete does a full mirror).
paths-ignore:
- 'docs/images/**'
# Cancel previous runs on the same branch/PR # Cancel previous runs on the same branch/PR
concurrency: concurrency:
group: ci-${{ github.ref }} group: ci-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
# Least-privilege default for every job. Individual jobs may override (e.g. # Least-privilege default for every job.
# update-screenshots needs contents: write + pull-requests: write to open a PR).
permissions: permissions:
contents: read contents: read
@@ -30,13 +23,11 @@ jobs:
name: Backend (Build, Test, Lint) name: Backend (Build, Test, Lint)
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 10 timeout-minutes: 10
# Skip on bot PRs that only touch version metadata (release-please) or # Skip on the release-please bot PR. It only touches version metadata,
# doc screenshots. Neither changes the backend surface, so running the # so the full build+test+lint+audit stack is pure action-minute waste.
# full build+test+lint+audit stack is pure action-minute waste.
if: >- if: >-
github.event_name == 'pull_request' github.event_name == 'pull_request'
&& github.head_ref != 'release-please--branches--main--components--sencho' && github.head_ref != 'release-please--branches--main--components--sencho'
&& github.head_ref != 'chore/refresh-screenshots'
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
@@ -87,7 +78,6 @@ jobs:
if: >- if: >-
github.event_name == 'pull_request' github.event_name == 'pull_request'
&& github.head_ref != 'release-please--branches--main--components--sencho' && github.head_ref != 'release-please--branches--main--components--sencho'
&& github.head_ref != 'chore/refresh-screenshots'
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
@@ -123,7 +113,6 @@ jobs:
if: >- if: >-
github.event_name == 'pull_request' github.event_name == 'pull_request'
&& github.head_ref != 'release-please--branches--main--components--sencho' && github.head_ref != 'release-please--branches--main--components--sencho'
&& github.head_ref != 'chore/refresh-screenshots'
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
@@ -191,7 +180,6 @@ jobs:
if: >- if: >-
github.event_name == 'pull_request' github.event_name == 'pull_request'
&& github.head_ref != 'release-please--branches--main--components--sencho' && github.head_ref != 'release-please--branches--main--components--sencho'
&& github.head_ref != 'chore/refresh-screenshots'
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
@@ -212,7 +200,12 @@ jobs:
skip-backend-build: 'true' skip-backend-build: 'true'
- name: Run E2E tests - name: Run E2E tests
run: npx playwright test # `--project=chromium` is explicit because playwright.config.ts also
# defines a `screenshots` project that captures docs/images/ for
# manual review. That project must not run in CI: its output would
# be discarded after the run, wasting minutes per PR. Keep this
# flag; do not "simplify" back to `npx playwright test`.
run: npx playwright test --project=chromium
- name: Upload E2E report and service logs - name: Upload E2E report and service logs
if: failure() if: failure()
@@ -225,69 +218,6 @@ jobs:
ci-logs/ ci-logs/
retention-days: 7 retention-days: 7
# ---------------------------------------------------------------------------
# Post-release only: Screenshot refresh
# Only runs when release-please merges a "chore(main): release" commit,
# so screenshots are refreshed once per release - not on every merge.
# ---------------------------------------------------------------------------
update-screenshots:
name: Refresh Doc Screenshots
runs-on: ubuntu-latest
timeout-minutes: 15
if: >-
github.event_name == 'push'
&& github.ref == 'refs/heads/main'
&& startsWith(github.event.head_commit.message, 'chore(main): release')
permissions:
contents: write
pull-requests: write
steps:
# Mint a short-lived installation token for the `sencho-token-app`
# GitHub App. Reused by the checkout, PR creation, and auto-merge
# steps below so we make exactly one /app/installations token call.
- name: Generate GitHub App installation token
id: app-token
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: sencho
permission-contents: write
permission-pull-requests: write
- name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ steps.app-token.outputs.token }}
- name: Start app & install Playwright
uses: ./.github/actions/start-app
- name: Capture screenshots
run: npx playwright test e2e/screenshots.spec.ts --project=chromium
- name: Open / update screenshots PR
id: create-pr
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ steps.app-token.outputs.token }}
branch: chore/refresh-screenshots
commit-message: "docs: refresh screenshots"
title: "docs: refresh screenshots"
body: "Automated screenshot refresh - generated by the `update-screenshots` CI job on push to `main`."
add-paths: docs/images/
delete-branch: true
- name: Auto-merge screenshots PR
if: steps.create-pr.outputs.pull-request-number != ''
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
gh pr merge ${{ steps.create-pr.outputs.pull-request-number }} \
--squash \
--repo ${{ github.repository }}
sync-docs: sync-docs:
name: Sync Docs to sencho-docs name: Sync Docs to sencho-docs
runs-on: ubuntu-latest runs-on: ubuntu-latest
+5 -4
View File
@@ -2,10 +2,11 @@
* Docs screenshot capture. * Docs screenshot capture.
* *
* Takes canonical screenshots of key UI views and writes them to docs/images/. * Takes canonical screenshots of key UI views and writes them to docs/images/.
* Run via: npx playwright test e2e/screenshots.spec.ts * Run manually after a UI change that affects a documented view:
* * npx playwright test --project=screenshots
* The CI `update-screenshots` job runs this on every push to develop and * Then review the diff under docs/images/ and commit on a chore branch.
* commits any changed images back to the repo so sync-docs picks them up. * The default `playwright test` invocation skips this spec via the
* project-level testIgnore in playwright.config.ts.
*/ */
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
+14 -1
View File
@@ -30,6 +30,19 @@ export default defineConfig({
}, },
projects: [ projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }, {
// Default project: skips the manual screenshot capture spec so
// `npx playwright test` does not regenerate docs images on every run.
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
testIgnore: ['**/screenshots.spec.ts'],
},
{
// Manual-only project for capturing docs/images/. Run explicitly:
// npx playwright test --project=screenshots
name: 'screenshots',
use: { ...devices['Desktop Chrome'] },
testMatch: ['**/screenshots.spec.ts'],
},
], ],
}); });