Skip to content

Take five more of the guide's screenshots automatically, on a fixture that is a real checkout - #631

Merged
zaerl merged 3 commits into
trunkfrom
docs/automate-repo-screenshots
Oct 5, 2026
Merged

zaerl merged 3 commits into
trunkfrom
docs/automate-repo-screenshots

Conversation

@zaerl

@zaerl zaerl commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Why

Third part of #561. After #621 sixteen of the guide's screenshots were taken by npm run shots and eleven still needed a person. Ten of those eleven need what the fixture's empty folders are not: a site with a real Git checkout in it. This gives the fixture one, and moves the first five across. Settings (#559) and dark mode (#560) will each change every picture in the guide again, so a picture that takes a person is one that will be stale.

What changes

Five shots join the automatic tier, which is now twenty-one. All five were live:

  • submit-changes-diff: the review dialog's diff, of one changed line and one new test file.
  • submit-destinations: the same dialog's three destinations on a Core site.
  • github-sign-in: the Open a pull request card while it waits for the code to be entered.
  • apply-patch-conflict: the ticket's patch applied over an edit to the same line.
  • trunk-update-progress: an update at its third step.

A fixture that is a checkout. The repo: variants are a real repository under the fixture's folder, made with the app's bundled Git binary through the helpers the journeys' and unit tests' sites are made with. The shot then does the rest through the app: links the ticket, edits a file, opens the review, applies the patch, or updates from an origin (a second repository beside it, on file://) that is one commit ahead. Each has a repository and a launch of its own, since it writes to both.

More of the outside answered for the app: GitHub's account and sign-in, the ticket's patch from Trac, an install and a build. The sign-in's code is made up.

What the harness gained for them:

  • A shot can ask for a taller window than the one on screen (viewport). The destinations need it: three cards, one under another.
  • A spinner is drawn standing still. It turned between one run and the next, and the picture with it.
  • The fixture's folders are removed with the helper that unlocks Git's read-only objects first, and a launch's profile folder is removed when the launch ends.

Beside the images: the alt text of the five, and one more image changes, linked-pull-requests, because the size its card gives for the ticket's patch is now the patch's own.

Not in this pull request:

  • The six that are left: setup-wizard, and five that no script takes (carried-work-notice, site-with-tickets, ticket-list-card, ticket-list-unlinked, trunk-work-question, all in the ticket branches page). The five are the next pull request, on this fixture. setup-wizard may have to stay a person's: the setup it shows starts only when a clone finishes.
  • The guide's prose. Two pages now say things beside these pictures that the pictures contradict; the list is in the review outcome.

How to test this

Platforms: macOS to reproduce the committed images; the harness is written to run on any, and I have run it on macOS only. Nothing here ships in the app.

From the repository root, on the current head, after npm ci:

npm run shots
git status --short docs/public/screenshots
  1. The run prints twenty-one lines, each ✓ <name>.png, and exits 0. It opens the app's window nine times; do not type while it runs, and no browser tab opens.
  2. On the machine and the UTC day the images were taken, git status usually shows nothing.
  3. Open apply-patch-conflict.png: a red notice that the checkout was not changed, then src/wp-includes/summary-length.php, "Near" a line of code, and the lines that did not fit. trunk-update-progress.png: step 3 of 3, with the install skipped. submit-destinations.png: a heading and three destinations in two cards, nothing cut off below "Change these".

What must not have happened: anything asked of GitHub or Trac, an npm install or a build started, a browser tab opened; a folder named wpct-docs-fixture or wpct-userdata-… left in the temporary directory after the run; a crop with part of another column in it.

What cannot be promised: the same bytes on every run. After the last change to what is drawn I took the tier four times, and once more after the last commit, and the five runs gave the same bytes; the corner of a card drawn a few pixels differently, about one run in ten, is from #621 and nothing here removes it.

What I could not test: Windows. Two things here are written for it and not run on it: the removal of the fixture's repositories, and the size of window a launch lays out for, which is asked of the window and assumes Windows' menu bar is not counted in it.

Risks and limitations

  • Review: 2 passes, 9 findings fixed here, 2 follow-ups taken here, 1 left. Details below.
  • The fixture's ticket, pull requests, patch and PHP file are made up, and say so nowhere in the picture: #60000 is not that ticket on Trac, and summary-length.php is not a file of WordPress.
  • The update's picture is of a build that is not running. The build is answered for the app and never ends; the picture is of the card at that step.
  • The harness now requires tests/unit/helpers/git.cjs. A change to how the tests build a repository changes how the fixture does.
  • The guide's text beside these pictures is still the old window's.

Related

Part of #561, which is part of #542. Follows #621.


Design decisions and alternatives considered
  • A real repository, and the app's own flows on it, and not a seeded state. What these five show (a diff, a refused patch, an update's steps) the app computes from Git; a picture of numbers written into a settings file would be a picture of a state the app never reaches.
  • One repository and one launch per shot. Each shot writes to its checkout and to the app's settings, and a shot handed the checkout of the one before would depend on the order they are taken in. It costs five launches.
  • The origin is a repository on disk, so the update's fetch is a real fetch and asks nothing of the network.
  • The patch is generated from the fixture file's own lines, with its hunk header counted and not typed, so that changing the file cannot leave a patch that no longer describes it.
  • The fixture's PHP is of nothing in WordPress. The first version was close enough to a real function and its comment to read as a copy of it.
Review outcome (required — see AGENTS.md)

Pass 1: 8 [fix here] · 3 [follow-up]. Pass 2 (on the fix-up): 1 [fix here] · 0 [follow-up]. All 9 fixed, 2 follow-ups taken here, 1 left.

  • Review: completed — a separate agent context, read-only; head b688f1c / base d1616d2; the five images opened and each alt text read against its picture, every request a shot's flow makes of the main process traced to a stand-in or to something local, the fixture's Git checked for reading nothing of the host's; lint, tests and the shots not run; 8 [fix here], 3 [follow-up].
    • Fixed: the fixture's folders were removed with a plain removal, which Windows refuses for Git's read-only objects, and since every variant starts by cleaning, the second would not have started; the update's shot waited a second and a half where it now waits for the step it is a picture of; the patch's hunk header was off by one and its single line of context made the notice say "Near */"; the fixture's PHP followed a real function's comment closely; the checkout's site was not marked as set up; the destinations' crop would have taken a cut-off column silently, and had no room above its heading; the size of window a launch lays out for was read from the page, which learns of a resize late; one alt text misquoted its picture.
    • Follow-ups, taken here: the size the ticket's card gave for the patch was not the patch's; every launch left its profile folder behind.
    • Follow-up left: the notice's own sentence, "None of this patch's 1 change still fit your checkout", whose verb does not follow its count. It is the app's wording and not this change's; the alt text quotes it as it is.
    • Listed and left for the text: in submitting-changes.md, the diff "titled Your changes" (it is "Your changes for ticket #60000"), "Two buttons sit above the diff" (there is also Discard all changes), which of two subtitles a linked ticket's diff has, and "Each card" (Trac and the mentor share one); in submit-github-pr.md, Not now, which is not on screen during sign-in.
  • Review: completed — a second separate agent context, read-only; head e14eb32 / base d1616d2; the patch evaluated from its constants and followed through the app's path rewrite and its choice of the "Near" line, the removal helper read for following a link out of the fixture, the four retaken images opened; ESLint run on the harness, npm test and the shots not run; 1 [fix here], 0 [follow-up].
    • Fixed: a profile folder that could not be removed would have taken the place of a shot's own error, or ended a run whose pictures were taken. It is now said and left.
    • Nothing found: the removal helper, the patch, the fixture's PHP, the patch's size, the wait for the update's step, the crop's padding, the changed comments. On the window's size it found nothing by reading and says, as I do above, that Windows was not run.
  • Since review: e14eb32 → 91fffb0 is that one fix, not reviewed again: a try around one removal. After it the tier was taken once more with no image changed, and npm run lint and npm test pass.
Implementation notes
  • scripts/screenshots/fixtures.cjs: buildRepoFixture, the SUMMARY_* file and TICKET_PATCH made from it; standInForTheOutside also answers trac:fetch-attachment, github:account, github:sign-in, github:sign-in-cancel, npm:install and npm:run-script; cleanFixtureSites runs before every variant and uses removeRepo.
  • scripts/screenshots/capture.cjs: viewport per shot, the default asked of the window; no animation; the profile folder removed after each launch.
  • scripts/screenshots/shots.cjs: linkTheTicket, editTheCheckout, openTheReview; the five shots; five live entries removed, one left.
  • No app code changes, so the Electron suite, the journeys and the packaged smoke were not run.
Screenshots or recording

The images are the change: docs/public/screenshots/ in the diff, which GitHub shows before and after.

🤖 Generated with Claude Code

zaerl and others added 3 commits October 5, 2026 16:43
…utomatically, on a real checkout

Five more of the guide's screenshots that needed a person at a real site
join the automatic tier (#561), which is now twenty-one: the review
dialog's diff, its destinations and the GitHub sign-in's code, a patch
that does not fit, and an update part of the way through.

They need what the fixture's empty folders are not: a checkout. The
`repo:` variants are a real repository, made with the app's own Git
binary as the journeys' sites are, and the shot does the rest through the
app: links the ticket, edits a file, opens the review, applies the
ticket's patch over an edit to the same line, or updates from an origin
that is a commit ahead. Each has a repository and a launch of its own,
since it writes to both. GitHub's sign-in, the ticket's patch and an
install are answered for the app, like the rest of the outside.

A shot can ask for a taller window than the one on screen, which the
destinations need: three cards, one under another. A spinner is drawn
standing still, since it turned between one run and the next and the
picture with it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e that says where it failed

From the review. The fixture's folders are removed with the helper that
unlocks Git's read-only objects first: a plain removal is refused on
Windows, and since every variant now starts by cleaning, the second one
would not have started. A launch's profile folder is removed when the
launch ends.

The ticket's patch carries the three lines either side that a patch
usually does, with a hunk header that counts them right, so the notice
for a patch that does not fit names a line of code where it named a
comment's last line. Its file is not WordPress's: the fixture's function
and its comment were close to a real one's. The size the ticket's card
gives for the patch is the patch's.

The update's shot waits for the step it is a picture of, where it waited
a second and a half. The destinations' crop is refused if the cards do
not fit their column, and has room above its heading. The size of window
a launch lays out for is asked of the window.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The launch's profile is removed in the finally after the app closes. A
removal that throws there took the place of the shot's own error, and
after a variant whose pictures were taken it ended the run before the
next variant. It is now said and left.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: WordPress/contributor-toolkit/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 107b4444-c633-485f-9406-7c0ef60dfd34

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@zaerl
zaerl merged commit be7fa7b into trunk Oct 5, 2026
10 checks passed
@zaerl
zaerl deleted the docs/automate-repo-screenshots branch October 5, 2026 15:30
zaerl added a commit that referenced this pull request Oct 5, 2026
## Why

Fourth part of #561. After
#631 six of the
guide's screenshots were still a person's to take, and five of those no
script took at all: the pictures on the ticket branches page. Settings
(#559) and dark mode (#560) will each change every picture in the guide
again, so a picture that takes a person is one that will be stale. This
takes the five automatically, on the checkout fixture of #631.

## What changes

**Five shots join the automatic tier**, which is now twenty-six of
twenty-seven:

- `site-with-tickets`: a Core site with a ticket in hand and the card of
its other tickets at the foot of the page.
- `ticket-list-card`: that card, with a ticket linked.
- `ticket-list-unlinked`: the same card with none linked, two tickets in
it.
- `trunk-work-question`: what the app asks when a ticket is linked over
an edit on trunk.
- `carried-work-notice`: the ticket's card after the edit came along.

**Tickets the site was left with are the fixture's.** A row in the list
has an age ("Edited 1 day ago"), which a shot cannot give it through the
app: every ticket it left would have been left just now. So for these
variants the fixture makes what the app makes when a ticket is started
and left with nothing done: a branch where trunk was, and the record of
it (which ticket, where it branched, when it was last worked on). The
hours are chosen well inside the wording they come out as, so a picture
is the same at any time of day.

**The checkout fixture's trunk commit is dated** as the seeded sites'
code is, two days back. It was dated the moment it was made, so a site's
details said its code was newer than the site.

**What the harness gained for them:**

- A wait for a button that can be pressed and not only one that is on
the page. A row's buttons are disabled until a link has wholly ended.
- A whole-window picture can refuse to be taken when the page has
outgrown the window (`site-with-tickets` is taken in a window 1480 high,
since its second card is at the foot of the page).

**One change outside the harness:** `commitFiles` in
`tests/unit/helpers/git.cjs` takes a `date`. It is the fixture layer the
tests build their repositories with; no test passes the option, and
without it the command is the one it was.

**Beside the images:** the alt text of the five, and the sentence in
`CONTRIBUTING.md` about which pictures need a person.

**Not in this pull request:**

- `setup-wizard`, the one picture still taken by a person. It can be
taken automatically too, and is the next pull request, with the removal
of the live tier it leaves empty.
- The guide's prose. The ticket branches page now says things beside
these pictures that the pictures contradict; the list is in the review
outcome.

## How to test this

Platforms: macOS to reproduce the committed images; the harness is
written to run on any, and I have run it on macOS only. Nothing here
ships in the app.

From the repository root, on the current head, after `npm ci`:

```
npm run shots
git status --short docs/public/screenshots
```

1. The run prints twenty-six lines, each `✓ <name>.png`, and exits 0. It
opens the app's window fourteen times; do not type while it runs, and no
browser tab opens.
2. On the machine and the UTC day the images were taken, `git status`
usually shows nothing. Some runs show one or two images changed by a
handful of pixels on a rounded corner (4 of the 17 runs I made today,
always in a picture older than this change, 12 pixels in the one I
measured); take it again and it is gone. That is more often than the one
in ten #621
measured: there are more pictures to a run now.
3. Open `ticket-list-unlinked.png`: two rows, #60000 "Edited 3 hours
ago" above #61002 "Edited 1 day ago", each with Continue working and
Delete this ticket’s work, none greyed. `carried-work-notice.png`: a
blue notice that 1 uncommitted change came along into #60000, and under
it "You have 1 unsubmitted change for ticket #60000".
`site-with-tickets.png`: under Details, "Trunk as of" is two days before
the run, the day "Created" gives.

**What must not have happened:** a button in a ticket's row drawn greyed
or as if the pointer were on it; anything asked of GitHub or Trac; a
folder named `wpct-docs-fixture` or `wpct-userdata-…` left in the
temporary directory after the run.

**What I could not test:** Windows. And on Windows the fixture is under
the user's temporary folder, so a whole-window picture taken there would
have the user's name in "Local path"; that was so before this change,
and the committed pictures are taken on macOS, where the path is
`/tmp/wpct-docs-fixture/…`.

## Risks and limitations

- Review: 2 passes, 5 findings fixed here, 2 follow-ups taken here, 1
left. Details below.
- **Three of the five pictures start from a state the fixture wrote**,
where #631's start from one the app made: the tickets a site was left
with. The record is the app's own, key for key, and the reviewer checked
it against the code that writes it; a change to what the app records for
a ticket would have to be made here too.
- **A shared test helper changes.** `npm test` passes, and I checked by
hand that a commit made with a date carries it as author's and
committer's, and that one made without is dated now.
- The fixture's tickets are made up: #60000 and #61002 are not those
tickets on Trac.
- The guide's text beside these pictures is still the old window's.

## Related

Part of #561, which is part of #542. Follows
#631.

---

<details>
<summary>Design decisions and alternatives considered</summary>

- **Seeded tickets, and not tickets left through the app.** Through the
app the rows all read "Edited just now", in a page whose text is about
coming back to a ticket days later. The age is the one thing a shot
cannot make; everything else about a left ticket is a branch and three
values, which is what is written.
- **One day and three hours, and not a week.** Past a week the row gives
a date, written the way the computer writes dates, which changes with
the day and the machine.
- **A taller window for the two cards**, and not a page scrolled to its
foot: the picture is of a site with a ticket in hand and others below,
and scrolled it would lose the ticket in hand.
- **The date as an option of the fixture layer's commit.** The first
version ran the Git binary from the harness, with the commit's identity
written out again: a third way to the binary beside the app's and the
tests'.

</details>

<details>
<summary>Review outcome (required — see AGENTS.md)</summary>

**Pass 1: 3 [fix here] · 3 [follow-up]. Pass 2 (on the fix-up): 2 [fix
here] · 0 [follow-up]. All 5 fixed, 2 follow-ups taken here, 1 left.**

Both passes were made before the rebase onto #631's merge, on commits
that are the same changes as these; the heads below are the ones
reviewed.

- **Review:** completed — a separate agent context, read-only; head
`551457e` on `91fffb0`, the head #631 merged; the five images opened and
each alt text read against its picture, the seeded record compared with
what linking and leaving a ticket write, every request the five flows
make traced to a stand-in or to something local; ESLint run on the
harness, `npm test` and the shots not run; 3 [fix here], 3 [follow-up].
- Fixed: the notice's picture did not wait for the line that says there
is one unsubmitted change, which a read of its own brings later, and
could come out without it; two pictures waited for a row's buttons to be
on the page and not to be ones that can be pressed; a comment said
leaving a ticket is the one thing a shot does not do through the app,
where editing the checkout is another.
- Follow-ups, taken here: `CONTRIBUTING.md` said a running server and a
real diff need a person; the checkout's trunk was dated the day of the
run, newer than the site.
- Follow-up left: on Windows the fixture's path has the user's name in
it. See "What I could not test".
- Listed and left for the text, in `ticket-branches.md`: "each row is a
**Continue working on #NNNNN** link" and "**Continue working on**" twice
more (it is a Continue working button); "**edited 2 days ago**"
(capitalised, and the pictures' are a day and three hours); "Delete this
ticket's" with a straight apostrophe; "came along into #62281" and "1
unsubmitted change for ticket #29798" (the pictures' ticket is #60000);
and the delete question, which the app now words "Delete all work on
ticket #61002?" and "This can’t be undone."
- **Review:** completed — a second separate agent context, read-only;
head `c0cd36e` on `91fffb0`; the dated commit followed through the
fixture's order and the app's reading of trunk's date, the trial click
checked against how the row's buttons are disabled, the two retaken
images opened; ESLint run on the harness, `npm test` and the shots not
run; 2 [fix here], 0 [follow-up].
- Fixed: the harness dated its commit by running the Git binary itself
(now an option of the fixture layer's commit); a comment said a row's
buttons can be pressed after the card has read the ticket, an order the
app does not promise.
  - A style note, taken: one wait the trial click already does.
- **Since review:** `c0cd36e → ce66772` is those fixes, not reviewed
again; it is what changes `tests/unit/helpers/git.cjs`. The three
commits were then rebased onto #631's merge with no conflict and are
`1765fc9`, `48b78ea`, `f56f33f`. On that head: `npm run lint` and `npm
test` pass, and a retake of the tier changed no image.

</details>

<details>
<summary>Implementation notes</summary>

- `scripts/screenshots/fixtures.cjs`: `OTHER_TICKET`, `PARKED_TICKETS`;
`buildRepoFixture` makes the branches and writes their record; the trunk
commit dated `FRESH.trunkDate`.
- `scripts/screenshots/shots.cjs`: `waitUntilPressable`, `fixTheLine`,
`askToLinkOverAnEdit`; the five shots.
- `tests/unit/helpers/git.cjs`: `git` and `gitOk` take an environment,
`commitFiles` a `date`.
- No app code changes, so the Electron suite, the journeys and the
packaged smoke were not run.

</details>

<details>
<summary>Screenshots or recording</summary>

The images are the change: `docs/public/screenshots/` in the diff, which
GitHub shows before and after.

</details>

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@zaerl zaerl added this to the v2.0.0 milestone Oct 7, 2026
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