229 lines
8.8 KiB
YAML
229 lines
8.8 KiB
YAML
name: Release
|
|
|
|
on:
|
|
push:
|
|
tags: ["v*"]
|
|
|
|
jobs:
|
|
macos:
|
|
runs-on: macos-arm64
|
|
steps:
|
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
with:
|
|
path: carrier
|
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
with:
|
|
repository: randogoth/fumi
|
|
ref: main
|
|
path: fumi
|
|
- uses: https://code.forgejo.org/actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.cargo/registry
|
|
carrier/target
|
|
fumi/target
|
|
key: cargo-macos-${{ hashFiles('carrier/Cargo.lock') }}
|
|
restore-keys: cargo-macos-
|
|
- run: devbox run build
|
|
working-directory: carrier
|
|
env:
|
|
GITHUB_TOKEN: ""
|
|
- run: mv target/release/carrier target/release/carrier-macos-arm64
|
|
working-directory: carrier
|
|
# This runner is a laptop that's frequently asleep/offline, so this
|
|
# job must not gate the release (and must not be gated by it either).
|
|
# Instead of going through actions/forgejo-release - which only knows
|
|
# how to blind-create a release, not append to one that may already
|
|
# exist - this polls for the release the linux+flatpak job creates
|
|
# and appends its own asset directly via the Forgejo API, landing
|
|
# next to whatever binaries are already there. grep (not jq, whose
|
|
# presence here isn't guaranteed) is safe for pulling the id out: per
|
|
# Forgejo's structs.Release, ID is the first declared field and Go's
|
|
# encoding/json marshals in declaration order, ahead of the nested
|
|
# per-asset "id" fields in the "assets" array.
|
|
- run: |
|
|
REPO="${{ forge.repository }}"
|
|
TAG="${{ forge.ref_name }}"
|
|
FORGEJO="${{ env.FORGEJO_SERVER_URL }}"
|
|
FORGEJO="${FORGEJO%%/}"
|
|
TOKEN="${{ forge.token }}"
|
|
FILE="target/release/carrier-macos-arm64"
|
|
NAME="carrier-macos-arm64"
|
|
|
|
release_id=""
|
|
for i in $(seq 1 40); do
|
|
body=$(curl --retry 5 -sS -H "Authorization: token $TOKEN" "$FORGEJO/api/v1/repos/$REPO/releases/tags/$TAG")
|
|
release_id=$(echo "$body" | grep -o '"id":[0-9]*' | head -1 | grep -o '[0-9]*')
|
|
if [ -n "$release_id" ]; then
|
|
break
|
|
fi
|
|
echo "release for $TAG not ready yet, waiting 15s ($i/40)"
|
|
sleep 15
|
|
done
|
|
|
|
if [ -z "$release_id" ]; then
|
|
echo "release for $TAG never appeared after 10 minutes" >&2
|
|
exit 1
|
|
fi
|
|
|
|
curl --retry 5 --fail -sS -X POST \
|
|
-H "Authorization: token $TOKEN" \
|
|
-H "Content-Type: multipart/form-data" \
|
|
-F "attachment=@$FILE" \
|
|
"$FORGEJO/api/v1/repos/$REPO/releases/$release_id/assets?name=$NAME"
|
|
working-directory: carrier
|
|
|
|
# Same non-gating strategy as the macos job above: this runner is a
|
|
# desktop machine that isn't guaranteed to be on when a tag is pushed,
|
|
# so it must never gate the release (and must not be gated by it
|
|
# either). It builds and bundles via windows/bundle.sh - the same
|
|
# script windows/setup.sh runs for local one-command builds - wraps
|
|
# the bundle in an Inno Setup installer (windows/installer.sh; Inno
|
|
# lives in this runner host's user profile), then appends both the
|
|
# portable zip and the setup.exe to the release the linux+flatpak jobs
|
|
# create, with the same poll-for-the-release the macos job does.
|
|
windows:
|
|
runs-on: windows-x86_64
|
|
steps:
|
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
with:
|
|
path: carrier
|
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
with:
|
|
repository: randogoth/fumi
|
|
ref: main
|
|
path: fumi
|
|
- uses: https://code.forgejo.org/actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.cargo/registry
|
|
carrier/target
|
|
fumi/target
|
|
key: cargo-windows-${{ hashFiles('carrier/Cargo.lock') }}
|
|
restore-keys: cargo-windows-
|
|
- run: bash windows/bundle.sh
|
|
working-directory: carrier
|
|
shell: bash
|
|
- run: bash windows/installer.sh
|
|
working-directory: carrier
|
|
shell: bash
|
|
- run: |
|
|
REPO="${{ forge.repository }}"
|
|
TAG="${{ forge.ref_name }}"
|
|
FORGEJO="${{ env.FORGEJO_SERVER_URL }}"
|
|
FORGEJO="${FORGEJO%%/}"
|
|
TOKEN="${{ forge.token }}"
|
|
VERSION=$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -1)
|
|
FILES="carrier-windows-$VERSION.zip carrier-windows-$VERSION-setup.exe"
|
|
|
|
release_id=""
|
|
for i in $(seq 1 40); do
|
|
body=$(curl --retry 5 -sS -H "Authorization: token $TOKEN" "$FORGEJO/api/v1/repos/$REPO/releases/tags/$TAG")
|
|
release_id=$(echo "$body" | grep -o '"id":[0-9]*' | head -1 | grep -o '[0-9]*')
|
|
if [ -n "$release_id" ]; then
|
|
break
|
|
fi
|
|
echo "release for $TAG not ready yet, waiting 15s ($i/40)"
|
|
sleep 15
|
|
done
|
|
|
|
if [ -z "$release_id" ]; then
|
|
echo "release for $TAG never appeared after 10 minutes" >&2
|
|
exit 1
|
|
fi
|
|
|
|
for FILE in $FILES; do
|
|
curl --retry 5 --fail -sS -X POST \
|
|
-H "Authorization: token $TOKEN" \
|
|
-H "Content-Type: multipart/form-data" \
|
|
-F "attachment=@$FILE" \
|
|
"$FORGEJO/api/v1/repos/$REPO/releases/$release_id/assets?name=$FILE"
|
|
done
|
|
working-directory: carrier
|
|
shell: bash
|
|
|
|
linux:
|
|
runs-on: linux-x86_64
|
|
steps:
|
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
with:
|
|
path: carrier
|
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
with:
|
|
repository: randogoth/fumi
|
|
ref: main
|
|
path: fumi
|
|
- uses: https://code.forgejo.org/actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.cargo/registry
|
|
carrier/target
|
|
fumi/target
|
|
key: cargo-linux-${{ hashFiles('carrier/Cargo.lock') }}
|
|
restore-keys: cargo-linux-
|
|
- run: devbox run build
|
|
working-directory: carrier
|
|
env:
|
|
GITHUB_TOKEN: ""
|
|
- run: mv target/release/carrier target/release/carrier-linux-x86_64
|
|
working-directory: carrier
|
|
- uses: https://code.forgejo.org/forgejo/upload-artifact@v5
|
|
with:
|
|
name: carrier-linux-x86_64
|
|
path: carrier/target/release/carrier-linux-x86_64
|
|
|
|
# Builds from source inside flatpak-builder's own sandbox, via the
|
|
# rust-stable SDK extension (same as com.randogoth.carrier.json already
|
|
# does for local `devbox run package`). Reusing the linux job's binary
|
|
# was tried and reverted: that binary is dynamically linked against ~100
|
|
# libraries at absolute /nix/store paths, including its own ELF
|
|
# interpreter - none of which exist inside the Flatpak sandbox, so it
|
|
# can never execute there regardless of how it's packaged in.
|
|
flatpak:
|
|
runs-on: linux-x86_64
|
|
steps:
|
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
with:
|
|
path: carrier
|
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
with:
|
|
repository: randogoth/fumi
|
|
ref: main
|
|
path: fumi
|
|
- run: devbox run bundle-flatpak
|
|
working-directory: carrier
|
|
env:
|
|
GITHUB_TOKEN: ""
|
|
- uses: https://code.forgejo.org/forgejo/upload-artifact@v5
|
|
with:
|
|
name: carrier-x86_64.flatpak
|
|
path: carrier/carrier-x86_64.flatpak
|
|
|
|
# forgejo-release.sh (the engine behind actions/forgejo-release) always
|
|
# does a blind create-then-upload of the release for the tag, with no
|
|
# check for one already existing - running it from two parallel jobs
|
|
# against the same tag either hard-fails the second create (override:
|
|
# false) or races a delete-and-recreate that can wipe out the first job's
|
|
# just-uploaded assets (override: true). So platform jobs only ever
|
|
# produce artifacts; exactly one job, gated on both finishing, does the
|
|
# single release create + upload. macos is deliberately left out of
|
|
# needs (see that job): re-running this job after macos has appended its
|
|
# asset will wipe that asset out via override - rerun macos again after
|
|
# to restore it.
|
|
release:
|
|
needs: [linux, flatpak]
|
|
runs-on: linux-x86_64
|
|
steps:
|
|
- uses: https://code.forgejo.org/forgejo/download-artifact@v7
|
|
with:
|
|
path: dist/release
|
|
merge-multiple: true
|
|
- uses: https://code.forgejo.org/actions/forgejo-release@v2.13.4
|
|
with:
|
|
direction: upload
|
|
release-dir: dist/release
|
|
# Safe here specifically because this is the only job that ever
|
|
# calls forgejo-release for a given tag: re-running this same job
|
|
# for the same tag (e.g. a manual rerun) replaces its release
|
|
# cleanly instead of failing on "already exists".
|
|
override: true
|