server: HTTP run-now for prune / check / unlock

Adds POST /api/hosts/{id}/repo/{prune,check,unlock} (and matching outer
routes for HTMX form posts). Prune pushes the admin-cred slot via
pushAdminCredsToAgent before dispatch and refuses with
admin_creds_required when the slot is not set. Check reads
check_subset_pct from host_repo_maintenance (overridable via ?subset=N,
clamped 0-100; non-numeric override falls back to DB value silently).
Unlock needs no admin creds. All three share the same wantsHTML/HX-Redirect
response split as the per-source-group run-now endpoint.
This commit is contained in:
2026-05-03 22:57:07 +01:00
parent 35f07c3cee
commit 69abc40786
3 changed files with 505 additions and 0 deletions
+11
View File
@@ -141,12 +141,23 @@ func (s *Server) routes(r chi.Router) {
// mounted at the equivalent path outside /api below — both
// resolve to the same handler, which sniffs HX-Request.
r.Post("/hosts/{id}/source-groups/{gid}/run", s.handleRunSourceGroup)
// Repo-level run-now: prune (needs admin creds), check, unlock.
// HTMX forms are also mounted outside /api below.
r.Post("/hosts/{id}/repo/prune", s.handleRunRepoPrune)
r.Post("/hosts/{id}/repo/check", s.handleRunRepoCheck)
r.Post("/hosts/{id}/repo/unlock", s.handleRunRepoUnlock)
})
// Per-source-group Run-now (HTMX form action). Available even
// when the server is started without UI templates so REST callers
// against the non-/api path also work.
r.Post("/hosts/{id}/source-groups/{gid}/run", s.handleRunSourceGroup)
// Repo-level run-now (HTMX form actions). Same handlers as the /api
// variants — wantsHTML sniff distinguishes JSON vs HTMX response.
r.Post("/hosts/{id}/repo/prune", s.handleRunRepoPrune)
r.Post("/hosts/{id}/repo/check", s.handleRunRepoCheck)
r.Post("/hosts/{id}/repo/unlock", s.handleRunRepoUnlock)
// Retired routes — see ui_handlers.go for the messages. Mounted
// outside the UI gate so cached browser tabs get a clear 410
// even if the server runs without templates.