Rewrite dmr as a standalone, engine-independent binary#996
Conversation
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- In the Makefile,
DMR_VERSIONusesgit describe --match 'v*', which won’t pick updmr-v*tags used by the new release flow; consider changing the match pattern (or dropping it) so localmake build-dmrbuilds get the same versioning as thedmr-vX.Y.Zreleases. - The GitHub
release-dmr.ymlworkflow re-encodes the dmr build flags, ldflags, and target matrix instead of reusingmake build-dmr-cross, which risks them drifting; consider calling the Makefile target from the workflow or sharing a single source of truth for build configuration. - For
dmr serve, double-check whethercommands.NewRootCmddefines aPersistentPreRun(E)on the root; if it does, that will still run beforeserveeven thoughservesets its ownPersistentPreRunE, so you may need an explicit override to avoid the Docker CLI plugin initialization path you’re trying to bypass.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In the Makefile, `DMR_VERSION` uses `git describe --match 'v*'`, which won’t pick up `dmr-v*` tags used by the new release flow; consider changing the match pattern (or dropping it) so local `make build-dmr` builds get the same versioning as the `dmr-vX.Y.Z` releases.
- The GitHub `release-dmr.yml` workflow re-encodes the dmr build flags, ldflags, and target matrix instead of reusing `make build-dmr-cross`, which risks them drifting; consider calling the Makefile target from the workflow or sharing a single source of truth for build configuration.
- For `dmr serve`, double-check whether `commands.NewRootCmd` defines a `PersistentPreRun(E)` on the root; if it does, that will still run before `serve` even though `serve` sets its own `PersistentPreRunE`, so you may need an explicit override to avoid the Docker CLI plugin initialization path you’re trying to bypass.
## Individual Comments
### Comment 1
<location path="Makefile" line_range="63" />
<code_context>
build-cli:
$(MAKE) -C cmd/cli
+DMR_VERSION := $(shell git describe --tags --always --dirty --match 'v*')
+DMR_LDFLAGS := -s -w \
+ -X main.Version=$(DMR_VERSION) \
</code_context>
<issue_to_address>
**issue (bug_risk):** Version discovery ignores dmr-specific tags and may not match released dmr binaries
DMR_VERSION uses `git describe --match 'v*'`, but dmr releases are now tagged `dmr-vX.Y.Z`. As a result, `build-dmr`/`build-dmr-cross` will keep picking up the generic `v*` tags (container image scheme), so locally built dmr binaries won’t match published dmr release versions. Please either drop `--match` or switch to `--match 'dmr-v*'` (and strip the prefix) so standalone dmr builds follow the dmr tag scheme.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Code Review
This pull request introduces a standalone dmr binary that bundles the inference daemon and model management CLI, removing dependencies on Docker Desktop or Docker Engine. It adds cross-compilation support, documentation, and refactors the CLI command tree to hide engine-specific commands. Feedback focuses on improving the CLI flag handling in cmd/dmr/serve.go by ensuring explicit flags correctly override conflicting environment variables and enforcing mutual exclusivity between the --port and --socket flags.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
The previous cmd/dmr/main.go was a 69-line hack that reused the full "docker model" CLI command tree and bolted on a "serve" subcommand. It worked, but its structure gave no attention to being genuinely engine-independent, its command surface still exposed Docker-Engine container-management commands that don't apply to it, and there was no build/release story for distributing it outside this repo. This rewrites cmd/dmr from scratch as a small, documented package: - root.go builds the CLI command tree and always forces MODEL_RUNNER_HOST to the local daemon before doing so, guaranteeing every dmr invocation takes the "manual host" code path in cmd/cli/desktop/context.go and never probes for Docker Desktop or a Docker Engine connection. A regression test locks in the cobra semantics this relies on (a child command's own PersistentPreRunE replaces, rather than chains after, its parent's). - serve.go runs pkg/server in-process, with --port/--socket/ --models-path flags in addition to the existing env vars. --port and --socket are mutually exclusive, and an explicit flag clears the other transport's environment variable so an inherited MODEL_RUNNER_PORT/MODEL_RUNNER_SOCK can never silently override it (pkg/server prefers MODEL_RUNNER_PORT over MODEL_RUNNER_SOCK whenever both happen to be set). - Engine-only commands that manage a docker-model-runner *container* (install-runner, start-runner, stop-runner, restart-runner, reinstall-runner, uninstall-runner) are hidden from the dmr command tree, since "dmr serve" replaces the container entirely. Also: - pkg/envconfig.LlamaServerPath() no longer defaults to the Docker Desktop bundle path on non-macOS platforms, since that path can never exist there; it only applies as a last-resort lookup on macOS itself. - dmr has no cgo dependencies (confirmed via CGO_ENABLED=0 builds), so Makefile's build-dmr now builds statically, versioned from the dmr-vX.Y.Z tag scheme (git describe --match 'dmr-v*', stripped of its prefix) rather than the container image's v* tags. A new build-dmr-cross target cross-compiles it for every platform we intend to package: macOS (arm64), Linux (amd64/arm64), and Windows (amd64). - Adds .github/workflows/release-dmr.yml, which builds those targets by invoking make build-dmr-cross directly (a single source of truth for dmr's build flags shared with local/dev builds, rather than re-encoding them in the workflow), publishes a GitHub release, and opens the corresponding Homebrew formula PR (docker/homebrew-tap) and WinGet manifest submission (microsoft/winget-pkgs), so dmr becomes installable via `brew install docker/tap/dmr` and `winget install Docker.dmr` without depending on Docker Desktop's or Docker Engine's own release pipelines. - Documents all of the above in README.md, cmd/dmr/README.md, and packaging/README.md. go.mod/go.sum are tidy, golangci-lint and `go test -race ./...` both pass across the whole repo.
feb3d95 to
a11caa2
Compare
|
Addressed all three review points from @sourcery-ai and both from @gemini-code-assist-bot in the latest push:
Rebased on current |
Summary
This rewrites
cmd/dmr(previously a ~70-line hack combining the CLI commandtree with a bolted-on
servesubcommand) into a small, documented,genuinely standalone package, and adds the build/release plumbing needed to
distribute it outside this repo — laying the groundwork for adoption by
tools like sbx that
don't want a Docker Desktop or Docker Engine dependency.
What changed
cmd/dmr/root.gobuilds the full model management command tree(
run,ls,pull,rm,ps,inspect,logs, ...) and always forcesMODEL_RUNNER_HOSTto the local daemon first. This guarantees everydmrinvocation takes the "manual host" path in
cmd/cli/desktop/context.goand never probes for Docker Desktop or a Docker Engine connection. A
regression test (
TestServePersistentPreRunEOverridesParent) locks in thecobra semantics this relies on: a child command's own
PersistentPreRunEreplaces, rather than chains after, its parent's.
cmd/dmr/serve.gorunspkg/serverin-process (the same daemon usedby the
docker-model-runnercontainer and Docker Desktop's bundledrunner), with
--port/--socket/--models-pathflags in addition to theexisting env vars.
--port/--socketare mutually exclusive(
MarkFlagsMutuallyExclusive), and an explicit flag clears the othertransport's environment variable first, since
pkg/serverprefersMODEL_RUNNER_PORToverMODEL_RUNNER_SOCKwhenever both happen to beset — otherwise an inherited env var could silently override an explicit
flag. Covered by
TestApplyServeEnv.docker-model-runnercontainer (
install-runner,start-runner,stop-runner,restart-runner,reinstall-runner,uninstall-runner) are now hiddenfrom the
dmrcommand tree —dmr servereplaces the containerentirely, so these no longer apply and only added confusion.
pkg/envconfig.LlamaServerPath()no longer defaults to the Docker Desktopbundle path on non-macOS platforms (that path can never exist there); it's
now only checked as a last-resort lookup on macOS itself, where Desktop
vendors its own copy.
dmrhas zero cgo dependencies, somake build-dmrnow buildswith
CGO_ENABLED=0, versioned from thedmr-vX.Y.Ztag scheme(
git describe --match 'dmr-v*', stripped of its prefix) rather than thecontainer image's
v*tags. A newmake build-dmr-crosstargetcross-compiles it for every platform we intend to package: macOS
(arm64), Linux (amd64/arm64), Windows (amd64) — all verified locally.
.github/workflows/release-dmr.yml: on admr-vX.Y.Ztag, the buildjob runs
make build-dmr-crossdirectly (rather than re-encodingGOOS/GOARCH/ldflags in YAML, so there's a single source of truth for
dmr's build flags), publishes a GitHub release, opens the Homebrew
formula PR against
docker/homebrew-tap, and submits the WinGet manifestto
microsoft/winget-pkgsviawingetcreate— sodmrbecomesinstallable via
brew install docker/tap/dmr/winget install Docker.dmron its own release cadence, independent of Docker Desktop's or Docker
Engine's pipelines. Modeled on
docker/sandboxes'spublish-brew.yml/publish-winget.yml.README.md,cmd/dmr/README.md, and thenew
packaging/README.md.Testing
go build ./...,go vet ./...,gofmt -l— cleanmake lint(golangci-lint run ./...) — 0 issuesgo test -race ./...— all packages pass, including new tests forcmd/dmr(TestRemoveEngineOnlyCommands,TestServePersistentPreRunEOverridesParent,TestApplyServeEnv) andpkg/envconfig(LlamaServerPathplatform behavior)go mod tidy— no changesdmr serve --port 19434with no Docker installed/running,confirmed
/modelsresponds and the daemon downloads llama.cpp from theregistry on demand
dmr version/dmr --helpfor all four targetplatforms (darwin/arm64, linux/amd64, linux/arm64, windows/amd64 build
only, not run), and exercised the release workflow's packaging step
locally against real
make build-dmr-crossoutputmain(no conflicts) and squashed to a single commitNot in scope here
Linux
.deb/.rpmpackaging is unaffected — it continues through theexisting
docker-model-pluginpipeline referenced inrelease.yml.