Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 51283d5

Browse files
authored
fix(version): embed VERSION file so source builds show a real version
Embed internal/cmd/VERSION so source archive builds report a meaningful dev version, keep injected dev versions authoritative, harden the post-release bump workflow, and require release tags to be cut with VERSION set to the release version. Co-authored-by: Sheng <[email protected]>
1 parent a2df2ec commit 51283d5

7 files changed

Lines changed: 124 additions & 7 deletions

File tree

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: post-release-bump
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
bump-version-file:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
16+
with:
17+
fetch-depth: 0
18+
ref: main
19+
token: ${{ secrets.GITHUB_TOKEN }}
20+
21+
- name: Compute next dev version
22+
id: nextver
23+
run: |
24+
if ! [[ "$GITHUB_REF_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then
25+
echo "::error::Invalid tag format: $GITHUB_REF_NAME"
26+
exit 1
27+
fi
28+
# Policy: VERSION = "<just-pushed-tag>-dev". The just-pushed tag is
29+
# the latest released version; -dev marks the period afterwards.
30+
next="${GITHUB_REF_NAME}-dev"
31+
printf 'next=%s\n' "$next" >> "$GITHUB_OUTPUT"
32+
33+
- name: Write VERSION
34+
env:
35+
NEXT_VERSION: ${{ steps.nextver.outputs.next }}
36+
run: printf '%s\n' "$NEXT_VERSION" > internal/cmd/VERSION
37+
38+
- name: Commit & push
39+
env:
40+
NEXT_VERSION: ${{ steps.nextver.outputs.next }}
41+
run: |
42+
git config user.name "github-actions[bot]"
43+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
44+
if git diff --quiet -- internal/cmd/VERSION; then
45+
echo "VERSION unchanged, nothing to commit"
46+
exit 0
47+
fi
48+
git add internal/cmd/VERSION
49+
git commit -m "chore(release): bump VERSION to $NEXT_VERSION
50+
51+
[skip ci]"
52+
git push origin main

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- CLI: harden backup writes, config/credentials atomic saves, keyring write verification, line input buffering, disabled-API hints, JSON transform number handling, and untrusted-content wrapping after ClawPatch review.
1414
- CLI: bound retry request replay buffering, recover failed async backup pushes, ignore global git commit signing in backup snapshots, and protect account manager OAuth redirects with CSRF checks.
1515
- Release: update the Homebrew handoff to publish through `openclaw/tap`.
16+
- Version: `gog --version` now reports an informative fallback (for example, `v0.17.0-dev`) when built from source with plain `go build` instead of returning `dev`.
1617

1718
## 0.17.0 - 2026-05-15
1819

docs/RELEASING.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ gh run list -L 5 --branch main
4343

4444
## 2) Update changelog
4545
- Update `CHANGELOG.md` for the version you’re releasing.
46+
- Update `internal/cmd/VERSION` to `vX.Y.Z` before tagging. The post-release
47+
bump workflow rewrites it to `vX.Y.Z-dev` on `main` after the tag is pushed.
4648

4749
Example heading:
4850
- `## 0.1.0 - 2025-12-12`
@@ -52,7 +54,7 @@ Example heading:
5254
git checkout main
5355
git pull
5456

55-
# commit changelog + any release tweaks
57+
# commit changelog, internal/cmd/VERSION, and any release tweaks
5658
git commit -am "release: vX.Y.Z"
5759

5860
git tag -a vX.Y.Z -m "Release X.Y.Z"

internal/cmd/VERSION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v0.17.0-dev

internal/cmd/version.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cmd
22

33
import (
44
"context"
5+
_ "embed"
56
"fmt"
67
"os"
78
"runtime/debug"
@@ -10,18 +11,21 @@ import (
1011
"github.com/steipete/gogcli/internal/outfmt"
1112
)
1213

13-
const devVersion = "dev"
14+
//go:embed VERSION
15+
var embeddedVersion string
16+
17+
const sentinelDev = "dev"
1418

1519
var (
16-
version = devVersion
20+
version = sentinelDev
1721
commit = ""
1822
date = ""
1923
readBuildInfo = debug.ReadBuildInfo
2024
)
2125

2226
func resolvedVersion() string {
2327
v := strings.TrimSpace(version)
24-
if v != "" && v != devVersion && !strings.HasSuffix(v, "-dev") {
28+
if v != "" && v != sentinelDev {
2529
return v
2630
}
2731
info, ok := readBuildInfo()
@@ -31,10 +35,10 @@ func resolvedVersion() string {
3135
return moduleVersion
3236
}
3337
}
34-
if v == "" {
35-
return devVersion
38+
if baked := strings.TrimSpace(embeddedVersion); baked != "" {
39+
return baked
3640
}
37-
return v
41+
return sentinelDev
3842
}
3943

4044
func VersionString() string {

internal/cmd/version_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,55 @@ func TestVersionStringPrefersInjectedVersion(t *testing.T) {
6262
}
6363
}
6464

65+
func TestResolvedVersionUsesEmbeddedVersionWhenBuildInfoIsDevel(t *testing.T) {
66+
origVersion, origReadBuildInfo, origEmbedded := version, readBuildInfo, embeddedVersion
67+
t.Cleanup(func() {
68+
version, readBuildInfo, embeddedVersion = origVersion, origReadBuildInfo, origEmbedded
69+
})
70+
71+
version = sentinelDev
72+
embeddedVersion = "v0.17.0-dev\n"
73+
readBuildInfo = func() (*debug.BuildInfo, bool) {
74+
return &debug.BuildInfo{Main: debug.Module{Version: "(devel)"}}, true
75+
}
76+
77+
if got := resolvedVersion(); got != "v0.17.0-dev" {
78+
t.Fatalf("expected v0.17.0-dev, got %q", got)
79+
}
80+
}
81+
82+
func TestResolvedVersionPrefersInjectedDevVersionOverEmbedded(t *testing.T) {
83+
origVersion, origReadBuildInfo, origEmbedded := version, readBuildInfo, embeddedVersion
84+
t.Cleanup(func() {
85+
version, readBuildInfo, embeddedVersion = origVersion, origReadBuildInfo, origEmbedded
86+
})
87+
88+
version = "v0.18.0-dev"
89+
embeddedVersion = "v0.17.0-dev\n"
90+
readBuildInfo = func() (*debug.BuildInfo, bool) {
91+
return &debug.BuildInfo{Main: debug.Module{Version: "(devel)"}}, true
92+
}
93+
94+
if got := resolvedVersion(); got != "v0.18.0-dev" {
95+
t.Fatalf("expected injected dev version, got %q", got)
96+
}
97+
}
98+
99+
func TestResolvedVersionFallsBackToSentinelWhenEverythingEmpty(t *testing.T) {
100+
origVersion, origReadBuildInfo, origEmbedded := version, readBuildInfo, embeddedVersion
101+
t.Cleanup(func() {
102+
version, readBuildInfo, embeddedVersion = origVersion, origReadBuildInfo, origEmbedded
103+
})
104+
105+
version = sentinelDev
106+
embeddedVersion = ""
107+
readBuildInfo = func() (*debug.BuildInfo, bool) { return nil, false }
108+
109+
if got := resolvedVersion(); got != sentinelDev {
110+
t.Fatalf("expected dev, got %q", got)
111+
}
112+
}
113+
65114
func TestVersionCmd_JSON(t *testing.T) {
66115
origVersion, origCommit, origDate, origReadBuildInfo := version, commit, date, readBuildInfo
67116
t.Cleanup(func() { version, commit, date, readBuildInfo = origVersion, origCommit, origDate, origReadBuildInfo })

scripts/release.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ if rg -q "^## ${version} - Unreleased" "$changelog"; then
3030
exit 2
3131
fi
3232

33+
version_file="internal/cmd/VERSION"
34+
expected_version="v$version"
35+
if [[ "$(tr -d '[:space:]' < "$version_file")" != "$expected_version" ]]; then
36+
echo "$version_file must contain $expected_version before tagging" >&2
37+
echo "This keeps source archives built from the release tag from embedding a stale dev fallback." >&2
38+
exit 2
39+
fi
40+
3341
notes_file="$(mktemp -t gogcli-release-notes)"
3442
awk -v ver="$version" '
3543
$0 ~ "^## "ver" " {print "## "ver; in_section=1; next}

0 commit comments

Comments
 (0)