feat(tpagectl): implement preview deploy subcommand #576

Merged
fuzzy merged 2 commits from feat/cli-preview-deploy into main 2026-08-07 00:14:14 +00:00
Owner

What

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

Daemon

  • New POST /api/v1/sites/{name}/preview handler (#223): owner-scoped (403), binds {"branch"}, calls the existing PublishPreview service method, returns 200 with the Deployment, 400 on invalid body or previews disabled, 404 when the site is missing.
  • isValidationError now maps "disabled" messages (e.g. "site X has previews disabled") to 400.
  • Tests: handler 200 / previews-disabled 400 / 404 / invalid-body 400.

CLI

  • Flags (#232): --site (required), --branch (required), --timeout (default 60s).
  • POST (#223): /api/v1/sites/{name}/preview body {"branch": ...}.
  • Wait-for-ready (#224): polls the previews list until the branch reports active or the --timeout elapses (deploy is synchronous, so usually immediate); timeout returns a clear error.
  • Display URL (#225): prints Preview ready for site "X": <site-url>/preview/<branch> (falls back to the path when the site URL is unavailable).
  • Friendly errors: 404 site, previews are disabled for site "X" on 400, missing --site/--branch.
  • Tests: happy path (body + URL), previews-disabled, 404, timeout (short --timeout, branch stays building), missing --site, missing --branch.

Why

Phase 4 roadmap task #226.

Testing

  • Daemon: handler deploy-preview 200/400/404 tests
  • CLI: happy path, disabled, 404, timeout, missing --site/--branch
  • go test -race ./... passes (19 packages)
  • golangci-lint run clean
  • pre-commit hooks pass (gofmt, go mod tidy, go test)

Breaking Changes

None. isValidationError broadened to also classify "disabled" messages as client errors.

Notes

The remaining preview subcommands (delete, get) are still stubs tracked by their own issues.

Closes #223
Closes #224
Closes #225
Closes #226
Closes #232

## What Implements `preview deploy` end to end: the daemon's missing `POST /api/v1/sites/{name}/preview` endpoint plus the tpagectl `preview deploy` subcommand. **Daemon** - New `POST /api/v1/sites/{name}/preview` handler (#223): owner-scoped (403), binds `{"branch"}`, calls the existing `PublishPreview` service method, returns 200 with the `Deployment`, 400 on invalid body or previews disabled, 404 when the site is missing. - `isValidationError` now maps "disabled" messages (e.g. "site X has previews disabled") to 400. - Tests: handler 200 / previews-disabled 400 / 404 / invalid-body 400. **CLI** - **Flags** (#232): `--site` (required), `--branch` (required), `--timeout` (default 60s). - **POST** (#223): `/api/v1/sites/{name}/preview` body `{"branch": ...}`. - **Wait-for-ready** (#224): polls the previews list until the branch reports `active` or the `--timeout` elapses (deploy is synchronous, so usually immediate); timeout returns a clear error. - **Display URL** (#225): prints `Preview ready for site "X": <site-url>/preview/<branch>` (falls back to the path when the site URL is unavailable). - Friendly errors: 404 site, `previews are disabled for site "X"` on 400, missing `--site`/`--branch`. - Tests: happy path (body + URL), previews-disabled, 404, timeout (short `--timeout`, branch stays building), missing `--site`, missing `--branch`. ## Why Phase 4 roadmap task #226. ## Testing - [x] Daemon: handler deploy-preview 200/400/404 tests - [x] CLI: happy path, disabled, 404, timeout, missing `--site`/`--branch` - [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. `isValidationError` broadened to also classify "disabled" messages as client errors. ## Notes The remaining preview subcommands (`delete`, `get`) are still stubs tracked by their own issues. Closes #223 Closes #224 Closes #225 Closes #226 Closes #232
Add the daemon POST /api/v1/sites/{name}/preview endpoint and the tpagectl
preview deploy subcommand.

Daemon: the handler binds a branch, calls the existing PublishPreview
service method, and returns 200 with the deployment, 400 on invalid body
or previews disabled, 404 when the site is missing. isValidationError now
maps 'disabled' messages to 400.

CLI: preview deploy takes --site and --branch (required) plus --timeout,
posts to the preview endpoint, polls the previews list until the branch is
active or the timeout elapses, and displays the preview URL built from the
site's public URL.
docs(roadmap): mark preview deploy subcommand complete
All checks were successful
Test and Release / lint (pull_request) Successful in 7m9s
Test and Release / test (pull_request) Successful in 7m21s
dc6acb4f92
Record completion of the tpagectl preview deploy subcommand and its daemon
endpoint: --site/--branch flags, POST /api/v1/sites/{name}/preview, wait
for readiness with a timeout, and preview URL display.

closes #223
closes #224
closes #225
closes #226
closes #232
fuzzy scheduled this pull request to auto merge when all checks succeed 2026-08-07 00:07:23 +00:00
the.auditor left a comment

Summary

preview deploy: daemon POST /api/v1/sites/{name}/preview + tpagectl subcommand. Verified: go test -race ./... passes (19 packages) and golangci-lint run ./... is clean. Closes #223-226 + #232.

Verified the branch convention is consistent: the webhook passes full test/… branches to PublishPreview (webhook.go:47-61), which stores Version: branch raw — so the CLI's --branch test/feature matches the daemon model.

No blocking issues; no new issues filed (remaining items are recurring gaps already tracked).

References (covered by existing issues)

  1. internal/tpagectl/preview/deploy.go – the 404→friendly mapping is now an eighth inline copy (extends #565/#561); previewURL swallows the site-status GET error and falls back to the path (pattern from #569); previewSiteStatus near-duplicates the promote/rollback status structs (#565); non-404/400 passthrough remains untested (#571).

Praise

  • Context-aware waitForPreview polling with deadline and a clean timeout error; aborts on ctx.Done()
  • "disabled" → 400 handler mapping via the broadened isValidationError
  • Friendly previews are disabled / site not found messages
  • Solid coverage: happy path (POST body + URL), disabled, 404, timeout (branch stays building), missing --site/--branch, handler 200/400/404
## Summary `preview deploy`: daemon `POST /api/v1/sites/{name}/preview` + tpagectl subcommand. Verified: `go test -race ./...` passes (19 packages) and `golangci-lint run ./...` is clean. Closes #223-226 + #232. Verified the branch convention is consistent: the webhook passes full `test/…` branches to `PublishPreview` (webhook.go:47-61), which stores `Version: branch` raw — so the CLI's `--branch test/feature` matches the daemon model. No blocking issues; no new issues filed (remaining items are recurring gaps already tracked). ## References (covered by existing issues) 1. `internal/tpagectl/preview/deploy.go` – the 404→friendly mapping is now an eighth inline copy (extends #565/#561); `previewURL` swallows the site-status GET error and falls back to the path (pattern from #569); `previewSiteStatus` near-duplicates the promote/rollback status structs (#565); non-404/400 passthrough remains untested (#571). ## Praise - Context-aware `waitForPreview` polling with deadline and a clean timeout error; aborts on `ctx.Done()` - "disabled" → 400 handler mapping via the broadened `isValidationError` - Friendly `previews are disabled` / `site not found` messages - Solid coverage: happy path (POST body + URL), disabled, 404, timeout (branch stays building), missing `--site`/`--branch`, handler 200/400/404
fuzzy merged commit dc6acb4f92 into main 2026-08-07 00:14:14 +00:00
fuzzy deleted branch feat/cli-preview-deploy 2026-08-07 00:14:14 +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!576
No description provided.