name: Windows Release # Forgejo-orchestrated Windows portable zip. # Tower `desktop-release` triggers the private GitHub builder (MSVC), then # verifies the public Forgejo release tag `windows-continuous`. # 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: runs-on: desktop-release timeout-minutes: 360 steps: - name: Resolve expected asset id: ver shell: bash run: | set -euo pipefail # 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))")" 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}" echo "short_sha=${short_sha}" } >> "$GITHUB_OUTPUT" echo "Expect Forgejo asset: ${zip_name}" - name: Dispatch or reuse GitHub Windows build id: gh shell: bash env: GH_BUILDER_TOKEN: ${{ secrets.GH_BUILDER_TOKEN }} WANT_SHA: ${{ github.sha }} run: | 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}" - name: Wait for GitHub build + Forgejo public release shell: bash env: GH_BUILDER_TOKEN: ${{ secrets.GH_BUILDER_TOKEN }} FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }} RUN_ID: ${{ steps.gh.outputs.run_id }} ZIP_NAME: ${{ steps.ver.outputs.zip_name }} ASSET_VER: ${{ steps.ver.outputs.asset_ver }} SHORT_SHA: ${{ steps.ver.outputs.short_sha }} run: | set -euo pipefail 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