#!/usr/bin/env bash # Publish a Furtka release to the Forgejo releases page. # # Usage: ./scripts/publish-release.sh # # Preconditions: # - $FORGEJO_TOKEN set (PAT with write:repository) # - dist/furtka-.tar.gz + .sha256 + release.json already built # # Behaviour: # 1. Read the [] section from CHANGELOG.md for the release body. # 2. Create a release on Forgejo (or fail if one already exists for the tag). # 3. Upload the three assets sequentially (Forgejo's release API has been # observed to choke on parallel uploads). set -euo pipefail VERSION="${1:?usage: $0 }" : "${FORGEJO_TOKEN:?FORGEJO_TOKEN must be set}" HOST="${FORGEJO_HOST:-forgejo.sourcegate.online}" REPO="${FORGEJO_REPO:-daniel/furtka}" REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" DIST_DIR="$REPO_ROOT/dist" TARBALL="$DIST_DIR/furtka-$VERSION.tar.gz" SHA_FILE="$TARBALL.sha256" RELEASE_JSON="$DIST_DIR/release.json" for f in "$TARBALL" "$SHA_FILE" "$RELEASE_JSON"; do [ -f "$f" ] || { echo "missing: $f"; exit 1; } done # Extract the changelog section for this version. Matches `## []` # up to (but not including) the next `## [` line. BODY="$(awk -v v="$VERSION" ' BEGIN { inside=0 } /^## \[/ { if (inside) exit if (index($0, "[" v "]") > 0) { inside=1; next } } inside { print } ' "$REPO_ROOT/CHANGELOG.md")" if [ -z "$BODY" ]; then BODY="Release $VERSION" fi PRERELEASE=false if [[ "$VERSION" == *-alpha* || "$VERSION" == *-beta* || "$VERSION" == *-rc* ]]; then PRERELEASE=true fi api() { curl --silent --show-error --fail-with-body \ --header "Authorization: token $FORGEJO_TOKEN" \ "$@" } base="https://$HOST/api/v1/repos/$REPO" # 1. Create the release. Python for JSON assembly so we don't depend on jq # on the runner — the previous `apt-get install -y jq` step in release.yml # hung for 15+ minutes on a slow mirror and stalled the whole publish. release_body_json="$( VERSION="$VERSION" BODY="$BODY" PRE="$PRERELEASE" python3 -c ' import json, os print(json.dumps({ "tag_name": os.environ["VERSION"], "name": os.environ["VERSION"], "body": os.environ["BODY"], "prerelease": os.environ["PRE"] == "true", })) ' )" echo "==> Creating release $VERSION" release_response="$(api --request POST "$base/releases" \ --header "Content-Type: application/json" \ --data "$release_body_json")" release_id="$(echo "$release_response" | python3 -c 'import json, sys; print(json.load(sys.stdin).get("id", ""))')" if [ -z "$release_id" ] || [ "$release_id" = "null" ]; then echo "error: couldn't parse release id from response:" echo "$release_response" exit 1 fi echo " release id: $release_id" # 2. Upload assets — one at a time. upload_asset() { local path="$1" local name name="$(basename "$path")" echo "==> Uploading $name" api --request POST "$base/releases/$release_id/assets?name=$name" \ --form "attachment=@$path" > /dev/null } upload_asset "$TARBALL" upload_asset "$SHA_FILE" upload_asset "$RELEASE_JSON" echo "Release $VERSION published: https://$HOST/$REPO/releases/tag/$VERSION"