Files
Classroom_Desktop/tests/test-gitea-release.sh
ekklesiaandClaude Opus 5.5 0f96019714 feat: gitea-release, a release record that never replaces published bytes
Gitea lets anyone with write access swap a release asset for another of
the same name. tools/gitea-release, which the workflows use for every
release write, uploads only under a name the release lacks, leaves
identical bytes alone, refuses different ones, never moves a tag, and
only appends to the record. Measured on a throwaway Gitea 1.27.2 with the
automatic Actions token; tested here against a stand-in API.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 18:47:42 -05:00

129 lines
5.4 KiB
Bash
Executable File

#!/bin/bash
# The Gitea release record, against a stand-in for Gitea's API.
#
# Nothing here reaches the real Gitea. The stand-in keeps tags, releases
# and assets in memory, answers the handful of calls tools/gitea-release
# makes the way Gitea 1.27 answers them, and refuses any write that does
# not carry the token. The questions are the ones that matter for a
# permanent record: a tag is never moved, an asset's bytes are never
# replaced, and the record only ever grows.
set -uo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
WORK="$(mktemp -d)"
SERVER_PID=""
cleanup() {
[[ -z "$SERVER_PID" ]] || kill "$SERVER_PID" 2>/dev/null
rm -rf "$WORK"
}
trap cleanup EXIT
passed=0
failed=0
check() {
local label="$1"
shift
if "$@" >/dev/null 2>&1; then
echo " ok $label"
passed=$((passed + 1))
else
echo " FAIL $label"
failed=$((failed + 1))
fi
}
refuses() {
! "$@"
}
python3 "$ROOT/tests/fake-gitea.py" > "$WORK/port" 2>"$WORK/gitea.log" &
SERVER_PID=$!
for _ in $(seq 1 50); do
[[ -s "$WORK/port" ]] && break
sleep 0.1
done
export GITEA_URL="http://127.0.0.1:$(cat "$WORK/port")"
export GITEA_REPO=church/classroom
export GITEA_TOKEN=not-a-real-token
RELEASE="$ROOT/tools/gitea-release"
A=$(printf 'a%.0s' {1..40})
B=$(printf 'b%.0s' {1..40})
printf 'the package\n' > "$WORK/ekklesia-classroom_0.9.1_amd64.deb"
printf '# 0.9.1\n\nNotes.\n' > "$WORK/notes.md"
echo "1. a release, created once, at one commit"
check "no release yet is its own answer" \
bash -c "'$RELEASE' show v0.9.1; [[ \$? -eq 3 ]]"
check "it is created at the commit named" \
"$RELEASE" create v0.9.1 "$A" "0.9.1" "$WORK/notes.md" --prerelease
check "and its tag names that commit" \
bash -c "[[ \$(curl -fsS '$GITEA_URL/api/v1/repos/church/classroom/tags/v0.9.1' | python3 -c 'import json,sys; print(json.load(sys.stdin)[\"commit\"][\"sha\"])') == $A ]]"
check "it is a pre-release until it is promoted" \
bash -c "api() { curl -fsS '$GITEA_URL/api/v1/repos/church/classroom'\$1; }; api /releases/tags/v0.9.1 | grep -q '\"prerelease\": true'"
check "creating it again at the same commit changes nothing" \
"$RELEASE" create v0.9.1 "$A" "0.9.1" "$WORK/notes.md" --prerelease
check "a tag is never moved to another commit" \
refuses "$RELEASE" create v0.9.1 "$B" "0.9.1" "$WORK/notes.md"
check "nor is a tag that already exists taken over" \
refuses "$RELEASE" create v0.1.5 "$B" "0.1.5" "$WORK/notes.md"
echo "2. assets: attached once, never replaced"
check "the package is attached" \
"$RELEASE" upload v0.9.1 "$WORK/ekklesia-classroom_0.9.1_amd64.deb"
check "and reads back as the same bytes" \
bash -c "'$RELEASE' download v0.9.1 ekklesia-classroom_0.9.1_amd64.deb '$WORK/back.deb' \
&& cmp -s '$WORK/back.deb' '$WORK/ekklesia-classroom_0.9.1_amd64.deb'"
check "the same file again is left alone, and is not an error" \
bash -c "'$RELEASE' upload v0.9.1 '$WORK/ekklesia-classroom_0.9.1_amd64.deb' | grep -q 'left alone'"
mkdir -p "$WORK/rebuilt"
printf 'a different build\n' > "$WORK/rebuilt/ekklesia-classroom_0.9.1_amd64.deb"
check "different bytes under the same name are refused" \
refuses "$RELEASE" upload v0.9.1 "$WORK/rebuilt/ekklesia-classroom_0.9.1_amd64.deb"
check "and the published bytes are still the first ones" \
bash -c "'$RELEASE' download v0.9.1 ekklesia-classroom_0.9.1_amd64.deb '$WORK/back2.deb' \
&& cmp -s '$WORK/back2.deb' '$WORK/ekklesia-classroom_0.9.1_amd64.deb'"
check "an asset the release does not have is refused, not invented" \
refuses "$RELEASE" download v0.9.1 nothing.deb "$WORK/nothing"
curl -fsS "$GITEA_URL/test/tamper/v0.9.1/ekklesia-classroom_0.9.1_amd64.deb" >/dev/null
check "an asset changed by hand is caught at the next upload" \
refuses "$RELEASE" upload v0.9.1 "$WORK/ekklesia-classroom_0.9.1_amd64.deb"
echo "3. the record only grows"
check "a line is recorded" \
"$RELEASE" record v0.9.1 "published to Preview (canary)"
check "and another" \
"$RELEASE" record v0.9.1 "promoted to Stable"
check "the notes, the creation line and both records are all there, in order" \
bash -c "curl -fsS '$GITEA_URL/api/v1/repos/church/classroom/releases/tags/v0.9.1' \
| python3 -c 'import json,sys
b = json.load(sys.stdin)[\"body\"]
order = [b.index(t) for t in (\"Notes.\", \"## Record\", \"release created at\", \"Preview (canary)\", \"promoted to Stable\")]
assert order == sorted(order), order
assert b.count(\"## Record\") == 1'"
check "the notes and record read back as text" \
bash -c "'$RELEASE' notes v0.9.1 | grep -q 'Preview (canary)'"
check "and asking for a release there is none of is refused" \
refuses "$RELEASE" notes v0.0.0
check "promoted, it is no longer a pre-release" \
bash -c "'$RELEASE' stable v0.9.1 && curl -fsS '$GITEA_URL/api/v1/repos/church/classroom/releases/tags/v0.9.1' | grep -q '\"prerelease\": false'"
echo "4. credentials"
check "a write without the token is refused by Gitea, and reported" \
refuses env GITEA_TOKEN= "$RELEASE" record v0.9.1 "nobody"
check "the token never appears in anything it prints" \
bash -c "! { '$RELEASE' show v0.9.1; '$RELEASE' record v0.9.1 x; '$RELEASE' upload v0.9.1 '$WORK/rebuilt/ekklesia-classroom_0.9.1_amd64.deb'; } 2>&1 | grep -q not-a-real-token"
check "nothing works without knowing which Gitea" \
refuses env -u GITEA_URL -u GITHUB_SERVER_URL "$RELEASE" show v0.9.1
echo
echo "$passed passed, $failed failed"
[[ $failed -eq 0 ]]