Add continuous Windows release workflow and runner docs
Some checks failed
Windows Release / windows-x86_64 (push) Has been cancelled

Public repo already; workflow builds portable zip on windows-release
and publishes windows-continuous. Bump linux Conan profile to gcc 16.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
copilot 2026-09-21 16:36:16 +02:00
parent 042fe8f5a6
commit 8ac02f1b7b
4 changed files with 217 additions and 17 deletions

View file

@ -0,0 +1,178 @@
name: Windows Release
# Continuous Windows portable build on every push to main.
# Needs self-hosted runner label `windows-release` (MSVC 2022).
# 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: windows-release
timeout-minutes: 240
steps:
- name: Checkout
shell: bash
env:
FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
rm -rf .git
git init .
origin_url="${GITHUB_SERVER_URL#https://}"
origin_url="${origin_url#http://}"
git remote add origin "https://oauth2:${FORGEJO_TOKEN}@${origin_url}/${GITHUB_REPOSITORY}.git"
git -c http.sslVerify=false fetch --depth=1 origin "${GITHUB_SHA}"
git checkout --force FETCH_HEAD
git submodule update --init --recursive
- name: Resolve version
id: ver
shell: bash
run: |
set -euo pipefail
ver="$(grep -E 'CURRENT_VERSION_STRING' src/VersionConstants.hpp | head -1 | sed -E 's/.*"([^"]+)".*/\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}"
} >> "$GITHUB_OUTPUT"
- name: Ensure Conan
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
if (-not (Get-Command conan -ErrorAction SilentlyContinue)) {
python -m pip install --user "conan>=2,<3"
Get-ChildItem "$env:USERPROFILE\AppData\Roaming\Python" -Recurse -Filter conan.exe -ErrorAction SilentlyContinue |
ForEach-Object { $env:Path = "$($_.DirectoryName);$env:Path" }
}
conan --version
- name: Build Windows x86_64
shell: cmd
run: |
call windowsinstall\conan_init_x86_64.bat
if errorlevel 1 exit /b 1
call windowsinstall\build_x86_64.bat
if errorlevel 1 exit /b 1
- name: Package portable zip
id: pkg
shell: pwsh
env:
ZIP_NAME: ${{ steps.ver.outputs.zip_name }}
run: |
$ErrorActionPreference = "Stop"
$exe = Get-ChildItem -Path . -Recurse -Filter infinipaint.exe |
Where-Object { $_.FullName -match 'Release' } |
Select-Object -First 1
if (-not $exe) { throw "infinipaint.exe not found under Release" }
$outDir = Join-Path (Get-Location) "dist\portable"
Remove-Item -Recurse -Force $outDir -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
Copy-Item $exe.FullName (Join-Path $outDir "infinipaint.exe")
$dllDir = Join-Path (Get-Location) "windowsinstall\dlls-x86_64"
if (Test-Path $dllDir) {
Copy-Item (Join-Path $dllDir "*.dll") $outDir -ErrorAction SilentlyContinue
}
$dataSrc = Join-Path (Get-Location) "assets\data"
if (-not (Test-Path $dataSrc)) { $dataSrc = Join-Path (Get-Location) "data" }
Copy-Item -Recurse $dataSrc (Join-Path $outDir "data")
New-Item -ItemType Directory -Force -Path "dist" | Out-Null
$zipPath = Join-Path (Get-Location) "dist\$env:ZIP_NAME"
if (Test-Path $zipPath) { Remove-Item $zipPath }
Compress-Archive -Path (Join-Path $outDir "*") -DestinationPath $zipPath
"zip_path=$zipPath" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
Get-Item $zipPath | Format-List FullName, Length
- name: Publish Forgejo release
shell: bash
env:
FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION_TAG: ${{ steps.ver.outputs.tag }}
ASSET_VER: ${{ steps.ver.outputs.asset_ver }}
VERSION: ${{ steps.ver.outputs.version }}
ZIP_NAME: ${{ steps.ver.outputs.zip_name }}
FORGEJO_CURL_INSECURE: "true"
run: |
set -euo pipefail
zip_path="dist/${ZIP_NAME}"
test -f "$zip_path"
command -v jq >/dev/null
command -v curl >/dev/null
curl_tls=()
if [ "${FORGEJO_CURL_INSECURE}" = "true" ]; then
curl_tls+=(--insecure)
fi
api_base="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases"
body=$(printf '%s\n' \
"Continuous Windows build from \`main\`." \
"" \
"- Version: **${VERSION}**" \
"- Commit: \`${GITHUB_SHA}\`" \
"- Asset: \`${ZIP_NAME}\`" \
"" \
"Updated on every push to \`main\`. Requires runner label \`windows-release\` (see docs/windows-runner.md).")
payload=$(jq -n \
--arg tag "$VERSION_TAG" \
--arg name "Windows continuous (${ASSET_VER})" \
--arg body "$body" \
'{tag_name:$tag, name:$name, body:$body, draft:false, prerelease:true}')
tag_enc=$(jq -nr --arg t "$VERSION_TAG" '$t|@uri')
resp_file=$(mktemp)
status=$(curl "${curl_tls[@]}" -sS -o "$resp_file" -w '%{http_code}' \
-H "Authorization: token ${FORGEJO_TOKEN}" \
"${api_base}/tags/${tag_enc}")
release_id=""
if [ "$status" = "200" ]; then
release_id=$(jq -r '.id' < "$resp_file")
curl "${curl_tls[@]}" -sS -X PATCH \
-H "Authorization: token ${FORGEJO_TOKEN}" \
-H "Content-Type: application/json" \
-d "$payload" \
"${api_base}/${release_id}" >/dev/null
jq -r --arg n "$ZIP_NAME" '.assets[]? | select(.name==$n) | .id' < "$resp_file" | while read -r aid; do
[ -n "$aid" ] || continue
curl "${curl_tls[@]}" -sS -X DELETE \
-H "Authorization: token ${FORGEJO_TOKEN}" \
"${api_base}/${release_id}/assets/${aid}" >/dev/null || true
done
elif [ "$status" = "404" ]; then
status=$(curl "${curl_tls[@]}" -sS -o "$resp_file" -w '%{http_code}' -X POST \
-H "Authorization: token ${FORGEJO_TOKEN}" \
-H "Content-Type: application/json" \
-d "$payload" \
"$api_base")
[ "$status" = "200" ] || [ "$status" = "201" ] || { cat "$resp_file"; exit 1; }
release_id=$(jq -r '.id' < "$resp_file")
else
cat "$resp_file"; exit 1
fi
name_enc=$(jq -nr --arg n "$ZIP_NAME" '$n|@uri')
curl "${curl_tls[@]}" -sS -X POST \
-H "Authorization: token ${FORGEJO_TOKEN}" \
-H "Content-Type: application/octet-stream" \
--data-binary @"${zip_path}" \
"${api_base}/${release_id}/assets?name=${name_enc}" \
| jq -r '.browser_download_url // .name // .'

30
FORK.md
View file

@ -1,33 +1,31 @@
# Fork features (copilot/infinipaint)
Upstream: [ErrorAtLine0/infinipaint](https://github.com/ErrorAtLine0/infinipaint)
Forgejo: https://forgejo.fsociety00.cc/copilot/infinipaint
Forgejo: https://forgejo.fsociety00.cc/copilot/infinipaint (public)
Save format: `INFPNT000007` / version `0.7.0-fork` (not network-compatible with stock 0.6.x peers).
## CI
| Workflow | Trigger | Runner | Output |
|----------|---------|--------|--------|
| `.forgejo/workflows/windows_release.yml` | every push to `main` | **`windows-release`** (Windows + MSVC) | prerelease tag `windows-continuous` |
Register a Windows self-hosted runner: [docs/windows-runner.md](docs/windows-runner.md).
Jobs queue until that runner is online (Tower dual-boots Windows).
## Bring Everyone Here (host)
In the player list, the lobby host gets **Bring Everyone Here**. Clients receive `CLIENT_FORCE_CAMERA_JUMP` and run the same `smooth_move_to` path as **Jump To**.
## Group / Ungroup
## Group / Ungroup (canvas objects)
With a multi-selection (images, text boxes, shapes, …), use **Group** / **Ungroup** in the selection panel. Grouped objects auto-expand into the selection so they transform together. Membership syncs via `SET_COMPONENT_GROUP_IDS`.
With a multi-selection (images, brush strokes, text boxes, shapes, …), use **Group** / **Ungroup** in the selection panel. Grouped objects auto-expand into the selection so they transform together. Not related to players.
## Image compression
Settings → **Images**:
- Compress on insert (default on)
- Format: Keep / WebP / PNG
- WebP quality
Selection toolbar: **Compress Images** re-encodes already placed images.
Settings → **Images**: compress on insert (WebP/PNG/Keep). Selection: **Compress Images**.
## Freistellen
Settings → **Images**:
- Freistellen on insert
- Modes: White background (always), or rembg **Schnell** (`silueta`) / **Allgemein** (`bria-rmbg`) when Tower rembg is installed (`~/.local/share/tower-rembg` or `rembg` on `PATH`)
Selection: **Freistellen** applies the configured mode to selected images (then compresses).
Settings → **Images**: white-key and optional rembg (Tower `silueta` / `bria-rmbg`). Selection: **Freistellen**.

View file

@ -4,7 +4,7 @@ build_type=Release
compiler=gcc
compiler.cppstd=gnu23
compiler.libcxx=libstdc++11
compiler.version=15
compiler.version=16
os=Linux
[tool_requires]

24
docs/windows-runner.md Normal file
View file

@ -0,0 +1,24 @@
# Windows Forgejo runner (`windows-release`)
Tower dual-boots Windows. Native InfiniPaint Windows builds need **MSVC 2022**
(see `docs/BUILDING.md` + `windowsinstall/`). There is no Linux cross-build path.
## One-time setup (on Windows)
1. Install Visual Studio 2022 Build Tools (C++), CMake, Git, Python 3.
2. `pip install "conan>=2,<3"`.
3. Download [forgejo-runner](https://code.forgejo.org/forgejo/runner/releases) for Windows.
4. Register against `https://forgejo.fsociety00.cc` with label **`windows-release`**
(repo or org runner; Actions must be enabled — already on for `copilot/infinipaint`).
5. Run the runner as a service or in a logged-on session when you want CI to drain.
## Behaviour
Workflow: `.forgejo/workflows/windows_release.yml`
- Triggers on every push to `main` (and `workflow_dispatch`)
- Builds x86_64 portable zip via `windowsinstall/*_x86_64.bat`
- Publishes/updates prerelease tag **`windows-continuous`**
Jobs stay queued in Forgejo until a `windows-release` runner is online
(same pattern as `desktop-release` capacity/queue on Tower Linux).