Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 35 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,13 @@ jobs:
- name: Build Desktop App
working-directory: ./desktop
run: |
wails build -platform darwin/amd64 -clean
# Stamp the same build info the CLI gets from GoReleaser.
VERSION=${GITHUB_REF#refs/tags/v}
BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
LDFLAGS="-X github.com/ganbitlabs/walgo/internal/buildinfo.version=${VERSION}"
LDFLAGS="${LDFLAGS} -X github.com/ganbitlabs/walgo/internal/buildinfo.commit=${GITHUB_SHA}"
LDFLAGS="${LDFLAGS} -X github.com/ganbitlabs/walgo/internal/buildinfo.buildDate=${BUILD_DATE}"
wails build -platform darwin/amd64 -clean -ldflags "$LDFLAGS"

- name: Sign and Package App
working-directory: ./desktop/build/bin
Expand Down Expand Up @@ -121,7 +127,13 @@ jobs:
- name: Build Desktop App
working-directory: ./desktop
run: |
wails build -platform darwin/arm64 -clean
# Stamp the same build info the CLI gets from GoReleaser.
VERSION=${GITHUB_REF#refs/tags/v}
BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
LDFLAGS="-X github.com/ganbitlabs/walgo/internal/buildinfo.version=${VERSION}"
LDFLAGS="${LDFLAGS} -X github.com/ganbitlabs/walgo/internal/buildinfo.commit=${GITHUB_SHA}"
LDFLAGS="${LDFLAGS} -X github.com/ganbitlabs/walgo/internal/buildinfo.buildDate=${BUILD_DATE}"
wails build -platform darwin/arm64 -clean -ldflags "$LDFLAGS"

- name: Sign and Package App
working-directory: ./desktop/build/bin
Expand Down Expand Up @@ -173,7 +185,13 @@ jobs:
- name: Build Desktop App
working-directory: ./desktop
run: |
wails build -platform windows/amd64 -clean
# Stamp the same build info the CLI gets from GoReleaser.
VERSION=${GITHUB_REF#refs/tags/v}
BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
LDFLAGS="-X github.com/ganbitlabs/walgo/internal/buildinfo.version=${VERSION}"
LDFLAGS="${LDFLAGS} -X github.com/ganbitlabs/walgo/internal/buildinfo.commit=${GITHUB_SHA}"
LDFLAGS="${LDFLAGS} -X github.com/ganbitlabs/walgo/internal/buildinfo.buildDate=${BUILD_DATE}"
wails build -platform windows/amd64 -clean -ldflags "$LDFLAGS"

- name: Package App
working-directory: ./desktop/build/bin
Expand Down Expand Up @@ -218,7 +236,13 @@ jobs:
- name: Build Desktop App
working-directory: ./desktop
run: |
wails build -platform windows/arm64 -clean
# Stamp the same build info the CLI gets from GoReleaser.
VERSION=${GITHUB_REF#refs/tags/v}
BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
LDFLAGS="-X github.com/ganbitlabs/walgo/internal/buildinfo.version=${VERSION}"
LDFLAGS="${LDFLAGS} -X github.com/ganbitlabs/walgo/internal/buildinfo.commit=${GITHUB_SHA}"
LDFLAGS="${LDFLAGS} -X github.com/ganbitlabs/walgo/internal/buildinfo.buildDate=${BUILD_DATE}"
wails build -platform windows/arm64 -clean -ldflags "$LDFLAGS"

- name: Package App
working-directory: ./desktop/build/bin
Expand Down Expand Up @@ -268,7 +292,13 @@ jobs:
- name: Build Desktop App
working-directory: ./desktop
run: |
wails build -platform linux/amd64 -clean
# Stamp the same build info the CLI gets from GoReleaser.
VERSION=${GITHUB_REF#refs/tags/v}
BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
LDFLAGS="-X github.com/ganbitlabs/walgo/internal/buildinfo.version=${VERSION}"
LDFLAGS="${LDFLAGS} -X github.com/ganbitlabs/walgo/internal/buildinfo.commit=${GITHUB_SHA}"
LDFLAGS="${LDFLAGS} -X github.com/ganbitlabs/walgo/internal/buildinfo.buildDate=${BUILD_DATE}"
wails build -platform linux/amd64 -clean -ldflags "$LDFLAGS"

- name: Package App
working-directory: ./desktop/build/bin
Expand Down
8 changes: 5 additions & 3 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ builds:
- amd64
- arm64
# All OS + all architectures supported
# main only holds func main(); the version lives in internal/buildinfo, which
# the CLI, the API and the desktop app all read.
ldflags:
- -s -w
- -X main.version={{.Version}}
- -X main.commit={{.Commit}}
- -X main.date={{.Date}}
- -X github.com/ganbitlabs/walgo/internal/buildinfo.version={{.Version}}
- -X github.com/ganbitlabs/walgo/internal/buildinfo.commit={{.FullCommit}}
- -X github.com/ganbitlabs/walgo/internal/buildinfo.buildDate={{.Date}}

archives:
- id: walgo-archives
Expand Down
17 changes: 10 additions & 7 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ import (
"strings"
"time"

"github.com/ganbitlabs/walgo/internal/buildinfo"
"github.com/ganbitlabs/walgo/internal/ui"
"github.com/spf13/cobra"
)

// Build details, resolved from ldflags or the embedded build info.
// See internal/buildinfo.
var (
// Version will be set during build time via ldflags
Version = "0.4.0"
// GitCommit will be set during build time via ldflags
GitCommit = "dev"
// BuildDate will be set during build time via ldflags
BuildDate = "unknown"
Version = buildinfo.Version()
GitCommit = buildinfo.Commit()
BuildDate = buildinfo.BuildDate()
)

const (
Expand Down Expand Up @@ -121,7 +121,10 @@ func checkForUpdates() {
func compareSemver(a, b string) int {
parse := func(input string) [3]int {
var result [3]int
clean := strings.SplitN(input, "-", 2)[0]
// Drop pre-release ("-rc1") and build metadata ("+dirty"), which the
// build-info fallback appends when the working tree was modified.
clean, _, _ := strings.Cut(input, "-")
clean, _, _ = strings.Cut(clean, "+")
parts := strings.Split(clean, ".")
for i := 0; i < len(result) && i < len(parts); i++ {
if n, err := strconv.Atoi(parts[i]); err == nil {
Expand Down
108 changes: 108 additions & 0 deletions internal/buildinfo/buildinfo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Package buildinfo is the single source of the version reported by the CLI,
// the API and the desktop app.
package buildinfo

import (
"runtime/debug"
"strings"
"time"
)

// Values injected at build time. GoReleaser and the desktop build set these
// through -X flags; see .goreleaser.yml and .github/workflows/release.yml.
//
// Keep releaseVersion in sync with the current release: it is what a plain
// `go build ./...` reports, and what tags are cut from.
var (
version string
commit string
buildDate string
)

const (
releaseVersion = "0.4.0"
unknownCommit = "dev"
unknownDate = "unknown"
)

// Version returns the release version, without a leading "v".
func Version() string {
if version != "" {
return strings.TrimPrefix(version, "v")
}

// `go install github.com/ganbitlabs/walgo@v1.2.3` records the version in the
// build info even though no ldflags were passed.
if info, ok := debug.ReadBuildInfo(); ok {
if v := info.Main.Version; v != "" && v != "(devel)" {
return strings.TrimPrefix(v, "v")
}
}

return releaseVersion
}

// Commit returns the git revision the binary was built from, suffixed with
// "-dirty" when the working tree had uncommitted changes.
func Commit() string {
if commit != "" {
return commit
}

revision, modified := vcsInfo()
if revision == "" {
return unknownCommit
}
if modified {
return revision + "-dirty"
}

return revision
}

// BuildDate returns when the binary was built, in RFC 3339 form.
func BuildDate() string {
if buildDate != "" {
return buildDate
}

if _, _, buildTime := vcsSettings(); buildTime != "" {
return buildTime
}

return unknownDate
}

// vcsInfo reports the revision recorded by the Go toolchain and whether the
// working tree was dirty. Both are empty for builds outside a repository.
func vcsInfo() (revision string, modified bool) {
revision, dirty, _ := vcsSettings()
return revision, dirty == "true"
}

// vcsSettings extracts the vcs.* build settings the toolchain stamps into
// binaries built from a repository.
func vcsSettings() (revision, modified, buildTime string) {
info, ok := debug.ReadBuildInfo()
if !ok {
return "", "", ""
}

for _, setting := range info.Settings {
switch setting.Key {
case "vcs.revision":
revision = setting.Value
case "vcs.modified":
modified = setting.Value
case "vcs.time":
// Normalize so it matches the format used by the ldflags path.
if parsed, err := time.Parse(time.RFC3339, setting.Value); err == nil {
buildTime = parsed.UTC().Format(time.RFC3339)
} else {
buildTime = setting.Value
}
}
}

return revision, modified, buildTime
}
71 changes: 71 additions & 0 deletions internal/buildinfo/buildinfo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package buildinfo

import (
"strings"
"testing"
)

func TestVersionPrefersLdflags(t *testing.T) {
defer restore(version, commit, buildDate)

version = "v1.2.3"
if got := Version(); got != "1.2.3" {
t.Errorf("Version() = %q, want 1.2.3 (leading v stripped)", got)
}
}

func TestVersionFallsBack(t *testing.T) {
defer restore(version, commit, buildDate)

version = ""
got := Version()
if got == "" {
t.Fatal("Version() is empty without ldflags")
}
if strings.HasPrefix(got, "v") {
t.Errorf("Version() = %q, should not carry a leading v", got)
}
}

func TestCommitPrefersLdflags(t *testing.T) {
defer restore(version, commit, buildDate)

commit = "abc1234"
if got := Commit(); got != "abc1234" {
t.Errorf("Commit() = %q, want abc1234", got)
}
}

func TestCommitFallsBack(t *testing.T) {
defer restore(version, commit, buildDate)

commit = ""
// Tests build from the repository, so the toolchain stamps a revision; a
// build from outside one reports the placeholder instead.
if got := Commit(); got == "" {
t.Error("Commit() is empty without ldflags")
}
}

func TestBuildDatePrefersLdflags(t *testing.T) {
defer restore(version, commit, buildDate)

buildDate = "2026-08-01T00:00:00Z"
if got := BuildDate(); got != "2026-08-01T00:00:00Z" {
t.Errorf("BuildDate() = %q", got)
}
}

func TestBuildDateFallsBack(t *testing.T) {
defer restore(version, commit, buildDate)

buildDate = ""
if got := BuildDate(); got == "" {
t.Error("BuildDate() is empty without ldflags")
}
}

// restore puts the injected build values back after a test mutates them.
func restore(v, c, d string) {
version, commit, buildDate = v, c, d
}
7 changes: 4 additions & 3 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"time"

"github.com/ganbitlabs/walgo/internal/ai"
"github.com/ganbitlabs/walgo/internal/buildinfo"
"github.com/ganbitlabs/walgo/internal/compress"
"github.com/ganbitlabs/walgo/internal/config"
"github.com/ganbitlabs/walgo/internal/deployer"
Expand Down Expand Up @@ -560,9 +561,9 @@ type VersionResult struct {
// GetVersion returns current version information
func GetVersion() VersionResult {
return VersionResult{
Version: "0.4.0",
GitCommit: "dev",
BuildDate: "unknown",
Version: buildinfo.Version(),
GitCommit: buildinfo.Commit(),
BuildDate: buildinfo.BuildDate(),
}
}

Expand Down
Loading