Report development builds as such, not as the release version
Only a release build (the commit tagged v<VERSION>, unchanged) gives a version number. Others print 'dev <commit> (3 commits after v0.2.0-rc.1)', from git describe (the Makefile's DESCRIBE), in jarld version, jarl --version, jarl status, jarl whoami and the startup log; a build without git says '(source build)'. The CLI's User-Agent and the footer's tooltip follow suit, and /status's build gains since and ahead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
88bb89a9ff
commit
fb1ee09250
7 files changed
+123
-23
No files matched your search
+7
-3
@@ -88,9 +88,13 @@ All notable changes to Jarl are documented here. The format follows
|
|||||||
linking to the release on Gitea. A build that isn't of a release tag
|
linking to the release on Gitea. A build that isn't of a release tag
|
||||||
shows its commit instead, linked to the commit and marked `-modified`
|
shows its commit instead, linked to the commit and marked `-modified`
|
||||||
with uncommitted changes. Before, every build of a commit after a
|
with uncommitted changes. Before, every build of a commit after a
|
||||||
release still showed the release's version. `jarld version`,
|
release still showed the release's version. `GET /status` and
|
||||||
`jarl --version`, `GET /status` and `/auth/whoami` report the same, the
|
`/auth/whoami` report the build as `build` (docs/development.md).
|
||||||
latter two as `build` (docs/development.md).
|
- `jarld version`, `jarl --version`, `jarl status` and `jarl whoami` give
|
||||||
|
a version number only for release builds. Other builds say they are
|
||||||
|
development builds and how far past the last tag they are: `dev
|
||||||
|
ca0f148b78b6 (3 commits after v0.2.0-rc.1)`. In 0.2.0-rc.1 they still
|
||||||
|
printed `0.2.0-rc.1 (ca0f148b78b6)`.
|
||||||
- The view in the zone list, and on the zone page, links to that view,
|
- The view in the zone list, and on the zone page, links to that view,
|
||||||
and the views page highlights it. It used to be plain text, and the zone
|
and the views page highlights it. It used to be plain text, and the zone
|
||||||
page linked to the views page as a whole.
|
page linked to the views page as a whole.
|
||||||
|
|||||||
@@ -18,7 +18,11 @@ VERSION ?= $(shell cat VERSION 2>/dev/null || echo 0.0.0-dev)
|
|||||||
# the release rather than the commit): set when HEAD is tagged v$(VERSION)
|
# the release rather than the commit): set when HEAD is tagged v$(VERSION)
|
||||||
# and no tracked file is changed.
|
# and no tracked file is changed.
|
||||||
RELEASE_TAG ?= $(shell t=v$(VERSION); git tag --points-at HEAD 2>/dev/null | grep -qx "$$t" && git diff --quiet HEAD 2>/dev/null && echo $$t)
|
RELEASE_TAG ?= $(shell t=v$(VERSION); git tag --points-at HEAD 2>/dev/null | grep -qx "$$t" && git diff --quiet HEAD 2>/dev/null && echo $$t)
|
||||||
LDFLAGS := -s -w -X jarl/internal/version.Version=$(VERSION) -X jarl/internal/version.Tag=$(RELEASE_TAG)
|
# DESCRIBE places other builds relative to the last tag ("3 commits after
|
||||||
|
# v0.2.0-rc.1").
|
||||||
|
DESCRIBE ?= $(shell git describe --tags --long --match 'v[0-9]*' --abbrev=12 HEAD 2>/dev/null)
|
||||||
|
LDFLAGS := -s -w -X jarl/internal/version.Version=$(VERSION) -X jarl/internal/version.Tag=$(RELEASE_TAG) \
|
||||||
|
-X jarl/internal/version.Describe=$(DESCRIBE)
|
||||||
GOFLAGS := -trimpath
|
GOFLAGS := -trimpath
|
||||||
export CGO_ENABLED := 0
|
export CGO_ENABLED := 0
|
||||||
|
|
||||||
|
|||||||
+12
-6
@@ -232,17 +232,23 @@ runs it as a check before building.
|
|||||||
|
|
||||||
### Which version a build reports
|
### Which version a build reports
|
||||||
|
|
||||||
The footer of the web UI, `jarld version` and `jarl --version` say what a
|
The footer of the web UI, `jarld version`, `jarl --version`, `jarl status`
|
||||||
binary was built from, linking to it on Gitea:
|
and `jarl whoami` say what a binary was built from (the footer links to
|
||||||
|
it on Gitea). Only a release build reports a version number:
|
||||||
|
|
||||||
* **A release**: `make` run on the commit tagged `v<VERSION>` with no
|
* **A release**: `make` run on the commit tagged `v<VERSION>` with no
|
||||||
tracked file changed. The Makefile then sets `RELEASE_TAG`, and the
|
tracked file changed. The Makefile then sets `RELEASE_TAG`, and the
|
||||||
footer reads "Powered by Jarl v0.2.0", linking to the release. The
|
footer reads "Powered by Jarl v0.2.0", linking to the release. The
|
||||||
release workflow sets `RELEASE_TAG` itself.
|
release workflow sets `RELEASE_TAG` itself.
|
||||||
* **Any other build**: the commit, which Go records from git: "Powered by
|
* **Any other build** is a development build, named by its commit (which
|
||||||
Jarl 1a2b3c4d5e6f", linking to the commit. With uncommitted changes it
|
Go records from git) rather than `VERSION`: "Powered by Jarl
|
||||||
is marked `-modified`. The version commands print `0.2.0 (1a2b3c4d5e6f)`.
|
1a2b3c4d5e6f", linking to the commit. With uncommitted changes it is
|
||||||
* **No git** (a build from a source tarball): just `VERSION`.
|
marked `-modified`. The other places add where it stands relative to
|
||||||
|
the last tag, from `git describe` (the Makefile's `DESCRIBE`):
|
||||||
|
`dev 1a2b3c4d5e6f (3 commits after v0.2.0-rc.1)`, or
|
||||||
|
`dev 1a2b3c4d5e6f-modified (v0.2.0-rc.1 with uncommitted changes)`.
|
||||||
|
* **No git** (a build from a source archive): `VERSION`, marked as such:
|
||||||
|
`0.2.0 (source build)`.
|
||||||
|
|
||||||
`RELEASE_TAG=v0.2.0 make` forces the first case.
|
`RELEASE_TAG=v0.2.0 make` forces the first case.
|
||||||
|
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ func (c *Client) Do(ctx context.Context, method, path string, query url.Values,
|
|||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
}
|
}
|
||||||
req.Header.Set("Accept", "application/json")
|
req.Header.Set("Accept", "application/json")
|
||||||
req.Header.Set("User-Agent", "jarl-cli/"+version.Version)
|
req.Header.Set("User-Agent", "jarl-cli/"+version.Short())
|
||||||
if c.Token != "" {
|
if c.Token != "" {
|
||||||
req.Header.Set("Authorization", "Bearer "+c.Token)
|
req.Header.Set("Authorization", "Bearer "+c.Token)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,17 @@
|
|||||||
//
|
//
|
||||||
// The Makefile sets Version from the VERSION file, and Tag only when the
|
// The Makefile sets Version from the VERSION file, and Tag only when the
|
||||||
// build is of that release: HEAD is the tag v<VERSION> and no tracked file
|
// build is of that release: HEAD is the tag v<VERSION> and no tracked file
|
||||||
// is changed. Other builds are identified by their commit, which Go
|
// is changed. Only such a build reports a version number. Other builds
|
||||||
// records from git by itself.
|
// are development builds, identified by their commit (which Go records
|
||||||
|
// from git by itself) and by where they stand relative to the last tag
|
||||||
|
// (Describe, from git describe).
|
||||||
package version
|
package version
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"regexp"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -23,6 +28,11 @@ var Tag = ""
|
|||||||
// information when not set at build time.
|
// information when not set at build time.
|
||||||
var Commit = ""
|
var Commit = ""
|
||||||
|
|
||||||
|
// Describe is 'git describe --tags --long' of the build's commit
|
||||||
|
// ("v0.2.0-rc.1-3-gca0f148b78b6"), set by the Makefile; it says how many
|
||||||
|
// commits a development build is past the last tag.
|
||||||
|
var Describe = ""
|
||||||
|
|
||||||
// Repo is Jarl's source repository.
|
// Repo is Jarl's source repository.
|
||||||
const Repo = "https://gitea.adbraun.lol/adam/jarl"
|
const Repo = "https://gitea.adbraun.lol/adam/jarl"
|
||||||
|
|
||||||
@@ -32,6 +42,11 @@ type Build struct {
|
|||||||
Tag string `json:"tag,omitempty"`
|
Tag string `json:"tag,omitempty"`
|
||||||
Commit string `json:"commit,omitempty"`
|
Commit string `json:"commit,omitempty"`
|
||||||
Modified bool `json:"modified,omitempty"` // built with uncommitted changes
|
Modified bool `json:"modified,omitempty"` // built with uncommitted changes
|
||||||
|
// Since is the last tag before a development build's commit, and
|
||||||
|
// Ahead how many commits the build is past it (0: the tag's commit,
|
||||||
|
// with uncommitted changes).
|
||||||
|
Since string `json:"since,omitempty"`
|
||||||
|
Ahead int `json:"ahead,omitempty"`
|
||||||
// Label is the short form to show: the tag of a release, otherwise
|
// Label is the short form to show: the tag of a release, otherwise
|
||||||
// the abbreviated commit (or the version when the commit is unknown).
|
// the abbreviated commit (or the version when the commit is unknown).
|
||||||
Label string `json:"label"`
|
Label string `json:"label"`
|
||||||
@@ -53,9 +68,23 @@ var info = sync.OnceValue(func() Build {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return describe(Version, Tag, commit, modified)
|
b := describe(Version, Tag, commit, modified)
|
||||||
|
b.Since, b.Ahead = parseDescribe(Describe, b.Commit)
|
||||||
|
return b
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// parseDescribe splits git describe --long output, if it is of commit.
|
||||||
|
func parseDescribe(d, commit string) (since string, ahead int) {
|
||||||
|
m := describeRe.FindStringSubmatch(d)
|
||||||
|
if m == nil || commit == "" || !strings.HasPrefix(commit, m[3]) {
|
||||||
|
return "", 0
|
||||||
|
}
|
||||||
|
n, _ := strconv.Atoi(m[2])
|
||||||
|
return m[1], n
|
||||||
|
}
|
||||||
|
|
||||||
|
var describeRe = regexp.MustCompile(`^(v.+)-(\d+)-g([0-9a-f]+)$`)
|
||||||
|
|
||||||
func describe(version, tag, commit string, modified bool) Build {
|
func describe(version, tag, commit string, modified bool) Build {
|
||||||
b := Build{Version: version, Tag: tag, Commit: commit, Modified: modified}
|
b := Build{Version: version, Tag: tag, Commit: commit, Modified: modified}
|
||||||
switch {
|
switch {
|
||||||
@@ -76,14 +105,41 @@ func describe(version, tag, commit string, modified bool) Build {
|
|||||||
// Info describes this build.
|
// Info describes this build.
|
||||||
func Info() Build { return info() }
|
func Info() Build { return info() }
|
||||||
|
|
||||||
// String is the version for logs and 'version' commands: "0.2.0" for a
|
// String is the version for logs and 'version' commands. Only a release
|
||||||
// release, otherwise the version and the commit ("0.2.0-dev (a1b2c3d4e5f6)").
|
// build gives a version ("0.2.0"); any other build says it's a
|
||||||
func String() string {
|
// development build: "dev a1b2c3d4e5f6 (3 commits after v0.2.0-rc.1)".
|
||||||
b := Info()
|
func String() string { return Info().String() }
|
||||||
if b.Tag != "" || b.Commit == "" {
|
|
||||||
|
func (b Build) String() string {
|
||||||
|
switch {
|
||||||
|
case b.Tag != "":
|
||||||
return b.Version
|
return b.Version
|
||||||
|
case b.Commit == "":
|
||||||
|
// No git information (built from a source archive).
|
||||||
|
return b.Version + " (source build)"
|
||||||
}
|
}
|
||||||
return b.Version + " (" + b.Label + ")"
|
s := "dev " + b.Label
|
||||||
|
switch {
|
||||||
|
case b.Since == "":
|
||||||
|
case b.Ahead == 1:
|
||||||
|
s += " (1 commit after " + b.Since + ")"
|
||||||
|
case b.Ahead > 1:
|
||||||
|
s += " (" + strconv.Itoa(b.Ahead) + " commits after " + b.Since + ")"
|
||||||
|
case b.Modified:
|
||||||
|
s += " (" + b.Since + " with uncommitted changes)"
|
||||||
|
default:
|
||||||
|
s += " (at " + b.Since + ")"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Short is the version for a User-Agent: the version of a release,
|
||||||
|
// otherwise the label ("a1b2c3d4e5f6").
|
||||||
|
func Short() string {
|
||||||
|
if b := Info(); b.Tag == "" && b.Commit != "" {
|
||||||
|
return b.Label
|
||||||
|
}
|
||||||
|
return Version
|
||||||
}
|
}
|
||||||
|
|
||||||
func short(commit string) string {
|
func short(commit string) string {
|
||||||
|
|||||||
@@ -20,3 +20,30 @@ func TestDescribe(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestString(t *testing.T) {
|
||||||
|
const c = "ca0f148b78b6e1f0a9b8c7d6e5f4a3b2c1d0e9f8"
|
||||||
|
build := func(tag, commit string, modified bool, desc string) Build {
|
||||||
|
b := describe("0.2.0-rc.1", tag, commit, modified)
|
||||||
|
b.Since, b.Ahead = parseDescribe(desc, b.Commit)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
for _, tc := range []struct {
|
||||||
|
b Build
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{build("v0.2.0-rc.1", c, false, "v0.2.0-rc.1-0-gca0f148b78b6"), "0.2.0-rc.1"},
|
||||||
|
{build("", c, false, "v0.2.0-rc.1-3-gca0f148b78b6"), "dev ca0f148b78b6 (3 commits after v0.2.0-rc.1)"},
|
||||||
|
{build("", c, true, "v0.2.0-rc.1-1-gca0f148b78b6"), "dev ca0f148b78b6-modified (1 commit after v0.2.0-rc.1)"},
|
||||||
|
{build("", c, true, "v0.2.0-rc.1-0-gca0f148b78b6"), "dev ca0f148b78b6-modified (v0.2.0-rc.1 with uncommitted changes)"},
|
||||||
|
{build("", c, false, "v0.1.0-0-gca0f148b78b6"), "dev ca0f148b78b6 (at v0.1.0)"},
|
||||||
|
{build("", c, false, ""), "dev ca0f148b78b6"},
|
||||||
|
// A describe of another commit (stale ldflags) is ignored.
|
||||||
|
{build("", c, false, "v0.2.0-rc.1-3-gdeadbeef0000"), "dev ca0f148b78b6"},
|
||||||
|
{build("", "", false, ""), "0.2.0-rc.1 (source build)"},
|
||||||
|
} {
|
||||||
|
if got := tc.b.String(); got != tc.want {
|
||||||
|
t.Errorf("String() = %q, want %q", got, tc.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -173,10 +173,13 @@ let modeHolder;
|
|||||||
// builds, linked to it in the repository.
|
// builds, linked to it in the repository.
|
||||||
function footer(b) {
|
function footer(b) {
|
||||||
if (!b) return null;
|
if (!b) return null;
|
||||||
const what = b.tag ? "release " + b.tag
|
let title = b.tag ? "Jarl " + b.version + " (release " + b.tag + ")" : "Jarl " + b.version + " (built without git)";
|
||||||
: b.commit ? "commit " + b.commit + (b.modified ? ", with uncommitted changes" : "") : "version " + b.version;
|
if (!b.tag && b.commit) {
|
||||||
|
title = "Development build of commit " + b.commit + (b.modified ? " with uncommitted changes" : "");
|
||||||
|
if (b.since) title += b.ahead ? ", " + b.ahead + (b.ahead === 1 ? " commit" : " commits") + " after " + b.since : ", at " + b.since;
|
||||||
|
}
|
||||||
return h("footer", { class: "site" }, "Powered by ",
|
return h("footer", { class: "site" }, "Powered by ",
|
||||||
h("a", { href: b.url, target: "_blank", rel: "noopener", title: "Jarl " + b.version + ", built from " + what }, "Jarl " + b.label));
|
h("a", { href: b.url, target: "_blank", rel: "noopener", title }, "Jarl " + (b.tag || b.commit ? b.label : b.version)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderNav() {
|
function renderNav() {
|
||||||
|
|||||||
Reference in new issue
Block a user