PKG_VERSION/PKG_RELEASE were hand-written literals nobody bumped, so
v0.2.2 … v0.2.6 all shipped as `shaterd 0.2.0-r3` with different binaries
inside (v0.2.6's ELF is 5 491 616 B against r2's 5 488 336 B). Both opkg
and apk offer an upgrade only when the feed's version string differs from
the installed one, so `apk update` saw nothing new and the routers could
not be updated through the normal path at all.
ci/version.sh is now the single source of truth. It derives the version
from `git describe`:
tag `vX.Y.Z` -> PKG_VERSION=X.Y.Z PKG_RELEASE=1
off-tag build -> nearest tag + PKG_RELEASE=<commits since it> + 1
no tag/no git -> 0.0.0-r1 (below everything ever published)
Ordering verified with the real tools, not from memory — apk-tools 3.0.3
(`apk version -t`) and opkg 38eccbb1 (`opkg compare-versions`) agree that
0.2.0-r3 < 0.2.6-r2 < 0.2.6-r10 < 0.2.6-r12 < 0.2.7-r1 < 0.3.0-r1, so a
release always outranks the rolling builds that preceded it and rolling
builds grow monotonically between releases.
The value travels as SHATER_PKG_VERSION/SHATER_PKG_RELEASE in the SDK
build environment of BOTH lanes; the Makefiles keep a literal fallback so
a manual/offline build still works with no CI and no git. Because the
hand-off crosses docker, `su` and make's env import, ci/sdk-build.sh and
ci/sdk-build-apk.sh now ASSERT that the produced .ipk/.apk really carries
that version — the B4 failure mode was a stale version shipping silently,
and that can no longer happen quietly.
The binary agrees with the package: scripts/build-shaterd.sh takes
constant.Version from the same ci/version.sh (vX.Y.Z-rR[-g<sha>]) instead
of its own `git describe`, and the workflow computes it once per job.
Both build jobs now check out with fetch-depth: 0 — `git describe` needs
tags and ancestry, which the default shallow checkout has neither of.
byedpi is deliberately left alone: PKG_VERSION:=0.17.3 is upstream
ByeDPI's own version, what PKG_HASH pins and what tells an operator which
ByeDPI is installed. Stamping our tag on it would also be a downgrade —
every comparator reads 0.2.7 < 0.17.3 (component-wise, 2 < 17), verified.
Docs: INSTALL.md gains §2.1 (the scheme + the ordering evidence), and the
update sections of §5/§6 now explicitly warn against a bare `opkg upgrade`
/ `apk upgrade` and give the targeted form instead, quoting apk-tools 3:
"If list of packages is provided, only those packages are upgraded along
with needed dependencies". README.md and the release bodies match.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
134 lines
5.6 KiB
Bash
Executable File
134 lines
5.6 KiB
Bash
Executable File
#!/bin/sh
|
|
# ci/version.sh — the SINGLE source of truth for "what version is this build?".
|
|
#
|
|
# WHY THIS EXISTS (bug B4)
|
|
# -----------------------
|
|
# PKG_VERSION/PKG_RELEASE used to be hand-written literals in the four package
|
|
# Makefiles, and nobody remembered to bump them: v0.2.2 … v0.2.6 all shipped as
|
|
# `shaterd 0.2.0-r3` with DIFFERENT binaries inside (v0.2.6's ELF is 5 491 616 B
|
|
# vs r2's 5 488 336 B). Since both opkg and apk offer an upgrade only when the
|
|
# feed's version string differs from the installed one, `apk update` saw nothing
|
|
# new and the routers could not be updated through the normal path at all.
|
|
#
|
|
# So the version is now DERIVED, in CI, from the git tag, and the package
|
|
# Makefiles only carry a fallback for manual/offline builds.
|
|
#
|
|
# THE SCHEME
|
|
# ----------
|
|
# tag push `vX.Y.Z` -> PKG_VERSION=X.Y.Z PKG_RELEASE=1
|
|
# any other build -> PKG_VERSION=X.Y.Z of the NEAREST reachable tag,
|
|
# (workflow_dispatch, PKG_RELEASE=<commits since that tag> + 1
|
|
# rolling `latest`)
|
|
# no tag / no git at all -> PKG_VERSION=0.0.0 PKG_RELEASE=1 (+ warning)
|
|
#
|
|
# Both managers compare `<upstream>-r<rel>` the same way: the dotted upstream
|
|
# part first (numerically, component by component), the `r<rel>` only as a
|
|
# tie-break. Verified against the real tools, not from memory:
|
|
# apk-tools 3.0.3 (`apk version -t`) and apk-tools 2.14.6:
|
|
# 0.2.6-r1 > 0.2.0-r3 0.2.6-r12 > 0.2.6-r1
|
|
# 0.2.7-r1 > 0.2.6-r12 0.0.0-r1 < 0.2.0-r3
|
|
# opkg 38eccbb1 from openwrt/rootfs:x86-64-24.10.4 (`opkg compare-versions`):
|
|
# identical results (opkg implements the Debian algorithm).
|
|
# That is exactly the ordering this scheme needs:
|
|
# * a release always outranks every rolling build that preceded it
|
|
# (0.2.7-r1 > 0.2.6-rN for any N — the dotted part decides), and
|
|
# * rolling builds between two releases grow monotonically (r2 < r10 < r11),
|
|
# so a rolling build can never look newer than the next release, and the
|
|
# `latest` feed still moves forward on every dispatch.
|
|
#
|
|
# +1 on the commit count (rather than the raw count) only avoids `-r0` and makes
|
|
# a dispatch build of the tagged commit itself identical to the release build of
|
|
# that same commit — which is the truth: same tree, same binary.
|
|
#
|
|
# `byedpi` is deliberately NOT versioned from our tag — see openwrt/byedpi/Makefile.
|
|
#
|
|
# USAGE
|
|
# ci/version.sh # or --env: eval-able / $GITHUB_ENV-able lines
|
|
# ci/version.sh --pkg-version # X.Y.Z
|
|
# ci/version.sh --pkg-release # R
|
|
# ci/version.sh --binary # vX.Y.Z-rR[-g<sha>] for constant.Version
|
|
#
|
|
# Env:
|
|
# SHATER_REF / GITHUB_REF when it is `refs/tags/<tag>` that tag wins and no
|
|
# git history is needed (the tag-push path is exact
|
|
# even on a shallow checkout).
|
|
set -eu
|
|
|
|
REPO="$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)"
|
|
|
|
TAG=""
|
|
EXACT=0
|
|
N=0
|
|
SHA=""
|
|
|
|
# --- 1) an explicit tag ref is authoritative (and needs no git) --------------
|
|
REF="${SHATER_REF:-${GITHUB_REF:-}}"
|
|
case "$REF" in
|
|
refs/tags/*) TAG="${REF#refs/tags/}"; EXACT=1 ;;
|
|
esac
|
|
|
|
# --- 2) otherwise ask git for the nearest reachable release tag --------------
|
|
# `--match 'v[0-9]*'` keeps non-release tags (latest, sdk-cache, apk-latest-*,
|
|
# musl-toolchain-cache) out. This repo is a sing-box FORK and therefore also
|
|
# carries upstream's v1.x tags — `git describe` picks the CLOSEST tag by commit
|
|
# distance, so our own v0.2.x (a handful of commits back) always wins over
|
|
# upstream's v1.x (thousands of commits back). The tag it picked is logged
|
|
# below, so a surprise is visible in the CI log rather than silently shipped.
|
|
if [ "$EXACT" -eq 0 ]; then
|
|
if D="$(git -C "$REPO" describe --tags --long --match 'v[0-9]*' 2>/dev/null)"; then
|
|
# `v0.2.6-1-g02c266188` -> TAG=v0.2.6 N=1 SHA=g02c266188.
|
|
# `%` strips the SHORTEST matching suffix, so a tag that itself contains a
|
|
# dash (`v0.2.0-healthplan`) survives intact.
|
|
TAG="${D%-*-g*}"
|
|
REST="${D#"$TAG"-}"
|
|
N="${REST%%-*}"
|
|
SHA="${REST#*-}"
|
|
if [ "$N" -eq 0 ]; then EXACT=1; fi
|
|
fi
|
|
fi
|
|
|
|
# --- 3) tag -> numeric PKG_VERSION ------------------------------------------
|
|
# Keep the leading dotted-numeric run only: `v0.2.0-healthplan` -> `0.2.0`.
|
|
VER=""
|
|
if [ -n "$TAG" ]; then
|
|
VER="$(printf '%s' "${TAG#v}" | sed -n 's/^\([0-9][0-9.]*\).*/\1/p' | sed 's/\.*$//')"
|
|
fi
|
|
|
|
if [ -z "$VER" ]; then
|
|
# No release tag anywhere (shallow clone with no tags, a tarball export, a
|
|
# fresh fork). 0.0.0 is BELOW every version we have ever published, so such a
|
|
# build can never masquerade as an upgrade on a real router; the commit count
|
|
# still makes successive dev builds distinguishable.
|
|
VER="0.0.0"
|
|
EXACT=0
|
|
N="$(git -C "$REPO" rev-list --count HEAD 2>/dev/null || echo 0)"
|
|
SHA="$(git -C "$REPO" rev-parse --short HEAD 2>/dev/null || echo '')"
|
|
[ -z "$SHA" ] || SHA="g$SHA"
|
|
echo "[version] WARNING: no reachable vX.Y.Z tag (and/or no git) -> $VER" >&2
|
|
fi
|
|
|
|
# --- 4) PKG_RELEASE + the string stamped into the binary --------------------
|
|
if [ "$EXACT" -eq 1 ]; then
|
|
REL=1
|
|
FULL="v${VER}-r${REL}"
|
|
else
|
|
REL=$((N + 1))
|
|
FULL="v${VER}-r${REL}${SHA:+-$SHA}"
|
|
fi
|
|
|
|
echo "[version] tag='${TAG:-none}' commits_since=$N exact=$EXACT -> ${VER}-r${REL} (binary: $FULL)" >&2
|
|
|
|
case "${1:---env}" in
|
|
--env|"")
|
|
printf 'SHATER_PKG_VERSION=%s\n' "$VER"
|
|
printf 'SHATER_PKG_RELEASE=%s\n' "$REL"
|
|
printf 'SHATER_VERSION=%s\n' "$FULL"
|
|
;;
|
|
--pkg-version) printf '%s\n' "$VER" ;;
|
|
--pkg-release) printf '%s\n' "$REL" ;;
|
|
--binary|--version) printf '%s\n' "$FULL" ;;
|
|
*)
|
|
echo "usage: $0 [--env|--pkg-version|--pkg-release|--binary]" >&2
|
|
exit 2 ;;
|
|
esac
|