diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9377a6a..d048605 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -71,62 +71,111 @@ jobs: - name: Create release env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} REPO: ${{ github.repository }} TAG: ${{ github.ref_name }} + GH_API_URL: ${{ github.api_url }} run: | set -euo pipefail - if [ -z "${GITEA_TOKEN:-}" ]; then - echo "::error::GITEA_TOKEN secret is not set. Create a personal access token in Gitea with 'write:repository' scope and add it as a repository secret named GITEA_TOKEN." >&2 - exit 1 - fi - API="https://git.keithsolomon.net/api/v1" + # Branch on host: github.com sets GITHUB_API_URL; Gitea leaves it empty + # (or set to the Gitea base, which we detect by path). We treat any + # api_url that is the github.com default as GitHub and anything else as Gitea. - # Build the JSON payload with python (no jq dependency). - payload=$(TAG="$TAG" python3 -c ' - import json, os, sys - tag = os.environ["TAG"] - body = ( - "Automated release.\n\n" - "Built from commit " + os.environ.get("GITHUB_SHA", "unknown") + ".\n\n" - "See the workflow run for the artifact." - ) - print(json.dumps({ - "tag_name": tag, - "name": tag, - "body": body, - "draft": False, - "prerelease": False, - })) - ') - - # 1. Create the release (Gitea doesn't auto-generate notes). - release_json=$(curl -fsS -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - -d "$payload" \ - "${API}/repos/${REPO}/releases") - - # 2. Extract the release id (Gitea returns the full release object). - release_id=$(TAG="$TAG" python3 -c ' - import json, sys - data = json.loads(sys.stdin.read()) - print(data.get("id", "")) - ' <<<"$release_json") - - if [ -z "$release_id" ]; then - echo "::error::Failed to create release. Response: $release_json" >&2 - exit 1 - fi - echo "Created release id=$release_id" - - # 3. Upload the zip as a release asset. zip_path=( dist/projects-portfolio-*.zip ) zip_path="${zip_path[0]}" - curl -fsS -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/zip" \ - --data-binary "@${zip_path}" \ - "${API}/repos/${REPO}/releases/${release_id}/assets?name=$(basename "$zip_path")" - echo "Uploaded asset: $(basename "$zip_path")" + asset_name=$(basename "$zip_path") + asset_bytes=$(wc -c < "$zip_path") + + if [[ "$GH_API_URL" == "https://api.github.com" ]]; then + # ---- GitHub.com path ---- + if [ -z "${GITHUB_TOKEN:-}" ]; then + echo "::error::GITHUB_TOKEN is not available on this runner. Check repo permissions." >&2 + exit 1 + fi + + payload=$(TAG="$TAG" python3 -c ' + import json, os + tag = os.environ["TAG"] + print(json.dumps({ + "tag_name": tag, + "name": tag, + "body": ( + "Automated release.\n\n" + "Built from commit " + os.environ.get("GITHUB_SHA", "unknown") + ".\n\n" + "See the workflow run for the artifact." + ), + "draft": False, + "prerelease": False, + "generate_release_notes": True, + })) + ') + + release_json=$(curl -fsS -X POST \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "Accept: application/vnd.github+json" \ + -H "Content-Type: application/json" \ + -d "$payload" \ + "${GH_API_URL}/repos/${REPO}/releases") + release_id=$(python3 -c 'import json,sys; print(json.loads(sys.stdin.read())["id"])' <<<"$release_json") + upload_url=$(python3 -c 'import json,sys; print(json.loads(sys.stdin.read())["upload_url"])' <<<"$release_json") + echo "Created GitHub release id=$release_id" + + # Asset upload uses the per-release upload_url (template with {?name,label}). + curl -fsS -X POST \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "Accept: application/vnd.github+json" \ + -H "Content-Type: application/zip" \ + --data-binary "@${zip_path}" \ + "${upload_url}?name=${asset_name}" + echo "Uploaded GitHub asset: ${asset_name}" + else + # ---- Gitea path ---- + if [ -z "${GITEA_TOKEN:-}" ]; then + echo "::error::GITEA_TOKEN secret is not set. Create a personal access token in Gitea with 'write:repository' scope and add it as a repository secret named GITEA_TOKEN." >&2 + exit 1 + fi + + # Gitea's api_url may be unset or set to the Gitea base. + if [ -z "${GH_API_URL:-}" ] || [[ "$GH_API_URL" == "https://git.keithsolomon.net"* ]]; then + API="https://git.keithsolomon.net/api/v1" + else + API="${GH_API_URL%/}/api/v1" + fi + + payload=$(TAG="$TAG" python3 -c ' + import json, os + tag = os.environ["TAG"] + print(json.dumps({ + "tag_name": tag, + "name": tag, + "body": ( + "Automated release.\n\n" + "Built from commit " + os.environ.get("GITHUB_SHA", "unknown") + ".\n\n" + "See the workflow run for the artifact." + ), + "draft": False, + "prerelease": False, + })) + ') + + release_json=$(curl -fsS -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "$payload" \ + "${API}/repos/${REPO}/releases") + release_id=$(python3 -c 'import json,sys; print(json.loads(sys.stdin.read())["id"])' <<<"$release_json") + if [ -z "$release_id" ]; then + echo "::error::Failed to create Gitea release. Response: $release_json" >&2 + exit 1 + fi + echo "Created Gitea release id=$release_id" + + curl -fsS -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/zip" \ + --data-binary "@${zip_path}" \ + "${API}/repos/${REPO}/releases/${release_id}/assets?name=${asset_name}" + echo "Uploaded Gitea asset: ${asset_name}" + fi