Documentation
¶
Overview ¶
Package cli wires the commands and owns the exit-code contract (R-17). Distinct, documented, scriptable:
0 success — applied, or audit found nothing 1 no-op — nothing to change 2 refused — would violate INV-1 or INV-2 (or S-4 size cap) 3 invalid input — malformed op, unresolvable scope, conflicting batch 4 audit findings present 5 inconclusive — API unavailable, token insufficient, rate limited (R-12) 6 validation failed post-write; rolled back
`sync` and `check` run under a coarser three-code contract of their own (R-19: only 0, 2 and 3), because their question is "did this repo converge?" rather than "what exactly happened?". See sync.go.
`audit --lint` narrows 0 and 4 rather than redefining them: it never returns 1, because a file that needs no repair is that verb's SUCCESS and exiting no-op would make every healthy repo in a fleet read as a failure under `set -e`; and its 4 is still "findings present", counting a fix computed but not written (--dry-run) as one. See lint.go.
Index ¶
Constants ¶
const ( ExitOK = 0 ExitNoOp = 1 ExitRefused = 2 ExitInvalid = 3 ExitFindings = 4 ExitInconclusive = 5 ExitValidation = 6 )
Exit codes (R-17).
const ( StatusApplied = "applied" StatusUnchanged = "unchanged" StatusSkipped = "skipped" StatusRefused = "refused" StatusError = "error" )
Sync statuses (R-24). "skipped" is distinct from "unchanged" so a policy that matches nothing anywhere cannot read as "already correct" across a whole fleet.
Variables ¶
var Version = "dev"
Version is the build this binary is, stamped at link time by the release workflow with
-ldflags "-X github.com/jordonpeterson/codeowners-tool/internal/cli.Version=v0.0.7"
and left as "dev" for anything built locally, which is exactly the honest answer for a binary nobody released. Without it an operator holding a binary cannot tell whether it is the one with a given fix, so both rollback and CVE response are guesswork across a fleet.
Functions ¶
Types ¶
type SyncRecord ¶ added in v0.0.5
type SyncRecord struct {
Repo string `json:"repo"`
// Policy is the --policy path as the operator spelled it, absent on an --op
// run — the same key, and the same omitempty meaning, as `check --format
// json`. R-20 rests on the policy file being the complete statement of what
// ran; a directory of `--out records/$repo.json` that cannot say which
// artifact produced it cannot check that claim, and two waves in one week
// leave an aggregation nobody can attribute. Absent means "no policy file
// was involved", which an empty string would not: `group_by(.policy)` would
// bucket every ad-hoc --op run together with a policy that has no name.
Policy string `json:"policy,omitempty"`
// CodeownersPath is the repo-relative file this run CHANGED, or under
// --dry-run would have. A rollout has to stage and commit that file, and
// which of the three legal locations it is differs per repo (S-8), so a
// loop without this field can only `git add -A` and hope nothing else moved
// in the clone.
//
// It is emitted only when Status is StatusApplied. Absent therefore means
// "this run wrote nothing", NOT "no file was chosen": an `unchanged` repo
// has a perfectly good CODEOWNERS and simply nothing to stage. A refusal
// names its file in Error instead. One caveat the fleet script has to
// respect: a --dry-run record reports `applied` for a run that would have
// written, so DryRun must be checked before anything is staged.
CodeownersPath string `json:"codeowners_path,omitempty"`
Status string `json:"status"` // applied|unchanged|skipped|refused|error
Ops []plan.OpResult `json:"ops,omitempty"`
OpsApplied int `json:"ops_applied"`
OpsSkipped int `json:"ops_skipped"`
PathsChanged int `json:"paths_changed"`
Created bool `json:"created"`
// DryRun marks a record produced under --dry-run. Without it a preview row
// and a row from a real rollout are byte-identical, so an operator holding
// results.jsonl cannot tell whether the fleet was changed or only modelled —
// and neither can the script that reads it. omitempty keeps the common case
// (a real run) at the same six unconditional keys as before.
DryRun bool `json:"dry_run,omitempty"`
Warnings []string `json:"warnings,omitempty"`
Changes []plan.Change `json:"changes,omitempty"`
Error string `json:"error,omitempty"`
}
SyncRecord is one `sync` run, rendered as one JSON object (R-24). One line per repo is what lets `jq -s` aggregate a fleet without parsing stderr.