Skip to content

Add a testable Run(...) int CLI entry point - #63

Merged
MPV merged 1 commit into
masterfrom
claude/cli-run-entrypoint
Aug 2, 2026
Merged

Add a testable Run(...) int CLI entry point#63
MPV merged 1 commit into
masterfrom
claude/cli-run-entrypoint

Conversation

@MPV

@MPV MPV commented Aug 2, 2026

Copy link
Copy Markdown
Owner

What

Replace cmd.Execute(args) with a single testable entry point:

func Run(args []string, stdin io.Reader, stdout, stderr io.Writer) int
func main() { os.Exit(cmd.Run(os.Args[1:], os.Stdin, os.Stdout, os.Stderr)) }

Run resolves the arguments, writes images to the injected stdout, reports errors to the injected stderr (via a local log.New(stderr, "", 0) rather than the global logger), and returns the exit code. processor.ProcessStdin now takes an io.Reader so stdin is injectable too.

Why

The CLI's observable contract — argv + stdin → stdout, stderr, exit code — could not be asserted in-process: Execute wrote to os.Stdout, read os.Stdin, and exited via log.Fatal. Tests had to hijack os.Stdout/os.Args. Making the exit code a returned value and the streams injected parameters means the whole triple is now assertable from a plain function call — the enabler for keeping the e2e/triple goldens in approvals/ in-process (no subprocess, no go build).

Behavior change

None — verified byte-for-byte. Built the binary and compared against master across every scenario: single file, multi-document file, stdin, unsupported kind (stderr + exit 0), missing path (silent + exit 0), and no-args usage (stderr + exit 1). Identical stdout/stderr/exit in all cases.

The cmd tests are rewritten to call Run with bytes.Buffers and assert the triple directly — no os.Stdout/os.Stdin/os.Args swapping, no chdir.

Relationship to the open CLI stack

This supersedes #50 (Execute(args, out io.Writer) error): Run is the fuller version — it returns an exit code and injects stdin/stderr as well. The behavior changes in the other open PRs are orthogonal and would layer cleanly on top of Run rather than on Execute:

If you adopt Run, the cleanest path is to close/rework #50 and re-base #55 onto this shape — say the word and I'll reorganize that stack. No dependency change; -race/vet/gofmt/go mod tidy all clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Pc6NAURAqjU4LYJx93tgSC


Generated by Claude Code

main() previously called cmd.Execute(args), which wrote to os.Stdout,
read os.Stdin, and terminated via the global log's Fatal, so the CLI's
observable contract (argv + stdin -> stdout, stderr, exit code) could not
be asserted without hijacking process globals.

Replace Execute with Run(args []string, stdin io.Reader, stdout, stderr
io.Writer) int: it resolves the arguments, writes images to the injected
stdout, reports errors to the injected stderr via a local logger, and
returns the exit code. main() becomes a one-line os.Exit(cmd.Run(...)),
and processor.ProcessStdin now takes an io.Reader so stdin is injectable
too.

Behavior is byte-for-byte unchanged, verified across the file,
multi-document, stdin, unsupported-kind, missing-file, and no-args
scenarios. The cmd tests now call Run with buffers and assert the (exit,
stdout, stderr) triple directly, with no os.Stdout/os.Args swapping.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pc6NAURAqjU4LYJx93tgSC
@MPV
MPV merged commit 4b23c28 into master Aug 2, 2026
1 check passed
@MPV
MPV deleted the claude/cli-run-entrypoint branch August 2, 2026 07:46
MPV pushed a commit that referenced this pull request Aug 2, 2026
Reworked from the earlier subprocess e2e track onto the Run(...) int
entry point (#63): the CLI is now driven in-process via cmd.Run, so no
binary is built and no subprocess is spawned. Everything lives in
approvals/ alongside the existing processor-level tests — no separate
folder.

Each scenario is approved as three per-stream golden files — stdout,
stderr, and a new exitcode stream — extending this package's existing
stdout/stderr convention with the exit code. Inputs are co-located
cli_test.TestCLI.<name>.input.yaml fixtures, so a scenario's input and
its results share one name stem.

Six scenarios: a single file, a multi-document file, stdin, an
unsupported kind, a missing path, and no-args usage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pc6NAURAqjU4LYJx93tgSC
MPV pushed a commit that referenced this pull request Aug 2, 2026
Reworked from the earlier subprocess e2e track onto the Run(...) int
entry point (#63): the CLI is now driven in-process via cmd.Run, so no
binary is built and no subprocess is spawned. The tests live in the
existing approvals/kir_test.go alongside the processor-level tests — same
high-level scope, one file, no separate folder.

Each scenario is approved as three per-stream golden files — stdout,
stderr, and a new exitcode stream — extending this package's existing
stdout/stderr convention with the exit code. Inputs are co-located
kir_test.TestCLI.<name>.input.yaml fixtures, so a scenario's input and
its results share one name stem.

Six scenarios: a single file, a multi-document file, stdin, an
unsupported kind, a missing path, and no-args usage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pc6NAURAqjU4LYJx93tgSC
MPV pushed a commit that referenced this pull request Aug 2, 2026
Reworked from the earlier subprocess e2e track onto the Run(...) int
entry point (#63): the CLI is now driven in-process via cmd.Run, so no
binary is built and no subprocess is spawned. The tests live in the
existing approvals/kir_test.go alongside the processor-level tests — same
high-level scope, one file, no separate folder.

TestCLI covers only what the CLI layer adds over processor.ProcessFile:
stdin wiring, argument resolution, and no-args usage. Plain manifest ->
images extraction is already covered by TestKind/TestError/TestMultiple,
so those scenarios are not duplicated here. Each run is approved as three
per-stream golden files — stdout, stderr, and a new exitcode stream.

Three scenarios: stdin, a missing path, and no-args usage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pc6NAURAqjU4LYJx93tgSC
MPV pushed a commit that referenced this pull request Aug 3, 2026
Route the whole behavioral golden suite through cmd.Run — the real entry
point (#63) — via one verify(args, stdin) helper, and approve each
scenario's (stdout, stderr, exit code) triple as three golden files.

Every test now exercises the actual CLI seam rather than the internal
processor.ProcessFile, so the goldens capture exactly what the tool emits
(the trailing newline on stdout, the "error:" prefix on stderr, and the
exit code). Granular, per-layer coverage stays in the
k8s/yamlparser/processor/fileutil unit tests; this package is the
behavioral golden layer.

Scenarios: the seven workload kinds, a Service (error), a multi-document
file, plus the CLI-only cases stdin, a missing path, and no-args usage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pc6NAURAqjU4LYJx93tgSC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants