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"