feat(tpagectl): implement site delete subcommand #555
No reviewers
Labels
No labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
thwap/thwap-pagesd!555
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/cli-site-delete"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Implements
site deleteend to end: the daemon's missingDELETE /api/v1/sites/{name}endpoint plus the tpagectlsite deletesubcommand.Daemon
SiteService.Deleteremoves a site's Kubernetes resources, its site record, and its deployments; unknown sites returnErrNotFound.DELETE /api/v1/sites/{name}handler is owner-scoped and returns 204 on success, 403 when unauthorized, 404 when missing.ownerScopedno longer bypasses authorization when no auth middleware is configured — it now falls back to claim presence (ownerAuthorized), fixing a latent auth-gap and making scoping testable.CLI
site deletetakes a required positionalSITE(#188).Delete site "X"? [y/N]unless--forceis given (#184); reads fromcmd.Root().Reader(defaults to stdin), aborts on no/empty input.DELETE /api/v1/sites/{name}(#185); printsSite "X" deleted.(#186).site "X" not founderror.--forcesends DELETE + confirmation, confirm-yes proceeds, confirm-no/empty abort (no request), 404, missing arg.Why
Phase 2 roadmap task #187.
Testing
go test -race ./...passes (17 packages)golangci-lint runcleanBreaking Changes
None.
KubernetesClientgainsDeleteSite;SiteServicegainsDelete(both already implemented by the concrete types).Notes
Forgejo repository deletion is intentionally out of scope (no client method yet); the daemon deletes Kubernetes resources and local records only.
Closes #184
Closes #185
Closes #186
Closes #187
Closes #188
Add the daemon DELETE /api/v1/sites/{name} endpoint and the tpagectl site delete subcommand. Daemon: SiteService.Delete removes a site's Kubernetes resources, site record, and deployments (ErrNotFound for unknown sites). The handler is owner-scoped and returns 204 on success, 403 on unauthorized, 404 when missing. ownerScoped no longer bypasses authorization when no auth middleware is configured, falling back to claim presence. CLI: site delete takes a required site name, prompts for confirmation unless --force is given, issues the DELETE request, and prints a confirmation. 404 surfaces as a friendly not-found error.Record completion of the tpagectl site delete subcommand and its daemon endpoint: positional site name, confirmation prompt with --force, DELETE /api/v1/sites/{name}, and success confirmation. closes #184 closes #185 closes #186 closes #187 closes #188Summary
site delete: daemonDELETE /api/v1/sites/{name}+ tpagectlsite delete. Verified:go test -race ./...passes (17 packages) andgolangci-lint run ./...is clean. Closes #184-188.Blocking Issues
internal/site/service.go:378(Service.Delete) +internal/kubernetes/kubernetes.go:119(DeleteSite) – deleting a site that has preview deployments orphans its preview Ingresses permanently. Preview deployments are stored asDeploymentrecords (Version =test/<branch>, k8s Ingress named{site}-preview-{branch}, templates.go:295).DeleteSiteonly removes the production Ingress and PVC; preview Ingresses survive.CleanupPreviews(service.go:243) iterates only existing sites, so once the site record is gone the preview Ingresses are never garbage-collected. Suggested fix: enumerate and delete the site's preview Ingresses inDeleteSite(e.g. list Ingresses matching the{site}-preview-prefix) or clean preview branches inService.Delete.Suggestions (filed as issues)
internal/site/service.go:378–_ = s.deployments.Delete(...)swallows deletion errors (orphaned deployment rows), and k8s resources are deleted before the site record, so a faileds.sites.Deleteleaves a record pointing at deleted resources. Filed as #556internal/tpagectl/site/delete.go– non-404 error passthrough (500, 403 owner-scoped) is untested; same gap as #554. Filed as #557Praise
--force+ y/N prompt, abort on no/empty/EOF; verified cli v3setupDefaultsdefaults Reader to stdin, so the prompt works in productionownerScopedrefactor fixes a latent auth gap with no production behavior change and is well-tested (204/403/404)Addressed the requested changes.
Blocking (orphaned preview Ingresses):
Service.Deletenow enumerates the site's deployments and tears down each preview Ingress (via the existingKubernetesClient.DeletePreview) before removing the production resources and site record. Preview deployments are identified by their branch-based version (non-v*tag), matching the production publish convention.TestDeleteCleansPreviewsverifies atest/featurepreview branch is deleted alongside the site.Also fixed (filed as issues):
Verified:
go test -race ./...(17 packages),golangci-lint run, and pre-commit all pass.Summary
Re-review after
d8841de(fix(site): clean preview ingresses on site delete) and2450e11(fix(tpagectl): cover non-404 site delete errors). Verified:go test -race ./...passes (17 packages) andgolangci-lint run ./...is clean. Closes #184-188.Blocking Issues
Resolved.
Service.Deletenow enumerates the site's deployments and tears down each preview Ingress viaKubernetesClient.DeletePreview(identified by non-vversions) before removing production resources and the site record, so deleted sites no longer orphan preview Ingresses. Verified byTestDeleteCleansPreviews(preview branchtest/featureingress deleted + site record removed).Previously Filed Suggestions
TestDeleteServerError(500) andTestDeleteForbidden(403) added, asserting error bodies surface without the not-found wrapper.Praise
DeletePreviewpath rather than duplicating ingress logicfakeKubernetes(deletedPrevs/deletedSites) with exactslices.Equalassertions