From 7fa80e6f436e548ddbec5d9e067c24c879ae69fb Mon Sep 17 00:00:00 2001 From: DTTerastar Date: Mon, 20 Jul 2026 22:43:28 -0400 Subject: [PATCH] ci: comment a review-binary download link on PRs, add Windows build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI already cross-compiled review binaries for every PR, but nothing linked them, so trying a PR before merge meant knowing to dig through the Actions run page. Post the link automatically instead. Contributor PRs come from forks, and fork PRs get a read-only GITHUB_TOKEN, so a comment step inside CI cannot post. This runs as a separate workflow_run workflow in the base-repo context, where the token is writable. It never checks out or executes PR code — it only reads run metadata and comments — so the writable token is never exposed to untrusted input. Also adds windows/amd64 to the cross-compile matrix. Goreleaser has always shipped a Windows binary for releases, but CI built darwin and linux only, so Windows users had nothing to test with. The reporter of #55 is on Windows. The comment is sticky: --edit-last updates the existing comment rather than stacking one per push, falling back to a new comment when there is none. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_013JJnPtEtP97to9Rv2QMoer --- .github/workflows/ci.yml | 5 +- .github/workflows/pr-review-binaries.yml | 73 ++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/pr-review-binaries.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 083d5dc..628aa56 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,10 +62,11 @@ jobs: - name: cross-compile run: | mkdir -p dist - for target in darwin/arm64 darwin/amd64 linux/amd64 linux/arm64; do + for target in darwin/arm64 darwin/amd64 linux/amd64 linux/arm64 windows/amd64; do os="${target%/*}"; arch="${target#*/}" + ext=""; [ "$os" = "windows" ] && ext=".exe" GOOS=$os GOARCH=$arch go build -trimpath -ldflags="-s -w" \ - -o "dist/liftoff-export-${os}-${arch}" . + -o "dist/liftoff-export-${os}-${arch}${ext}" . done ls -lh dist/ - uses: actions/upload-artifact@v4 diff --git a/.github/workflows/pr-review-binaries.yml b/.github/workflows/pr-review-binaries.yml new file mode 100644 index 0000000..feb51a0 --- /dev/null +++ b/.github/workflows/pr-review-binaries.yml @@ -0,0 +1,73 @@ +name: PR review binaries link + +# Posts a download link for the review binaries CI just built, so a PR can be +# tried end-to-end before merge without a local Go toolchain. +# +# Why workflow_run and not a step inside CI: contributor PRs come from forks, +# and fork PRs get a read-only GITHUB_TOKEN, so a comment step inside CI can't +# post. workflow_run runs in the base-repo context with a writable token. +# It deliberately does NOT check out or execute any PR code — it only reads +# the run's metadata and comments — so the writable token never touches +# untrusted input. +on: + workflow_run: + workflows: [CI] + types: [completed] + +permissions: + contents: read + pull-requests: write + +jobs: + comment: + if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' + runs-on: ubuntu-latest + steps: + - name: find the PR and comment + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + RUN_ID: ${{ github.event.workflow_run.id }} + HEAD_SHA: ${{ github.event.workflow_run.head_sha }} + run: | + set -euo pipefail + + # workflow_run.pull_requests is empty for fork PRs, so resolve the + # PR from the head SHA instead. + pr=$(gh api "repos/$REPO/commits/$HEAD_SHA/pulls" \ + --jq '[.[] | select(.state == "open")][0].number // empty') + if [ -z "$pr" ]; then + echo "no open PR for $HEAD_SHA; nothing to comment on" + exit 0 + fi + + run_url="https://github.com/$REPO/actions/runs/$RUN_ID" + body=$(cat <\`. + + Downloading requires being signed in to GitHub, and artifacts expire 14 days after the run. + + Posted automatically. Updated on each push to this PR. + EOF + ) + # Strip the heredoc's leading indentation. + body=$(printf '%s\n' "$body" | sed 's/^ //') + + # Sticky: edit our previous comment rather than stacking one per push. + # --edit-last fails when there's nothing to edit, so fall back to new. + gh pr comment "$pr" --repo "$REPO" --edit-last --body "$body" \ + || gh pr comment "$pr" --repo "$REPO" --body "$body"