build: make the git tag the single source of truth for the version (DR-153)
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 6m55s
Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m21s
Traceability Validation / Check Requirement Traces (push) Successful in 15s
Build & Release / Run Tests (push) Successful in 7m36s
🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 2m57s
Build & Release / Build Linux (push) Successful in 20m4s
Build & Release / Build Windows (push) Successful in 8m42s
Build & Release / Build Android (push) Successful in 30m30s
Build & Release / Create Release (push) Successful in 17s
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 6m55s
Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m21s
Traceability Validation / Check Requirement Traces (push) Successful in 15s
Build & Release / Run Tests (push) Successful in 7m36s
🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 2m57s
Build & Release / Build Linux (push) Successful in 20m4s
Build & Release / Build Windows (push) Successful in 8m42s
Build & Release / Build Android (push) Successful in 30m30s
Build & Release / Create Release (push) Successful in 17s
The version lived in four files — package.json, tauri.conf.json, Cargo.toml and
Cargo.lock — that had to be hand-edited in lockstep, and the release workflow
rewrote exactly one of them. A tagged build therefore produced an installer
named for the tag wrapped around package metadata naming the previous release,
and the Linux job, which had no version step at all, shipped whatever happened
to be committed.
scripts/set-version.sh now writes all four from one argument and is the only
thing that does. Every release job calls it with the tag, including the Linux
job that was missing one. The committed versions become a placeholder for dev
builds rather than something to maintain by hand.
The Android versionCode moves into the same script, unchanged in formula
(1000 + major*10000 + minor*100 + patch). It stays inline-documented because the
reasoning is not obvious: builds already in the field shipped code 1000, and
Android refuses an update whose code is lower than the installed one, so a
formula that can emit a smaller number for a newer release bricks updates
irreversibly. UT-150 asserts that property directly — monotonic across an
upgrade sequence, and always above the floor.
Two edge cases the previous inline version got wrong:
- A prerelease tag (v0.6.0-rc1) made $(( 0-rc1 )) abort the step under set -e.
The suffix is stripped before the arithmetic; the manifests keep it.
- CI passes "${GITHUB_REF#refs/tags/}" unconditionally, which on a branch build
is still a full ref. That reached the validator verbatim and would have failed
every untagged Android build; a non-tag ref now falls back to git describe.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -96,6 +96,12 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: bun install
|
||||
|
||||
# The Linux job previously had no version step at all, so a tagged release
|
||||
# built Linux packages from whatever version happened to be committed.
|
||||
- name: Set app version from tag
|
||||
run: ./scripts/set-version.sh "${GITHUB_REF#refs/tags/}"
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
|
||||
- name: Build for Linux
|
||||
run: bun run tauri build
|
||||
env:
|
||||
@@ -156,15 +162,13 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-bun-
|
||||
|
||||
# The tag is the single source of truth for a release version; the script
|
||||
# stamps every file that carries it (package.json, tauri.conf.json,
|
||||
# Cargo.toml, Cargo.lock). This step used to sed only tauri.conf.json, so
|
||||
# the other three shipped whatever was committed.
|
||||
- name: Set app version from tag
|
||||
run: |
|
||||
# On a tag build the tag is the single source of truth for the version.
|
||||
if echo "$GITHUB_REF" | grep -q '^refs/tags/v'; then
|
||||
VERSION="${GITHUB_REF#refs/tags/v}"
|
||||
echo "Setting version to $VERSION"
|
||||
sed -i "s/\"version\": \"[^\"]*\"/\"version\": \"$VERSION\"/" src-tauri/tauri.conf.json
|
||||
fi
|
||||
grep '"version"' src-tauri/tauri.conf.json
|
||||
run: ./scripts/set-version.sh "${GITHUB_REF#refs/tags/}"
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
|
||||
- name: Build Windows (NSIS installer + exe)
|
||||
run: OUTPUT_DIR="$PWD/dist/windows" WIN_BUNDLES=nsis ./scripts/build-windows-cross.sh
|
||||
@@ -217,48 +221,22 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: bun install
|
||||
|
||||
# Stamp before `android init`: it derives its generated project (including
|
||||
# the initial versionCode) from tauri.conf.json.
|
||||
- name: Set app version from tag
|
||||
run: |
|
||||
# On a tag build, the tag is the single source of truth for the
|
||||
# version name. On non-tag runs keep whatever is in tauri.conf.json.
|
||||
if echo "$GITHUB_REF" | grep -q '^refs/tags/v'; then
|
||||
VERSION="${GITHUB_REF#refs/tags/v}"
|
||||
echo "Setting version to $VERSION"
|
||||
sed -i "s/\"version\": \"[^\"]*\"/\"version\": \"$VERSION\"/" src-tauri/tauri.conf.json
|
||||
fi
|
||||
grep '"version"' src-tauri/tauri.conf.json
|
||||
run: ./scripts/set-version.sh "${GITHUB_REF#refs/tags/}"
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
|
||||
- name: Initialize Android project
|
||||
run: bun run tauri android init
|
||||
|
||||
# Re-run after init: tauri.properties only exists now, and its
|
||||
# autogenerated versionCode (0.0.15 -> 15) is both tiny and NOT monotonic
|
||||
# against the 1000 floor already shipped in the field. The script rewrites
|
||||
# it as 1000 + major*10000 + minor*100 + patch. Runs unconditionally so
|
||||
# untagged builds get a sane code too, derived from git describe.
|
||||
- name: Pin a monotonic Android versionCode
|
||||
run: |
|
||||
# `tauri android init` autogenerates src-tauri/gen/android/app/tauri.properties
|
||||
# with a versionCode derived from the semver (e.g. 0.0.15 -> 15). That
|
||||
# number is (a) tiny and (b) NOT monotonic across our history: earlier
|
||||
# local/dev builds shipped versionCode 1000 (from a 0.1.0 config), so a
|
||||
# plain 15 would be a *downgrade* and Android would refuse the update.
|
||||
#
|
||||
# Derive an explicit code that is both monotonic in semver order and
|
||||
# always above the 1000 floor already in the field:
|
||||
# code = 1000 + major*10000 + minor*100 + patch
|
||||
# e.g. 0.0.14 -> 1014, 0.0.15 -> 1015, 0.1.0 -> 1100, 1.0.0 -> 11000.
|
||||
# POSIX sh only (the runner uses dash): no here-strings, no \s in sed.
|
||||
PROPS="src-tauri/gen/android/app/tauri.properties"
|
||||
VERSION=$(grep '"version"' src-tauri/tauri.conf.json | head -1 | sed -E 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/')
|
||||
MAJ=$(echo "$VERSION" | cut -d. -f1)
|
||||
MIN=$(echo "$VERSION" | cut -d. -f2)
|
||||
PAT=$(echo "$VERSION" | cut -d. -f3)
|
||||
# Guard against a malformed/missing component so we never emit code 0.
|
||||
: "${MAJ:=0}" "${MIN:=0}" "${PAT:=0}"
|
||||
CODE=$(( 1000 + MAJ*10000 + MIN*100 + PAT ))
|
||||
echo "version=$VERSION -> versionCode=$CODE"
|
||||
if grep -q '^tauri.android.versionCode=' "$PROPS"; then
|
||||
sed -i "s/^tauri.android.versionCode=.*/tauri.android.versionCode=$CODE/" "$PROPS"
|
||||
else
|
||||
echo "tauri.android.versionCode=$CODE" >> "$PROPS"
|
||||
fi
|
||||
cat "$PROPS"
|
||||
run: ./scripts/set-version.sh "${GITHUB_REF#refs/tags/}"
|
||||
|
||||
- name: Sync custom Android sources & gradle config
|
||||
run: ./scripts/sync-android-sources.sh
|
||||
|
||||
Reference in New Issue
Block a user