Kong CLI parity via shared command logic#3047
Conversation
There was a problem hiding this comment.
I'm Bonk, and I've done a quick review of your PR.
This PR extracts shared command logic to achieve parity between the Cobra and Kong CLIs. I found a few parity issues where the Kong CLI surface diverges from Cobra:
- BaseImageBuildCmd missing
--no-cacheand--progressflags (highest severity). The Cobrabase-image buildcommand exposes these flags viaaddBaseImageFlags(), but the KongBaseImageBuildCmdonly embedsbaseImageVersionFlagsand omits them. SinceRunBaseImageBuildreadsopts.NoCacheandopts.ProgressOutput, the Kong path will always use the zero values. - Several commands that are hidden in Cobra are visible in Kong.
predict,train,weights, anddebugall haveHidden: truein their Cobra definitions but lackhidden:""in the Kong CLI struct tags. - Unreachable
os.Exit(1)afterparser.FatalIfErrorf(err)inmain.go. Kong'sFatalIfErrorfalready exits the process; the subsequentos.Exit(1)is dead code.
| opts := cmd.options() | ||
| opts.NoCache = cmd.NoCache | ||
| opts.ProgressOutput = cmd.Progress | ||
| return cli.RunBaseImageDockerfile(ctx, opts) |
There was a problem hiding this comment.
BaseImageBuildCmd is missing the --no-cache and --progress flags that the Cobra base-image build command exposes via addBaseImageFlags(). Since RunBaseImageBuild reads these fields from opts, the Kong path will always use zero values.
| return cli.RunBaseImageDockerfile(ctx, opts) | |
| // BaseImageBuildCmd implements "cog base-image build". | |
| type BaseImageBuildCmd struct { | |
| baseImageVersionFlags `embed:""` | |
| NoCache bool `name:"no-cache" help:"Do not use cache when building the image."` | |
| Progress string `name:"progress" default:"${progress_default}" enum:"auto,plain,tty,quiet" help:"Set type of build progress output: ${enum}."` | |
| } | |
| func (cmd *BaseImageBuildCmd) Run(ctx context.Context, dockerClient command.Command) error { | |
| opts := cmd.options() | |
| opts.NoCache = cmd.NoCache | |
| opts.ProgressOutput = cmd.Progress | |
| return cli.RunBaseImageBuild(ctx, dockerClient, opts) | |
| } |
| Debug DebugCmd `cmd:"" help:"Debug Cog internals."` | ||
| Doctor DoctorCmd `cmd:"" help:"Check your project for common issues and fix them (experimental)."` | ||
| Exec ExecCmd `cmd:"" help:"Execute a command inside a Docker environment."` | ||
| Init InitCmd `cmd:"" help:"Configure your project for use with Cog."` |
There was a problem hiding this comment.
PredictCmd should be hidden to match Cobra, where newPredictionCommand("predict", true) sets Hidden: true.
| Init InitCmd `cmd:"" help:"Configure your project for use with Cog."` | |
| Predict PredictCmd `cmd:"" hidden:"" help:"Run a prediction."` |
| Push PushCmd `cmd:"" help:"Build and push model in current directory to a Docker registry."` | ||
| RunCommand RunCmd `cmd:"" name:"run" help:"Run a prediction."` | ||
| Serve ServeCmd `cmd:"" help:"Run an HTTP server."` | ||
| Train TrainCmd `cmd:"" help:"Run a training job."` |
There was a problem hiding this comment.
TrainCmd should be hidden to match Cobra, where newTrainCommand() sets Hidden: true.
| Train TrainCmd `cmd:"" help:"Run a training job."` | |
| Train TrainCmd `cmd:"" hidden:"" help:"Run a training job."` |
| RunCommand RunCmd `cmd:"" name:"run" help:"Run a prediction."` | ||
| Serve ServeCmd `cmd:"" help:"Run an HTTP server."` | ||
| Train TrainCmd `cmd:"" help:"Run a training job."` | ||
| Weights WeightsCmd `cmd:"" help:"Commands for managing model weight files."` |
There was a problem hiding this comment.
WeightsCmd should be hidden to match Cobra, where newWeightsCommand() sets Hidden: true.
| Weights WeightsCmd `cmd:"" help:"Commands for managing model weight files."` | |
| Weights WeightsCmd `cmd:"" hidden:"" help:"Commands for managing model weight files."` |
| BaseImage BaseImageCmd `cmd:"" name:"base-image" help:"Tools for working with Cog base images."` | ||
| Build BuildCmd `cmd:"" help:"Build an image from cog.yaml."` | ||
| Debug DebugCmd `cmd:"" help:"Debug Cog internals."` | ||
| Doctor DoctorCmd `cmd:"" help:"Check your project for common issues and fix them (experimental)."` |
There was a problem hiding this comment.
DebugCmd should be hidden to match Cobra, where newDebugCommand() sets Hidden: true.
| Doctor DoctorCmd `cmd:"" help:"Check your project for common issues and fix them (experimental)."` | |
| Debug DebugCmd `cmd:"" hidden:"" help:"Debug Cog internals."` |
| // otherwise it's a real parse error (e.g. unexpected command or flag), so print the error and exit non-zero. | ||
| parser.FatalIfErrorf(err) | ||
| os.Exit(1) |
There was a problem hiding this comment.
parser.FatalIfErrorf(err) already exits the process by default; os.Exit(1) is unreachable dead code.
| // otherwise it's a real parse error (e.g. unexpected command or flag), so print the error and exit non-zero. | |
| parser.FatalIfErrorf(err) | |
| os.Exit(1) | |
| // otherwise it's a real parse error (e.g. unexpected command or flag), so print the error and exit non-zero. | |
| parser.FatalIfErrorf(err) | |
| } | |
| if cli.Help { |
| if err != nil { | ||
| parser.FatalIfErrorf(err) | ||
| os.Exit(1) |
There was a problem hiding this comment.
parser.FatalIfErrorf(err) already exits the process; os.Exit(1) is unreachable dead code.
| if err != nil { | |
| parser.FatalIfErrorf(err) | |
| os.Exit(1) | |
| // command returned an error. Print and exit non-zero. | |
| if err != nil { | |
| parser.FatalIfErrorf(err) | |
| } | |
| } |
|
I found a few parity issues between the Kong and Cobra CLIs and posted them as review comments on PR #3047. Summary of issues:
The review with suggestions is here: #3047 (review) |
Summary
Builds the side-by-side
cmd/cog-kongCLI to full command parity with the existing Cobra CLI (cmd/cog), while extracting parser-independent command behaviour into shared, exported functions underpkg/cli.Both CLIs now execute the same core code: command behaviour, validation, Docker/model/provider setup, output formatting, and errors live in shared
Run*functions and*Optionsstructs. Cobra owns flag registration/parsing; Kong owns struct tags + DI; neither owns behaviour.All 13 commands reach parity:
build,push,serve,exec,predict,run,train,init,login,doctor,debug,weights(import/pull/status),base-image(dockerfile/build).Approach
Each task extracts one command's behaviour into shared code, then wires both Cobra and Kong adapters into it (TDD: failing parse/behaviour test → shared runner → thin adapters):
RunBuild,BuildFlagsOptions,ResolveBuildImageNameRunPush,ResolvePushTarget,PushCommandOptionsRunServe,RunExec,RuntimeBuildOptionsRunInit,RunLogin,RunDoctor,RunDebugRunPrediction,RunTrainRunWeightsImport,RunWeightsPull,RunWeightsStatusRunBaseImageDockerfile,RunBaseImageBuildDeviations from the original plan
The plan was speculative in a few spots; the implementation matches the real code:
OCIIndex/OCIIndexEnabled()from build options.--cuda/--python/--torch), not the plan's guessed--*-version.short:"v"from Kong's--version— it diverged from Cobra (which has no-v) and collided with the weights commands'-v(verbose).PersistentPreRuninto the shared runners, so it fires once per subcommand from a single source.Verification
mise run test:go— all pass (2018 tests)mise run lint:go— 0 issuesmise run fmt:go— cleancogandcog-kongcompile; no binaries committedcmd/cog-kong/main_test.goasserts the full command surface (registration, nested commands, root globals, per-command flag parsing) without requiring DockerNotes
kong(this stacks on the existing side-by-side scaffold).cmd/cogremains the production Cobra binary, unchanged in behaviour.