Skip to content

faeat: add ffi pre-built .a library #1

faeat: add ffi pre-built .a library

faeat: add ffi pre-built .a library #1

Workflow file for this run

# ===============================================================
# Release FFI - Build, sign, and publish libcpex_ffi.a artifacts
# ===============================================================
#
# Triggered by semver-strict tag pushes. Matrix-builds the FFI
# static library for the supported target tuples, packages each into
# a tarball with VERSION / FFI_ABI / LICENSE metadata, signs every
# tarball + the aggregate SHA256SUMS with cosign keyless (Sigstore),
# and attaches everything to the GitHub Release for the tag.
#
# See crates/cpex-ffi/RELEASE.md for the artifact schema and the
# consumer-side verify-and-unpack recipe.
name: Release FFI
on:
push:
tags:
# Semver-strict. Two patterns so vMAJOR.MINOR.PATCH (release)
# and vMAJOR.MINOR.PATCH-<prerelease> (rc / beta / ffi.test)
# both fire, while loose `v*` matches (vendor-bump, v1, v-foo)
# and the legacy non-prefixed tags (0.1.0, plugins.dev1) do not.
# Dry-run tags like v0.0.0-ffi.test.1 deliberately hit the
# prerelease branch.
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-*'
# id-token: write is what unlocks Sigstore keyless signing (Fulcio
# reads the GHA OIDC token to issue the short-lived signing cert).
# contents: write is needed to create / upload to the GitHub Release.
permissions:
contents: write
id-token: write
# Prevent concurrent runs on the same tag from racing the release
# creation. Tag pushes are one-shot, so this is belt-and-suspenders.
concurrency:
group: release-ffi-${{ github.ref }}
cancel-in-progress: false
jobs:
build:
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false # one tuple failing should not cancel the others
matrix:
include:
- target: x86_64-unknown-linux-gnu
runner: ubuntu-latest
- target: aarch64-unknown-linux-gnu
runner: ubuntu-22.04-arm
- target: x86_64-unknown-linux-musl
runner: ubuntu-latest
- target: aarch64-unknown-linux-musl
runner: ubuntu-22.04-arm
- target: aarch64-apple-darwin
runner: macos-14
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust toolchain
# dtolnay/rust-toolchain is the de-facto rustup action.
# `stable` picks the latest stable; pin if we need a floor.
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Cache cargo build
uses: Swatinem/rust-cache@v2
with:
# Share cache across tags (the key includes the target +
# Cargo.lock hash by default). Significant speedup on
# subsequent releases of the same target.
key: ${{ matrix.target }}
- name: Build artifact
env:
TARGET: ${{ matrix.target }}
# VERSION drops the leading "refs/tags/" so the tarball
# name matches the tag verbatim.
VERSION: ${{ github.ref_name }}
DIST_DIR: dist
run: bash scripts/release/build-artifact.sh
- name: Upload tarball + sha256
uses: actions/upload-artifact@v4
with:
# Unique per-target name so the download step in
# sign-and-release can merge them all into one dist/.
name: cpex-ffi-${{ github.ref_name }}-${{ matrix.target }}
path: dist/cpex-ffi-*
if-no-files-found: error
retention-days: 7
sign-and-release:
name: Sign and publish release
needs: [build]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download all matrix artifacts
uses: actions/download-artifact@v4
with:
path: dist
# merge-multiple flattens the per-target subdirs into one
# dist/ so the sign script and gh release upload see a
# flat layout.
merge-multiple: true
- name: Generate aggregate SHA256SUMS
env:
VERSION: ${{ github.ref_name }}
run: |
set -euo pipefail
cd dist
# Concat all individual .sha256 files into one signed
# integrity manifest. The per-tarball .sha256 files stay
# as convenience companions, but the SHA256SUMS file is
# what auditors care about.
: > "cpex-ffi-${VERSION}-SHA256SUMS"
for f in cpex-ffi-*.tar.gz; do
if command -v sha256sum >/dev/null; then
sha256sum "$f" >> "cpex-ffi-${VERSION}-SHA256SUMS"
else
shasum -a 256 "$f" >> "cpex-ffi-${VERSION}-SHA256SUMS"
fi
done
echo "--- SHA256SUMS ---"
cat "cpex-ffi-${VERSION}-SHA256SUMS"
- name: Install cosign
uses: sigstore/cosign-installer@v3
- name: Sign artifacts
env:
DIST_DIR: dist
run: bash scripts/release/sign-artifact.sh
- name: Create or update GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.ref_name }}
run: |
set -euo pipefail
# Auto-detect prerelease by suffix so dry-run tags
# (v0.0.0-ffi.test.1) land as prereleases and don't surface
# as "latest" on the repo's Releases page.
PRERELEASE_FLAG=""
if [[ "$TAG" == *-* ]]; then
PRERELEASE_FLAG="--prerelease"
fi
# Idempotent: if the release exists, upload --clobber the
# new files; if it doesn't, create it with the tarballs +
# SHA256SUMS + sigs in one shot.
if gh release view "$TAG" >/dev/null 2>&1; then
echo "Release $TAG exists; uploading artifacts with --clobber"
gh release upload "$TAG" dist/cpex-ffi-* --clobber
else
echo "Creating release $TAG"
gh release create "$TAG" \
--title "$TAG" \
--notes "Automated FFI artifact release. See crates/cpex-ffi/RELEASE.md for the schema and verify-and-consume recipe." \
$PRERELEASE_FLAG \
dist/cpex-ffi-*
fi