57 lines
3.2 KiB
Bash
57 lines
3.2 KiB
Bash
#!/usr/bin/env bash
|
|
# Test clusev-release.sh `stage`: bump config version, commit, tag vX.Y.Z-betaN, push to a (local)
|
|
# Gitea-stand-in remote; beta auto-increment; refusals (dirty / unpushed / downgrade); push-fail rollback.
|
|
set -euo pipefail
|
|
here="$(cd "$(dirname "$0")" && pwd)"
|
|
work="$(mktemp -d)"; trap 'rm -rf "$work"' EXIT
|
|
export GIT_AUTHOR_NAME=t GIT_AUTHOR_EMAIL=t@t GIT_COMMITTER_NAME=t GIT_COMMITTER_EMAIL=t@t
|
|
|
|
# bare "Gitea" remote + a working clone with a config/clusev.php on branch main
|
|
git init -q --bare "$work/remote.git"
|
|
git clone -q "$work/remote.git" "$work/proj"
|
|
git -C "$work/proj" checkout -q -b main
|
|
mkdir -p "$work/proj/config"
|
|
printf "<?php\nreturn [\n 'version' => '0.9.58',\n];\n" > "$work/proj/config/clusev.php"
|
|
git -C "$work/proj" add -A && git -C "$work/proj" commit -qm init && git -C "$work/proj" push -q -u origin main
|
|
|
|
printf 'GIT_ACCESS_TOKEN=dummy\n' > "$work/.env.gitea"
|
|
run() { CLUSEV_DIR="$work/proj" CLUSEV_RELEASE_BRANCH=main CLUSEV_GITEA_ENV="$work/.env.gitea" bash "$here/clusev-release.sh" "$@"; }
|
|
|
|
# happy path: minor -> 0.10.0-beta1, config bumped, tag pushed to the remote
|
|
tag="$(run stage 0.10.0)"
|
|
test "$tag" = "v0.10.0-beta1" || { echo "FAIL: expected v0.10.0-beta1, got '$tag'"; exit 1; }
|
|
grep -q "'version' => '0.10.0-beta1'" "$work/proj/config/clusev.php" || { echo "FAIL: config not bumped"; exit 1; }
|
|
git -C "$work/remote.git" tag | grep -qx 'v0.10.0-beta1' || { echo "FAIL: tag not pushed to remote"; exit 1; }
|
|
|
|
# second run, same target -> beta2
|
|
tag2="$(run stage 0.10.0)"
|
|
test "$tag2" = "v0.10.0-beta2" || { echo "FAIL: expected beta2, got '$tag2'"; exit 1; }
|
|
|
|
# downgrade rejected (target below the current base 0.10.0)
|
|
if run stage 0.9.0 2>/dev/null; then echo "FAIL: downgrade not rejected"; exit 1; fi
|
|
|
|
# dirty tree rejected
|
|
echo dirt > "$work/proj/dirt.txt"
|
|
if run stage 0.11.0 2>/dev/null; then echo "FAIL: dirty tree not rejected"; exit 1; fi
|
|
rm -f "$work/proj/dirt.txt"
|
|
|
|
# unpushed commit rejected
|
|
echo x >> "$work/proj/config/clusev.php"; git -C "$work/proj" commit -qam wip
|
|
if run stage 0.11.0 2>/dev/null; then echo "FAIL: unpushed commit not rejected"; exit 1; fi
|
|
git -C "$work/proj" reset -q --hard origin/main
|
|
|
|
# push-fail rollback: a remote that ACCEPTS fetch but REJECTS push (pre-receive exit 1). _precheck
|
|
# passes (fetch ok, HEAD == origin), _do_stage creates the commit+tag, the push is rejected, and
|
|
# _rollback must delete the tag + reset HEAD so no half-release lingers. (A dead remote would fail at
|
|
# _precheck's fetch and never reach _do_stage, leaving the rollback path untested.)
|
|
printf '#!/bin/sh\nexit 1\n' > "$work/remote.git/hooks/pre-receive"
|
|
chmod +x "$work/remote.git/hooks/pre-receive"
|
|
before="$(git -C "$work/proj" rev-parse HEAD)"
|
|
if run stage 0.11.0 2>/dev/null; then echo "FAIL: push to a rejecting remote should fail"; exit 1; fi
|
|
rm -f "$work/remote.git/hooks/pre-receive"
|
|
git -C "$work/proj" tag | grep -qx 'v0.11.0-beta1' && { echo "FAIL: tag not rolled back after push reject"; exit 1; }
|
|
test "$(git -C "$work/proj" rev-parse HEAD)" = "$before" || { echo "FAIL: HEAD not rolled back after push reject"; exit 1; }
|
|
test -z "$(git -C "$work/proj" status --porcelain)" || { echo "FAIL: config not restored (dirty) after rollback"; exit 1; }
|
|
|
|
echo "PASS"
|