Release Runtimes #41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release Runtimes | |
| on: | |
| push: | |
| paths: | |
| - 'runtimes/*.squashfs' | |
| workflow_dispatch: | |
| workflow_run: | |
| # The push trigger above doesn't fire for pushes made by the default | |
| # GITHUB_TOKEN (GitHub suppresses this to prevent workflow recursion), | |
| # so any workflow that commits runtime payloads must be chained here. | |
| workflows: ["Build Runtimes"] | |
| types: [completed] | |
| concurrency: | |
| group: release-runtimes | |
| cancel-in-progress: true | |
| jobs: | |
| release-runtimes: | |
| runs-on: ubuntu-latest | |
| if: github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' | |
| permissions: | |
| contents: write | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Ensure release exists | |
| run: | | |
| gh release view runtimes-latest >/dev/null 2>&1 || \ | |
| gh release create runtimes-latest \ | |
| --title "Runtimes" \ | |
| --notes "Squashfs runtimes for ports (auto-updated)" | |
| - name: Sync runtimes/ ↔ release | |
| run: | | |
| set -euo pipefail | |
| # Collect local runtimes | |
| mapfile -t LOCAL < <(find runtimes -maxdepth 1 -name '*.squashfs' -type f | sort) | |
| declare -A LOCAL_SET | |
| for f in "${LOCAL[@]}"; do | |
| LOCAL_SET[$(basename "$f")]=1 | |
| done | |
| # Snapshot remote assets (name → size, name → id) | |
| RELEASE_ID=$(gh api repos/${GITHUB_REPOSITORY}/releases/tags/runtimes-latest --jq '.id') | |
| declare -A REMOTE_SIZES REMOTE_IDS | |
| while IFS=: read -r name size id; do | |
| [ -z "$name" ] && continue | |
| REMOTE_SIZES["$name"]="$size" | |
| REMOTE_IDS["$name"]="$id" | |
| done < <( | |
| gh api "repos/${GITHUB_REPOSITORY}/releases/$RELEASE_ID/assets" \ | |
| --jq '.[] | "\(.name):\(.size):\(.id)"' 2>/dev/null || true | |
| ) | |
| # Upload new or size-changed runtimes | |
| for f in "${LOCAL[@]}"; do | |
| name=$(basename "$f") | |
| local_size=$(stat -c %s "$f") | |
| remote_size="${REMOTE_SIZES[$name]:-}" | |
| if [ "$local_size" = "$remote_size" ]; then | |
| echo "Skipping $name (unchanged: $local_size bytes)" | |
| continue | |
| fi | |
| if [ -n "$remote_size" ]; then | |
| echo "Replacing $name (remote: $remote_size → local: $local_size bytes)" | |
| else | |
| echo "Uploading new $name ($local_size bytes)" | |
| fi | |
| gh release upload runtimes-latest "$f" --clobber | |
| done | |
| # Purge orphaned remote assets | |
| for name in "${!REMOTE_IDS[@]}"; do | |
| if [ -z "${LOCAL_SET[$name]:-}" ]; then | |
| echo "Deleting orphaned asset: $name" | |
| gh api -X DELETE \ | |
| "repos/${GITHUB_REPOSITORY}/releases/assets/${REMOTE_IDS[$name]}" || true | |
| fi | |
| done |