From 5d097143a5a622f256e5892b355a72d56b723d05 Mon Sep 17 00:00:00 2001 From: randogoth Date: Wed, 7 Oct 2026 20:53:22 +0300 Subject: [PATCH] Decouple macOS from the release job apfel is a laptop that's frequently asleep/offline; gating the release on it (needs: [macos, linux, flatpak]) meant the whole release stalled whenever it wasn't reachable. macos now appends its own asset directly via the Forgejo API once it finishes, polling for the release that linux+flatpak already created/overrode, instead of going through actions/forgejo-release (which can only blind-create, not append to an existing release). --- .forgejo/workflows/release.yml | 57 ++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index 94b0db8..b6eb49f 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -30,14 +30,48 @@ jobs: GITHUB_TOKEN: "" - run: mv target/release/carrier target/release/carrier-macos-arm64 working-directory: carrier - # actions/upload-artifact@v4 talks the newer Artifacts-v2 protocol, - # which Forgejo's server rejects ("not currently supported on GHES"). - # forgejo/upload-artifact is Forgejo's own patched fork with that - # check disabled - needed on both upload and download ends. - - uses: https://code.forgejo.org/forgejo/upload-artifact@v5 - with: - name: carrier-macos-arm64 - path: carrier/target/release/carrier-macos-arm64 + # 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 linux: runs-on: linux-x86_64 @@ -105,9 +139,12 @@ jobs: # 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. + # 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: [macos, linux, flatpak] + needs: [linux, flatpak] runs-on: linux-x86_64 steps: - uses: https://code.forgejo.org/forgejo/download-artifact@v7