Skip to content

[Fix] Keep the install step in progress until npm ci has exited - #496

Merged
juanmaguitar merged 1 commit into
trunkfrom
fix/install-step-not-done-while-installing
Sep 19, 2026
Merged

juanmaguitar merged 1 commit into
trunkfrom
fix/install-step-not-done-while-installing

Conversation

@juanmaguitar

@juanmaguitar juanmaguitar commented Sep 19, 2026 •

Copy link
Copy Markdown
Collaborator

Why

While the setup wizard is still installing (banner step 2 of 3, Installing dependencies, npm ci streaming in the terminal), the Install npm dependencies step flipped to COMPLETED and Run full build to READY with its button enabled. A click there starts a build over a half-written node_modules. Seen on Windows during the v1.2.0-beta.1 pass on a Gutenberg site, whose install is long enough to switch windows during; the rule is shared by every site (#495).

What changes

Root cause. computeSetupStepState took the step as done when node_modules exists and is non-empty and the last install did not fail. It ignored installing. Any status refresh mid-install (switching back to the window triggers one) reads the partial directory as done.

The fix. An install still running overrides existence, exactly as a failed one already did (#42): installOk also requires !installing. One line. When npm ci exits 0 the flag clears, the next status read sees the full directory, and the step completes as before.

How to test this

Platforms: either. Build: the Buildkite artifact for the current head, or npm start from the repository root.

Starting state: no site yet, or a site whose wizard is at the download step.

  1. Create a Gutenberg site (its install runs for minutes) and wait until the banner reads step 2 of 3, Installing dependencies.
  2. Switch to another application and back, two or three times, while the terminal still shows npm http fetch lines. Expected: Install npm dependencies keeps its in-progress state and Run full build stays locked.
  3. Let the install finish. Expected: the step turns COMPLETED and the build starts on its own (the wizard chains it).
  4. On an existing, fully installed site, open it. Expected: the step reads COMPLETED as before; nothing regresses for a site that is not installing.

What must not have happened: Run full build enabled while npm ci is running; a completed site's install step reading as not done.

Test: tests/unit/setup-steps.test.cjs, a half-written node_modules during an install does not complete the step. Fails on trunk, checked in a trunk worktree.

Risks and limitations

None beyond the one-line rule. The installing flag is set by the renderer for the wizard's install and for a manual npm install from the terminal alike, so both paths get the same hold.

Related

Fixes #495. Part of the v1.2.0-beta.1 pass, follows #489, #491, #493.


Review outcome (required — see AGENTS.md)

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Sep 19, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: WordPress/contributor-toolkit/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 00aed479-93a9-4d50-ae23-f5229ef43a7e

📥 Commits

Reviewing files that changed from the base of the PR and between 5167e88 and 2b6634c.

📒 Files selected for processing (2)
  • src/renderer/setup-steps.cjs
  • tests/unit/setup-steps.test.cjs

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

computeSetupStepState now requires node_modules to exist, the previous install to have succeeded, and no install to be running before marking installation complete. A unit test covers the case where node_modules exists during an active install and verifies that the install remains incomplete and the build remains locked.

Assessment against linked issues

Objective Addressed Explanation
Keep the install step incomplete and keep the build locked while npm ci is running [#495] ✅

Priority: ➖ Normal

Severity of issue fixed: Medium

🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description includes the required Why, What changes, How to test, Risks and limitations, Related, and Review outcome sections. It explains the root cause, fix, regression test, validation evidence…

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.

The step read as completed, with the build unlocked, whenever a status
refresh ran mid-install and found a half-written node_modules. An
install still running now overrides existence, the same way a failed
one already did.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@juanmaguitar
juanmaguitar force-pushed the fix/install-step-not-done-while-installing branch from 44570f4 to 2b6634c Compare September 19, 2026 14:15
@juanmaguitar

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 19, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@juanmaguitar
juanmaguitar merged commit ffbdb3c into trunk Sep 19, 2026
8 checks passed
@juanmaguitar
juanmaguitar deleted the fix/install-step-not-done-while-installing branch September 19, 2026 14:28
juanmaguitar added a commit that referenced this pull request Sep 20, 2026
…504)

## Why

On a Gutenberg site the wizard's **Run full build** step flipped to
**COMPLETED** ("Build complete") and **Start dev server & finish
wizard** to **READY** while `npm run build` was still running: banner on
*step 3 of 3*, terminal in phase 4 (widgets). Seen on 20 Sep 2026 on
Windows (UTM VM, trunk artifact `ffbdb3c`), right after #496 fixed the
same thing for the install step. Since #500 a click there starts
Playground at once on that half-written `build/` (#502).

## What changes

**Root cause.** `computeSetupStepState` took the build step as done when
the status's `hasBuilt` was true. That is one marker file,
`build/scripts/block-library/index.min.js`, which Gutenberg's build
writes mid-way (phase 2), with routes, widgets and the PHP registries
still to come. Any status refresh during the build (switching windows is
enough) read the site as built. The `building` flag was ignored, exactly
as `installing` was in #495.

**The fix.** The step is built only when the marker is there **and** no
build is running **and** the last build did not fail: `builtOk =
hasBuilt && !building && !buildFailed`. It drives the build step's done
state and the dev step's ready state; the step's label and the button's
variant follow the step state instead of the raw flag. The failed-build
half comes from the self-review: a build stopped or failed late leaves
the marker on disk, and within a session `buildFailed` is never stale
(every build path clears it on success), so a flag still set outranks
the marker.

## How to test this

Platforms: either; Windows is where the build is slow enough to catch.
Build: the Buildkite artifact for the current head, or `npm start` from
the repository root.

**Starting state:** no site, or a Gutenberg site at the download step.

1. Create a Gutenberg site and let the wizard reach *step 3 of 3*.
2. While the terminal is past *Transpiled …* and into *Built route …*,
switch to another window and back, two or three times. Expected: **Run
full build** stays **IN PROGRESS** with its button busy, **Start dev
server & finish wizard** stays **LOCKED**.
3. Let the build finish. Expected: the step turns **COMPLETED**, "Build
complete", the dev step **READY**; click it and the site opens.
4. New site, same steps, but press Ctrl+C in the terminal during *Built
route …*. Expected: the build step reads **FAILED** with "Retry the
build", the dev step stays **LOCKED**; retry, let it finish, and the
step completes.
5. Open an existing, fully built site. Expected: the step reads
**COMPLETED** as before.

**What must not have happened:** the dev server enabled while `npm run
build` runs; a build stopped mid-way reading "Build complete"; a built
site's step reading anything but complete.

Tests: `tests/unit/setup-steps.test.cjs`, *a marker written mid-build
does not complete the build step* and *a build still running reads in
progress, whatever the marker says* fail on trunk (`build.done` was the
raw marker) and pass here; *a build that failed over an existing marker
reads failed, not complete* replaces the earlier test that had the
opposite premise, with the reason in its comment. Lint clean, 1596 unit
tests pass.

## Risks and limitations

- `buildFailed` is session-local: after an app restart a build that
failed late over an existing marker reads complete again, as on trunk.
Persisting it like the install outcome is in #503.
- Outside the wizard, **Start dev server** and **Start build watch** are
still reachable while a build runs from the terminal or an apply;
pre-existing, #503.

## Related

Fixes #502. Same rule as #496 (#495). Follow-up #503. Part of the
v1.2.0-beta.1 pass.

---

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

2 [fix here] · 1 [follow-up] on `e5b762d` — both fix-here fixed in
`f1ed783`.

- Fixed: a build that failed or was stopped over an existing marker read
complete and unlocked the dev server (`builtOk` now requires
`!buildFailed`; `build.failed` no longer tests the raw marker; the
colliding test's premise revisited and rewritten).
- Fixed: the "In progress" status string had no ladder assertion; added.
- Fixed (style): the build button's variant keyed off the raw marker
while its label followed the step state.
- Deferred to #503: the skip-wizard path (action bar reachable while a
build runs) and persisting the build outcome across restarts; both
pre-existing.

- **Review:** completed — `/self-review` (Explore subagent, judgement
pass; lint and unit inline); reviewed head `e5b762d` / base `ffbdb3c`
(trunk); evidence: findings above; outcome: 2 fixed, 1 deferred.
- **Since review:** `e5b762d → f1ed783` checked: the fixes above plus
their tests; lint clean, 1596 unit tests pass on the new head.

</details>

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

No new surface: the same checklist, now honest about a running build.
The Windows screenshot of the bug is on #502.

</details>

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

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
juanmaguitar added a commit that referenced this pull request Sep 20, 2026
## Why

`v1.1.0` shipped on 16 September. Sixteen commits since then reach
trunk, and this beta is the first build that carries the Gutenberg
contribution target (#251): a site can now be a checkout of
`WordPress/gutenberg`, served through Playground as a plugin in a stock
WordPress, with a GitHub issue as its work item, pull request checkout
from that issue, and a pull request opened against `WordPress/gutenberg`
from the app. The manual pass of that work ran on macOS and on Windows
over 18 to 20 September and found six issues; the four that affected the
first-run path are fixed on trunk (#489, #493, #496, #500, #504, and
#491 for the hint), the rest are on the `v1.2.0-beta.2` milestone.

`electron-builder` derives artifact names from `package.json`, so the
version has to move before the tag and the artifacts exist. A beta is a
pre-release, so `releases/latest` stays on `v1.1.0`.

## What changes

Only the version. All three package-version fields in `package.json` and
`package-lock.json` move together from `1.1.0` to `1.2.0-beta.1`. No
dependency versions change, and there is no application behaviour change
in this PR.

## How to test this

Platforms: any for the suite; macOS and Windows for the artifact checks
that follow the merge.

1. `npm run lint` is clean and `npm test` passes.
2. `node -e "console.log(require('./package.json').version)"` prints
`1.2.0-beta.1`.
3. `python3 -c "import
json;d=json.load(open('package-lock.json'));print(d['version'],
d['packages']['']['version'])"` prints `1.2.0-beta.1 1.2.0-beta.1`.

**What must not have happened:** no dependency version may change. `git
diff` must show exactly three changed lines, all of them the root
package version.

After merge, the release build must produce artifacts named
`wordpress-contributor-toolkit-1.2.0-beta.1-*`; the asar root must be
exactly `node_modules`, `package.json`, `src`, with npm 11 under
`node_modules/npm` and no `.codesigning` directory; on macOS
`CFBundleShortVersionString` reads `1.2.0-beta.1`.

## Risks and limitations

No UI change. The risk is a mis-scoped edit in `package-lock.json`,
where dependencies also carry version fields; the replacement was
confined to the first 2000 bytes of the file, which hold the two root
entries and nothing else, and both files were re-parsed as JSON
afterwards.

Verified locally on this branch: lint clean, `npm test` 1596 pass / 0
fail.

## Related

Part of #251. Release notes follow on the pre-release; docs publish for
the tag per #487.

---

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

0 [fix here] · 0 [follow-up]. Deterministic layer only: lint clean, 1596
tests pass, both files valid JSON, diff confined to the three root
version fields. No judgement pass was run: this change has no logic to
review.

- **Review:** completed — deterministic layer, in session; head is the
single bump commit / base `b5ca272` (trunk); evidence above; outcome:
nothing to fix.
- **Since review:** none.

</details>

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

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
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.

The install step reads as completed while npm ci is still running

1 participant