onionwire/scripts/publish-release.sh
Sirius DevOps 91fd9601b8
Some checks failed
ci / test (push) Failing after 1m6s
ci: Forgejo-native ci + release workflows
The GitHub workflows could never run on this instance: jobs asked for
ubuntu-24.04 runners (the Pi runner only registers the 'docker' label, so
every job sat in waiting), and release.yml published to github.com, which
is not a remote of this repo.

- .forgejo/workflows/ci.yml  — cargo test + clippy on the 'docker' label,
  Rust work in a rust:1.87-bookworm sibling container (aarch64 native)
- .forgejo/workflows/release.yml — on v*.*.* tags, build aarch64, strip,
  sha256, publish to the Forgejo release; workflow_dispatch takes a tag
  to re-publish
- scripts/publish-release.sh — idempotent create-or-update release +
  asset upload via the Forgejo API (replaces same-named assets)
- scripts/build-release-local.sh — x86_64 path (no x86_64 runner exists)
- scripts/release-body.md — release notes template (@TAG@ substituted)
- README: install URLs -> Forgejo, accurate maintainer release procedure
- remove .github/workflows/*
2026-09-10 13:10:56 -04:00

88 lines
3.3 KiB
Bash
Executable file

#!/usr/bin/env bash
# Create-or-update a Forgejo release and (re)upload its assets.
#
# Usage: publish-release.sh <tag> <release-name> <body-file> <asset> [<asset>...]
# Env: FORGEJO_TOKEN user PAT with repo write (required)
# REPO_API default https://forgejo.siriusdevops.com/api/v1/repos/sirius/onionwire
# TARGET_COMMITISH default: push-triggered commit (CI) else "main"
#
# Idempotent: re-running for the same tag reuses the release and replaces
# same-named assets instead of failing with 409.
set -euo pipefail
tag="${1:?usage: publish-release.sh <tag> <name> <body-file> <asset>...}"
name="${2:?missing release name}"
body_file="${3:?missing body file}"
shift 3
: "${FORGEJO_TOKEN:?FORGEJO_TOKEN is not set}"
api="${REPO_API:-https://forgejo.siriusdevops.com/api/v1/repos/sirius/onionwire}"
target="${TARGET_COMMITISH:-main}"
jqp() { python3 -c "import json,sys; d=json.load(sys.stdin); print($1)"; }
# Body with @TAG@ substituted, JSON-encoded by python (handles newlines/quotes).
python3 - "$body_file" "$tag" "$target" "$name" > /tmp/release-body.json <<'PY'
import json, sys
body = open(sys.argv[1]).read().replace("@TAG@", sys.argv[2])
print(json.dumps({
"tag_name": sys.argv[2],
"target_commitish": sys.argv[3],
"name": sys.argv[4],
"body": body,
"draft": False,
"prerelease": False,
}))
PY
code=$(curl -s -o /tmp/release-rel.json -w '%{http_code}' \
-H "Authorization: Bearer $FORGEJO_TOKEN" "$api/releases/tags/$tag")
if [ "$code" = "404" ]; then
echo "publish: creating release $tag"
curl -sf -X POST "$api/releases" \
-H "Authorization: Bearer $FORGEJO_TOKEN" \
-H 'Content-Type: application/json' \
--data @/tmp/release-body.json -o /tmp/release-rel.json
elif [ "$code" = "200" ]; then
echo "publish: release $tag exists, updating"
rid=$(jqp "d['id']" < /tmp/release-rel.json)
curl -sf -X PATCH "$api/releases/$rid" \
-H "Authorization: Bearer $FORGEJO_TOKEN" \
-H 'Content-Type: application/json' \
--data @/tmp/release-body.json -o /tmp/release-rel.json
else
echo "publish: unexpected status $code from GET releases/tags/$tag" >&2
cat /tmp/release-rel.json >&2; exit 1
fi
rid=$(jqp "d['id']" < /tmp/release-rel.json)
echo "publish: release id $rid ($tag)"
# Replace same-named assets so re-runs are clean.
for f in "$@"; do
[ -f "$f" ] || { echo "publish: missing asset $f" >&2; exit 1; }
asset=$(basename "$f")
curl -s -H "Authorization: Bearer $FORGEJO_TOKEN" "$api/releases/$rid/assets" \
| python3 -c "
import json,sys
for a in json.load(sys.stdin):
print(a['id'], a.get('name',''))
" | while read -r aid aname; do
if [ "$aname" = "$asset" ]; then
echo "publish: deleting stale asset $aname ($aid)"
curl -sf -X DELETE -H "Authorization: Bearer $FORGEJO_TOKEN" \
"$api/releases/$rid/assets/$aid" > /dev/null
fi
done
curl -sf -X POST "$api/releases/$rid/assets?name=$asset" \
-H "Authorization: Bearer $FORGEJO_TOKEN" \
-F "attachment=@$f" -o /tmp/release-asset.json
python3 -c "
import json;d=json.load(open('/tmp/release-asset.json'))
print('publish: uploaded', d['name'], d['size'], 'bytes')"
done
curl -s -H "Authorization: Bearer $FORGEJO_TOKEN" "$api/releases/$rid/assets" \
| python3 -c "
import json,sys
for a in json.load(sys.stdin):
print('publish: asset ', a['name'], a['size'])"