Skip to content

fix(create): report install and format failures in the create summary - #2543

Open
m0g3r wants to merge 2 commits into
voidzero-dev:mainfrom
m0g3r:fix/2453-report-failed-create-steps
Open

fix(create): report install and format failures in the create summary#2543
m0g3r wants to merge 2 commits into
voidzero-dev:mainfrom
m0g3r:fix/2453-report-failed-create-steps

Conversation

@m0g3r

@m0g3r m0g3r commented Aug 23, 2026

Copy link
Copy Markdown

Closes #2453

Problem

vp create writes the template files first, then installs dependencies and formats the result. Those last two steps can fail after the project directory already exists — and when they did, the completion summary reported the run as a success anyway.

Reproduced with the issue's recipe against this branch's base (c4dcb15), using the built local CLI:

$ env -u VP_SKIP_INSTALL VP_CLI_BIN=/usr/bin/false \
    vp create vite:application --no-interactive --no-hooks --no-git \
    --directory create-failure-demo
You may need to run "vp install" manually in .../create-failure-demo
You may need to run "vp fmt" manually in .../create-failure-demo
◇ Scaffolded create-failure-demo with Vite application
• Node 22.22.2  pnpm 11.23.0
→ Next: cd create-failure-demo && vp run
=== EXIT CODE: 0 ===
node_modules missing

Three success signals — Scaffolded, Next: vp run, exit 0 — for a project that cannot run. The earlier "you may need to…" lines are easy to lose above a long install log, and a CI job reading only the exit code records the operation as successful.

Changes

  • resolveCreateCompletion (in create/utils.ts) turns the install and format results into: which steps failed, which command is worth suggesting next, and whether the exit code should be non-zero.
  • showCreateSummary names each failed step, points Next: at vp install when dependencies are missing (the suggested vp run cannot work without them), and raises process.exitCode.
  • The format result was previously discarded at all three runViteFmt call sites; it is now threaded through alongside the install result.

Same input on this branch:

◇ Scaffolded create-failure-demo with Vite application
• Node 22.22.2  pnpm 11.23.0
✗ Dependencies were not installed
✗ Code was not formatted
→ Next: cd create-failure-demo && vp install
=== EXIT CODE: 1 ===

The directory is still reported as scaffolded — as the issue notes, that part is true and is not the confusing bit.

Three behaviours deliberately preserved:

  • A skipped install is not a failure. VP_SKIP_INSTALL returns status: 'skipped'; only 'failed' counts.
  • The exit code is only ever raised, never lowered. handleIgnoredBuilds already sets process.exitCode = 1 for a gated build that failed under --approve-builds, and this must not clear it.
  • Only a failed install fails the command. See below.

The success path is unchanged, byte for byte — no new line is printed and Next: still reads vp run.

A format failure is reported but does not fail the command

The first revision of this PR exited non-zero for a format-only failure too, and flagged that as a call for you to make. CI answered it, so I have taken the exit-0 variant rather than leave it open.

The PTY snapshot suite failed on create_framework_shim_vue and new_create_vite, on all three platforms. Both scaffold a template whose generated vite.config.ts imports a plugin that is not installed at the moment vp fmt runs:

vite.config.ts (2:16) [UNRESOLVED_IMPORT] Could not resolve '@vitejs/plugin-vue' in vite.config.ts
error: Failed to resolve vite config: ... Cannot find package '@vitejs/plugin-vue'
You may need to run "vp fmt" manually in <workspace>/vite-plus-application
◇ Scaffolded vite-plus-application with Vue + TypeScript
✗ Code was not formatted
→ Next: cd vite-plus-application && vp run

That project is complete and runnable; only formatting was skipped. Those two cases declare the vp create step as snapshot = false, so they recorded nothing until the step started exiting 1 — which is exactly the point: a routine vp create of a react-ts or vue-ts template would have started failing every CI job that runs it.

So resolveCreateCompletion now returns exitCode: installFailed ? 1 : 0. A format failure is still named in the summary (✗ Code was not formatted) — silently dropping it is what #2453 is about — and Next: still points at vp run, because the project runs. Only a missing node_modules makes the command itself fail.

Happy to scope the non-zero exit to --no-interactive runs as well, mirroring the existing handleIgnoredBuilds condition, if you would prefer that.

A note on the small refactor

showCreateSummary and getNextCommand moved from create/bin.ts to a new create/summary.ts, unchanged apart from the fix. bin.ts runs main() on import, so nothing in it can be unit-tested; moving these two functions is what let the regression test assert on the real summary output and exit code rather than only on the decision helper. Happy to drop the move if you would rather keep them in bin.ts.

Testing

New create/__tests__/summary.spec.ts covers the summary output and exit code; six cases added to create/__tests__/utils.spec.ts cover the decision helper. Two of them now assert that a format-only failure is reported and leaves the exit code alone, so the snapshot regression above cannot come back silently.

Verified in both directions. With exitCode restored to the previous failures.length > 0 ? 1 : 0 (and the tests kept), exactly the two guarding tests fail — 2 failed | 53 passed:

× reports a failed format without failing the command
  AssertionError: expected { …(3) } to deeply equal { …(3) }
× still suggests running the project and succeeds when only formatting failed
  AssertionError: expected 1 to be undefined

With the change applied, 55 passed.

Checks actually run on the latest commit:

  • vitest run packages/cli/src/create/__tests__/{summary,utils}.spec.ts — 55 passed, and the both-directions result above.
  • oxlint@1.79.0 -D correctness -D perf -D suspicious on all four files — exit 0.
  • oxfmt@0.64.0 --check with this repo's fmt block from vite.config.ts — all four files correctly formatted. (Run without -c it reports issues on untouched files too, so the repo config is the meaningful check.)
  • git diff --check — clean.

Earlier revision, still valid for the parts it covers: vitest run (full unit suite) — 1034 passed, 1 skipped, with 7 pre-existing packages/prompts snapshot failures confirmed identical on a clean tree; tsgo -b tsconfig.json — error set byte-identical to a clean tree.

Correcting the previous description: it said no create snapshot exercises a failing install or format, so I would not expect snapshot churn, and that I could not confirm it by running the suite. The first half was wrong — no fixture records such a failure, but two fixtures produce one, and they surface it through the exit code rather than through recorded output. CI caught what I could not run locally.

The PTY snapshot suite still cannot run in my environment, so the fix above is verified by unit tests and by root-causing both recorded diffs, not by a local suite run.

AI assistance

Claude Opus 5 wrote the implementation, the tests, the reproductions, and this description. The change is agent-authored and has not had a separate human review. Every result quoted above is from an actual run, not an estimate.

`vp create` writes the template files first, then installs dependencies
and formats the result. When either later step failed, the completion
summary still reported "Scaffolded", suggested `vp run`, and exited 0 —
three success signals for a project whose `node_modules` was missing.

Track both step results, name the ones that failed, point `Next:` at the
step that has to succeed first, and raise the exit code so scripts and CI
see the failure. A skipped install (`VP_SKIP_INSTALL`) is not a failure,
and the success path is unchanged.

Closes voidzero-dev#2453
@netlify

netlify Bot commented Aug 23, 2026

Copy link
Copy Markdown

Deploy Preview for viteplus-preview ready!

Name Link
🔨 Latest commit 33214c2
🔍 Latest deploy log https://app.netlify.com/projects/viteplus-preview/deploys/6a8c7218f2b3450008a592e9
😎 Deploy Preview https://deploy-preview-2543--viteplus-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

The PTY snapshot suite caught this: `create_framework_shim_vue` and
`new_create_vite` both scaffold a template whose `vite.config.ts` imports a
plugin that is not installed yet (`@vitejs/plugin-vue`, `@vitejs/plugin-react`),
so `vp fmt` cannot load the config and the format step fails on a project that
is otherwise complete. Raising the exit code there turned both cases red.

Only a failed install now changes the exit code. A format failure is still
named in the summary — it is real, and silently dropping it is what voidzero-dev#2453 is
about — but it leaves a runnable project, so it does not fail the command.

m0g3r commented Aug 24, 2026

Copy link
Copy Markdown
Author

Thanks for approving the workflows — the run caught a real regression in this PR, and 33214c2 fixes it.

What failed. CLI snapshot test on all three platforms, 699 passed / 2 failed: create_framework_shim_vue and new_create_vite. Everything else was green, and main is green at both this branch's base and current head, so it was mine.

Root cause. Both cases scaffold a template whose generated vite.config.ts imports a plugin that is not installed at the moment vp fmt runs, so the format step fails on a project that is otherwise complete:

vite.config.ts (2:16) [UNRESOLVED_IMPORT] Could not resolve '@vitejs/plugin-vue' in vite.config.ts
error: Failed to resolve vite config: ... Cannot find package '@vitejs/plugin-vue'
◇ Scaffolded vite-plus-application with Vue + TypeScript
✗ Code was not formatted
→ Next: cd vite-plus-application && vp run

Both declare that vp create step as snapshot = false, so it recorded nothing until the step started exiting 1.

Why this settles the open question rather than needing a snapshot update. The PR body asked whether a format-only failure should exit non-zero, and offered the exit-0 variant. These two fixtures are the argument for it: a routine vp create of a react-ts or vue-ts template hits this path, so keeping the non-zero exit would fail every CI job that scaffolds one — and the project it produces is fine. Re-recording the snapshots would have baked that in.

So resolveCreateCompletion now returns exitCode: installFailed ? 1 : 0. The ✗ Code was not formatted line stays — dropping it silently is what #2453 is about — and Next: still reads vp run. Only a missing node_modules fails the command. Both snapshots should return to their recorded state untouched, since an exit-0 snapshot = false step records nothing.

Verified in both directions: with the old expression restored, exactly the two guarding tests fail (2 failed | 53 passed); with the fix, 55 passed. oxlint and oxfmt clean against this repo's config. I still cannot run the PTY suite in my environment, so that part rests on root-causing both recorded diffs rather than a local run — worth a second look on your side.

I have also corrected the description, which claimed I would not expect snapshot churn here.


Generated by Claude Code

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.

Improve vp create completion reporting when installation or formatting fails

1 participant