Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,29 +49,39 @@ jobs:
artifacts:
# Cross-compile review binaries for the platforms reviewers actually use.
# Goreleaser owns tagged releases; this job exists so a PR's diff can be
# tried end-to-end without a local Go toolchain — download from the run
# page, chmod +x, run. Retention is short (14d) to keep storage tidy.
name: review binaries
# tried end-to-end without a local Go toolchain.
#
# One artifact per platform, not one bundle: the PR comment links each
# artifact directly, and a Windows user shouldn't download 33MB of Linux
# and macOS binaries to get their 6MB .exe.
name: review binary (${{ matrix.goos }}/${{ matrix.goarch }})
runs-on: ubuntu-latest
strategy:
matrix:
include:
- { goos: darwin, goarch: arm64 }
- { goos: darwin, goarch: amd64 }
- { goos: linux, goarch: amd64 }
- { goos: linux, goarch: arm64 }
- { goos: windows, goarch: amd64, ext: .exe }
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: cross-compile
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
run: |
mkdir -p dist
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}${ext}" .
done
go build -trimpath -ldflags="-s -w" \
-o "dist/liftoff-export-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.ext }}" .
ls -lh dist/
- uses: actions/upload-artifact@v4
with:
name: liftoff-export
name: liftoff-export-${{ matrix.goos }}-${{ matrix.goarch }}
path: dist/
retention-days: 14
if-no-files-found: error
58 changes: 41 additions & 17 deletions .github/workflows/pr-review-binaries.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
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.
# Posts one-click download links 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.
#
# Why nightly.link: GitHub has no permanent public download URL for an
# artifact. The /actions/runs/<id>/artifacts/<id> endpoint needs browser
# session cookies (a token gets a 404), so a plain link only works for signed-in
# users, and even then only after finding the right row on the run page.
# nightly.link is a third-party redirector that resolves an artifact to an
# anonymous, no-login download. Public repos need no app install.
on:
workflow_run:
workflows: [CI]
Expand Down Expand Up @@ -41,30 +48,47 @@ jobs:
exit 0
fi

# nightly.link addresses artifacts by check-suite, not run.
suite=$(gh api "repos/$REPO/actions/runs/$RUN_ID" --jq '.check_suite_id')

label() {
case "$1" in
*darwin-arm64*) echo "macOS (Apple silicon)" ;;
*darwin-amd64*) echo "macOS (Intel)" ;;
*linux-amd64*) echo "Linux x86_64" ;;
*linux-arm64*) echo "Linux arm64" ;;
*windows-amd64*) echo "Windows x86_64" ;;
*) echo "$1" ;;
esac
}

rows=""
while IFS=$'\t' read -r name id; do
[ -n "$name" ] || continue
url="https://nightly.link/$REPO/suites/$suite/artifacts/$id"
rows="${rows}| $(label "$name") | [\`${name}.zip\`]($url) |"$'\n'
done < <(gh api "repos/$REPO/actions/runs/$RUN_ID/artifacts" \
--jq '.artifacts[] | [.name, .id] | @tsv' | sort)

if [ -z "$rows" ]; then
echo "run $RUN_ID produced no artifacts; nothing to link"
exit 0
fi

run_url="https://github.com/$REPO/actions/runs/$RUN_ID"
body=$(cat <<EOF
### Try this PR without building it

CI cross-compiled review binaries for commit \`${HEAD_SHA:0:7}\`:

**[Download from the run page]($run_url#artifacts)** — the \`liftoff-export\` artifact holds all platforms.
Review binaries for commit \`${HEAD_SHA:0:7}\` — direct download, no login required:

| Platform | File |
| Platform | Download |
|---|---|
| macOS (Apple silicon) | \`liftoff-export-darwin-arm64\` |
| macOS (Intel) | \`liftoff-export-darwin-amd64\` |
| Linux x86_64 | \`liftoff-export-linux-amd64\` |
| Linux arm64 | \`liftoff-export-linux-arm64\` |
| Windows x86_64 | \`liftoff-export-windows-amd64.exe\` |

On macOS and Linux, unzip then \`chmod +x liftoff-export-*\` before running. macOS Gatekeeper will block the unsigned binary on first run — right-click → Open, or \`xattr -d com.apple.quarantine <file>\`.

Downloading requires being signed in to GitHub, and artifacts expire 14 days after the run.
${rows}
Unzip, then on macOS/Linux \`chmod +x\` the binary before running. macOS Gatekeeper blocks unsigned binaries on first run — right-click → Open, or \`xattr -d com.apple.quarantine <file>\`.

<sub>Posted automatically. Updated on each push to this PR.</sub>
<sub>Links are resolved by [nightly.link](https://nightly.link/), a third-party redirector for GitHub Actions artifacts, because GitHub has no anonymous artifact URL of its own. Signed-in users can also [browse the run directly]($run_url#artifacts). Artifacts expire 14 days after the run. Updated on each push to this PR.</sub>
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.
Expand Down
Loading