From cbdbe1ba8661ac12ea70761ebbac02546f1a9af2 Mon Sep 17 00:00:00 2001 From: Roman Lemekha Date: Fri, 26 Jun 2026 13:43:20 +0200 Subject: [PATCH] fix: parse release version from PRS json; tag-move via API (no checkout) The auto-merge step ran `gh pr view` but the job has no checkout, so gh had no repo context and the call failed ("not a git repository"), leaving every release PR unmerged. Parse the number+title directly from steps.release .outputs.prs (already JSON) and pass --repo to `gh pr merge`. The major-tag-move step likewise relied on local git in a checkout-less job; switch it to the REST API (create-or-update ref) using the PAT. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/release-please.yml | 37 +++++++++++++++++----------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 2a39b5a..73662c2 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -44,41 +44,50 @@ jobs: # and has pull-request write on this repo. GH_TOKEN: ${{ secrets.RELEASE_PLEASE_TOKEN }} PRS: ${{ steps.release.outputs.prs }} + REPO: ${{ github.repository }} run: | set -euo pipefail - # outputs.prs is a JSON array of {number, ...}; outputs.prs_created is - # set, but the per-version flag lives in the PR title / labels. + # outputs.prs is a JSON array of PullRequest objects; the number and + # title (e.g. "chore(main): release 1.2.3") are both in the JSON, so + # parse them directly — no `gh pr view` (this job has no checkout, so + # gh has no repo context to infer) and pass --repo explicitly. echo "$PRS" | jq -c '.[]' | while read -r pr; do number=$(echo "$pr" | jq -r '.number') - # The release PR title is e.g. "chore(main): release 1.2.3". - version=$(gh pr view "$number" --json title --jq '.title' \ - | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true) + title=$(echo "$pr" | jq -r '.title') + version=$(printf '%s' "$title" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true) if [ -z "$version" ]; then - echo "PR #$number: could not parse version, leaving for manual review" + echo "PR #$number: could not parse version from title '$title', leaving for manual review" continue fi - major=${version%%.*} minorpatch=${version#*.} # A major bump is X.0.0 — leave it open for manual approval. if [ "$minorpatch" = "0.0" ]; then echo "PR #$number ($version): MAJOR bump — manual review required" else echo "PR #$number ($version): non-major — enabling auto-merge" - gh pr merge "$number" --auto --squash + gh pr merge "$number" --repo "$REPO" --auto --squash fi done # ----- after a release is CUT: move the major tag (v1) to it ----- + # Done via the REST API (not local git) because this job has no checkout. + # Force-move the lightweight moving major tag (e.g. v1) to the released + # commit so consumers who track @v1 follow non-breaking releases. - name: Move major tag to the new release if: ${{ steps.release.outputs.release_created == 'true' }} env: + GH_TOKEN: ${{ secrets.RELEASE_PLEASE_TOKEN }} + REPO: ${{ github.repository }} MAJOR: ${{ steps.release.outputs.major }} SHA: ${{ steps.release.outputs.sha }} run: | set -euo pipefail - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - # Force-move the moving major tag (e.g. v1) to the released commit so - # consumers who choose to track @v1 follow non-breaking releases. - git tag -fa "v${MAJOR}" "${SHA}" -m "Release v${MAJOR} -> ${SHA}" - git push origin "v${MAJOR}" --force + ref="tags/v${MAJOR}" + # Update the ref if it exists, otherwise create it. + if gh api "repos/${REPO}/git/refs/${ref}" >/dev/null 2>&1; then + gh api -X PATCH "repos/${REPO}/git/refs/${ref}" -F sha="${SHA}" -F force=true >/dev/null + echo "Moved tag v${MAJOR} -> ${SHA}" + else + gh api -X POST "repos/${REPO}/git/refs" -f ref="refs/tags/v${MAJOR}" -f sha="${SHA}" >/dev/null + echo "Created tag v${MAJOR} -> ${SHA}" + fi