Skip to content

feat(update): install-source-aware self-update subcommand (#7) #20

feat(update): install-source-aware self-update subcommand (#7)

feat(update): install-source-aware self-update subcommand (#7) #20

Workflow file for this run

name: Release
on:
push:
tags: ["v*.*.*"]
workflow_dispatch:
inputs:
version:
description: "Version to build (X.Y.Z), without the leading v. Used for dry-run dispatch."
required: true
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: write # create the GitHub Release
id-token: write # OIDC token for npm Trusted Publishing (public npm)
jobs:
build:
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.os }}
env:
CARGO_NET_GIT_FETCH_WITH_CLI: "true"
# Tolerate the reserved Windows name tests/fixtures/contexts/CON.json when
# git validates tree paths during checkout. Combined with the sparse
# checkout below (which never materializes tests/ on disk), this lets the
# win32 job clone. Honored by every git invocation, incl. actions/checkout.
# No-op on Linux/macOS.
GIT_CONFIG_COUNT: "1"
GIT_CONFIG_KEY_0: core.protectNTFS
GIT_CONFIG_VALUE_0: "false"
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-musl
os: ubuntu-24.04
musl: true
- target: aarch64-unknown-linux-musl
os: ubuntu-24.04-arm
musl: true
- target: aarch64-apple-darwin
os: macos-14
- target: x86_64-pc-windows-msvc
os: windows-latest
steps:
# Sparse checkout: building the binary only needs the crate sources and the
# root manifests. This also skips tests/fixtures, which contains an upstream
# fixture named CON.json — a reserved device name that git cannot check out
# on Windows (would fail the win32 job at checkout).
- uses: actions/checkout@v4
with:
sparse-checkout: |
src
benches
- name: Authenticate cargo git fetch (private quire-rs)
shell: bash
run: git config --global url."https://x-access-token:${{ secrets.REGISTRY_TOKEN }}@github.com/".insteadOf "https://github.com/"
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install musl toolchain
if: matrix.musl
run: sudo apt-get update && sudo apt-get install -y musl-tools
- name: Cache cargo artifacts
uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Build release binary
run: cargo build --release --target ${{ matrix.target }}
- name: Smoke test (--version)
shell: bash
run: |
BIN=target/${{ matrix.target }}/release/quire
[ "${{ runner.os }}" = "Windows" ] && BIN="$BIN.exe"
"$BIN" --version
- name: Stage binary
shell: bash
run: |
mkdir -p "dist/${{ matrix.target }}"
if [ "${{ runner.os }}" = "Windows" ]; then
cp "target/${{ matrix.target }}/release/quire.exe" "dist/${{ matrix.target }}/quire.exe"
else
cp "target/${{ matrix.target }}/release/quire" "dist/${{ matrix.target }}/quire"
fi
- name: Upload binary artifact
uses: actions/upload-artifact@v4
with:
name: bin-${{ matrix.target }}
path: dist/${{ matrix.target }}
if-no-files-found: error
retention-days: 7
package:
name: Package + publish
needs: build
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Resolve version
id: ver
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "version=${{ github.event.inputs.version }}" >> "$GITHUB_OUTPUT"
else
echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
fi
- name: Download all binaries
uses: actions/download-artifact@v4
with:
path: artifacts
pattern: bin-*
- name: Normalize binary artifact layout
run: |
mkdir -p normalized
for artifact_dir in artifacts/bin-*; do
target="${artifact_dir#artifacts/bin-}"
mkdir -p "normalized/${target}"
cp "${artifact_dir}"/quire* "normalized/${target}/"
done
rm -rf artifacts
mv normalized artifacts
- name: Build release tarballs + checksums
run: |
VERSION="${{ steps.ver.outputs.version }}"
mkdir -p release
cd artifacts
for target in */; do
target="${target%/}"
if [ -f "$target/quire.exe" ]; then
(cd "$target" && zip -q "../../release/quire-${VERSION}-${target}.zip" quire.exe)
else
tar -czf "../release/quire-${VERSION}-${target}.tar.gz" -C "$target" quire
fi
done
cd ../release
sha256sum * > "SHA256SUMS.txt"
ls -la
- name: Create GitHub Release
if: github.event_name == 'push'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "${GITHUB_REF_NAME}" release/* \
--title "${GITHUB_REF_NAME}" \
--notes "Automated release ${GITHUB_REF_NAME}. See CHANGELOG.md for details." \
--verify-tag
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "22" # OIDC Trusted Publishing requires Node >= 22.14
# OIDC Trusted Publishing needs npm >= 11.5.1.
- name: Upgrade npm for Trusted Publishing
run: npm install -g npm@latest
# Public npm via OIDC: route @agent-ix at registry.npmjs.org with no auth
# token. `npm publish` performs the tokenless OIDC token exchange (the
# id-token: write permission above supplies the GitHub OIDC token).
# Written to $HOME so every `npm publish` (run from each package dir) picks it up.
# Public npm. Steady state is tokenless OIDC (id-token: write above). The
# NPM_TOKEN fallback exists only to BOOTSTRAP: npm requires a package to
# exist before a trusted publisher can be attached, and these 5 packages'
# binaries can only be built by this CI matrix. Add NPM_TOKEN as a repo
# secret for the first release, configure the trusted publishers on
# npmjs.com, then DELETE the secret — every later release uses OIDC.
# provenance=false: this repo is private, where provenance is unsupported.
- name: Configure npm for public npm
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
if [ -n "$NPM_TOKEN" ]; then
printf 'registry=https://registry.npmjs.org/\n@agent-ix:registry=https://registry.npmjs.org/\n//registry.npmjs.org/:_authToken=%s\nprovenance=false\n' "$NPM_TOKEN" > "$HOME/.npmrc"
else
printf 'registry=https://registry.npmjs.org/\n@agent-ix:registry=https://registry.npmjs.org/\nprovenance=false\n' > "$HOME/.npmrc"
fi
- name: Generate per-platform npm packages
run: ARTIFACTS_DIR=artifacts node npm/build-packages.mjs "${{ steps.ver.outputs.version }}"
- name: Publish to public npm
if: github.event_name == 'push'
run: |
set -e
# Platform packages first so the launcher's optionalDependencies resolve.
for pkg in npm/dist/*/; do
echo "publishing $pkg"
(cd "$pkg" && npm publish)
done
echo "publishing launcher"
(cd npm/quire-cli && npm publish)