SkateSpots/scripts/publish-forgejo.sh
SkateSpots 383ff8a5cf
Some checks are pending
Deploy to GitHub Pages / deploy (push) Waiting to run
dist: add Forgejo release helper and F-Droid instructions
2026-10-30 22:49:23 +07:00

108 lines
3.4 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Publish a built APK to the self-hosted Forgejo release page.
#
# Usage:
# FORGEJO_TOKEN=... scripts/publish-forgejo.sh 1.7.62 [path/to.apk]
# FORGEJO_PASSWORD=... FORGEJO_USER=skatespots scripts/publish-forgejo.sh 1.7.62
#
# This uploads the APK and its .sha256 file. It does not push the git tag or
# source; do that separately (the Forgejo repo is a mirror, not an auto-push
# remote). Keep credentials in your shell/environment, never in this repo.
set -euo pipefail
VERSION="${1:?usage: publish-forgejo.sh <version> [apk]}"
APK="${2:-android/app/build/outputs/apk/release/app-release.apk}"
TAG="${FORGEJO_TAG:-v$VERSION}"
BASE="${FORGEJO_URL:-https://git.skate-spots.org}"
OWNER="${FORGEJO_OWNER:-skatespots}"
REPO="${FORGEJO_REPO:-SkateSpots}"
API="$BASE/api/v1/repos/$OWNER/$REPO"
command -v curl >/dev/null || { echo "curl is required" >&2; exit 1; }
command -v python3 >/dev/null || { echo "python3 is required" >&2; exit 1; }
[ -f "$APK" ] || { echo "APK not found: $APK" >&2; exit 1; }
AUTH=()
if [ -n "${FORGEJO_TOKEN:-}" ]; then
AUTH=(-H "Authorization: token $FORGEJO_TOKEN")
elif [ -n "${FORGEJO_PASSWORD:-}" ]; then
AUTH=(-u "${FORGEJO_USER:-skatespots}:$FORGEJO_PASSWORD")
else
echo "set FORGEJO_TOKEN (preferred) or FORGEJO_PASSWORD" >&2
exit 1
fi
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
sha="$(sha256sum "$APK" | awk '{print $1}')"
body="$tmpdir/release.md"
cat >"$body" <<EOF
## SkateSpots $VERSION
Signed Android release. SHA-256: \`$sha\`
- Source: $BASE/$OWNER/$REPO
- APK signing key: same as the Zapstore release.
EOF
python3 - "$TAG" "$VERSION" "$body" >"$tmpdir/payload.json" <<'PY'
import json
import sys
from pathlib import Path
tag, version, body_path = sys.argv[1:]
print(json.dumps({
"tag_name": tag,
"name": version,
"body": Path(body_path).read_text(),
"draft": False,
"prerelease": False,
}))
PY
create_code="$(curl -sS -o "$tmpdir/release.json" -w '%{http_code}' \
"${AUTH[@]}" -H 'Content-Type: application/json' \
-X POST "$API/releases" --data-binary @"$tmpdir/payload.json" || true)"
if [ "$create_code" = "201" ]; then
release_id="$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["id"])' "$tmpdir/release.json")"
elif [ "$create_code" = "409" ] || [ "$create_code" = "422" ]; then
curl -fsS "${AUTH[@]}" "$API/releases/tags/$TAG" -o "$tmpdir/release.json"
release_id="$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["id"])' "$tmpdir/release.json")"
else
echo "Forgejo release creation failed (HTTP $create_code)" >&2
cat "$tmpdir/release.json" >&2
exit 1
fi
sha_file="$tmpdir/SkateSpots-$VERSION.apk.sha256"
printf '%s SkateSpots-%s.apk\n' "$sha" "$VERSION" >"$sha_file"
existing_assets="$(python3 - "$tmpdir/release.json" <<'PY'
import json
import sys
data = json.load(open(sys.argv[1]))
print("\n".join(asset["name"] for asset in data.get("assets", [])))
PY
)"
for file in "$APK" "$sha_file"; do
name="$(basename "$file")"
if printf '%s\n' "$existing_assets" | grep -Fqx "$name"; then
echo "already present: $name"
continue
fi
code="$(curl -sS -o "$tmpdir/asset.json" -w '%{http_code}' \
"${AUTH[@]}" -X POST "$API/releases/$release_id/assets?name=$name" \
-F "attachment=@$file" || true)"
case "$code" in
201|202) echo "uploaded $name" ;;
*) echo "warning: upload of $name returned HTTP $code" >&2 ;;
esac
done
echo "release: $BASE/$OWNER/$REPO/releases/tag/$TAG"
echo "latest: $BASE/$OWNER/$REPO/releases/latest"