Vectrum
Sign In

build.sh -v sets the version before building

./build.sh -v 0.1.2 -r updates Cargo.toml and Cargo.lock, commits them as
Version 0.1.2, builds, tags and publishes the release. Uploads the AppImage
first and the checksums last, and shows why an upload failed; running the
same command again retries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
JjohannSocommitted 1 parent f298ee6commit91fc25a

Showing 2 changed files with 72 additions and 27 deletions.

+7−5README.mdView File
@@ -275,11 +275,13 @@ in its `scratch` folder.
275275
276276 ## Build and release
277277
278- `./build.sh` builds the release binary and an AppImage into `build/`. `./build.sh --release`
279- (or `-r`) also publishes them on Vectrum: it tags the commit with the version in `Cargo.toml`,
280- pushes the tag, and uploads the AppImage, the binary and `SHA256SUMS`, which publishes the
281- release. It needs a clean working tree, a version not tagged yet (bump it in `Cargo.toml` for
282- each release), and a read & write API token in `VECTRUM_TOKEN` or `~/.config/vectrum/token`.
278+ `./build.sh` builds the release binary and an AppImage into `build/`. `-v 0.1.2` first sets the
279+ version (in `Cargo.toml` and `Cargo.lock`, committed as "Version 0.1.2"), and `--release` (or
280+ `-r`) publishes the build on Vectrum: it tags the commit with the version, pushes the tag, and
281+ uploads the AppImage, the binary and `SHA256SUMS`, which publishes the release. So
282+ `./build.sh -v 0.1.2 -r` makes and publishes 0.1.2. Releasing needs a clean working tree, a
283+ version not tagged yet, and a read & write API token in `VECTRUM_TOKEN` or
284+ `~/.config/vectrum/token`; the version commit stays on your branch until you push it.
283285 `VECTRUM_URL` (`https://vectrum.cc`) and `VECTRUM_REPO` (from the origin remote) pick where
284286 it goes.
285287
+65−22build.shView File
@@ -6,23 +6,40 @@
66 # appimagetool is used from $PATH if present, otherwise downloaded once into
77 # build/.tools. Set APPIMAGETOOL=/path/to/appimagetool to use a specific one.
88 #
9- # ./build.sh --release (or -r) then publishes them as a release on Vectrum:
10- # it tags the commit with the version in Cargo.toml, pushes the tag, and
11- # uploads the AppImage, the binary and SHA256SUMS (the first upload
12- # publishes the release). Bump the version in Cargo.toml for each release.
9+ # Options:
10+ # -v, --version X set the version to X (0.1.2) first: updates Cargo.toml
11+ # and Cargo.lock and commits them as "Version X"
12+ # -r, --release then publish the build as a release on Vectrum: tag the
13+ # commit with the version, push the tag, and upload the
14+ # AppImage, the binary and SHA256SUMS (the first upload
15+ # publishes the release). Each release needs a new version.
16+ # -h, --help show this
17+ #
18+ # So ./build.sh -v 0.1.2 -r makes and publishes version 0.1.2. Releasing reads:
1319 # VECTRUM_TOKEN a read & write API token (vec_…); otherwise read from
1420 # ~/.config/vectrum/token (or $VECTRUM_TOKEN_FILE)
1521 # VECTRUM_URL the server, https://vectrum.cc by default
1622 # VECTRUM_REPO owner/repo, taken from the origin remote by default
1723 set -euo pipefail
1824
25+ log() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
26+ die() { printf '\033[1;31mxx\033[0m %s\n' "$*" >&2; exit 1; }
27+
1928 RELEASE=0
20- for arg in "$@"; do
21- case "$arg" in
29+ NEW_VERSION=""
30+ while (( $# )); do
31+ case "$1" in
2232 -r|--release) RELEASE=1 ;;
33+ -v|--version)
34+ [[ $# -ge 2 ]] || die "$1 needs a version, like $1 0.1.2"
35+ NEW_VERSION="$2"
36+ shift
37+ ;;
38+ --version=*) NEW_VERSION="${1#*=}" ;;
2339 -h|--help) sed -n '2,/^set -euo/p' "$0" | sed '$d; s/^# \{0,1\}//'; exit 0 ;;
24- *) printf 'Unknown option: %s (try --help)\n' "$arg" >&2; exit 2 ;;
40+ *) printf 'Unknown option: %s (try --help)\n' "$1" >&2; exit 2 ;;
2541 esac
42+ shift
2643 done
2744
2845 ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@@ -35,12 +52,21 @@ PRETTY="Vectrum Code"
3552 VERSION="$(sed -n 's/^version *= *"\(.*\)"/\1/p' "$ROOT/Cargo.toml" | head -n1)"
3653 ARCH="$(uname -m)"
3754
38- log() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
39- die() { printf '\033[1;31mxx\033[0m %s\n' "$*" >&2; exit 1; }
55+ dirty() { [[ -n "$(git -C "$ROOT" status --porcelain)" ]]; }
4056
41- # ── 0. Release checks, before spending time on a build ───────────────────────
57+ # Stops if tag $1 already names a commit other than $2 (any commit, if $2 is
58+ # empty), here or on origin. Sets REMOTE_TAG and LOCAL_TAG.
59+ check_tag() {
60+ REMOTE_TAG="$(git -C "$ROOT" ls-remote origin "refs/tags/$1^{}" "refs/tags/$1" | awk 'NR==1 || /\^\{\}$/ {sha=$1} END {print sha}')"
61+ LOCAL_TAG="$(git -C "$ROOT" rev-parse -q --verify "refs/tags/$1^{commit}" || true)"
62+ for tagged in "$REMOTE_TAG" "$LOCAL_TAG"; do
63+ [[ -z "$tagged" || "$tagged" == "$2" ]] ||
64+ die "$1 is already tagged at ${tagged:0:7}; pick a new version with -v"
65+ done
66+ }
67+
68+ # ── 0. Version and release checks, before spending time on a build ───────────
4269 if (( RELEASE )); then
43- TAG="$VERSION"
4470 SERVER="${VECTRUM_URL:-https://vectrum.cc}"
4571 SERVER="${SERVER%/}"
4672 TOKEN_FILE="${VECTRUM_TOKEN_FILE:-$HOME/.config/vectrum/token}"
@@ -52,14 +78,27 @@ if (( RELEASE )); then
5278 # ssh://git@git.vectrum.cc:2222/vectrum/code.git, https://…/vectrum/code → vectrum/code
5379 REPO="${VECTRUM_REPO:-$(git -C "$ROOT" remote get-url origin | sed -E 's#\.git$##; s#^.*[:/]([^/:]+/[^/:]+)$#\1#')}"
5480 [[ "$REPO" == */* ]] || die "Couldn't tell the repository from the origin remote; set VECTRUM_REPO=owner/repo"
55- [[ -z "$(git -C "$ROOT" status --porcelain)" ]] || die "Commit or stash your changes first: a release is built from a commit"
81+ fi
82+
83+ if [[ -n "$NEW_VERSION" && "$NEW_VERSION" != "$VERSION" ]]; then
84+ [[ "$NEW_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([-+][0-9A-Za-z.-]+)?$ ]] ||
85+ die "$NEW_VERSION isn't a version like 0.1.2"
86+ ! dirty || die "Commit or stash your changes first: the new version is committed on its own"
87+ if (( RELEASE )); then
88+ check_tag "$NEW_VERSION" ""
89+ fi
90+ log "Version $VERSION → $NEW_VERSION"
91+ sed -i "0,/^version *= *\".*\"/s//version = \"$NEW_VERSION\"/" "$ROOT/Cargo.toml"
92+ cargo update --workspace --offline --quiet --manifest-path "$ROOT/Cargo.toml"
93+ git -C "$ROOT" commit -q -m "Version $NEW_VERSION" -- Cargo.toml Cargo.lock
94+ VERSION="$NEW_VERSION"
95+ fi
96+
97+ if (( RELEASE )); then
98+ TAG="$VERSION"
99+ ! dirty || die "Commit or stash your changes first: a release is built from a commit"
56100 HEAD="$(git -C "$ROOT" rev-parse HEAD)"
57- REMOTE_TAG="$(git -C "$ROOT" ls-remote origin "refs/tags/$TAG^{}" "refs/tags/$TAG" | awk 'NR==1 || /\^\{\}$/ {sha=$1} END {print sha}')"
58- LOCAL_TAG="$(git -C "$ROOT" rev-parse -q --verify "refs/tags/$TAG^{commit}" || true)"
59- for tagged in "$REMOTE_TAG" "$LOCAL_TAG"; do
60- [[ -z "$tagged" || "$tagged" == "$HEAD" ]] ||
61- die "$TAG is already tagged at ${tagged:0:7}; bump the version in Cargo.toml for a new release"
62- done
101+ check_tag "$TAG" "$HEAD"
63102 log "Releasing $TAG of $REPO on $SERVER from ${HEAD:0:7}"
64103 fi
65104
@@ -146,14 +185,18 @@ if (( RELEASE )); then
146185 git -C "$ROOT" push -q origin "refs/tags/$TAG"
147186 fi
148187
149- for file in "$STAGE"/*; do
150- name="$(basename "$file")"
188+ # The checksums go last, so the release never shows them alone.
189+ for name in "$(basename "$OUT")" "$NAME-$VERSION-$ARCH" SHA256SUMS; do
190+ file="$STAGE/$name"
151191 log "Uploading $name"
152192 # The token goes in through a file descriptor, so it never shows in ps.
153193 if ! reply="$(curl -sS --fail-with-body -T "$file" -H @<(printf 'Authorization: Bearer %s\n' "$TOKEN") \
154- "$SERVER/$REPO/releases/download/$TAG/$name")"; then
155- die "Uploading $name failed: $reply"
194+ "$SERVER/$REPO/releases/download/$TAG/$name" 2>&1)"; then
195+ die "Uploading $name failed: $reply (run the same command again to retry)"
156196 fi
157197 done
158198 log "Released: $SERVER/$REPO/releases/tag/$TAG"
159199 fi
200+ if [[ -n "$NEW_VERSION" ]] && [[ -n "$(git -C "$ROOT" log --oneline '@{upstream}..HEAD' 2>/dev/null || echo unpushed)" ]]; then
201+ log "The version commit is only on your $(git -C "$ROOT" branch --show-current) branch here: git push to share it"
202+ fi