anwesen/.github/workflows/release.yml
Andreas Brenner 408fae4154 ANW-32 CI: switch release.yml to the IT-86 Forgejo->GitHub pipeline
Tag-triggered (v* on the Forgejo mirror) instead of a hand-made GitHub
release. Adds an aarch64-linux leg; a single publish job creates the GitHub
release and mirrors every binary back onto the matching Forgejo release via
FORGEJO_RELEASE_TOKEN. Keeps the hurl HTTP contract harness on x86_64-linux.

Assumed v* tags are the release trigger and the contract tests run once on the
deploy target (x86_64-linux); flag if either is wrong.
2026-06-24 17:55:43 +03:00

144 lines
5.3 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
os: linux
# arm64 Linux -- Graviton / Pi / ARM servers. Built natively.
- runner: ubuntu-24.04-arm
label: aarch64-linux
os: linux
# arm macOS -- aav's local machine. Built natively on Apple Silicon.
- runner: macos-14
label: aarch64-macos
os: 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. Name it so the target is unambiguous on the release.
- name: Name the asset for its target
run: |
install -m 0755 target/release/anwesen \
"anwesen-${{ github.event.inputs.tag || github.ref_name }}-${{ matrix.label }}"
- name: Stash the binary for the publish job
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.label }}
path: anwesen-*-${{ matrix.label }}
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"
id=$(curl -fsS -H "$auth" "$base/tags/$TAG" | jq -r '.id // empty')
if [ -z "$id" ]; then
id=$(curl -fsS -H "$auth" -H 'Content-Type: application/json' \
-X POST "$base" \
-d "{\"tag_name\":\"$TAG\",\"name\":\"$TAG\"}" | jq -r '.id')
fi
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