Add cli/contributing/changelog/archive: a CLI that trims CHANGELOG.md
to the last N entries (default 7) and writes every older release to
its own file under docs/changelog/ named <padded-semver>-<date>.md
(7.0.0 → 007.000.000-2026-05-08.md). The padded form makes a directory
listing already chronological, and the index in CHANGELOG.md is
rebuilt from the archive directory listing on every run, so it never
drifts away from what is on disk. The tool is idempotent and never
overwrites an existing archive file.
Run the migration once to split the 44-entry CHANGELOG.md into 7
inline entries plus 37 archived per-release files, with the index at
the bottom of CHANGELOG.md linking each archive in descending order.
Add docs/contributing/actions/release.md as the contributor-facing
release procedure (versioning, active window vs. archive, cutting a
release end-to-end, CI hand-off on tag push) and add a docs README
under docs/changelog/ that explains the archive directory layout and
filename schema. Cross-link release.md from pipeline.md and add
"releases" to the actions/ scope description.
Documentation cleanup pass on every page touched in the previous
mapping refactor:
- Remove "is the SPOT for X" / "Single Point of Truth" self-labels
across docs/contributing/, docs/agents/, and docs/changelog/. The
rule in documentation.md forbids self-declared SPOT status; status
is conferred by readers cross-linking, not by the page asserting
it. Rephrase to descriptive phrasing ("This page covers X",
"describes X", "lists X") throughout.
- Drop the orphaned docs/contributing/tools/actions.md duplicate
(101 lines paralleling tools/github/actions/workflows.md, with no
inbound links).
- Fix em-dashes used as thought breaks in dockerfile.md, origin.md,
agents/style.css.md, and suppression.md per documentation.md.
- Unwrap soft-wrapped sentences in iam/common.md, iam/ldap.md,
iam/oidc.md, image/origin.md, requirements.md, and dockerfile.md
so each logical line carries one full sentence.
Add a unit test for the archive CLI under
tests/unit/cli/contributing/changelog/archive/test_main.py covering
_pad_version, _split_into_entries, idempotency, dry-run, no-overwrite
of existing archives, and the multi-run index rebuild.
Quote `# noqa:` in CHANGELOG.md prose with backticks so the
noqa-only-ruff-codes lint does not parse "for" as a non-ruff code.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.5 KiB
Playwright Tests 🎭
This page covers Playwright end-to-end test requirements, runner integration, and file contracts.
For implementation guidance when writing or updating role-local files, see
Agent playwright.spec.js and
Agent playwright.env.j2.
For what the files/playwright.spec.js of a role MUST contain, see
playwright.spec.js (role file rules).
Framework 🧰
- Playwright runs inside Docker via the shared
test-e2e-playwrightrole. - There is no standalone
maketarget for Playwright. Tests run as part of local deploy flows (e.g.make deploy-fresh-purged-apps APPS=web-app-matomo FULL_CYCLE=true). For spec-only iteration after the first successful deploy, see Playwright Spec Loop.
When to Write ✍️
- You MUST provide Playwright tests for every
web-*role. - For when a spec MUST be added or updated (including the
javascript.js/style.csstrigger), see the Scenarios section ofplaywright.spec.js.
Role-Local Files 📁
Every Playwright-enabled role MUST provide exactly these two files:
| File | Purpose |
|---|---|
files/playwright.spec.js |
Test scenarios executed by the Playwright runner |
templates/playwright.env.j2 |
Rendered .env passed to the Playwright container |
playwright.config.js MUST remain centralized in roles/test-e2e-playwright/files/ and package.json in roles/test-e2e-playwright/templates/package.json.j2 (rendered per-deploy into the staging dir). You MUST NOT duplicate or override either per role.
The @playwright/test version pinned into the rendered package.json comes from images.playwright.version in roles/test-e2e-playwright/defaults/main.yml via the image_version filter. That YAML value is the single source of truth for the Playwright version.
CI Image Source 🪞
The Playwright container image is declared in roles/test-e2e-playwright/defaults/main.yml under images.playwright (image: + version:). CI mirrors that image into GHCR through the standard mirror pipeline before deploy tests run, so Playwright jobs do not depend on direct pulls from MCR during the test phase.
The version: MUST stay pinned to an exact Playwright version and distro pair such as v1.59.1-noble. You MUST NOT switch this to a mutable tag such as latest, because mutable upstream tags are more vulnerable to CDN propagation delays and make flaky CI failures much harder to reason about.
Runner 🚀
The test-e2e-playwright role discovers Playwright-enabled roles through the presence of
templates/playwright.env.j2. For each discovered role it:
- stages the test project
- renders
.envfromplaywright.env.j2 - copies
files/playwright.spec.jsinto the project astests/playwright.spec.js - renders the central
templates/package.json.j2and copies the centralfiles/playwright.config.jsinto the staging dir - waits until the app is reachable
- runs Playwright in Docker
File Requirements 📄
See the dedicated SPOT pages for authoring rules:
playwright.spec.js: what the role-local spec MUST contain (entry point, scenarios, selectors, final state)playwright.env.j2: rendered test input surface, variable naming, and entry-point selection
Recording Tests 🎬
Playwright Codegen (built-in) 🔧
Playwright ships a built-in code recorder:
npx playwright codegen https://<app-url>
This opens the Playwright Inspector alongside a browser. Every interaction is recorded and emitted as a runnable spec. Use the output as a starting draft and clean it up according to the authoring rules in playwright.spec.js.
playwright-recorder (Docker-based) 🐳
For infrastructure-heavy setups where Playwright should not live in the main repository, use playwright-recorder. It wraps Playwright codegen in Docker with X11/XWayland forwarding and an ephemeral workspace so no state leaks between recordings.
Requirements: Docker, X11 or XWayland, xhost
# Install
make install
# Record a flow starting at a specific URL
make codegen
# or directly:
./scripts/codegen.sh https://<app-url>/login
# Replay a recorded spec headlessly
make replay
# or directly:
./scripts/replay.sh recordings/login.spec.ts
Generated files are persisted in the local workspace (git-ignored). Copy the relevant parts into files/playwright.spec.js and adapt them.
Development Procedure 📋
This page owns framework and runner mechanics only. The procedure for writing, deploying, and reviewing a role-local spec lives in the dedicated SPOTs:
- Agent
playwright.spec.js: authoring procedure and live review. - Role Loop: baseline deploy, redeploy rules, Certificate Authority trust, Inspect-before-redeploy.
- Playwright Spec Loop: spec-only inner loop against the already-running stack.
playwright.spec.js(role file rules): what the spec MUST contain, including logged-out final state and console cleanliness.