Documentation
¶
Overview ¶
Command release-guard is the thin CLI the release workflows shell out to. It wraps the pure logic in internal/release so the workflows never re-encode the title/tag grammar or the final-release guard inline.
Subcommands:
release-guard parse-title "<pr title>"
Validate a release-PR title and emit version + kind. Exits non-zero with
an actionable message on a malformed title.
release-guard parse-tag "<git tag>"
Validate a git tag as a schema release reference (rejects the legacy
pkg/schema/v* and any non-release tag) and emit version + kind.
release-guard check-maintainer --user <login>
Assert a GitHub user is a release maintainer (admin/maintain collaborator
on $GITHUB_REPOSITORY). Reads the collaborator permission via the
GitHubClient and applies release.IsMaintainer — the single source of the
maintainer predicate consumed by both release-pr.yml gates.
release-guard check-approval --pr <number>
Assert a release PR has at least one standing APPROVED review from a
maintainer. Fetches all review pages via the GitHubClient, reduces each
reviewer's latest non-COMMENTED review, then applies release.IsMaintainer
per approver.
release-guard check-workflow [--release .github/workflows/release.yml] [--policy .github/release-guard.policy.yml]
Validate that the release workflow satisfies the per-repo policy
(.github/release-guard.policy.yml): every declared job exists with the
required needs-edges (and, for reusable gates, the required uses /
secrets:inherit / no-if shape; for OIDC-authenticated gates, the required
job permissions and GitHub environment binding). Repo-agnostic - the job graph lives in the
policy file, not in this tool.
Every subcommand that derives a (version, kind) writes "version=<v>" and "kind=<k>" to the file named by $GITHUB_OUTPUT when set (so workflow steps can consume them via steps.<id>.outputs.*), and always echoes them to stdout.
main() is the SOLE composition root: it reads GH_TOKEN + GITHUB_REPOSITORY from the environment ONCE, builds the GitHubClient (go-github), and injects it DOWN into pure handler funcs that take their deps as parameters and never touch os.Getenv. Handlers return an error; main maps a non-nil error to a non-zero exit via fatalf, preserving exit-code parity.