All checks were successful
check / check (push) Successful in 3m20s
The binary reported "dev" in every deployment: main.version carried a placeholder and nothing ever set it. Neither `make build` nor the Dockerfile passed -X, so a tagged release produced an artifact that could not say which commit it was, and the upgrade procedure's "confirm the new build is live" step had nothing to confirm against. script/version is now the single source of the value: $VERSION when set, else `git describe --tags --always --dirty`, else "unknown". A clean checkout at a tag reports exactly that tag; a tree with no git metadata reports "unknown" rather than failing or naming a tag it may not be at. Nothing time- or host-dependent is stamped, so two builds of one commit stay byte-identical. The Makefile's build target composes the flags -- `-X main.version` plus whatever GO_LDFLAGS adds -- and every compile goes through it, including the Dockerfile's static relink, which now contributes its -extldflags through GO_LDFLAGS instead of replacing -ldflags wholesale. Since .dockerignore excludes .git/, the image cannot derive the version: it takes a VERSION build arg, defaulted to "unknown", that script/docker fills in from the host checkout. The UI footer needed the other half of the fix. It renders .Version, which nothing ever put in the template data, so it printed its literal "dev" fallback no matter what the binary was built as; renderTemplate now supplies the value on both the map and the wrapper path.
66 lines
2.3 KiB
Bash
Executable File
66 lines
2.3 KiB
Bash
Executable File
#!/bin/sh
|
|
# script/version: output the version string the binary is stamped with.
|
|
# Our own extension to scripts-to-rule-them-all. The Makefile's build
|
|
# target and script/docker both take the value from here, so a `make
|
|
# build` binary and a `make docker` image built from the same checkout
|
|
# report the same thing.
|
|
#
|
|
# Order of precedence:
|
|
#
|
|
# 1. $VERSION, if set and non-empty. This is how the value reaches a
|
|
# build that cannot derive it: .dockerignore excludes .git/, so the
|
|
# builder stage has no git metadata and the Dockerfile takes the
|
|
# value as a build arg instead.
|
|
# 2. `git describe --tags --always --dirty` against this checkout. At
|
|
# a clean tagged commit that is exactly the tag; otherwise it
|
|
# carries the short SHA, the commit distance when a tag is
|
|
# reachable, and a -dirty suffix for uncommitted changes.
|
|
# 3. "unknown", for a tree with no git metadata and no $VERSION -- a
|
|
# source tarball, or `docker build .` with no --build-arg. That
|
|
# case must not fail the build and must not name a tag the tree may
|
|
# not be at, so it names nothing.
|
|
#
|
|
# The git step insists the enclosing repository is this checkout, not
|
|
# merely some repository above it: an unpacked tarball sitting inside an
|
|
# unrelated working copy would otherwise be stamped with that copy's
|
|
# version.
|
|
#
|
|
# Nothing here may vary between two builds of the same commit: the
|
|
# release gate asserts the binary is byte-identical across builds. That
|
|
# rules out a build timestamp, a hostname, and a builder identity.
|
|
set -eu
|
|
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
|
|
# in_this_checkout succeeds when git can read metadata for a repository
|
|
# whose work tree root is $ROOT.
|
|
in_this_checkout() {
|
|
command -v git >/dev/null 2>&1 || return 1
|
|
|
|
top="$(git rev-parse --show-toplevel 2>/dev/null)" || return 1
|
|
[ -n "$top" ] || return 1
|
|
|
|
top="$(cd "$top" 2>/dev/null && pwd -P)" || return 1
|
|
[ "$top" = "$ROOT" ]
|
|
}
|
|
|
|
main() {
|
|
if [ -n "${VERSION:-}" ]; then
|
|
echo "$VERSION"
|
|
|
|
return 0
|
|
fi
|
|
|
|
cd "$ROOT"
|
|
|
|
if in_this_checkout; then
|
|
# --always keeps an untagged history from failing the build: it
|
|
# falls back to the bare short SHA.
|
|
git describe --tags --always --dirty 2>/dev/null && return 0
|
|
fi
|
|
|
|
echo "unknown"
|
|
}
|
|
|
|
main "$@"
|