fix(providers): inject shim version at build time#338
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes issue #309, where each provider shim's reported version (InferenceProviderConfig.status.version, surfaced by kubectl, the Web UI, and Headlamp) was a hand-maintained Go const that drifted from the actually-published image tag. The fix replaces the const with a build-time -ldflags -X injection target so the reported version equals the image tag by construction, and falls back to a git-derived dev-<sha> stamp for non-release builds. The change is applied uniformly across all five in-tree shims (dynamo, kaito, kuberay, llmd, vllm) and fits the existing pattern already used for the pinned upstream versions (DynamoVersion, VLLMVersion).
Changes:
- In each
config.go, replace theProviderVersionconst withvar shimVersion = "dev"(the-Xinjection target) and a derivedvar ProviderVersion = ProviderConfigName + "-provider:" + shimVersion; tests switch from exact-literal toHasPrefixshape checks. - Each
Makefile/Dockerfileresolves the module path viago list -m, computes a git-stamp defaultSHIM_VERSION, wires it through-ldflags, and the Dockerfile adds atest -n "${SHIM_VERSION}"guard. - Release workflows pass
SHIM_VERSION=${{ inputs.version }}(a newrelease-vllm-provider.ymlmirrors the dynamo one), andtest.ymlgains a CI step asserting both the git-stamp default and an explicit override land in the binary.
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
providers/*/config.go (5) |
Convert ProviderVersion const to a var derived from build-injected shimVersion. |
providers/*/config_test.go (5) |
Replace exact-version assertions with strings.HasPrefix shape checks. |
providers/*/Makefile (5) |
Resolve MODULE from go.mod, add git-stamp SHIM_VERSION, wire -X flags and docker build-arg. |
providers/*/Dockerfile (5) |
Add ARG SHIM_VERSION + test -n guard, resolve MODULE, inject via -ldflags. |
.github/workflows/release-{dynamo,kaito,kuberay,llmd}-provider.yml |
Pass SHIM_VERSION build-arg from the release version input. |
.github/workflows/release-vllm-provider.yml |
New workflow mirroring dynamo, carrying VLLM_VERSION + SHIM_VERSION. |
.github/workflows/test.yml |
New CI guard asserting shimVersion wiring and git-stamp default. |
The implementation is consistent across all providers: the -X flag correctly targets the unexported shimVersion (not the composite ProviderVersion), Go's init-order ensures ProviderVersion picks up the injected value, and all ProviderVersion usages are runtime contexts so the const→var change is safe. The new vLLM workflow matches the proven dynamo workflow and pinned action SHAs. The only observation is a minor documentation nit about opaque "(decision N)" references in the Makefile comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Each provider shim hard-coded its reported version as a Go `const` in
`config.go`, written verbatim into
`InferenceProviderConfig.status.version`. The const was never bumped at
release, so the reported version lied. Inject it at build time from the
release workflow `version` input — the same value that tags the image —
so `status.version` equals the image tag by construction. Non-release
builds report a git stamp (`dev-<sha>`, `dev-<sha>-dirty`).
Applied across all 5 shims (dynamo, kaito, kuberay, llmd, vllm):
- `config.go`: drop the `ProviderVersion` const; add `var shimVersion =
"dev"` (the `-X` injection target) and derive `var ProviderVersion`
from it. Inject `shimVersion`, never the composite `ProviderVersion`
(a non-constant initializer that `-X` silently no-ops).
- `config_test.go`: replace exact-literal version assertions with
`strings.HasPrefix` shape checks.
- `Makefile`: resolve the module path via `go list -m` so the `-X`
target cannot drift from a hand-typed string; add a git-stamp
`SHIM_VERSION` default; pass `--build-arg SHIM_VERSION` to
`docker-build`. Retrofit dynamo/vllm `DynamoVersion`/`VLLMVersion`
flags onto the computed `$(MODULE)`.
- `Dockerfile`: add `ARG SHIM_VERSION` (no default) plus a `test -n`
guard so a bare `docker build` fails loud instead of shipping `:dev`;
resolve `MODULE` via `go list -m` in the build `RUN`.
CI and release wiring:
- `release-*-provider.yml`: pass `SHIM_VERSION=${{ inputs.version }}` as
a build-arg; add a new `release-vllm-provider.yml` mirroring the
dynamo workflow.
- `test.yml`: assert in `provider-go-checks` that the git-stamp default
and an explicit `SHIM_VERSION` override both land in the built binary.
Signed-off-by: Suraj Deshmukh <suraj.deshmukh@microsoft.com>
70fb715 to
4164b17
Compare
The CI `go version -m` check only proves the `-ldflags -X` flag was *passed* to `go build`, not that the linker *patched* the symbol. Making shimVersion a const, renaming it, or retargeting `ProviderVersion` would keep the flag present but silently no-op the injection, reverting `status.version` to `<name>-provider:dev` with CI still green. - add `TestShimVersionInjection` to all 5 shims: asserts the runtime value of `ProviderVersion` under injection, gated on `EXPECT_PROVIDER_VERSION` so a plain `go test` skips - wire the test into the `provider-go-checks` matrix, built with `-ldflags`, so a silent `-X` no-op now fails CI - harden the git-stamp regex in `test.yml` to tolerate `dev-unknown` (builds outside a git tree, e.g. source tarballs) - document the `shimVersion` / `SHIM_VERSION` contract in `providers/README.md` so a new shim cannot reintroduce the const bug - drop dead `(decision N)` references from all 5 Makefiles and clarify that the repo-wide `git status --porcelain` dirty check is a deliberate conservative superset Signed-off-by: Suraj Deshmukh <suraj.deshmukh@microsoft.com>
Description
Each provider shim hard-coded its reported version as a Go
constinconfig.go, which was written verbatim intoInferenceProviderConfig.status.version(shown bykubectl, the Web UI, and the Headlamp plugin). The const was never bumped at release time, so the reported version lied.This PR injects the shim version at build time from the release workflow's
versioninput — the same value that tags the image — sostatus.versionequals the image tag by construction. Non-release builds report a git-derived dev stamp (dev-<sha>, ordev-<sha>-dirtywhen the tree is dirty). The anti-pattern existed in all 5 shims:dynamo,kaito,kuberay,llmd,vllm.Visual Representation of the change
https://suraj.io/share/prs/github.com/kaito-project/airunway/pull/338/dashboard.html
Type of Change
Related Issues
Fixes #309
Changes Made
Go source —
providers/<p>/config.go(all 5)ProviderVersionconst(keptProviderConfigNameas a const).var shimVersion = "dev"as the build-time-ldflags -Xinjection target, and derivedvar ProviderVersion = ProviderConfigName + "-provider:" + shimVersion.shimVersion(a constant-string initializer), never the compositeProviderVersion—-Xsilently no-ops on a non-constant initializer.shimVersionstays unexported;-Xresolves the linker symbol regardless of Go visibility.Tests —
providers/<p>/config_test.go(all 5)strings.HasPrefix(ProviderVersion, "<name>-provider:")shape checks, so the test no longer needs lockstep edits.dynamo/kaito/kuberayedited their existingTestProviderConstantsin place;llmd/vllmgained a newTestProviderConstants(and a"strings"import) asserting bothProviderConfigNameand the version shape.providers/<p>/Makefile(all 5)MODULE := $(shell go list -m)so the-Xtarget can never drift from a hand-typed string.SHIM_VERSION ?= dev-$(GIT_SHA)$(GIT_DIRTY)(bin/provideris gitignored, so building never dirties the tree).-Xflag through$(MODULE);dynamo/vllmretrofit their existingDynamoVersion/VLLMVersionflags onto it.--build-arg SHIM_VERSION=$(SHIM_VERSION)is now passed to everydocker-build.providers/<p>/Dockerfile(all 5)ARG SHIM_VERSIONwith no default plus aRUN test -n "${SHIM_VERSION}"guard, mirroring the existingDYNAMO_VERSION/VLLM_VERSIONtreatment, so a hand-rundocker buildfails loud instead of silently shipping:dev.RUNresolvesMODULE=$(go list -m)and injects via${MODULE};dynamo/vllmretrofit their existing-Xflags (preserving-aand vllm's-mod=readonly).Release workflows —
.github/workflows/release-<p>-provider.ymldynamo/kaito/kuberay/llmd: passSHIM_VERSION=${{ inputs.version }}as a build-arg (the same value that tags the image).release-vllm-provider.ymlmirroringrelease-dynamo-provider.yml, carrying bothVLLM_VERSION(fromversions.env) andSHIM_VERSION.CI anti-regression guard —
.github/workflows/test.ymlprovider-go-checksmatrix (betweenmake buildandmake test) that reads the binary back withgo version -mto assert both the git-stamp default and an explicitSHIM_VERSIONoverride land — guarding against future wiring/symbol drift.Testing
bun run test)This change is Go/build-tooling only and does not touch the frontend/backend TypeScript, so
bun run testis not the relevant suite. Every check below is copy-pasteable from the repo root.1. Go unit + shape tests —
make -C providers/<p> test(vet +go test) passes for all 5, exercising the newTestProviderConstantsshape assertion. The second loop proves the bare fallback (no-ldflags) resolves to exactly<name>-provider:dev:2. Injection works —
go list -mmakes the-Xtarget correct-by-construction; this proves the symbol actually resolves soProviderVersionbecomes<name>-provider:v9.9.9for all 5 (also confirms theshimVersion→ProviderVersioninit-ordering):3. Real image build (
kuberay) — build the image with the release-style arg, then read the version baked into the binary inside the image. It must reportshimVersion=v0.6.0, sostatus.versionreadskuberay-provider:v0.6.0— matching the image tag by construction:4. Negative guard check —
make docker-buildalways injects the arg, so the missing-arg case must be exercised with a rawdocker build. With noSHIM_VERSION, theRUN test -nguard fails the build loud instead of silently shipping:dev:5. Repo guards — confirm no new version source was introduced; both still pass:
6. CI read-back step, run locally — mirrors the new
provider-go-checksstep for all 5: (a) the un-overriddenmake buildused the Makefile git-stamp default, and (b) an explicit override injects. (CI checkout is clean, so the stamp isdev-<sha>; the regex also allows-dirtyfor local trees.)Checklist
bun run lintAdditional Notes
dynamo-provider:v0.2.0examples indocs/api.md/docs/crd-reference.mdare shape examples, not assertions, and nothing tests them — any literal replacement would just re-stale, so they were left as-is.versions.env/verify-versionswiring for the shim version — there is no committed source of truth for it (unlikeDYNAMO_VERSION/VLLM_VERSION); the release tag is the source of truth, injected at build time.actionlintto CI. Release workflows areworkflow_dispatch-only and never lint in PR CI, so the hand-authoredrelease-vllm-provider.ymlcurrently relies on the Dockerfiletest -nguard as the release-time backstop.actionlintvalidates syntax/shape, not semantic completeness (it won't catch a missing build-arg), so it complements rather than replaces the guard.