ap keeps every release and the raw, unstripped binaries are the bulk of that storage. Strip symbols via the release profile and gzip -9 each asset before upload (~2.7x smaller); the publish job and Forgejo mirror-back pass the .gz assets through unchanged. Assumed .gz per binary over .tar.gz -- the assets are single files, so a tarball only adds a directory layer. Flag if a bundle (LICENSE/README) is wanted. E2E needs a release run; piggyback on the next real tag.
153 lines
5.9 KiB
YAML
153 lines
5.9 KiB
YAML
# Release builds for anwesen ([ANW-32], pattern from IT-86).
|
|
#
|
|
# Forgejo (carvers/anwesen on ap) is canonical for both code and releases.
|
|
# GitHub is only the build farm -- it has the macOS runners. Publishing is a
|
|
# single act on Forgejo: create a `v*` tag (or release) there, it mirrors to
|
|
# the GitHub mirror, and that pushed tag triggers this workflow. For each
|
|
# target the build job tests and builds the binary; a final publish job creates
|
|
# the GitHub release with every binary, then mirrors them back onto the
|
|
# matching Forgejo release. No manual "new release" step on GitHub.
|
|
name: release
|
|
|
|
on:
|
|
push:
|
|
tags: ['v*']
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: Existing tag to (re)build
|
|
required: true
|
|
|
|
# The publish job attaches binaries to the GitHub release it creates.
|
|
permissions:
|
|
contents: write
|
|
|
|
env:
|
|
# The Forgejo repo that receives the release assets (owner/name on ap).
|
|
FORGEJO_REPO: carvers/anwesen
|
|
FORGEJO_API: https://forge.crvrs.org/api/v1
|
|
|
|
jobs:
|
|
build:
|
|
name: ${{ matrix.label }}
|
|
runs-on: ${{ matrix.runner }}
|
|
strategy:
|
|
# One target's failure should not cancel the others' builds.
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
# amd64 Linux -- the deploy target. Built natively on ubuntu-latest.
|
|
- runner: ubuntu-latest
|
|
label: x86_64-linux
|
|
# arm64 Linux -- Graviton / Pi / ARM servers. Built natively.
|
|
- runner: ubuntu-24.04-arm
|
|
label: aarch64-linux
|
|
# arm macOS -- aav's local machine. Built natively on Apple Silicon.
|
|
- runner: macos-14
|
|
label: aarch64-macos
|
|
steps:
|
|
- name: Check out the release tag
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ github.event.inputs.tag || github.ref_name }}
|
|
|
|
# Stable channel; edition 2024 needs >= 1.85, and Cargo.toml pins the
|
|
# MSRV at 1.95. Pin an explicit version here if a frozen release
|
|
# toolchain is ever required.
|
|
- name: Install the Rust toolchain
|
|
uses: dtolnay/rust-toolchain@stable
|
|
|
|
- name: Cache cargo registry, index, and target
|
|
uses: Swatinem/rust-cache@v2
|
|
|
|
# The HTTP contract harness (tests/run-hurl.sh, per ADR-008) boots
|
|
# `anwesen serve` and runs hurl against it. The contract is
|
|
# arch-independent, so it runs once on the deploy target; the macOS
|
|
# runner's stock bash is 3.2 and the harness needs bash 4+
|
|
# (`shopt -s globstar`), which would only add fragility for no coverage.
|
|
- name: Install hurl
|
|
if: matrix.label == 'x86_64-linux'
|
|
run: |
|
|
curl -fsSL -o /tmp/hurl.deb \
|
|
https://github.com/Orange-OpenSource/hurl/releases/download/8.0.0/hurl_8.0.0_amd64.deb
|
|
sudo dpkg -i /tmp/hurl.deb
|
|
|
|
# Test before building the artifact so a release never ships a red build.
|
|
# The debug build here is what run-hurl.sh exercises.
|
|
- name: Run the Rust test suite
|
|
run: cargo test --locked
|
|
|
|
- name: Run the HTTP contract tests
|
|
if: matrix.label == 'x86_64-linux'
|
|
run: tests/run-hurl.sh
|
|
|
|
- name: Build the release binary
|
|
run: cargo build --release --locked
|
|
|
|
# The runner is native to its target, so target/release/anwesen is the
|
|
# target binary (already stripped via the release profile). Name it so
|
|
# the target is unambiguous, then gzip it -- ap keeps every release and
|
|
# the raw binaries are the bulk of that, so assets ship compressed.
|
|
- name: Name and compress the asset for its target
|
|
run: |
|
|
asset="anwesen-${{ github.event.inputs.tag || github.ref_name }}-${{ matrix.label }}"
|
|
install -m 0755 target/release/anwesen "$asset"
|
|
gzip -9 "$asset"
|
|
|
|
- name: Stash the binary for the publish job
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: ${{ matrix.label }}
|
|
path: anwesen-*-${{ matrix.label }}.gz
|
|
if-no-files-found: error
|
|
|
|
publish:
|
|
needs: build
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Collect every target's binary
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
path: dist
|
|
merge-multiple: true
|
|
|
|
- name: Create the GitHub release with all binaries
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
tag_name: ${{ github.event.inputs.tag || github.ref_name }}
|
|
files: dist/*
|
|
|
|
# Forgejo is canonical: push the same binaries onto the matching Forgejo
|
|
# release. Find the release by tag; create it if the tag has no release
|
|
# object yet; then upload each binary as an asset.
|
|
- name: Mirror binaries to the Forgejo release
|
|
env:
|
|
TAG: ${{ github.event.inputs.tag || github.ref_name }}
|
|
TOKEN: ${{ secrets.FORGEJO_RELEASE_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
auth="Authorization: token $TOKEN"
|
|
base="$FORGEJO_API/repos/$FORGEJO_REPO/releases"
|
|
|
|
# Look up the Forgejo release for this tag. Forgejo answers 404 when
|
|
# the tag has no release object yet, so branch on the status code:
|
|
# `curl -f` would exit 22 on that 404 and, under pipefail, abort the
|
|
# step before the create path could run.
|
|
body=$(mktemp)
|
|
code=$(curl -sS -o "$body" -w '%{http_code}' -H "$auth" "$base/tags/$TAG")
|
|
case "$code" in
|
|
200) id=$(jq -r '.id' "$body") ;;
|
|
404) id=$(curl -fsS -H "$auth" -H 'Content-Type: application/json' \
|
|
-X POST "$base" \
|
|
-d "{\"tag_name\":\"$TAG\",\"name\":\"$TAG\"}" | jq -r '.id') ;;
|
|
*) echo "Forgejo release lookup failed: HTTP $code" >&2
|
|
cat "$body" >&2
|
|
exit 1 ;;
|
|
esac
|
|
|
|
for f in dist/*; do
|
|
curl -fsS -H "$auth" \
|
|
-F "attachment=@$f;filename=$(basename "$f")" \
|
|
"$base/$id/assets?name=$(basename "$f")" >/dev/null
|
|
echo "uploaded $(basename "$f")"
|
|
done
|