Files
cfal 0f1aec2939 Refresh dependencies and CI tooling (#277)
* Refresh dependencies and CI tooling while preserving fork pins

* Make privileged test fixtures compatible with Ubuntu 26
2026-11-06 14:59:25 +08:00

224 lines
7.6 KiB
YAML

name: Build Binaries
on:
push:
branches: [ master ]
tags: [ 'v*' ]
pull_request:
branches: [ master ]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: binaries-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
CARGO_TERM_COLOR: always
CARGO_BUILD_JOBS: 1
CROSS_VERSION: 0.2.5
defaults:
run:
shell: bash
jobs:
version:
name: Validate release version
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check manifest, lockfile, and tag
run: |
python3 - <<'PY'
import os
import tomllib
from pathlib import Path
manifest = tomllib.loads(Path("Cargo.toml").read_text())["package"]
packages = tomllib.loads(Path("Cargo.lock").read_text())["package"]
locked = [p["version"] for p in packages if p["name"] == manifest["name"] and "source" not in p]
assert locked == [manifest["version"]], "Manifest and lockfile versions differ"
if os.environ["GITHUB_REF_TYPE"] == "tag":
assert os.environ["GITHUB_REF_NAME"] == f'v{manifest["version"]}', "Tag does not match package version"
PY
- name: Test release smoke checks
run: python3 scripts/test-smoke-release.py
build:
name: Build ${{ matrix.target }}
needs: version
runs-on: ${{ matrix.os }}
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-24.04
use_cross: false
- target: x86_64-unknown-linux-musl
os: ubuntu-24.04
use_cross: true
- target: aarch64-unknown-linux-gnu
os: ubuntu-24.04
use_cross: true
- target: aarch64-unknown-linux-musl
os: ubuntu-24.04
use_cross: true
- target: armv7-unknown-linux-gnueabihf
os: ubuntu-24.04
use_cross: true
- target: armv7-unknown-linux-musleabihf
os: ubuntu-24.04
use_cross: true
- target: x86_64-apple-darwin
os: macos-15-intel
use_cross: false
- target: aarch64-apple-darwin
os: macos-15
use_cross: false
env:
TARGET: ${{ matrix.target }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install Rust
uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec
with:
toolchain: 1.99.1
targets: ${{ matrix.target }}
- name: Install pinned cross binary
if: matrix.use_cross
run: |
curl --fail --location --retry 3 \
"https://github.com/cross-rs/cross/releases/download/v${CROSS_VERSION}/cross-x86_64-unknown-linux-gnu.tar.gz" \
--output "$RUNNER_TEMP/cross.tar.gz"
echo "642375d1bcf3bd88272c32ba90e999f3d983050adf45e66bd2d3887e8e838bad $RUNNER_TEMP/cross.tar.gz" | sha256sum --check --strict
tar -xzf "$RUNNER_TEMP/cross.tar.gz" -C "$HOME/.cargo/bin" cross
- name: Setup cache
uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2
with:
key: release-${{ matrix.target }}
save-if: ${{ github.ref == 'refs/heads/master' }}
- name: Build binary (cross)
if: matrix.use_cross
run: cross build --release --locked --target "$TARGET" --bin shoes
- name: Build binary (native)
if: ${{ !matrix.use_cross }}
run: cargo build --release --locked --target "$TARGET" --bin shoes
- name: Verify lockfile unchanged
run: git diff --exit-code -- Cargo.lock
# Cargo's release profile strips with the target toolchain before packaging.
- name: Package binary and notices
run: |
test -x "target/$TARGET/release/shoes"
file "target/$TARGET/release/shoes"
case "$TARGET" in
*musl*) file "target/$TARGET/release/shoes" | grep -E 'static.*linked' ;;
esac
mkdir -p package artifacts smoke
cp "target/$TARGET/release/shoes" THIRD_PARTY_NOTICES.md package/
cp -R licenses package/
tar -czf "artifacts/shoes-$TARGET.tar.gz" -C package shoes THIRD_PARTY_NOTICES.md licenses
python3 scripts/check-release-notices.py "artifacts/shoes-$TARGET.tar.gz"
tar -xzf "artifacts/shoes-$TARGET.tar.gz" -C smoke
- name: Smoke-test packaged binary (cross/QEMU)
if: matrix.use_cross
timeout-minutes: 5
run: |
image="$(python3 -c 'import sys, tomllib; print(tomllib.load(open("Cross.toml", "rb"))["target"][sys.argv[1]]["image"])' "$TARGET")"
runner=/linux-runner
case "$TARGET" in
*musl*) runner=/qemu-runner ;;
esac
python3 scripts/smoke-release.py docker run --rm \
--volume "$PWD:/work:ro" --workdir /work \
"$image" "$runner" "${TARGET%%-*}" ./smoke/shoes
- name: Smoke-test packaged binary (native)
if: ${{ !matrix.use_cross }}
timeout-minutes: 5
run: python3 scripts/smoke-release.py ./smoke/shoes
- name: Upload verified archive
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
with:
name: shoes-${{ matrix.target }}
path: artifacts/shoes-${{ matrix.target }}.tar.gz
if-no-files-found: error
release:
name: Create Draft Release
needs: build
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
contents: write
id-token: write
attestations: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Verify tag still targets this commit and release is unpublished
env:
GH_TOKEN: ${{ github.token }}
run: |
git fetch --no-tags origin "refs/tags/$GITHUB_REF_NAME"
test "$(git rev-parse 'FETCH_HEAD^{commit}')" = "$GITHUB_SHA"
gh api --paginate "repos/$GITHUB_REPOSITORY/releases" \
--jq '.[] | {tag_name, draft}' > "$RUNNER_TEMP/releases.jsonl"
jq --slurp --exit-status --arg tag "$GITHUB_REF_NAME" \
'[.[] | select(.tag_name == $tag)] | all(.draft)' "$RUNNER_TEMP/releases.jsonl"
- name: Download verified archives
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
with:
pattern: shoes-*
path: release-artifacts
merge-multiple: true
- name: Verify notices and checksum final archives
run: |
archives=(release-artifacts/shoes-*.tar.gz)
test "${#archives[@]}" -eq 8
for archive in "${archives[@]}"; do
python3 scripts/check-release-notices.py "$archive"
done
cd release-artifacts
sha256sum shoes-*.tar.gz > SHA256SUMS
sha256sum --check --strict SHA256SUMS
- name: Attest final release artifacts
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: release-artifacts/*
- name: Create Draft Release
uses: softprops/action-gh-release@8a0cd651e5b2365bd640854a3fa5dfc70e4875f3 # v3.0.4
with:
files: release-artifacts/*
fail_on_unmatched_files: true
draft: true
generate_release_notes: true