Skip to content

Local e2e via just e2e-live / just e2e-static#660

Merged
srid merged 12 commits intomasterfrom
e2e-just
Apr 25, 2026
Merged

Local e2e via just e2e-live / just e2e-static#660
srid merged 12 commits intomasterfrom
e2e-just

Conversation

@srid
Copy link
Copy Markdown
Owner

@srid srid commented Apr 25, 2026

The cucumber+Playwright suite at tests/ was CI-only by design
Playwright's bundled Chromium download wants apt-get + sudo, which
a Nix devshell can't provide. So the tests gating every PR couldn't
be exercised locally; you had to push and wait.
This wires up
pkgs.playwright-driver.browsers + PLAYWRIGHT_BROWSERS_PATH +
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 in tests/shell.nix so
just e2e-live / just e2e-static work on any Nix host.

The Playwright-side nixpkgs is a separate nixpkgs-latest flake
input
, decoupled from the main nixpkgs pin (which the Haskell
build owns). Bumping Playwright is a paired step:
nix flake update nixpkgs-latest plus a matching version bump in
tests/package.json. Drift between the two breaks Playwright at
launch with a "browser revision X not found" error
— the rationale
is documented at the bump site in tests/shell.nix.

CI is untouched. .github/workflows/ci.yaml keeps using
apt-provided Chromium — cheaper on Ubuntu runners than spinning up
a Nix devshell, and CI remains the single source of truth for the
{live, static} matrix.

Touches #657 (the "Run e2e tests locally" bullet of finish-AI-config).

Try it locally

nix develop github:srid/emanote/e2e-just -c just e2e-live

srid added 6 commits April 25, 2026 10:45
Move the cucumber+Playwright suite from CI-only to runnable on any Nix
host. tests/nix/ is a self-contained bundle (shell.nix + mod.just +
README) — its own nixpkgs pin is required because playwright-driver
must match the npm playwright version (1.57.0). The bundle is set up
to be lifted into a shared repo alongside chrome-devtools when a third
consumer appears; until then each repo carries its own copy.

CI (.github/workflows/ci.yaml) is untouched — apt-provided Chromium
on Ubuntu runners is cheaper than spinning up a Nix devshell, and CI
remains the single source of truth for the {live, static} matrix.
Extract the e2e-live / e2e-static recipe body into a private `_e2e
mode` recipe; the public recipes become argument-passing dependencies.
The live/static matrix stays atomic (CI ownership argument from the
prior Lowy round still holds), but the recipe body lives in one place.
`run *cmd` interpolates the caller's command inside single-quotes for
`nix-shell --run`, so a literal single-quote in `cmd` breaks shell
parsing. The README markets this bundle for cross-repo adoption, so the
constraint is now stated at the recipe site.
Project rule (.claude/skills/code-police): every just recipe must
carry a doc comment, including private ones.
just modules default to running recipes in the module's own directory,
which made `just e2e run "cd tests && ..."` fail with `cd: tests: No
such file or directory` — the inner shell had its cwd at tests/nix/.
[no-cd] keeps the cwd at the caller's invocation point so `cd tests`
resolves against the consumer's project root.
`npm install` regenerates the lockfile (adds peer: true annotations)
even when no real deps changed, leaving a dirty tree after every
local run. `npm ci` is lockfile-respecting and is what CI uses, so
local now matches CI exactly.
@srid
Copy link
Copy Markdown
Owner Author

srid commented Apr 25, 2026

Hickey/Lowy Analysis

# Lens Finding Disposition
1 Hickey Duplicate e2e-live / e2e-static recipe bodies Fixed in this PR
2 Hickey mod.just single-quote constraint undocumented Fixed in this PR
3 Hickey waitForHtml loses HTTP status (pre-existing) No-op (out of scope)
4 Hickey mod.just indirection layer No-op (warranted by extraction posture, conditioned on #2)
5 Hickey Independent nixpkgs pin in tests/nix/shell.nix No-op (intentional, documented)
6 Lowy Independent nixpkgs pin No-op
7 Lowy Atomic e2e-live / e2e-static (vs parameterised) No-op
8 Lowy Boundary between tests/nix/ and tests/{features,…} No-op
9 Lowy mod.just path contract via source_directory() No-op

Hickey rationale

The only structural issue introduced by this PR was duplication between the two recipe bodies (Finding 1) — extracted into a private _e2e mode recipe in 7723e3b. Public surface (e2e-live, e2e-static) is unchanged; the live/static atomic split is preserved per the prior Lowy round. Finding 2 is a latent quoting hazard that becomes relevant the moment a second consumer copies the pattern; documented at the recipe site in b4c3b50. Finding 3 is pre-existing in tests/support/hooks.ts and orthogonal to this PR. Finding 4 (the mod.just indirection) is warranted by the explicit extraction-to-shared-repo intent; Finding 5 (independent nixpkgs pin) is a hard requirement because playwright-driver must match tests/package.json's npm pin (1.57.0).

Lowy rationale

All four pre-considered questions resolve to no-ops. The decomposition correctly encapsulates independent axes of change without leakage:

Layer File(s) Volatility encapsulated
Infrastructure tests/nix/shell.nix playwright-driver + nixpkgs pin, NixOS apt-get incompatibility
Wrapper tests/nix/mod.just Shell invocation convention
Orchestration justfile (e2e-live, e2e-static) Build-configure-test sequence, mode constants
Documentation tests/README.md, tests/nix/README.md None (docs, not behavior)

The independent nixpkgs pin is decoupled from the parent flake on purpose: a Playwright upgrade rotates this pin and tests/package.json together, with no reason to touch the parent flake. Calling it duplication would conflate orthogonal change schedules.

@srid
Copy link
Copy Markdown
Owner Author

srid commented Apr 25, 2026

/do results

Step Status Duration Verification
sync 1s git fetch ok; forge=github; noGit=false
research 2m 45s Confirmed scope: nixpkgs in flake.lock has playwright-driver 1.53.1, but tests/package.json pins playwright 1.57.0 — version skew means tests/nix/shell.nix must own its own nixpkgs pin (matches Kolu rev f8573b9c, has playwright-driver 1.57.0). Just 1.42.2 supports source_directory() for module-relative paths.
branch 3s On branch e2e-just (created from origin/master)
implement 1m 40s Created tests/nix/{shell.nix,mod.just,README.md}; added mod e2e + e2e-live/e2e-static recipes to top-level justfile; rewrote tests/README.md Running section.
check 30s cabal build all: exit 0, all 56 modules + emanote exe built clean.
docs 16s Docs in sync. No prose docs reference the e2e suite.
fmt 30s pre-commit run --all-files: cabal-fmt + fourmolu + hlint + nixpkgs-fmt all Passed.
commit 14s Commit 397c94a on branch e2e-just; pushed to origin/e2e-just.
hickey+lowy 5m 6s Hickey: 5 findings (2 Fix in this PR, 3 No-op). Lowy: 4 No-ops. Two follow-up commits: 7723e3b (refactor) + b4c3b50 (docs).
police 2m 27s Rules: 1 violation (missing doc comment on _e2e), fact-check clean, elegance clean. Fix: 3d7a1f5.
test 1m 59s just e2e-live: 12/12 scenarios passed; just e2e-static: 12/12. Path bug found and fixed: [no-cd] attr in 3c4d1d4.
create-pr 2m 28s Draft PR #660 + hickey/lowy comment. Lockfile-drift fix 5536036 (npm ci) attached after creation.
ci 5m 11s flake-parts-docs SUCCESS, e2e-tests(live) SUCCESS, e2e-tests(static) SUCCESS, website SKIPPED.
done 0s PR #660 ready
Total 24m 48s

Slowest step: ci (5m 11s)

Optimization suggestions

  • ci (5m 11s) is the single largest fixed cost. Re-runs after a small fix should use --from ci-only to skip everything before. The 5m is dominated by e2e-tests matrix (apt + npm install + emanote build per leg, x2). Cutting this further would mean caching the npm dependencies on Actions runners, not a workflow-side change.
  • hickey+lowy (5m 6s) already ran the two sub-agents in parallel. Wall-time is bounded by the slower lens (hickey at ~3m); not further reducible without trimming sub-agent prompts.
  • test retried once because the first just e2e-live hit a path bug (just module's default cwd is the module's own directory, not the project root). The [no-cd] discovery is something a smoke-test of any new mod.just recipe would have caught earlier — worth folding into the implement step's verification next time, before commit.
  • police rules pass found one issue (missing doc comment on _e2e mode) — manual pre-flight of new recipes against the project's justfile rule would skip the police-fix loop entirely.

Workflow completed at 2026-04-25T15:03:22Z.

srid added 4 commits April 25, 2026 17:53
Drop the tests/nix/ subdirectory and its README. shell.nix and mod.just
now sit directly under tests/. Mod-import path becomes
`mod e2e 'tests/mod.just'`. Stripped the now-irrelevant cross-repo
language from shell.nix's header comment. Layout list in tests/README.md
points at the two files directly. The portable-bundle posture is gone;
this is just the e2e suite's local Nix runtime, no more, no less.
just --list takes only the line immediately preceding the recipe (or
its attribute) as the doc comment. The multi-line constraint comment
clobbered the descriptive line — `just --list e2e` was showing
"wherever they invoked just." instead of the recipe summary. Move the
caller-notes to a file-level header block; keep one descriptive line
above the recipe.
So the do workflow's test step picks them up alongside `just test`.
Comment thread tests/shell.nix Outdated
srid added 2 commits April 25, 2026 18:41
Drop the just-module indirection. `_e2e mode` now invokes
`nix-shell tests/shell.nix --run "..."` directly. One fewer file,
one fewer hop, same behavior.
Drops the hardcoded fetchTree rev in tests/shell.nix; it now reads
the locked rev from flake.lock's `nixpkgs-latest` input. The new
input tracks nixpkgs-unstable, decoupled from the main `nixpkgs`
input (which the Haskell build pins). Bumping playwright is now:
  nix flake update nixpkgs-latest
  npm install --package-lock-only --prefix tests
…paired so playwright-driver and the npm playwright stay aligned.

Bumps tests/package.json to playwright 1.58.2 to match the rev that
nixpkgs-latest currently locks (playwright-driver 1.58.2). 12/12
scenarios pass in both live and static modes.

Addresses PR review comment from @srid on tests/shell.nix.
@srid srid mentioned this pull request Apr 25, 2026
2 tasks
@srid srid marked this pull request as ready for review April 25, 2026 22:48
srid added a commit to juspay/skills that referenced this pull request Apr 25, 2026
## Summary
- New `nix-playwright` skill capturing the pattern from
[srid/emanote#660](srid/emanote#660) for running
an existing Playwright e2e suite locally on NixOS / pure-Nix hosts
- Covers the `nixpkgs-latest` flake input, a self-contained
`tests/shell.nix` that reads the parent lock to provide
`playwright-driver.browsers` + `PLAYWRIGHT_BROWSERS_PATH`, and a
justfile entry
- Flags the critical driver ↔ npm `playwright` version coupling (drift
triggers "browser revision X not found")

## Test plan
- [ ] Verify SKILL.md frontmatter and table entry render
- [ ] Apply skill to a project with an existing Playwright suite and
confirm `just e2e` works on NixOS

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@srid srid merged commit 29b517a into master Apr 25, 2026
4 checks passed
@srid srid deleted the e2e-just branch April 25, 2026 22:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant