feat(cli): add a project delete command so cloud projects can be torn down - #3618
Conversation
… down
`veryfront push` and `veryfront up` create a real cloud project on first run,
but the CLI exposed no way to remove one. Teardown required driving Studio
(project -> Settings -> Danger Zone -> Delete Project -> retype the slug), so
scripted cleanup after CI, dogfooding, or e2e runs needed browser automation.
The REST API already serves `DELETE /projects/{project_reference}`; only the
CLI surface was missing. Add `veryfront project delete [slug]` (alias
`veryfront projects`, subcommand alias `rm`) that resolves the slug from the
positional argument, `--project`, or the linked project in the current
directory, confirms before deleting, and supports `--force`, `--yes`, and
`--json`.
|
Warning Review limit reached
Next review available in: 1 minute Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (11)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 71ea29579e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (options.json) { | ||
| printJson({ success: true, project: projectSlug }); |
There was a problem hiding this comment.
Route JSON results through the standard output helper
When automation invokes this command with --json, this emits {success, project} instead of the standard {success, command, data} envelope. Because printJson also bypasses outputJson, --output <path> produces no output file even though the router accepts and configures that global flag. Use outputJson(createSuccessEnvelope("project", ...)) here and the corresponding standard envelope for cancellation.
AGENTS.md reference: cli/AGENTS.md:L74-L89
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 7920128. project delete --json now goes through outputJson(createSuccessEnvelope("project", ...)) for both the delete and the cancelled-at-prompt case, so --output <path> writes the file the router already configures. Verified against a real project: the command printed {"success":true,"command":"project","data":{"project":"dx-r2-29-teardown-2","deleted":true}} and wrote the same envelope to the --output path.
| default: | ||
| showProjectUsage(); |
There was a problem hiding this comment.
Reject unknown project subcommands
When the subcommand is misspelled or unsupported, for example veryfront project delet app --force, this default branch only prints usage and returns. cli/main.ts consequently exits with code 0, so a cleanup script can report success while leaving the cloud project and its resources intact; unknown subcommands should raise a usage error and exit with code 2.
AGENTS.md reference: AGENTS.md:L161-L166
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Agreed, and it matters most for exactly this command. Fixed in 7920128: an unrecognised subcommand now throws INVALID_ARGUMENT. veryfront project delet app --force exits 2 and, in JSON mode, prints a USAGE_ERROR envelope. Covered by a regression test in cli/commands/project/command.test.ts.
…commands
Review follow-up. `project delete --json` now emits the standard
{success, command, data} envelope through outputJson, so --output writes the
result file the router already accepts. An unrecognised subcommand raises a
usage error (exit 2) instead of printing usage and exiting 0, which a cleanup
script would otherwise read as a completed teardown.
Problem
Dogfooding round 2, finding [29] (new, confirmed against published
0.1.1229).veryfront pushcreates a real cloud project on first run ("Creating project..."), andveryfront deploythen creates environments and releases. The CLI exposed no way to remove anyof it:
Only
uploadsandfileshad delete verbs. Tearing a project down meant driving Studio(project -> Settings -> Danger Zone -> Delete Project -> retype the slug), which makes scripted
cleanup after CI, dogfooding, or e2e runs impossible without browser automation.
Root cause
Not a bug in the delete path — the path was never wired up. The REST API already serves
DELETE /projects/{project_reference}(204 on success, seeveryfront-api/src/api/http/rest/projects/delete-project/index.ts), and the token returned fromproject creation already carries the
project.deletecapability. The gap was purely the CLIsurface: no command in
cli/router.ts, no entry incli/help/command-definitions.ts.Change
Adds
veryfront project delete [slug]:cli/commands/project/— help definition, arg schema, command, handler, barrel.project(aliasprojects) incli/router.tsand in theCOMMANDShelpregistry, so it also flows into
veryfront schema --json, shell completions, and the generatedCLI reference.
--project/-p, then the project this directory islinked to.
--force/-fskips the prompt,--yes/-yauto-answers it (CI),--json/-jemits the standard envelope{"success": true, "command": "project", "data": {"project": "<slug>", "deleted": true}}through
outputJson, so--output <path>writes the result file too.deleteandrmare both accepted as the subcommand. An unrecognised subcommand raises ausage error and exits 2 rather than printing usage and exiting 0 — a cleanup script must not
read
veryfront project delet appas a completed teardown.Docs:
docs/guides/deploying.mdgains a short "Tear a project down" section, and the generateddocs/api-reference/veryfront/cli.mdpicks up the new row (regenerated withdeno task docsonDeno 2.7.7).
Tests
Written before the fix, confirmed red for the right reason:
cli/router.test.ts—projectadded to the expected-commands list. Before the fix:AssertionError: Values are not equal: Missing command: project.cli/commands/project/command.test.ts— slug parsing (positional and--project), therequest URL and its encoding, that
deleteRemoteProjectissues exactly oneDELETE /projects/<slug>, and that a blank project reference is rejected before any requestgoes out (so an empty slug can never widen into a delete-everything call), and that a
misspelled subcommand rejects with exit code 2.
tests/docs/guide-content.test.ts— the deploy guide documents a CLI teardown path.Verified against the published repro
Not "tests pass" — the original symptom, re-run end to end.
0.1.1229(installed into a scratch dir outside the monorepo):veryfront project delete foo --force --json->{"success": false, ..., "message": "Unknown command: project"}.veryfront pushuses:POST https://api.veryfront.com/projects {"slug":"dx-r2-29-teardown"}->201.veryfront project delete dx-r2-29-teardown --force --json->{"success": true, ...}.GET https://api.veryfront.com/projects/dx-r2-29-teardown->404.(Repeated end to end after the review fixes with
dx-r2-29-teardown-2:201on create,the standard envelope on delete, the same envelope written to
--output, then404.)veryfront help --all | grep -iE 'delete|destroy|remove'now listsproject (projects) Delete a cloud project and everything it owns.No browser automation involved at any step.
Live doc page to check after merge
The CLI reference is synced into veryfront-docs by the
Update Code Docsworkflow, so no PR isneeded there — but the sync has silently not landed before. After merge, this page must list
veryfront project:https://veryfront.com/docs/code/api-reference/veryfront/cli
Notes
.veryfront/; a follow-up run ofpushagainst a deleted slug re-creates the project. Out of scope here.
(
cli/utils/git.test.tsambient-repo,veryfront dev output,schedule command,startproduction MCP boundary) plus onesrc/cache/backends/disk.test.tsflake that passesin isolation and passed on the pre-push re-run.
error: Promise resolution is still pending but the event loop has already resolvedin coverage shard 1/8 after0 failed. That is a pre-existing flake, notthis branch: main run 31526576753 failed identically in shard 4/8 with the same text and the
same
0 failedsummary. It passed on re-run here.