Skip to content

add BuildDate to version#293

Merged
kindermax merged 1 commit intomasterfrom
add-build-date-to---version
Mar 13, 2026
Merged

add BuildDate to version#293
kindermax merged 1 commit intomasterfrom
add-build-date-to---version

Conversation

@kindermax
Copy link
Copy Markdown
Collaborator

@kindermax kindermax commented Mar 13, 2026

Summary by Sourcery

Add build date metadata to the lets binary and include it in the version output when provided.

New Features:

  • Display the build date alongside the version in the CLI version output when available.

Enhancements:

  • Pass build date through the root command using Cobra annotations to support version message formatting.

Build:

  • Inject BuildDate via ldflags in GoReleaser configuration and local build commands to embed build time into the binary.

Tests:

  • Extend version tests to cover build date output and update config version tests to build binaries with a fixed build date.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Mar 13, 2026

Reviewer's Guide

Adds build date metadata to the lets binary, wires it through the root command via Cobra annotations, adjusts build tooling to set it via ldflags, and updates tests to validate the new version output format.

Sequence diagram for version command with BuildDate annotation

sequenceDiagram
    actor User
    participant Shell
    participant Main as main
    participant CmdPkg as internal_cmd
    participant RootCmd as cobra_Command

    User->>Shell: lets --version
    Shell->>Main: start process
    Main->>CmdPkg: CreateRootCommand(Version, BuildDate)
    CmdPkg->>RootCmd: newRootCmd(Version)
    CmdPkg->>RootCmd: set Annotations[buildDate] = BuildDate
    CmdPkg-->>Main: *cobra_Command
    Main->>RootCmd: Execute()
    RootCmd->>RootCmd: detect --version flag
    RootCmd->>CmdPkg: PrintVersionMessage(cmd)
    CmdPkg->>CmdPkg: msg = sprintf("lets version %s", cmd.Version)
    CmdPkg->>CmdPkg: buildDate = cmd.Annotations[buildDate]
    CmdPkg->>CmdPkg: if buildDate != "" then append " (buildDate)"
    CmdPkg->>RootCmd: Fprintln(cmd.OutOrStdout(), msg)
    RootCmd-->>User: print version with optional build date
Loading

Class diagram for main and root command with BuildDate

classDiagram
    class main {
        +string Version
        +string BuildDate
        +main()
        -getContext() Context
    }

    class internal_cmd_Root {
        +CreateRootCommand(version string, buildDate string) *cobra_Command
        +PrintRootHelpMessage(cmd *cobra_Command) error
        +PrintVersionMessage(cmd *cobra_Command) error
        -newRootCmd(version string) *cobra_Command
        -initRootFlags(cmd *cobra_Command)
    }

    class cobra_Command {
        +string Version
        +map~string,string~ Annotations
        +io_Writer OutOrStdout()
        +Execute() error
    }

    main --> internal_cmd_Root : calls CreateRootCommand
    internal_cmd_Root --> cobra_Command : constructs and configures
    cobra_Command ..> internal_cmd_Root : uses PrintVersionMessage for --version
Loading

File-Level Changes

Change Details Files
Propagate build date into the root Cobra command and version output.
  • Extend CreateRootCommand to accept a buildDate parameter.
  • Store the build date in the root command annotations under the key "buildDate".
  • Update PrintVersionMessage to append the build date to the version string when present, using the format: "lets version ()".
  • Switch PrintVersionMessage to use fmt.Fprintln with the constructed message string.
internal/cmd/root.go
Update tests to cover the new build date behavior and API.
  • Load shared Bats test helpers and define TEST_VERSION and TEST_BUILD_DATE constants.
  • Add a Bats test building lets with both Version and BuildDate ldflags and asserting the version output includes the build date.
  • Adjust Go tests creating root commands to pass an empty buildDate argument.
  • Update config_version Bats test build to set a fixed BuildDate ldflag for consistency.
tests/version.bats
internal/cmd/root_test.go
tests/config_version.bats
Wire BuildDate variable through the main entrypoint.
  • Introduce a global BuildDate variable with default empty value.
  • Pass BuildDate into CreateRootCommand so it can be surfaced in version output.
cmd/lets/main.go
Ensure release and dev builds set BuildDate via ldflags.
  • Extend GoReleaser ldflags to set main.BuildDate using the template value {{.Date}} for all build targets.
  • Update lets.yaml dev build commands to include main.BuildDate ldflag computed from the current UTC time in ISO-8601 format.
.goreleaser.yml
lets.yaml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@kindermax kindermax force-pushed the add-build-date-to---version branch 2 times, most recently from 5f20567 to 20743cb Compare March 13, 2026 18:59
Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="internal/cmd/root_test.go" line_range="14" />
<code_context>

 func newTestRootCmd(args []string) (rootCmd *cobra.Command) {
-	root := CreateRootCommand("v0.0.0-test")
+	root := CreateRootCommand("v0.0.0-test", "")
 	root.SetArgs(args)
 	InitCompletionCmd(root, nil)
</code_context>
<issue_to_address>
**suggestion (testing):** Add a unit test covering PrintVersionMessage with a non-empty build date

Right now all Go tests call `CreateRootCommand` with an empty build date, so the code path that formats `"lets version %s (%s)"` is only exercised by Bats. Please add a unit test that constructs a root command with a non-empty build date (e.g. `CreateRootCommand("v0.0.0-test", "2024-01-15T10:30:00Z")`), calls `PrintVersionMessage`, and asserts the output includes the date in parentheses.

Suggested implementation:

```golang
)

func TestPrintVersionMessage_WithBuildDate(t *testing.T) {
	bufOut := &bytes.Buffer{}

	root := CreateRootCommand("v0.0.0-test", "2024-01-15T10:30:00Z")
	root.SetOut(bufOut)

	PrintVersionMessage(root)

	got := bufOut.String()
	expectedSubstring := "lets version v0.0.0-test (2024-01-15T10:30:00Z)"
	if !strings.Contains(got, expectedSubstring) {
		t.Fatalf("expected version output %q to contain %q", got, expectedSubstring)
	}
}

```

```golang
import (
	"bytes"
	"strings"

```

Because I can only see part of `internal/cmd/root_test.go`, please double-check:
1. The `import` block: ensure `bytes` and `strings` are not already imported to avoid duplicates. If `import (` already exists with other imports, merge these two into that block instead of creating a new one.
2. The function name `PrintVersionMessage` and its signature: if it requires additional parameters (e.g. context or writer), adapt the test to call it correctly while still setting `root.SetOut(bufOut)` so the message is captured in `bufOut`.
3. If the existing tests construct the root command or capture output in a helper (e.g. `newTestRootCmd` or a shared `bufOut`), you may want to reuse that helper to be consistent with the rest of the test suite.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 13, 2026

Greptile Summary

This PR adds a BuildDate field to the lets --version output. When built via GoReleaser or the local dev build commands, the binary is stamped with an ISO 8601 UTC timestamp using -X main.BuildDate=... ldflags; for non-stamped dev builds the field is an empty string and is silently omitted.

Key changes:

  • cmd/lets/main.go: Declares var BuildDate = "" and threads it into CreateRootCommand.
  • internal/cmd/root.go: CreateRootCommand now accepts buildDate, stores it in rootCmd.Annotations["buildDate"], and PrintVersionMessage appends (date) to the version string when non-empty.
  • .goreleaser.yml: All three build targets (darwin-amd64, darwin-arm64, linux-amd64) updated with -X main.BuildDate={{.Date}}.
  • lets.yaml: Both local build commands embed the current UTC time via $(date -u +%Y-%m-%dT%H:%M:%SZ).
  • tests/version.bats: New integration test builds a temporary binary with explicit ldflags and verifies the full version string including the date; uses a hardcoded /tmp/lets-version-test path that could conflict in parallel CI runs.

Confidence Score: 5/5

  • This PR is safe to merge; the changes are additive, well-scoped, and all existing call sites are correctly updated.
  • The change is purely additive — a new optional field appended to version output. All callers of CreateRootCommand are updated, the empty-string default preserves existing behaviour for dev builds, and integration tests validate the new output format. The only minor concern is the hardcoded /tmp path in the new BATS test.
  • tests/version.bats — hardcoded /tmp/lets-version-test path could cause flakiness in parallel CI runs.

Important Files Changed

Filename Overview
.goreleaser.yml Added -X main.BuildDate={{.Date}} to ldflags for all three build targets (darwin-amd64, darwin-arm64, linux-amd64). All targets are consistently updated.
cmd/lets/main.go Added var BuildDate = "" package-level variable and passes it to CreateRootCommand. The empty default correctly results in no build date being shown for dev builds.
internal/cmd/root.go Updated CreateRootCommand to accept buildDate, stored in rootCmd.Annotations. PrintVersionMessage conditionally appends the date only when non-empty. Implementation is clean and correct.
internal/cmd/root_test.go All call sites of CreateRootCommand updated to pass "" as the second argument. No new unit tests for PrintVersionMessage with a non-empty build date, but integration coverage is added in tests/version.bats.
lets.yaml Updated two local go build invocations to embed the current UTC timestamp via $(date -u +%Y-%m-%dT%H:%M:%SZ). Consistent with the goreleaser format.
tests/config_version.bats Updated the go build in setup to pass a hardcoded BuildDate=2024-01-01T00:00:00Z. This doesn't affect config-version test assertions which don't inspect build date.
tests/version.bats Added a new integration test for build date display with ldflags. The test binary is written to a hardcoded /tmp/lets-version-test path, which could conflict in parallel CI runs.

Sequence Diagram

sequenceDiagram
    participant User
    participant main as cmd/lets/main.go
    participant root as internal/cmd/root.go

    Note over main: var Version = "0.0.0-dev"<br/>var BuildDate = "" (or injected via ldflags)

    main->>root: CreateRootCommand(Version, BuildDate)
    root->>root: newRootCmd(version)
    root->>root: rootCmd.Annotations["buildDate"] = buildDate
    root-->>main: rootCmd

    User->>main: lets --version
    main->>root: PrintVersionMessage(rootCmd)
    root->>root: msg = "lets version " + cmd.Version
    alt buildDate != ""
        root->>root: msg += " (" + buildDate + ")"
    end
    root-->>User: "lets version 1.2.3 (2024-01-15T10:30:00Z)"
Loading

Last reviewed commit: 20743cb

Comment on lines +24 to +28
go build -ldflags="-X main.Version=${TEST_VERSION} -X main.BuildDate=${TEST_BUILD_DATE}" -o /tmp/lets-version-test cmd/lets/main.go
run /tmp/lets-version-test --version
assert_success
assert_line --index 0 "lets version ${TEST_VERSION} (${TEST_BUILD_DATE})"
rm -f /tmp/lets-version-test
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded /tmp path may fail in parallel CI runs

The test binary is written to /tmp/lets-version-test, a shared path across all processes. If this test suite runs concurrently (e.g., multiple CI jobs on the same runner), two jobs could race on the same file — one deleting it while the other is trying to use it, or one overwriting the binary during another's execution.

Consider using a unique temp path, such as one derived from $BATS_TMPDIR (provided by the BATS framework), which is isolated per test run:

Suggested change
go build -ldflags="-X main.Version=${TEST_VERSION} -X main.BuildDate=${TEST_BUILD_DATE}" -o /tmp/lets-version-test cmd/lets/main.go
run /tmp/lets-version-test --version
assert_success
assert_line --index 0 "lets version ${TEST_VERSION} (${TEST_BUILD_DATE})"
rm -f /tmp/lets-version-test
go build -ldflags="-X main.Version=${TEST_VERSION} -X main.BuildDate=${TEST_BUILD_DATE}" -o "${BATS_TMPDIR}/lets-version-test" cmd/lets/main.go
run "${BATS_TMPDIR}/lets-version-test" --version
assert_success
assert_line --index 0 "lets version ${TEST_VERSION} (${TEST_BUILD_DATE})"
rm -f "${BATS_TMPDIR}/lets-version-test"

@kindermax kindermax force-pushed the add-build-date-to---version branch from 20743cb to d6cae4f Compare March 13, 2026 19:28
@kindermax kindermax merged commit 2236cea into master Mar 13, 2026
5 checks passed
@kindermax kindermax deleted the add-build-date-to---version branch March 13, 2026 19:37
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.

1 participant