~ knotless Search/
↑↓ move↵ open⇧↵ all results

grain.social/grain

photography-focused photo sharing platform

grain.social
1 collaborator
0
2

ci: The pages and grain-serve are checked together, end to end

Merged
Merged chadtmiller.com asked to merge into feature/rust from grain.social/grain:ci/e2e

What changes

An e2e check (.knotless/workflows/e2e.yml, harness/e2e/), modelled on knotless's. grain-serve and the web's build run as deploy/docker-compose.yml runs them, with grain-serve handing the pages to the web through --web. They sit behind harness/tls-proxy.mjs at the harness's client hostname, over the reference PDS and PLC from harness/pds.mjs. Backfill is on, reading each account a login tracks from its PDS, as production does: only backfill or Jetstream gives the index an account's handle. Chromium logs in through the PDS's own approval page. Each write the pages make is then read back on the page, from the writer's repo at the PDS, and on the other account's page through the index.

Over the stock PDS (flows.spec.mjs, alice and bob):

  • a login that seeds a grain profile from alice's Bluesky one;
  • a login with none, which seeds a bare one for bob, and shows no Groups tab;
  • the home feed and the story tray, and the reads behind them;
  • a gallery made with a photo upload, kept in her repo with its photo, blob and item, and shown in the feed, on her profile and on its page;
  • a favorite, a comment and a follow from bob;
  • alice's notifications showing all three;
  • editing the gallery, read back from her repo, from the index, and on the page she is sent back to;
  • editing her profile, seen from bob's page;
  • deleting the gallery, with its items, and gone from both accounts' pages.

Over the spaces alpha (spaces.spec.mjs, the alpha built as harness.yml builds it): social.grain.server.getSpaceSupport says yes, the Groups tab shows, and /groups opens to the groups list rather than the notice that spaces are needed.

Each spec ends by checking that no call the pages made to grain-serve was answered 5xx, and it names each method that was. That would have caught the 22 unspecced methods.

web: Saving a gallery's edits shows them. The editor invalidated ['gallery', uri], a key no query has: the gallery page reads ['getGallery', uri], so after saving it showed the title from before the edit until it was reloaded. It now invalidates galleryQuery's own key. The edit flow found this.

The browser reaches only the world. Its requests to plc.directory, which the pages make directly to find a PDS, are answered by the harness's PLC, and every other host is refused. The root layout sets data-ready once mounted, as knotless's does, so a flow clicks only once a click reaches a handler. When a flow fails, the check prints the page's accessibility snapshot, what the browser logged, and the servers' logs, and keeps a screenshot. just e2e runs it, and AGENTS.md says what it is.

Why

CI checks grain-serve (rust, harness) and the web (check, test) separately, and nothing ran them together. That is how the web came to call 22 social.grain.unspecced.* methods that grain-serve answers with 501, which left next.grain.social with no Groups tab. With feature/rust merged in at c9b7fb4, which has the method-name pull, the spaces flows pass.

How it was checked

Only on the runner; nothing was built or run on this machine. Nothing touches next.grain.social, grain.social or a real account: the flows run against a local PDS and the alpha, and the browser is fenced to them.

At 4a82c5b every check passes, e2e included: 12 of 12 flows over the stock PDS (38s) and 3 of 3 over the alpha (14s). Before the method-name pull was merged in, the spaces flows failed on unspecced.getSpaceSupport answering 501, as expected.

The e2e check takes about 12 minutes on the runner. Most of that is building the alpha and the build: pull runs keep no cache until this workflow has run on main. The flows themselves take under two minutes.

Shortcomings

  • No private gallery and no group is made. Private galleries are gone (c9b7fb4). Starting a group takes a group host (--group-host), and the harness has none. The Rust tests stand one up in-process (crates/grain-serve/tests/host); doing the same here would be a follow-up. Until then, groups are checked only as far as getSpaceSupport, the tab and /groups.
  • A login does not give the index the account's handle. Only backfill and Jetstream do, so without backfill /profile/<handle> is "Profile not found" right after signing up, and the sidebar's Profile link goes by DID. The world runs backfill as production does, so this check does not catch it. It is grain-serve's, and is left to its own pull.
  • The gallery menu offers "Edit gallery" to one DID only, so the edit flow opens the editor by its address.
  • A gallery's page lists the gallery itself under "More galleries from".
  • Stories beyond the tray, replies, blocks and mutes, search, and the mobile layout are not covered, to keep the run short.
  • Images point at Bluesky's CDN when there is no --cdn, and that host is refused, so images are checked by their records and not by their pixels. The service worker does not register under the harness's self-signed certificate.

🤖 Generated with Claude Code

Approved

This adds an e2e workflow and a Playwright harness. It runs grain-serve and the web build together over the harness PDS, with Chromium logging in through the PDS's approval page. A second pass runs the spaces specs on the alpha. It also adds a data-ready marker on the root layout and a just e2e recipe.

I read the workflow and the Playwright config and found nothing that has to change.

  • The two runs write to separate outputDirs (results and spaces), so the second run can't wipe the first run's failure artifacts.
  • Logs are copied aside between the runs.
  • The $status handling means a failure in either run fails the check.
  • The browser is fenced to the local servers, so nothing reaches production.

The e2e check for 8e53b84 was still running when I looked, so I haven't seen whether the remaining flows pass. The check workflow passed. test, rust and harness were still queued and lexicons was skipped. The pull's own description says the results for the flows after the gallery creation are still to come. Please don't merge until e2e is green at this head.

Smaller points:

  • The header comment says the alpha and build "are kept between runs", but the body says the cache doesn't carry them between pull runs. If that holds, the comment is misleading.
  • The just e2e recipe and the new harness/e2e paths aren't described in AGENTS.md. A line under "The Rust tests" would help the next agent.
Approved

The only change since round 1 is in the "editing a gallery" flow. It now reads the gallery back from her repo, then from the index through getGallery, and only then checks the heading. That is a sound way to tell a write that never landed from one the index hasn't picked up, and I found nothing wrong with it.

The e2e check at this head was still running when I looked, so I haven't seen whether the later flows pass. check passed. test, rust and harness were queued and lexicons was skipped. Please don't merge until e2e is green at 8a2e131.

Two points from round 1 are still open, and neither blocks the merge:

  • The header comment says the alpha and build are kept between runs, but the description says the cache doesn't carry them.
  • AGENTS.md doesn't mention just e2e or harness/e2e.
Approved

Since round 2 the pull has three changes. AGENTS.md and the cache comment are updated, which covers both points I left open. feature/rust is merged in. And the gallery editor now invalidates the query key the gallery page actually reads.

That last change is a real web fix that the new edit flow found. galleryQuery is already imported in the editor, and the page's createQuery and the load function both use it. The new invalidation therefore hits a key that exists, and I found nothing wrong with it.

The e2e check at 4a82c5b is still queued, along with check, test, rust and harness. lexicons was skipped. I haven't seen the remaining flows pass, so please don't merge until e2e is green at this head.

Answered at 4a82c5b, where every check passes, e2e included: 12 of 12 flows over the stock PDS and 3 of 3 over the alpha.

  • The cache comment in e2e.yml now says the alpha and the build are kept as main's runs leave them, so a pull's run builds the alpha again until this workflow has run on main.
  • AGENTS.md has a section, "The end-to-end flows", after "The Rust tests": what the check runs, where its parts are, what a failure leaves, and just e2e.

Since the review, the edit flow found a web bug, now fixed here: the gallery editor invalidated a cache key no query uses, so the page it returns to showed the old title. feature/rust is also merged in at c9b7fb4, and with private galleries gone, the spaces flows check getSpaceSupport, the Groups tab and /groups.

Merged as 4a82c5b
Part of a stack of 2
  1. ci: The pages and grain-serve are checked together, end to end Landed as 4a82c5b
  2. main