diff --git a/.forgejo/workflows/windows_release.yml b/.forgejo/workflows/windows_release.yml new file mode 100644 index 0000000..525c04d --- /dev/null +++ b/.forgejo/workflows/windows_release.yml @@ -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 // .' diff --git a/FORK.md b/FORK.md index 9c91897..10b3ef3 100644 --- a/FORK.md +++ b/FORK.md @@ -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**. diff --git a/conan/profiles/linux-x86_64 b/conan/profiles/linux-x86_64 index eb753d6..ee8b744 100644 --- a/conan/profiles/linux-x86_64 +++ b/conan/profiles/linux-x86_64 @@ -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] diff --git a/docs/windows-runner.md b/docs/windows-runner.md new file mode 100644 index 0000000..cc8a6ee --- /dev/null +++ b/docs/windows-runner.md @@ -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).