#!/usr/bin/env bash # Publishes a Cobble release to the Gitea mirror. # # scripts/publish-gitea.sh # # Runs the same release gate as the GitHub script, tags HEAD with the # package.json version, pushes main and the tag to the `gitea` remote, then # creates the Gitea release over the API. # # Gitea has no release workflow, so nothing is built here: the image is built # once by .github/workflows/release.yml and mirrored to # git.tben.me/moduletrace/cobble. This script only publishes the source and # the release object. # # The token comes from GITEA_TOKEN, or from the Gitea section of ~/.config/tea # if the tea CLI is installed. It needs the `write:repository` scope on the # repository, which is what the repo scope gives. set -Eeuo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=lib/publish-common.sh . "$SCRIPT_DIR/lib/publish-common.sh" # shellcheck source=lib/publish-release.sh . "$SCRIPT_DIR/lib/publish-release.sh" REMOTE="gitea" TEA_CONFIG="${TEA_CONFIG:-$HOME/.config/tea/config.yml}" usage() { cat </dev/null 2>&1; then python3 - "$config" "$host" <<'PY' import re import sys path, host = sys.argv[1], sys.argv[2] text = open(path, encoding="utf-8").read() token = None current = None for line in text.splitlines(): line = line.rstrip() if line.startswith("- name:"): current = line.split(":", 1)[1].strip().strip('"').strip("'") continue match = re.match(r"\s+url:\s*(.+)$", line) if match: url = match.group(1).strip().strip('"').strip("'") current = re.sub(r"^[a-z]+://", "", url) current = current.split("/")[0].split("@")[-1] continue match = re.match(r"\s+token:\s*(.+)$", line) if match and current == host: token = match.group(1).strip().strip('"').strip("'") if token: print(token) PY return 0 fi # No python: the token line of the first login block that names the host. awk -v host="$host" ' /- name:/ { block = $0; next } /url:/ { block = block " " $0 } /token:/ { if (index(block, host) > 0) { sub(/^[^:]*:[[:space:]]*/, "", $0) gsub(/["'"'"']/, "", $0) print $0 exit } } ' "$config" } # END:tea-token require_repo_root preflight "$REMOTE" resolve_version remote_url="$(git remote get-url "$REMOTE")" parse_remote_url "$remote_url" API_URL="${GITEA_API_URL:-https://${REMOTE_HOST}/api/v1}" REPO_SLUG="${REMOTE_OWNER}/${REMOTE_REPO}" COMPARE_URL="https://${REMOTE_HOST}/${REPO_SLUG}/compare/" step "Checking the Gitea token" TOKEN="${GITEA_TOKEN:-}" if [ -z "$TOKEN" ]; then TOKEN="$(tea_token_for_host "$REMOTE_HOST" | head -n1)" if [ -n "$TOKEN" ]; then detail "Using the token from $TEA_CONFIG." fi fi if [ -z "$TOKEN" ]; then fail "No Gitea token. Set GITEA_TOKEN, or run 'tea login add --url https://$REMOTE_HOST --token '." fi ok "A token for $REMOTE_HOST is set." require_cmd curl "Install curl." run_release_checks prepare_tag write_notes_file "$COMPARE_URL" step "Publishing $TAG to Gitea ($REPO_SLUG)" printf ' %sremote%s %s\n' "$C_DIM" "$C_RESET" "$remote_url" printf ' %sapi%s %s\n' "$C_DIM" "$C_RESET" "$API_URL" printf ' %snotes%s %s\n' "$C_DIM" "$C_RESET" "$NOTES_FILE" confirm "Publish $TAG to Gitea?" push_branch_and_tag "$REMOTE" if is_dry_run; then # Nothing is asked of the server during a dry run. release_status="404" else release_status="$( curl -s -o /dev/null -w '%{http_code}' \ -H "Authorization: token $TOKEN" \ -H "Accept: application/json" \ "$API_URL/repos/$REPO_SLUG/releases/tags/$TAG" || printf '000' )" fi if [ "$release_status" = "200" ]; then release_already_exists "The Gitea release" else body="$(cat "$NOTES_FILE")" payload="$(printf '{"tag_name":"%s","target_commitish":"%s","name":"%s","body":"%s","draft":false,"prerelease":false}' \ "$TAG" \ "$BRANCH" \ "$TAG" \ "$(json_escape "$body")")" # MARK:create-release if is_dry_run; then detail "[dry run] POST $API_URL/repos/$REPO_SLUG/releases" detail "[dry run] $payload" api_status="201" else response_file="$(mktemp -t cobble-gitea-release.XXXXXX)" api_status="$( printf '%s' "$payload" | curl -s -o "$response_file" -w '%{http_code}' \ -X POST \ -H "Authorization: token $TOKEN" \ -H "Accept: application/json" \ -H "Content-Type: application/json" \ --data-binary @- \ "$API_URL/repos/$REPO_SLUG/releases" || printf '000' )" fi # END:create-release case "$api_status" in 201 | 200) ok "Created the Gitea release." ;; 409) release_already_exists "The Gitea release" ;; *) if [ -n "${response_file:-}" ] && [ -s "$response_file" ]; then printf '%s\n' "$(cat "$response_file")" >&2 fi if [ -n "${response_file:-}" ]; then rm -f "$response_file" fi fail "Gitea answered HTTP $api_status for the release." ;; esac if [ -n "${response_file:-}" ]; then rm -f "$response_file" fi fi print_release_summary "$REMOTE" "$BRANCH" "https://${REMOTE_HOST}/${REPO_SLUG}/releases/tag/$TAG" printf '\nThe image is built by the GitHub release; mirror it into the Gitea registry with:\n' printf ' docker buildx imagetools create --tag git.tben.me/moduletrace/cobble:latest \\\n' printf ' ghcr.io/moduletrace/cobble:latest\n'