Commit be3e6f28d7

be3e6f28d76c9c775997dea9bddf5047095d0be9

parent: 4cfe0c4c82

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-12 06:00 UTC

control, cli, wiki: admin runners remove, with forget as an alias for one release

Ref #183
.gitbay/wiki/Admin.org +1 −1
@@ -434,7 +434,7 @@ podman. A runner without it builds trusted commits only.
434434that has polled as a runner: the account, the key's fingerprint, when it
435435last polled, the repositories it may claim — its attachments for a runner
436436key, the =-repos= it asked for or =any= for an admin key — and the build
437it holds; =admin runners forget <fingerprint>= drops the row for a key
437it holds; =admin runners remove <fingerprint>= (=forget= until the next release) drops the row for a key
438438that polled by mistake, the key itself untouched. =admin runners= also
439439heads the list with the queue: builds
440440pending now, and over the last day how many were claimed, how long they
cmd/gitbay/main.go +2 −1
@@ -129,7 +129,8 @@ func newRoot() *cobra.Command {
129129 pass("invite", "issue a registration invite and mail its code: --email <address>", passOpts{server: []string{"admin", "invite"}}),
130130 pass("stats", "instance statistics: counts and per-repository disk usage", passOpts{server: []string{"admin", "stats"}}),
131131 withSub(pass("runners", "the build queue and runner keys: last poll, scope, the build each holds", passOpts{server: []string{"admin", "runners"}}),
132 pass("forget", "drop a key's heartbeat row: <fingerprint>", passOpts{server: []string{"admin", "runners", "forget"}})),
132 pass("remove", "drop a key's heartbeat row: <fingerprint>", passOpts{server: []string{"admin", "runners", "remove"}}),
133 pass("forget", "alias of remove: <fingerprint>", passOpts{server: []string{"admin", "runners", "forget"}})),
133134 group("repo", "any repository, for moderation (audited)",
134135 pass("list", "every repository with size and last push: [--owner o] [--visibility v] [--limit n] [--cursor c]", passOpts{server: []string{"admin", "repo", "list"}}),
135136 pass("archive", "archive a repository: <owner/name>", passOpts{server: []string{"admin", "repo", "archive"}}),
internal/control/admin.go +8 −2
@@ -33,8 +33,14 @@ func init() {
3333 Summary: "the build queue and runner accounts: last poll, scope, the build each holds (instance admins)",
3434 Usage: "admin runners",
3535 ReadOnly: true, SSHOnly: true, Run: runAdminRunners})
36 register(Command{Path: []string{"admin", "runners", "forget"},
36 register(Command{Path: []string{"admin", "runners", "remove"},
3737 Summary: "drop a key's runner heartbeat row, e.g. one that polled once by mistake (instance admins)",
38 Usage: "admin runners remove <fingerprint>",
39 SSHOnly: true, Run: runAdminRunnersForget})
40 // forget is the name this shipped under in v1.18; remove is the verb
41 // every other noun uses. Both stay for one release.
42 register(Command{Path: []string{"admin", "runners", "forget"},
43 Summary: "alias of admin runners remove",
3844 Usage: "admin runners forget <fingerprint>",
3945 SSHOnly: true, Run: runAdminRunnersForget})
4046 register(Command{Path: []string{"admin", "repo", "list"},
@@ -62,7 +68,7 @@ func init() {
6268// requireInstanceAdmin gates the admin noun. -1 means proceed.
6369func requireInstanceAdmin(c *Ctx) int {
6470 if !c.User.IsAdmin {
65 return c.fail(protocol.ExitDenied, "admin commands are for instance admins")
71 return c.fail(protocol.ExitDenied, "admin commands are for instance admins; ask one")
6672 }
6773 return -1
6874}