Skip to content

docs(readme): point at v1.31.0 "Ledger" #22

docs(readme): point at v1.31.0 "Ledger"

docs(readme): point at v1.31.0 "Ledger" #22

Workflow file for this run

name: Release
on:
push:
tags: ["v*"]
# Manual re-run against an already-tagged release — e.g. to backfill artifacts onto a release
# that predates this workflow's packaging/upload steps, or to rebuild after a transient
# platform-specific failure without re-tagging (which would be destructive to a published tag).
workflow_dispatch:
inputs:
tag:
description: "Existing tag to build and attach artifacts to (e.g. v0.2.0)"
required: true
# Invoked directly by release-auto.yml right after it creates a tag: a tag pushed by the
# built-in GITHUB_TOKEN does NOT trigger `on: push: tags` (GitHub's recursion guard), so
# release-auto.yml calls this workflow rather than relying on that push to fire it.
workflow_call:
inputs:
tag:
description: "Existing tag to build and attach artifacts to (e.g. v0.5.0)"
required: true
type: string
# A tag is normally pushed once, but this guards a mistaken re-push (delete+recreate the same
# tag) from queuing a redundant duplicate build behind the one already running. Manual dispatches
# for different tags get independent groups (keyed on the resolved tag, not the ref) so backfilling
# multiple historical releases in a row doesn't cancel each other.
concurrency:
group: ${{ github.workflow }}-${{ inputs.tag || github.ref_name }}
cancel-in-progress: true
# `gh release upload`/`gh release create` (below) need write access to create/attach to releases.
permissions:
contents: write
jobs:
build:
strategy:
matrix:
include:
- { os: ubuntu-latest, target: x86_64-unknown-linux-gnu }
- { os: macos-latest, target: aarch64-apple-darwin }
- { os: windows-latest, target: x86_64-pc-windows-msvc }
runs-on: ${{ matrix.os }}
env:
# A manual dispatch supplies the target tag explicitly (defaults are not evaluated for a
# `push` trigger, where `github.ref_name` is already the pushed tag).
TAG: ${{ inputs.tag || github.ref_name }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
ref: ${{ env.TAG }}
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
key: release-${{ matrix.target }}
- name: Install Linux frontend system deps
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libxkbcommon-dev libwayland-dev libasound2-dev \
libudev-dev libx11-dev libxcursor-dev libxrandr-dev libxi-dev
- run: cargo build --release -p rustysnes-frontend --target ${{ matrix.target }}
# Package the built binary + docs/license into one archive per platform, named
# `rustysnes-<tag>-<target>.<tar.gz|zip>` — tar.gz on Unix (the customary format, and
# preserves the executable bit), zip on Windows (no executable bit to preserve, and zip is
# what Windows users expect to double-click-extract).
- name: Package (Linux/macOS)
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
stage="rustysnes-${TAG}-${{ matrix.target }}"
mkdir -p "$stage"
cp "target/${{ matrix.target }}/release/rustysnes" "$stage/"
cp README.md LICENSE-MIT LICENSE-APACHE NOTICE LICENSES-THIRD-PARTY-FONTS.txt "$stage/"
tar czf "$stage.tar.gz" "$stage"
echo "ASSET=$stage.tar.gz" >> "$GITHUB_ENV"
- name: Package (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$stage = "rustysnes-${env:TAG}-${{ matrix.target }}"
New-Item -ItemType Directory -Force -Path $stage | Out-Null
Copy-Item "target/${{ matrix.target }}/release/rustysnes.exe" $stage/
Copy-Item README.md, LICENSE-MIT, LICENSE-APACHE, NOTICE, LICENSES-THIRD-PARTY-FONTS.txt $stage/
Compress-Archive -Force -Path $stage -DestinationPath "$stage.zip"
Add-Content -Path $env:GITHUB_ENV -Value "ASSET=$stage.zip"
# A detached SHA-256 checksum alongside each archive, so a downloader can verify the
# binary they fetched matches what CI actually built without trusting GitHub's transport
# alone. Neither `sha256sum` (GNU coreutils — absent on macOS) nor `shasum` (Perl-based —
# not guaranteed present in Windows' Git-Bash `PATH`) is available on every runner this
# matrix uses, so try both rather than assuming one.
- name: Checksum
shell: bash
run: |
set -euo pipefail
if command -v sha256sum >/dev/null 2>&1; then
sha256sum "$ASSET" > "$ASSET.sha256"
else
shasum -a 256 "$ASSET" > "$ASSET.sha256"
fi
# Attach to the GitHub release matching this tag, creating a minimal one first if it
# doesn't exist yet (the release ceremony normally authors the real release notes with
# `gh release create --notes-file` around the same time the tag is pushed — this is a
# self-healing fallback for whichever finishes first, not the primary way releases get
# their notes). `--clobber` makes a re-run (e.g. after a failed job, or a manual backfill
# dispatch) idempotent.
- name: Attach artifact to the GitHub release
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
set -euo pipefail
REPO="${{ github.repository }}"
if ! gh release view "$TAG" --repo "$REPO" >/dev/null 2>&1; then
# All 3 matrix legs run concurrently and race this same check-then-create — a second
# leg's `gh release create` can fail with "already exists" if a racing leg won. That
# is not a real failure (the release now exists either way), so don't let it fail the
# job; instead re-check existence and only error if the release is STILL missing
# (a genuine creation failure, e.g. a permissions problem).
gh release create "$TAG" --repo "$REPO" --title "$TAG" --generate-notes || true
gh release view "$TAG" --repo "$REPO" >/dev/null 2>&1 || {
echo "::error::release $TAG still missing after create attempt" >&2
exit 1
}
fi
gh release upload "$TAG" "$ASSET" "$ASSET.sha256" --repo "$REPO" --clobber