diff --git a/.golangci.yml b/.golangci.yml index 4ecd93c..19cf480 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -96,6 +96,11 @@ linters: linters: - forbidigo text: user agent of the front end + # A test's child process stands in for a program whose stdout is its output. + - path: _test\.go + linters: + - forbidigo + text: stdout is a command's output - path: internal/tfstate/apiproxy/ linters: - forbidigo @@ -142,6 +147,14 @@ linters: - pattern: ^time\.Sleep$ pkg: ^time$ msg: a test waits on synctest's fake clock; run it inside synctest.Test and call synctest.Sleep + # stdout carries only what a command outputs, so that a pipe reads nothing else. Taking it + # from the command lets a test capture it. + - pattern: ^fmt\.Print(f|ln)?$ + pkg: ^fmt$ + msg: &stdout-only stdout is a command's output; write that to cmd.OutOrStdout(), and anything for a person through slog or cmd.ErrOrStderr() + - pattern: ^os\.Stdout$ + pkg: ^os$ + msg: *stdout-only gocritic: disabled-checks: diff --git a/cmd/internal/output.go b/cmd/internal/output.go index 45bb242..f27e099 100644 --- a/cmd/internal/output.go +++ b/cmd/internal/output.go @@ -56,7 +56,8 @@ func (f *OutputFlag) Type() string { } // WriteList leaves a listing that fails part way through unterminated, so that json output which -// stopped early does not parse as a complete array. +// stopped early does not parse as a complete array. ndjson has no end to leave out, so there only +// the exit status tells a cut listing from a complete one. func (format OutputFormat) WriteList(w io.Writer, items iter.Seq2[jsontext.Value, error]) error { list, err := format.listing() if err != nil { diff --git a/skills/meshstack-cli/SKILL.md b/skills/meshstack-cli/SKILL.md index ace9c96..cd5e270 100644 --- a/skills/meshstack-cli/SKILL.md +++ b/skills/meshstack-cli/SKILL.md @@ -119,6 +119,8 @@ workspace identifier as meshPanel shows it (`metadata.name`, for example Commands for people (`auth status`, `profile list`) write Markdown. The others write one JSON array by default. For anything you consume yourself, use `-o ndjson`: one JSON object per line, so `jq` filters stream. A listing stops at 100 items unless you pass `--limit ` or `--limit unlimited`. +A listing that fails part way leaves the lines it got and exits non-zero, which a pipe hides: run +with `set -o pipefail`. ```sh meshstack bb list --limit unlimited -o ndjson | jq -r '...'