Skip to content

writ accepts any --output value: -o bogus prints the dashboard and exits 0 #754

Closed

Description

@David-Noble-at-work

Feature: #833 — Renderings: the pipeline from result value to stdout

writ status -o bogus prints the human dashboard and exits 0. A typo is silently honored as a request for
the default.

$ writ status -o bogus
Layers:
  base     (absent)
  ...
$ echo $?
0

devlore-test, which routes through the pipeline, rejects the same input:

$ devlore-test run -o bogus test_hello.star
Error: result.FormatterByName: unknown formatter "bogus"; expected one of csv, json, list, none, table,
template=BODY, value, yaml

Root cause

A flag registered on a root that no leaf consumes. cmd/writ/writ/root.go:49 calls
cli.AddOutputFlags(rootCmd, &outputOptions), so cobra advertises the whole common set on every writ
command. Consuming it is a separate act, and writ performs it once -- commands.go:302, inside
runVerify.

Validation lives in exactly one place, cmd/internal/cli/output.go:111:

formatter, err := result.FormatterByName(opts.Format)

A command that never calls BuildPipeline never validates. writ status instead compares the string to a
literal (config.go:160):

cfg.JSONOutput = outputOptions.Format == "json"

Everything that is not "json" -- valid or not -- falls to the same branch.

This is the same root cause as #753, where
--store is registered and read nowhere. That one is the severe face: writ reports on a different store
than the one it was told to read. This is the mild face: writ accepts input it should reject.

Scope: not only status

Every writ command except verify accepts any --output value. Confirmed:

writ status -o bogus   exit=0
writ repo   -o bogus   exit=0

--filter and --jq are inert on the same commands for the same reason.

Fix

Falls out of Phase 3b: runStatus calls BuildPipeline as runVerify already does, and FormatterByName
rejects the value. The general form is the missing enforcement invariant -- a command that registers the
common set must consume it
-- greppable as "every root calling AddOutputFlags has every leaf reaching
BuildPipeline". Neither of Phase 5's two current invariants would catch this: writ registers no flags of
its own, and the os.Stdout invariant would catch status alone, not repo.

Verification

  • writ status -o bogus exits non-zero and names the accepted set.
  • writ status -o none produces no output.
  • writ status -o yaml produces YAML a parser accepts.
  • The same holds for every writ command, not only status.

Metadata

Metadata

Labels

Area:CLICommand-line interfaceArea:ErrorHandlingError handling and propagationEpic:CommandLineOne output convention across every CLI in the suitebugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions