Skip to content
Open
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
2 changes: 1 addition & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ builds:
flags:
- -trimpath
ldflags:
- -s -w -X github.com/ustclug/rsync-proxy/pkg/info.Version={{.Version}} -X github.com/ustclug/rsync-proxy/pkg/info.BuildDate={{.Date}} -X github.com/ustclug/rsync-proxy/pkg/info.GitCommit={{.Commit}}
- -s -w -X github.com/ustclug/rsync-proxy/cmd.Version={{.Version}} -X github.com/ustclug/rsync-proxy/cmd.BuildDate={{.Date}} -X github.com/ustclug/rsync-proxy/cmd.GitCommit={{.Commit}}
archives:
- formats: binary
name_template: "{{ .Binary }}_{{ .Os }}_{{ .Arch }}"
Expand Down
53 changes: 53 additions & 0 deletions cmd/cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package cmd

import (
"bytes"
"encoding/json"
"runtime"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestPrintVersionReportsLinkerInjectedValues(t *testing.T) {
originalVersion := Version
originalCommit := GitCommit
originalBuildDate := BuildDate
t.Cleanup(func() {
Version = originalVersion
GitCommit = originalCommit
BuildDate = originalBuildDate
})

Version = "9.9.9"
GitCommit = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
BuildDate = "2026-05-26T15:23:43Z"

var buf bytes.Buffer
require.NoError(t, printVersion(&buf, false))

var got struct {
GitCommit string
BuildDate string
Version string
GoVersion string
Compiler string
Platform string
}
require.NoError(t, json.Unmarshal(buf.Bytes(), &got))

assert.Equal(t, "9.9.9", got.Version)
assert.Equal(t, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef", got.GitCommit)
assert.Equal(t, "2026-05-26T15:23:43Z", got.BuildDate)
assert.Equal(t, runtime.Version(), got.GoVersion)
assert.Equal(t, runtime.Compiler, got.Compiler)
assert.NotEmpty(t, got.Platform)
}

func TestPrintVersionPrettyIndentsJSON(t *testing.T) {
var buf bytes.Buffer
require.NoError(t, printVersion(&buf, true))

assert.Contains(t, buf.String(), "\n \"")
}
31 changes: 31 additions & 0 deletions test/release/env_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package release

import (
"os"
"path/filepath"
"testing"
)

func pathEnv() string {
return os.Getenv("PATH")
}

func homeEnv(t *testing.T) string {
t.Helper()
if home := os.Getenv("HOME"); home != "" {
return home
}
return filepath.Join(t.TempDir(), "home")
}

func goPathEnv() string {
return os.Getenv("GOPATH")
}

func goModCacheEnv() string {
return os.Getenv("GOMODCACHE")
}

func goProxyEnv() string {
return os.Getenv("GOPROXY")
}
104 changes: 104 additions & 0 deletions test/release/version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Package release verifies that the linker -X flags used by .goreleaser.yml
// reach the variables that printVersion reads. The check rebuilds the
// binary with the same package path goreleaser uses and asserts the
// injected values appear in the output of `rsync-proxy version`.
//
// Without this guard, a typo or rename in either the variable location or
// the goreleaser config silently leaves release binaries reporting the
// source defaults (Version=0.0.0, GitCommit=$Format:%H$, etc.).
package release

import (
"bytes"
"encoding/json"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// goreleaserLDFlagPackagePath is the package path that .goreleaser.yml passes
// to `go build -ldflags -X`. Keep it in sync with .goreleaser.yml; the test
// fails fast if the package no longer holds the version variables.
const goreleaserLDFlagPackagePath = "github.com/ustclug/rsync-proxy/cmd"

func TestReleaseLDFlagsInjectVersionMetadata(t *testing.T) {
if testing.Short() {
t.Skip("skipping release build test in -short mode")
}
if _, err := exec.LookPath("go"); err != nil {
t.Skipf("go toolchain not available: %v", err)
}

const (
injectedVersion = "9.9.9-test"
injectedCommit = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
injectedBuildDate = "2026-05-26T15:23:43Z"
)

binPath := filepath.Join(t.TempDir(), "rsync-proxy")
ldflags := strings.Join([]string{
"-s -w",
"-X " + goreleaserLDFlagPackagePath + ".Version=" + injectedVersion,
"-X " + goreleaserLDFlagPackagePath + ".GitCommit=" + injectedCommit,
"-X " + goreleaserLDFlagPackagePath + ".BuildDate=" + injectedBuildDate,
}, " ")

build := exec.Command("go", "build",
"-trimpath",
"-buildvcs=false",
"-ldflags", ldflags,
"-o", binPath,
"github.com/ustclug/rsync-proxy",
)
build.Env = append(build.Env,
"CGO_ENABLED=0",
"PATH="+pathEnv(),
"HOME="+homeEnv(t),
"GOCACHE="+filepath.Join(t.TempDir(), "gocache"),
)
if goPath := goPathEnv(); goPath != "" {
build.Env = append(build.Env, "GOPATH="+goPath)
}
if goModCache := goModCacheEnv(); goModCache != "" {
build.Env = append(build.Env, "GOMODCACHE="+goModCache)
}
if proxy := goProxyEnv(); proxy != "" {
build.Env = append(build.Env, "GOPROXY="+proxy)
}

var buildOut bytes.Buffer
build.Stdout = &buildOut
build.Stderr = &buildOut
require.NoErrorf(t, build.Run(), "go build failed: %s", buildOut.String())

run := exec.Command(binPath, "version")
var out bytes.Buffer
run.Stdout = &out
run.Stderr = &out
require.NoErrorf(t, run.Run(), "binary failed: %s", out.String())

var got struct {
GitCommit string
BuildDate string
Version string
GoVersion string
Compiler string
Platform string
}
require.NoErrorf(t, json.Unmarshal(out.Bytes(), &got), "output: %s", out.String())

assert.Equalf(t, injectedVersion, got.Version,
"Version was not injected; .goreleaser.yml ldflags package path is likely wrong (expected %q to point at the package that defines Version)", goreleaserLDFlagPackagePath)
assert.Equalf(t, injectedCommit, got.GitCommit,
"GitCommit was not injected; .goreleaser.yml ldflags package path is likely wrong (expected %q)", goreleaserLDFlagPackagePath)
assert.Equalf(t, injectedBuildDate, got.BuildDate,
"BuildDate was not injected; .goreleaser.yml ldflags package path is likely wrong (expected %q)", goreleaserLDFlagPackagePath)
assert.Contains(t, got.GoVersion, "go", "GoVersion should reflect runtime.Version()")
assert.Equal(t, runtime.Compiler, got.Compiler)
assert.NotEmpty(t, got.Platform)
}
Loading