Documentation
¶
Overview ¶
Package cli holds the command-line surface for registry-conformance: flag definitions, subcommands, and the input-layer resolution that happens before pkg/conformance.Config is constructed.
Built-in flag bindings flow through urfave/cli/v3 value sources, not direct os.Getenv calls. The documented exception is the `env:<NAME>` source kind of the --credential flag (see credential.go and S04 §Credential cases): the env-var name is part of the user-supplied flag value at parse time, so resolveEnv calls os.Getenv directly. The call is the spec contract for that source kind, not a hidden configuration source.
Index ¶
- func ExitCode(report *conformance.Report, err error) int
- func ListCommand() *cli.Command
- func ListFlags() []cli.Flag
- func OnUsageError(_ context.Context, _ *cli.Command, err error, _ bool) error
- func RunCommand(out *RunOutcome) *cli.Command
- func RunFlags() []cli.Flag
- func WriteError(w io.Writer, err error)
- func WriteRunError(w io.Writer, err error)
- type RunOutcome
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExitCode ¶
func ExitCode(report *conformance.Report, err error) int
ExitCode is the exported wrapper that maps a (report, error) pair to a process exit code. It delegates to the package-internal exitCode so the S04 §Exit codes taxonomy has exactly one implementation; the binary lives in package main and cannot reach the unexported exitCode directly.
func ListCommand ¶
ListCommand returns the urfave/cli `list` subcommand per S04 §list subcommand. It accepts only --format (the same flag definition the `run` subcommand uses, with the same allow-list validation and REGISTRY_CONFORMANCE_FORMAT env binding from S04 §Flag inventory). On success it resolves cfg.Format to the per-format Module, calls printCatalog, and writes the names to the command's Writer (stdout in production; an in-memory buffer in tests). The action does not open any network connections — AC #12 forbids registry I/O on the list subcommand.
OnUsageError (flags.go) is the shared unknown-flag rewrite; the run subcommand will also wire it at Step 18 / MR 2.7. An unknown flag (e.g. --filter, --registry-url) surfaces as `unknown flag: --<name>` per AC #13.
func ListFlags ¶
ListFlags returns the flag set for the `list` subcommand per S04 §Subcommand structure / §list subcommand: only `--format`, with the same allow-list validation as `run`.
func OnUsageError ¶
OnUsageError rewrites the stdlib `flag` package's unknown-flag wording (`flag provided but not defined: -<name>`) to the S04 §Error Cases / Input layer wording (`unknown flag: --<name>`). Non-matching errors pass through unchanged. The function satisfies urfave/cli's OnUsageErrorFunc signature and is wired onto the run and list subcommand `*cli.Command` values by their constructors; the helper ships here so that wiring has one canonical place to point at and tests can exercise the spec wording end-to-end.
func RunCommand ¶
func RunCommand(out *RunOutcome) *cli.Command
RunCommand returns the urfave/cli/v3 command for the `run` subcommand bound to the production dispatch call site.
Dispatch goes through dispatchRun (RunModule on the format's Module), not pkg/conformance.Run, because Run's internal formatFactories map is populated only by a registration seam no production code calls, so a Run-bound binary returns *ConfigError for every format. The CLI already owns the format→Module switch for `list` (moduleForFormat in list.go), so reusing it here keeps a single dispatch source in this package and makes `run` functional without a runtime registry. cfg.Format is validated at the flag boundary (validateFormat during urfave parse) before the Action runs, so moduleForFormat never reaches its panic arm; RunModule re-validates the rest of cfg internally, so *ConfigError / *FilterNoMatchError / *PriorityNoMatchError still surface unchanged.
Surface pinned by docs/specs/S04-contracts.md §Subcommand structure: Name = "run", Flags = RunFlags(), OnUsageError = OnUsageError, Action non-nil. Tests assert each of these on the returned command directly (TestRunCommand_Construction).
RunCommand panics if out is nil: out is the only channel the caller has to read Report/Err, so accepting nil would silently drop the run outcome.
func RunFlags ¶
RunFlags returns the flag set for the `run` subcommand per S04 §Flag inventory. Each flag carries Sources binding it to REGISTRY_CONFORMANCE_<UPPER_SNAKE> per S04 §Environment-variable binding; per-flag boundary validation lives in each flag's Validator hook per S04 §Validation rules. Credential validation lives in credential.go.
The returned slice is fresh on every call so the consumer can mutate it (for example by appending the `--credential` flag from credential.go) without affecting subsequent callers.
func WriteError ¶
WriteError writes err's message to w as a single line with control runes stripped, then a trailing newline. It is the one stderr write site for the cmd/conformance entry-point: routing every entry-point error through it enforces the print-site sanitization contract from docs/dev/go-secure-coding.md §Interpolating untrusted bytes at the internal/cli boundary, so the write site stays safe regardless of which error source feeds it, instead of trusting each upstream source to pre-sanitize.
stripControl (not %q) is used so the message keeps its bare, human-facing shape: %q would quote the whole line and break the S04-pinned `unknown flag: --<name>` rendering (S04 §Error Cases / Input layer). Both defeat terminal-mangling — %q escapes control bytes, stripControl replaces them with '?' — but only stripControl preserves the unquoted CLI error line. This mirrors the carve-out OnUsageError already applies in flags.go.
err must be non-nil; the sole caller writes only on a non-nil error.
func WriteRunError ¶
WriteRunError writes the stderr line for an error returned by pkg/conformance.Run on the `run` subcommand path, mapping the typed errors to the exact strings S04 §Output layer pins, then routing the result through the same stripControl sanitization as WriteError (defense-in-depth per docs/dev/go-secure-coding.md). It is the `run`-path counterpart to WriteError, which serves the usage/missing-subcommand path.
The CLI owns this mapping — not the pkg/conformance Error() methods, which serve Go consumers and logs. Two messages diverge from their Error() rendering and so are built from the typed fields here:
- *FilterNoMatchError → "filter: no test matched <Pattern>" with the pattern UNQUOTED (S04 AC #70/#75). The type's Error() renders the pattern with %q, which would surface quotes the spec line does not.
- *PriorityNoMatchError → "priority: no test matched <p1, p2, ...>" with priorities joined by ", " in input order (S04 AC #71/#76). The type's Error() joins with a bare ",".
*ConfigError already renders as "<Field>: <Reason>" — the AC #69 form — so it and every other error fall through to err.Error().
err must be non-nil; the sole caller writes only on a non-nil error.
Types ¶
type RunOutcome ¶
type RunOutcome struct {
// Report is whatever pkg/conformance.Run produced. May be nil if
// the run failed before producing any module results.
Report *conformance.Report
// Err is whatever pkg/conformance.Run returned. Nil on success.
// Distinct from Report because a non-nil Report where Report.Failed()
// is true is a normal "tests failed" outcome, not a tool error.
Err error
// ReportPath is the resolved --report flag value (empty when unset).
// The --report flag lives on the run subcommand, so the root binary
// (cmd/conformance) cannot read it post-hoc from the parsed command;
// runAction threads it out here so main can call
// internal/report.WriteJUnit on the success/partial path. S04
// §"--report <path>": JUnit XML; consumed by the output renderer
// after Run returns (S04 §391).
ReportPath string
}
RunOutcome is the out-parameter the `run` subcommand writes its terminal state into. Callers (the binary `main` and tests) construct a zero-value RunOutcome, hand it to RunCommand, and read both fields after the command returns; the exit-code adapter then maps (Report, Err) to a shell exit code.
Pinned by docs/specs/S04-contracts.md §Go module API and §Acceptance Criteria / §Library layer: the library boundary (pkg/conformance.Run) returns (Report, error) and the CLI's job is only to wire flags → Config → Run, then surface the pair for exit-code mapping.