#!/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 "$@"