152 lines
5.6 KiB
Bash
Executable file
152 lines
5.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# One-command SkateSpots release: bump → test → build APK → publish to
|
|
# Zapstore → verify → commit/push (+ optional git tag).
|
|
#
|
|
# Usage:
|
|
# scripts/release.sh patch|minor|major [--yes] [--deploy]
|
|
# scripts/release.sh 1.7.1 [--yes] [--deploy]
|
|
# --deploy also forces the web deploy (bypasses the 24h Netlify throttle,
|
|
# costs 15 credits); without it the deploy timer ships it shortly.
|
|
#
|
|
# Before running:
|
|
# 1. write the new section at the TOP of release-notes.txt (do not commit it —
|
|
# this script commits it with the version bump);
|
|
# 2. the signer is read from ~/.config/skatespots/zsp.env (chmod 600) by
|
|
# default. You can also export SIGN_WITH for the current shell, or set
|
|
# SKATES_RELEASE_ENV to another 0600 file.
|
|
#
|
|
# What it does NOT do: deploy the web (the skatespots-deploy.timer does that
|
|
# within ~3 min, 24h throttle) or touch the relay.
|
|
set -euo pipefail
|
|
|
|
REPO="/home/sovereignsk8/SkateSpots"
|
|
ZSP="${ZSP:-$HOME/go/bin/zsp}"
|
|
export ANDROID_HOME="${ANDROID_HOME:-$HOME/Android/Sdk}"
|
|
SPEC="${1:-}"
|
|
YES=0
|
|
DEPLOY=0
|
|
shift || true
|
|
for a in "$@"; do
|
|
[ "$a" = "--yes" ] && YES=1
|
|
[ "$a" = "--deploy" ] && DEPLOY=1
|
|
done
|
|
|
|
die() { echo "✗ $*" >&2; exit 1; }
|
|
log() { echo "• $*"; }
|
|
|
|
[ -n "$SPEC" ] || die "usage: scripts/release.sh patch|minor|major|<x.y.z> [--yes]"
|
|
[ -x "$ZSP" ] || die "zsp not found/executable at $ZSP (set ZSP=...)"
|
|
[ -d "$ANDROID_HOME" ] || die "Android SDK not found at $ANDROID_HOME (set ANDROID_HOME=...)"
|
|
|
|
# Protected env file (never commit it). Prefer the file documented in AGENTS.
|
|
if [ -z "${SKATES_RELEASE_ENV:-}" ] && [ -f "$HOME/.config/skatespots/zsp.env" ]; then
|
|
SKATES_RELEASE_ENV="$HOME/.config/skatespots/zsp.env"
|
|
fi
|
|
if [ -z "${SIGN_WITH:-}" ] && [ -n "${SKATES_RELEASE_ENV:-}" ]; then
|
|
[ -f "$SKATES_RELEASE_ENV" ] || die "SKATES_RELEASE_ENV does not exist: $SKATES_RELEASE_ENV"
|
|
mode="$(stat -c %a "$SKATES_RELEASE_ENV" 2>/dev/null || echo '?')"
|
|
case "$mode" in
|
|
600|400) ;;
|
|
*) log "warning: $SKATES_RELEASE_ENV is mode $mode (chmod 600 recommended)" ;;
|
|
esac
|
|
set -a
|
|
# shellcheck disable=SC1090
|
|
. "$SKATES_RELEASE_ENV"
|
|
set +a
|
|
fi
|
|
[ -n "${SIGN_WITH:-}" ] || die "SIGN_WITH is not set (use ~/.config/skatespots/zsp.env, SKATES_RELEASE_ENV, or export it)"
|
|
|
|
# Resolve the newest nvm Node (the old hard-coded path breaks after upgrades).
|
|
if [ -d "$HOME/.nvm/versions/node" ]; then
|
|
NODE_BIN="$(ls -d "$HOME"/.nvm/versions/node/*/bin 2>/dev/null | sort -V | tail -1)"
|
|
[ -n "$NODE_BIN" ] && export PATH="$NODE_BIN:$PATH"
|
|
fi
|
|
export PATH="$HOME/go/bin:$PATH"
|
|
|
|
cd "$REPO"
|
|
|
|
CURRENT="$(node -p "require('./package.json').version")"
|
|
log "current version: $CURRENT"
|
|
|
|
# The notes must be the only uncommitted change, so the release commit is clean.
|
|
if git diff --quiet -- release-notes.txt; then
|
|
die "release-notes.txt is unchanged — write the new section first (and don't commit it)"
|
|
fi
|
|
DIRTY="$(git status --porcelain | grep -vE '^ M release-notes\.txt$' || true)"
|
|
[ -z "$DIRTY" ] || die "working tree has other changes:
|
|
$DIRTY"
|
|
|
|
git fetch --quiet origin main
|
|
[ "$(git rev-parse HEAD)" = "$(git rev-parse origin/main)" ] || \
|
|
die "local main is not in sync with origin/main — push or pull first"
|
|
|
|
if [ "$YES" -eq 0 ]; then
|
|
[ -t 0 ] || die "non-interactive: pass --yes to confirm"
|
|
printf 'Release %s from %s? [y/N] ' "$SPEC" "$CURRENT"
|
|
read -r ans
|
|
case "$ans" in y|Y|yes|YES) ;; *) die "aborted" ;; esac
|
|
fi
|
|
|
|
log "running the full test gate (this also builds the web bundle)…"
|
|
npm test
|
|
|
|
log "bumping version ($SPEC)…"
|
|
# --force: the only dirty file is release-notes.txt, which `npm version`
|
|
# otherwise refuses to bump over. The tree was already validated above.
|
|
npm version "$SPEC" --no-git-tag-version --force >/dev/null
|
|
VERSION="$(node -p "require('./package.json').version")"
|
|
[ "$VERSION" != "$CURRENT" ] || die "version did not change"
|
|
log "version: $VERSION"
|
|
|
|
log "building the signed release APK…"
|
|
npm run android:build
|
|
|
|
APK="android/app/build/outputs/apk/release/app-release.apk"
|
|
[ -f "$APK" ] || die "APK not found at $APK"
|
|
SHA="$(sha256sum "$APK" | awk '{print $1}')"
|
|
log "APK: $APK (sha256 ${SHA:0:16}…)"
|
|
|
|
log "publishing to Zapstore…"
|
|
# shellcheck disable=SC2086
|
|
"$ZSP" publish --quiet zapstore.yaml
|
|
|
|
log "verifying the Zapstore release event…"
|
|
FOUND=0
|
|
for _ in 1 2 3 4 5 6; do
|
|
if command -v nak >/dev/null 2>&1; then
|
|
OUT="$(timeout 15 nak req -k 30063 -d "org.skatespots.app@$VERSION" wss://relay.zapstore.dev 2>/dev/null || true)"
|
|
if printf '%s' "$OUT" | grep -qE "\"version\"[[:space:]]*,[[:space:]]*\"$VERSION\""; then FOUND=1; break; fi
|
|
else
|
|
log "nak not installed — skipping relay verification"
|
|
FOUND=1
|
|
break
|
|
fi
|
|
sleep 4
|
|
done
|
|
[ "$FOUND" -eq 1 ] || log "warning: the release event did not appear on the relay yet (it usually propagates shortly)"
|
|
|
|
log "committing the release…"
|
|
git add package.json package-lock.json release-notes.txt
|
|
git commit -m "release: $VERSION" >/dev/null
|
|
git tag -a "v$VERSION" -m "SkateSpots $VERSION"
|
|
git push origin main
|
|
if ! git push origin "v$VERSION" 2>/dev/null; then
|
|
log "warning: tag v$VERSION was created locally but the push failed"
|
|
fi
|
|
|
|
if [ "$DEPLOY" -eq 1 ]; then
|
|
log "forcing the web deploy (bypasses the 24h Netlify throttle)…"
|
|
scripts/auto-deploy.sh --force || log "warning: web deploy failed — check journalctl --user -u skatespots-deploy"
|
|
fi
|
|
|
|
echo
|
|
echo "✓ SkateSpots $VERSION published"
|
|
echo " APK: $APK"
|
|
echo " SHA256: $SHA"
|
|
if [ "$DEPLOY" -eq 1 ]; then
|
|
echo " Web: forced deploy requested above"
|
|
else
|
|
echo " Web: the deploy timer picks up the commit within ~3 min (24h throttle)"
|
|
fi
|
|
echo " Zapstore: https://zapstore.dev/apps/org.skatespots.app"
|