feat(tpagectl): implement preview delete subcommand #577

Merged
fuzzy merged 2 commits from feat/cli-preview-delete into main 2026-08-07 02:31:10 +00:00
Owner

What

Implements preview delete end to end: the daemon's missing DELETE /api/v1/sites/{name}/preview/{branch} endpoint plus the tpagectl preview delete subcommand.

Daemon

  • New DELETE /api/v1/sites/{name}/preview/{branch} handler (#229): owner-scoped (403), calls the existing DeletePreview service method, returns 200 with the Deployment, 204 when the preview record is absent, 404 when the site is missing.
  • The branch path segment uses a wildcard (*branch) so branch names containing slashes (test/*) route correctly; the leading slash is stripped in the handler.
  • Tests: handler 200 / 404.

CLI

  • Flags (#227): --site (required) plus exactly one of --branch or --all (both or neither → error).
  • Confirm (#228): prompts Delete preview for site "X"? [y/N] (or Delete N previews … for --all) via cmd.Root().Reader unless --force; aborts on no/empty.
  • --all: resolves branches from the previews list, then deletes each.
  • DELETE (#229): /api/v1/sites/{name}/preview/{branch} per branch.
  • Confirmation (#230): Preview "X" for site "Y" deleted. / Deleted N preview(s) for site "Y"..
  • Friendly 404s; missing-site/branch-or-all errors.
  • Tests: --force single branch, --all (list → delete each), confirm-yes, confirm-no abort (no DELETE), 404, missing --site, missing selector, branch+all conflict.

Why

Phase 4 roadmap task #231.

Testing

  • Daemon: handler delete-preview 200/404 tests
  • CLI: single/--all/confirmed/declined/404/missing-site/missing-selector/conflict
  • go test -race ./... passes (19 packages)
  • golangci-lint run clean
  • pre-commit hooks pass (gofmt, go mod tidy, go test)

Breaking Changes

None.

Notes

The wildcard routing also applies to preview get (#233), which will use the same *branch pattern. The only remaining preview stub is get.

Closes #227
Closes #228
Closes #229
Closes #230
Closes #231

## What Implements `preview delete` end to end: the daemon's missing `DELETE /api/v1/sites/{name}/preview/{branch}` endpoint plus the tpagectl `preview delete` subcommand. **Daemon** - New `DELETE /api/v1/sites/{name}/preview/{branch}` handler (#229): owner-scoped (403), calls the existing `DeletePreview` service method, returns 200 with the `Deployment`, 204 when the preview record is absent, 404 when the site is missing. - The branch path segment uses a **wildcard** (`*branch`) so branch names containing slashes (`test/*`) route correctly; the leading slash is stripped in the handler. - Tests: handler 200 / 404. **CLI** - **Flags** (#227): `--site` (required) plus exactly one of `--branch` or `--all` (both or neither → error). - **Confirm** (#228): prompts `Delete preview for site "X"? [y/N]` (or `Delete N previews …` for `--all`) via `cmd.Root().Reader` unless `--force`; aborts on no/empty. - **`--all`**: resolves branches from the previews list, then deletes each. - **DELETE** (#229): `/api/v1/sites/{name}/preview/{branch}` per branch. - **Confirmation** (#230): `Preview "X" for site "Y" deleted.` / `Deleted N preview(s) for site "Y".`. - Friendly 404s; missing-site/branch-or-all errors. - Tests: `--force` single branch, `--all` (list → delete each), confirm-yes, confirm-no abort (no DELETE), 404, missing `--site`, missing selector, branch+all conflict. ## Why Phase 4 roadmap task #231. ## Testing - [x] Daemon: handler delete-preview 200/404 tests - [x] CLI: single/`--all`/confirmed/declined/404/missing-site/missing-selector/conflict - [x] `go test -race ./...` passes (19 packages) - [x] `golangci-lint run` clean - [x] pre-commit hooks pass (gofmt, go mod tidy, go test) ## Breaking Changes None. ## Notes The wildcard routing also applies to `preview get` (#233), which will use the same `*branch` pattern. The only remaining preview stub is `get`. Closes #227 Closes #228 Closes #229 Closes #230 Closes #231
Add the daemon DELETE /api/v1/sites/{name}/preview/{branch} endpoint and
the tpagectl preview delete subcommand.

Daemon: the handler calls the existing DeletePreview service method,
returning 200 with the deployment, 204 when the preview record is absent,
404 when the site is missing. The branch path segment uses a wildcard so
branch names containing slashes (test/*) route correctly.

CLI: preview delete takes --site plus exactly one of --branch or --all,
prompts for confirmation unless --force is given, deletes each selected
preview, and prints a confirmation. --all resolves branches from the
previews list.
docs(roadmap): mark preview delete subcommand complete
All checks were successful
Test and Release / lint (pull_request) Successful in 4m27s
Test and Release / test (pull_request) Successful in 23m58s
031894a6ca
Record completion of the tpagectl preview delete subcommand and its daemon
endpoint: --site with --branch or --all, confirmation with --force,
DELETE /api/v1/sites/{name}/preview/{branch}, and confirmation display.

closes #227
closes #228
closes #229
closes #230
closes #231
fuzzy scheduled this pull request to auto merge when all checks succeed 2026-08-07 02:23:39 +00:00
the.auditor left a comment

Summary

preview delete: daemon DELETE /api/v1/sites/{name}/preview/{branch} + tpagectl subcommand. Verified: go test -race ./... passes (19 packages) and golangci-lint run ./... is clean. Closes #227-231.

Verified routing: the gin *branch wildcard captures slash-containing branches and the handler strips the leading /, so test/feature round-trips correctly (exercised end-to-end by TestDeletePreviewHandlerOK). The 200/204/404 contract matches Service.DeletePreview (absent record → (nil, nil) → 204, with the ingress still cleaned; site missing → 404).

No blocking issues.

Suggestions (filed as issues)

  1. internal/httpapi/sites.go (deletePreview) – the 204 branch (d == nil → NoContent) is untested; handler tests cover only 200 and 404. Filed as #578

References (covered by existing issues)

  1. The 404→friendly mapping is now a ninth inline copy (extends #565/#561); confirmDeletePreviews is a fourth confirmation-prompt copy (#565); non-404 passthrough remains untested (#571).

Praise

  • Wildcard routing correctly handles slash-containing branches; noted reuse for the future preview get
  • Sensible 200/204/404 semantics
  • Clean --branch/--all mutual exclusion and required-selector validation
  • --all resolves branches from the previews list; confirmation UX mirrors site delete
  • Solid CLI coverage (single/--all/confirm/decline/404/missing-site/missing-selector/conflict)
## Summary `preview delete`: daemon `DELETE /api/v1/sites/{name}/preview/{branch}` + tpagectl subcommand. Verified: `go test -race ./...` passes (19 packages) and `golangci-lint run ./...` is clean. Closes #227-231. Verified routing: the gin `*branch` wildcard captures slash-containing branches and the handler strips the leading `/`, so `test/feature` round-trips correctly (exercised end-to-end by `TestDeletePreviewHandlerOK`). The 200/204/404 contract matches `Service.DeletePreview` (absent record → `(nil, nil)` → 204, with the ingress still cleaned; site missing → 404). No blocking issues. ## Suggestions (filed as issues) 1. `internal/httpapi/sites.go` (`deletePreview`) – the 204 branch (`d == nil` → NoContent) is untested; handler tests cover only 200 and 404. Filed as #578 ## References (covered by existing issues) 1. The 404→friendly mapping is now a ninth inline copy (extends #565/#561); `confirmDeletePreviews` is a fourth confirmation-prompt copy (#565); non-404 passthrough remains untested (#571). ## Praise - Wildcard routing correctly handles slash-containing branches; noted reuse for the future `preview get` - Sensible 200/204/404 semantics - Clean `--branch`/`--all` mutual exclusion and required-selector validation - `--all` resolves branches from the previews list; confirmation UX mirrors `site delete` - Solid CLI coverage (single/`--all`/confirm/decline/404/missing-site/missing-selector/conflict)
fuzzy merged commit 031894a6ca into main 2026-08-07 02:31:10 +00:00
fuzzy deleted branch feat/cli-preview-delete 2026-08-07 02:31:10 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
thwap/thwap-pagesd!577
No description provided.