@@ -14,6 +14,11 @@ name: Build
1414# - pushes that only change documentation do not build;
1515# - Windows, whose minutes cost twice Linux's, builds only Windows;
1616# - artifacts are kept for three days.
17+ #
18+ # A successful build of main is also published as a GitHub release, the
19+ # newest marked latest, so that
20+ # https://github.com/<repository>/releases/latest/download/<file> always
21+ # gives the latest build; the last five are kept.
1722on :
1823 push :
1924 paths-ignore :
@@ -192,12 +197,66 @@ jobs:
192197 path : dist/halo-windows-release
193198 retention-days : 3
194199
200+ release :
201+ # The six builds as a release, tagged build-<run number> and marked latest
202+ # (every file keeps its name from release to release, for the README's
203+ # latest/download links); then all but the newest five build-* releases
204+ # go, tags and all. Only for main, and only when every platform built.
205+ needs : [linux, android, windows]
206+ if : ${{ github.ref == 'refs/heads/main' }}
207+ runs-on : ubuntu-24.04
208+ timeout-minutes : 15
209+ permissions :
210+ contents : write
211+ outputs :
212+ tag : ${{ steps.publish.outputs.tag }}
213+ env :
214+ GH_TOKEN : ${{ github.token }}
215+ GH_REPO : ${{ github.repository }}
216+ steps :
217+ - uses : actions/download-artifact@v4
218+ with :
219+ pattern : halo-*
220+ path : artifacts
221+
222+ - name : Package
223+ run : |
224+ mkdir release
225+ for build in artifacts/*/; do
226+ name="$(basename "$build")"
227+ (cd "$build" && zip -qr "$GITHUB_WORKSPACE/release/$name.zip" .)
228+ done
229+ ls -l release
230+
231+ - name : Publish
232+ id : publish
233+ env :
234+ MESSAGE : ${{ github.event.head_commit.message }}
235+ COMMIT_URL : ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}
236+ RUN_URL : ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
237+ run : |
238+ tag="build-$GITHUB_RUN_NUMBER"
239+ subject="$(printf '%s' "${MESSAGE:-manual run}" | head -n 1)"
240+ printf '%s\n\nCommit: %s\nBuild: %s\n\nThe release builds are for playing; the debug builds stop at the first failed assertion and log it.\n' \
241+ "$subject" "$COMMIT_URL" "$RUN_URL" > notes.md
242+ gh release create "$tag" release/*.zip --target "$GITHUB_SHA" --latest \
243+ --title "Build $GITHUB_RUN_NUMBER (${GITHUB_SHA:0:7})" --notes-file notes.md
244+ echo "tag=$tag" >> "$GITHUB_OUTPUT"
245+
246+ - name : Keep the last five
247+ run : |
248+ gh release list --limit 100 --json tagName,createdAt \
249+ --jq '[.[] | select(.tagName | startswith("build-"))] | sort_by(.createdAt) | reverse | .[5:] | .[].tagName' |
250+ while read -r tag; do
251+ gh release delete "$tag" --cleanup-tag --yes
252+ done
253+
195254 notify :
196255 # A Discord embed for the run, to the DISCORD_WEBHOOK secret (nothing
197- # without it): green when every platform built, red when one did not, with each
198- # platform's result and links to the latest release builds (nightly.link
199- # serves the branch's latest successful run 's artifacts) .
200- needs : [linux, android, windows]
256+ # without it): green when every platform built, red when one did not,
257+ # with each platform's result, this run's release (main only), and links
258+ # to the latest release 's builds .
259+ needs : [linux, android, windows, release ]
201260 if : ${{ !cancelled() }}
202261 runs-on : ubuntu-24.04
203262 timeout-minutes : 5
@@ -208,6 +267,8 @@ jobs:
208267 LINUX : ${{ needs.linux.result }}
209268 ANDROID : ${{ needs.android.result }}
210269 WINDOWS : ${{ needs.windows.result }}
270+ RELEASE_TAG : ${{ needs.release.outputs.tag }}
271+ SERVER : ${{ github.server_url }}
211272 REPOSITORY : ${{ github.repository }}
212273 BRANCH : ${{ github.ref_name }}
213274 SHA : ${{ github.sha }}
@@ -233,13 +294,18 @@ jobs:
233294 else
234295 title="Build failed"; color=15548997
235296 fi
236- links="https://nightly.link/$REPOSITORY/workflows/build.yml/$BRANCH"
237- downloads="[Linux]($links/halo-linux-release.zip) · [Windows]($links/halo-windows-release.zip) · [Android]($links/halo-android-release.zip)"
297+ latest="$SERVER/$REPOSITORY/releases/latest"
298+ downloads="[Linux]($latest/download/halo-linux-release.zip) · [Windows]($latest/download/halo-windows-release.zip) · [Android]($latest/download/halo-android-release.zip) ([all builds]($latest))"
299+ if [ -n "$RELEASE_TAG" ]; then
300+ release="[$RELEASE_TAG]($SERVER/$REPOSITORY/releases/tag/$RELEASE_TAG)"
301+ else
302+ release="None (only a successful build of main makes one)"
303+ fi
238304 subject="$(printf '%s' "${MESSAGE:-manual run}" | head -n 1 | cut -c1-200)"
239305 jq -n \
240306 --arg title "$title" --argjson color "$color" --arg url "$RUN_URL" \
241- --arg description "[\`${SHA:0:7}\`]($COMMIT_URL) $subject — $ACTOR" \
242- --arg branch "$BRANCH " --arg downloads "$downloads" \
307+ --arg description "[\`${SHA:0:7}\`]($COMMIT_URL) $subject — $ACTOR ($BRANCH) " \
308+ --arg release "$release " --arg downloads "$downloads" \
243309 --arg linux "$(status "$LINUX")" --arg windows "$(status "$WINDOWS")" --arg android "$(status "$ANDROID")" \
244310 --arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
245311 '{embeds: [{
@@ -248,7 +314,8 @@ jobs:
248314 {name: "Linux", value: $linux, inline: true},
249315 {name: "Windows", value: $windows, inline: true},
250316 {name: "Android", value: $android, inline: true},
251- {name: ("Latest release builds (" + $branch + ")"), value: $downloads}
317+ {name: "Release", value: $release},
318+ {name: "Latest release builds", value: $downloads}
252319 ]
253320 }]}' > payload.json
254321 curl -fsS -H "Content-Type: application/json" -d @payload.json "$WEBHOOK"
0 commit comments