Skip to content

feat: add eko version command with runtime & git commit details - #184

Merged
kavix merged 1 commit into
kavix:mainfrom
vsolano9:feat/78-version-command
Aug 26, 2026
Merged

feat: add eko version command with runtime & git commit details#184
kavix merged 1 commit into
kavix:mainfrom
vsolano9:feat/78-version-command

Conversation

@vsolano9

Copy link
Copy Markdown
Contributor

Description

Adds an eko version subcommand and the matching -v / --version flags on the root command. Both print the CLI version, target OS/architecture, Go runtime version, Git commit, and build date.

eko version 1.1.0 (darwin/arm64)
Go version: go1.26.7
Git commit: 8c9d1a2f
Build date: 2026-08-26T08:22:00Z

What changed

  • cmd/version.go (new) — defines the Cobra versionCmd and the Version, Commit, BuildDate package variables that are stamped at release time via -ldflags. A single formatVersion helper renders the banner so the subcommand and the root flags can never drift apart.
  • cmd/root.go — wires Version onto rootCmd, sets a custom version template, and registers the -v / --version flags. Keeping the flag wiring in root.go matches the issue's implementation steps and keeps root-command configuration in one place.
  • .goreleaser.yaml — injects the release version, commit, and date through the Go linker so published archives report real metadata instead of dev.
  • cmd/commands_test.go — unit/integration tests, added to the existing CLI test file as the issue specifies.
  • README.md, docs/docs/cli-reference.md — document the command, the flags, and the ldflags build recipe.

Why the dev / unknown defaults

The variables default to dev and unknown, and formatVersion also substitutes those placeholders if a linker flag injects an empty string. That means a plain go build ./... (or the Dockerfile build, which does not pass -X flags) never prints blank fields. This is covered by a dedicated regression test.

Note on -v: -v was previously free on the root command. It is already used as a subcommand-local shorthand in eko diff -v (--full) and eko history -v (--verbose); those are unaffected because the new flag is registered on the root command's own flag set, not as a persistent flag. Verified by the full test suite, which includes the existing diff/history tests.

Related Issues

Closes #78

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring / Code quality improvement

Technical Details & Architecture Notes

No concurrency or database changes. The only design decisions worth flagging:

  1. Single source of truth for the banner. formatVersion(version, commit, buildDate) is used both by versionCmd.RunE and by rootCmd.SetVersionTemplate(...), so eko version, eko -v, and eko --version are byte-identical by construction. A test asserts that equality rather than trusting it.
  2. Output goes to cmd.OutOrStdout(), matching the existing command style and making the subcommand testable through the repo's existing executeCommand test helper.
  3. cobra.NoArgs so eko version extra fails loudly instead of silently ignoring input.
  4. Root-flag scope. The -v shorthand is registered with rootCmd.Flags() (local), not PersistentFlags(), deliberately avoiding a collision with the existing -v shorthands on eko diff and eko history.

How Has This Been Tested?

Automated tests added to cmd/commands_test.go: banner formatting, empty-metadata fallback, default build metadata, the subcommand, argument rejection, and -v/--version parity with the subcommand.

gofmt (only the files touched by this PR; unrelated pre-existing files are untouched):

$ gofmt -l cmd/version.go cmd/root.go cmd/commands_test.go
$ 

go build ./... and go vet ./...:

$ go build ./...
$ go vet ./...
$

go test ./... (full suite):

$ go test ./...
?       eko     [no test files]
ok      eko/cmd 1.028s
ok      eko/internal/ai 1.172s
?       eko/internal/ai/mind    [no test files]
ok      eko/internal/api        2.550s
?       eko/internal/cache      [no test files]
ok      eko/internal/db 0.435s
ok      eko/internal/manifest   2.238s
ok      eko/internal/notify     1.936s
ok      eko/internal/objects    3.196s
ok      eko/internal/snapshot   0.755s
ok      eko/internal/telemetry  1.663s
ok      eko/internal/util       2.908s

New tests, verbose:

$ go test ./cmd/ -run 'Version' -v
=== RUN   TestFormatVersion
--- PASS: TestFormatVersion (0.00s)
=== RUN   TestFormatVersion_blankBuildMetadataFallsBackToPlaceholders
--- PASS: TestFormatVersion_blankBuildMetadataFallsBackToPlaceholders (0.00s)
=== RUN   TestVersionCommand_defaultBuildMetadata
--- PASS: TestVersionCommand_defaultBuildMetadata (0.00s)
=== RUN   TestVersionCommand
--- PASS: TestVersionCommand (0.00s)
=== RUN   TestVersionCommand_rejectsArguments
--- PASS: TestVersionCommand_rejectsArguments (0.00s)
=== RUN   TestVersionFlags_matchVersionSubcommand
=== RUN   TestVersionFlags_matchVersionSubcommand/--version
=== RUN   TestVersionFlags_matchVersionSubcommand/-v
--- PASS: TestVersionFlags_matchVersionSubcommand (0.00s)
    --- PASS: TestVersionFlags_matchVersionSubcommand/--version (0.00s)
    --- PASS: TestVersionFlags_matchVersionSubcommand/-v (0.00s)
PASS
ok      eko/cmd 0.347s

Manual verification — un-stamped build (what a contributor's go build produces):

$ go build -o /tmp/eko-plain .
$ /tmp/eko-plain version
eko version dev (darwin/arm64)
Go version: go1.26.7
Git commit: unknown
Build date: unknown

$ /tmp/eko-plain -v
eko version dev (darwin/arm64)
Go version: go1.26.7
Git commit: unknown
Build date: unknown

$ /tmp/eko-plain --version
eko version dev (darwin/arm64)
Go version: go1.26.7
Git commit: unknown
Build date: unknown

$ /tmp/eko-plain version extra
Error: unknown command "extra" for "eko version"
$ echo $?
1

Manual verification — ldflags path, using the exact variable paths from .goreleaser.yaml:

$ go build -ldflags "-s -w -X eko/cmd.Version=1.1.0 -X eko/cmd.Commit=8c9d1a2f -X eko/cmd.BuildDate=2026-08-26T08:22:00Z" -o /tmp/eko-stamped .
$ /tmp/eko-stamped version
eko version 1.1.0 (darwin/arm64)
Go version: go1.26.7
Git commit: 8c9d1a2f
Build date: 2026-08-26T08:22:00Z

$ /tmp/eko-stamped -v
eko version 1.1.0 (darwin/arm64)
Go version: go1.26.7
Git commit: 8c9d1a2f
Build date: 2026-08-26T08:22:00Z

$ /tmp/eko-stamped --version
eko version 1.1.0 (darwin/arm64)
Go version: go1.26.7
Git commit: 8c9d1a2f
Build date: 2026-08-26T08:22:00Z

Help output confirms discoverability:

$ /tmp/eko-stamped --help
eko – AI Snapshot Versioning CLI

Usage:
  eko [command]

Available Commands:
  ...
  version     Print version, runtime and build information

Flags:
  -h, --help      help for eko
  -v, --version   print version, runtime and build information

Checklist

  • My code follows the style guidelines of this project (run gofmt and go vet)
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (including README.md and CONTRIBUTING.md)
  • My changes generate no new compiler or linter warnings
  • I have added/updated unit tests that prove my fix is effective or that my feature works
  • All new and existing unit tests pass locally with my changes

One thing for a maintainer to confirm: the sample output in the issue shows three lines; this implementation adds a fourth, Build date:, since the issue's implementation steps ask for a BuildDate variable. Happy to drop that line from the banner (keeping the variable for GoReleaser) if you prefer to match the issue's sample exactly.

Adds an `eko version` subcommand and matching `-v` / `--version` root
flags that report the CLI version, Go runtime version, target OS/arch,
Git commit, and build date.

- cmd/version.go: `versionCmd` plus the `Version`, `Commit` and
  `BuildDate` variables stamped via `-ldflags` at release time. A shared
  `formatVersion` helper renders the banner so the subcommand and the
  root flags cannot drift apart.
- cmd/root.go: wires `Version` and a custom version template into the
  root command and registers the `-v` / `--version` flags.
- .goreleaser.yaml: injects the release version, commit and date through
  the Go linker so published archives report real metadata.
- Build metadata falls back to `dev` / `unknown` when it is not stamped
  (and when a linker flag injects an empty string), so a plain
  `go build` never prints blank fields.
- cmd/commands_test.go: covers the banner format, the empty-metadata
  fallback, the subcommand, argument rejection, and `-v` / `--version`
  parity with the subcommand.
- Documents the command in README.md and docs/docs/cli-reference.md.

Closes kavix#78
@vercel

vercel Bot commented Aug 26, 2026

Copy link
Copy Markdown

@vsolano9 is attempting to deploy a commit to the Kavindu's projects Team on Vercel.

A member of the Team first needs to authorize it.

@kavix
kavix self-requested a review August 26, 2026 12:23
@kavix kavix self-assigned this Aug 26, 2026
@kavix kavix added the good first issue Good for newcomers label Aug 26, 2026
@kavix kavix added this to the 1.5 milestone Aug 26, 2026
@kavix
kavix merged commit 1096cfa into kavix:main Aug 26, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

good first issue Good for newcomers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Add 'eko version' command with runtime & git commit details

2 participants