2026-09-21 16:36:16 +02:00
|
|
|
name: Windows Release
|
|
|
|
|
|
2026-11-07 15:50:33 +01:00
|
|
|
# Forgejo-orchestrated Windows portable zip.
|
|
|
|
|
# Tower `desktop-release` triggers the private GitHub builder (MSVC), then
|
|
|
|
|
# verifies the public Forgejo release tag `windows-continuous`.
|
2026-09-21 16:36:16 +02:00
|
|
|
# See docs/windows-runner.md
|
|
|
|
|
|
|
|
|
|
on:
|
|
|
|
|
push:
|
|
|
|
|
branches: [main]
|
|
|
|
|
workflow_dispatch:
|
|
|
|
|
|
|
|
|
|
permissions:
|
|
|
|
|
contents: write
|
|
|
|
|
|
|
|
|
|
concurrency:
|
|
|
|
|
group: infinipaint-windows-release
|
|
|
|
|
cancel-in-progress: true
|
|
|
|
|
|
|
|
|
|
jobs:
|
|
|
|
|
windows-x86_64:
|
2026-11-07 15:50:33 +01:00
|
|
|
runs-on: desktop-release
|
|
|
|
|
timeout-minutes: 360
|
2026-09-21 16:36:16 +02:00
|
|
|
steps:
|
2026-11-07 15:50:33 +01:00
|
|
|
- name: Resolve expected asset
|
2026-09-21 16:36:16 +02:00
|
|
|
id: ver
|
|
|
|
|
shell: bash
|
|
|
|
|
run: |
|
|
|
|
|
set -euo pipefail
|
2026-11-07 15:50:33 +01:00
|
|
|
# Shallow metadata from the triggering commit (no full Windows checkout).
|
|
|
|
|
ver="$(curl -fsSL -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
|
|
|
|
"${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/contents/src/VersionConstants.hpp?ref=${GITHUB_SHA}" \
|
|
|
|
|
| python3 -c "import sys,json,base64,re; d=json.load(sys.stdin); t=base64.b64decode(d['content']).decode(); print(re.search(r'CURRENT_VERSION_STRING\s*=\s*\"([^\"]+)\"', t).group(1))")"
|
2026-09-21 16:36:16 +02:00
|
|
|
short_sha="$(echo "${GITHUB_SHA}" | cut -c1-7)"
|
|
|
|
|
asset_ver="${ver}+${short_sha}"
|
|
|
|
|
zip_name="infinipaint-${asset_ver}-win-x86_64-portable.zip"
|
|
|
|
|
{
|
|
|
|
|
echo "version=${ver}"
|
|
|
|
|
echo "tag=windows-continuous"
|
|
|
|
|
echo "asset_ver=${asset_ver}"
|
|
|
|
|
echo "zip_name=${zip_name}"
|
2026-11-07 15:50:33 +01:00
|
|
|
echo "short_sha=${short_sha}"
|
2026-09-21 16:36:16 +02:00
|
|
|
} >> "$GITHUB_OUTPUT"
|
2026-11-07 15:50:33 +01:00
|
|
|
echo "Expect Forgejo asset: ${zip_name}"
|
2026-09-21 16:36:16 +02:00
|
|
|
|
2026-11-07 15:50:33 +01:00
|
|
|
- name: Dispatch or reuse GitHub Windows build
|
|
|
|
|
id: gh
|
|
|
|
|
shell: bash
|
2026-09-21 16:36:16 +02:00
|
|
|
env:
|
2026-11-07 15:50:33 +01:00
|
|
|
GH_BUILDER_TOKEN: ${{ secrets.GH_BUILDER_TOKEN }}
|
|
|
|
|
WANT_SHA: ${{ github.sha }}
|
2026-09-21 16:36:16 +02:00
|
|
|
run: |
|
2026-11-07 15:50:33 +01:00
|
|
|
set -euo pipefail
|
|
|
|
|
if [ -z "${GH_BUILDER_TOKEN:-}" ]; then
|
|
|
|
|
echo "GH_BUILDER_TOKEN secret missing on Forgejo repo" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
api="https://api.github.com/repos/littlecodedragon/infinipaint"
|
|
|
|
|
auth=(-H "Authorization: Bearer ${GH_BUILDER_TOKEN}" -H "Accept: application/vnd.github+json")
|
|
|
|
|
gh_sha=$(curl -fsSL "${auth[@]}" "${api}/commits/main" | python3 -c "import sys,json; print(json.load(sys.stdin)['sha'])")
|
|
|
|
|
if [ "$gh_sha" != "$WANT_SHA" ]; then
|
|
|
|
|
echo "WARN: GitHub main=${gh_sha:0:7} != Forgejo ${WANT_SHA:0:7} — keep remotes synced (push both)." >&2
|
|
|
|
|
fi
|
|
|
|
|
runs=$(curl -fsSL "${auth[@]}" "${api}/actions/workflows/windows_release.yml/runs?branch=main&per_page=15")
|
|
|
|
|
run_id=$(echo "$runs" | python3 -c "
|
|
|
|
|
import sys, json, os
|
|
|
|
|
want = os.environ['WANT_SHA']
|
|
|
|
|
runs = json.load(sys.stdin).get('workflow_runs', [])
|
|
|
|
|
# Prefer live or successful run for this SHA.
|
|
|
|
|
for r in runs:
|
|
|
|
|
if r.get('head_sha') != want:
|
|
|
|
|
continue
|
|
|
|
|
st, conc = r.get('status'), r.get('conclusion')
|
|
|
|
|
if st in ('queued', 'in_progress') or (st == 'completed' and conc == 'success'):
|
|
|
|
|
print(r['id'])
|
|
|
|
|
break
|
|
|
|
|
")
|
|
|
|
|
if [ -z "${run_id}" ]; then
|
|
|
|
|
echo "No usable GitHub run for ${WANT_SHA:0:7} — dispatching workflow_dispatch"
|
|
|
|
|
code=$(curl -sS -o /tmp/gh-dispatch.json -w '%{http_code}' -X POST "${auth[@]}" \
|
|
|
|
|
-H "Content-Type: application/json" \
|
|
|
|
|
"${api}/actions/workflows/windows_release.yml/dispatches" \
|
|
|
|
|
-d '{"ref":"main"}')
|
|
|
|
|
[ "$code" = "204" ] || { cat /tmp/gh-dispatch.json; exit 1; }
|
|
|
|
|
sleep 8
|
|
|
|
|
runs=$(curl -fsSL "${auth[@]}" "${api}/actions/workflows/windows_release.yml/runs?branch=main&per_page=5")
|
|
|
|
|
run_id=$(echo "$runs" | python3 -c "import sys,json; print(json.load(sys.stdin)['workflow_runs'][0]['id'])")
|
|
|
|
|
fi
|
|
|
|
|
echo "run_id=${run_id}" >> "$GITHUB_OUTPUT"
|
|
|
|
|
echo "Tracking GitHub run ${run_id}"
|
2026-09-21 16:36:16 +02:00
|
|
|
|
2026-11-07 15:50:33 +01:00
|
|
|
- name: Wait for GitHub build + Forgejo public release
|
2026-09-21 16:36:16 +02:00
|
|
|
shell: bash
|
|
|
|
|
env:
|
2026-11-07 15:50:33 +01:00
|
|
|
GH_BUILDER_TOKEN: ${{ secrets.GH_BUILDER_TOKEN }}
|
2026-09-21 16:36:16 +02:00
|
|
|
FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
2026-11-07 15:50:33 +01:00
|
|
|
RUN_ID: ${{ steps.gh.outputs.run_id }}
|
2026-09-21 16:36:16 +02:00
|
|
|
ZIP_NAME: ${{ steps.ver.outputs.zip_name }}
|
2026-11-07 15:50:33 +01:00
|
|
|
ASSET_VER: ${{ steps.ver.outputs.asset_ver }}
|
|
|
|
|
SHORT_SHA: ${{ steps.ver.outputs.short_sha }}
|
2026-09-21 16:36:16 +02:00
|
|
|
run: |
|
|
|
|
|
set -euo pipefail
|
2026-11-07 15:50:33 +01:00
|
|
|
api="https://api.github.com/repos/littlecodedragon/infinipaint"
|
|
|
|
|
auth=(-H "Authorization: Bearer ${GH_BUILDER_TOKEN}" -H "Accept: application/vnd.github+json")
|
|
|
|
|
fj="https://forgejo.fsociety00.cc/api/v1/repos/copilot/infinipaint/releases/tags/windows-continuous"
|
|
|
|
|
for i in $(seq 1 240); do
|
|
|
|
|
g=$(curl -fsSL "${auth[@]}" "${api}/actions/runs/${RUN_ID}")
|
|
|
|
|
status=$(echo "$g" | python3 -c "import sys,json;d=json.load(sys.stdin);print(d.get('status'), d.get('conclusion') or '-')")
|
|
|
|
|
rel=$(curl -fsSL -H "Authorization: token ${FORGEJO_TOKEN}" "$fj" || echo '{}')
|
|
|
|
|
rname=$(echo "$rel" | python3 -c "import sys,json;print(json.load(sys.stdin).get('name',''))" 2>/dev/null || true)
|
|
|
|
|
assets=$(echo "$rel" | python3 -c "import sys,json;print([a.get('name') for a in json.load(sys.stdin).get('assets',[])])" 2>/dev/null || true)
|
|
|
|
|
echo "$(date -u +%H:%M:%S) github=${status} forgejo=${rname} assets=${assets}"
|
|
|
|
|
if echo "$assets" | grep -Fq "${ZIP_NAME}" || echo "$rname" | grep -Fq "${SHORT_SHA}"; then
|
|
|
|
|
echo "Public Forgejo release is up to date."
|
|
|
|
|
exit 0
|
|
|
|
|
fi
|
|
|
|
|
if echo "$status" | grep -q '^completed failure\|^completed cancelled\|^completed timed_out'; then
|
|
|
|
|
echo "GitHub Windows build failed: ${status}" >&2
|
|
|
|
|
echo "$g" | python3 -c "import sys,json;print(json.load(sys.stdin).get('html_url',''))"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
sleep 60
|
|
|
|
|
done
|
|
|
|
|
echo "Timed out waiting for Forgejo asset ${ZIP_NAME}" >&2
|
|
|
|
|
exit 1
|