Ship 0.8 fog/freistellen and fix Windows CI for friends
Some checks are pending
Windows Release / windows-x86_64 (push) Waiting to run
Some checks are pending
Windows Release / windows-x86_64 (push) Waiting to run
Publish the portable zip to public Forgejo from the private GitHub builder, and force Ninja so MSVC 195 deps build without CMake 4.2.
This commit is contained in:
parent
97b136de3b
commit
1c1d63f376
46 changed files with 1748 additions and 156 deletions
133
.github/workflows/windows_release.yml
vendored
133
.github/workflows/windows_release.yml
vendored
|
|
@ -1,7 +1,8 @@
|
|||
name: Windows Release
|
||||
|
||||
# Continuous Windows portable build on every push to main.
|
||||
# Uses GitHub-hosted windows-latest (MSVC preinstalled).
|
||||
# Uses GitHub-hosted windows-latest (MSVC) as a *private* builder.
|
||||
# Public download: Forgejo release tag windows-continuous.
|
||||
# See docs/windows-runner.md
|
||||
|
||||
on:
|
||||
|
|
@ -31,6 +32,9 @@ jobs:
|
|||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Setup Ninja
|
||||
uses: seanmiddleditch/gha-setup-ninja@v5
|
||||
|
||||
- name: Install Conan
|
||||
shell: pwsh
|
||||
run: |
|
||||
|
|
@ -44,6 +48,8 @@ jobs:
|
|||
$msvcVer = ($verLine.Line -split '=')[1].Trim()
|
||||
if (-not $msvcVer) { throw "could not read compiler.version from default profile" }
|
||||
# Host profile matching the runner (repo win-x86_64 still pins 194 for local Tower).
|
||||
# Force Ninja: recipes that tool_require cmake<4 cannot use "Visual Studio 18 2026"
|
||||
# (needs CMake >= 4.2). Ninja works with older CMake + MSVC 195.
|
||||
$p = Join-Path $env:USERPROFILE ".conan2\profiles\win-ci"
|
||||
@"
|
||||
[settings]
|
||||
|
|
@ -54,9 +60,13 @@ jobs:
|
|||
compiler.runtime=dynamic
|
||||
compiler.version=$msvcVer
|
||||
os=Windows
|
||||
|
||||
[conf]
|
||||
tools.cmake.cmaketoolchain:generator=Ninja
|
||||
"@.Trim() | Set-Content -Path $p -Encoding ascii
|
||||
Write-Host "win-ci MSVC version=$msvcVer"
|
||||
Write-Host "win-ci MSVC version=$msvcVer (generator=Ninja)"
|
||||
Get-Content $p
|
||||
ninja --version
|
||||
|
||||
- name: Resolve version
|
||||
id: ver
|
||||
|
|
@ -81,8 +91,14 @@ jobs:
|
|||
if errorlevel 1 exit /b 1
|
||||
conan install . -of=build-x86_64 --build=missing -pr:h=win-ci -pr:b=default
|
||||
if errorlevel 1 exit /b 1
|
||||
call windowsinstall\build_x86_64.bat
|
||||
if not exist build-x86_64\build mkdir build-x86_64\build
|
||||
cd build-x86_64\build
|
||||
call .\generators\conanbuild.bat
|
||||
cmake ..\.. -G Ninja -DCMAKE_TOOLCHAIN_FILE="generators\conan_toolchain.cmake" -DCMAKE_BUILD_TYPE=Release -DCONFIG_NEXT_TO_EXECUTABLE=OFF
|
||||
if errorlevel 1 exit /b 1
|
||||
cmake --build . --config Release
|
||||
if errorlevel 1 exit /b 1
|
||||
call .\generators\deactivate_conanbuild.bat
|
||||
|
||||
- name: Package portable zip
|
||||
id: pkg
|
||||
|
|
@ -92,9 +108,9 @@ jobs:
|
|||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$exe = Get-ChildItem -Path . -Recurse -Filter infinipaint.exe |
|
||||
Where-Object { $_.FullName -match 'Release' } |
|
||||
Where-Object { $_.FullName -match 'build-x86_64|Release' } |
|
||||
Select-Object -First 1
|
||||
if (-not $exe) { throw "infinipaint.exe not found under Release" }
|
||||
if (-not $exe) { throw "infinipaint.exe not found under build-x86_64/Release" }
|
||||
$outDir = Join-Path (Get-Location) "dist\portable"
|
||||
Remove-Item -Recurse -Force $outDir -ErrorAction SilentlyContinue
|
||||
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
|
||||
|
|
@ -106,6 +122,14 @@ jobs:
|
|||
$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")
|
||||
$rembgSrc = Join-Path (Get-Location) "third_party\rembg"
|
||||
if (Test-Path $rembgSrc) {
|
||||
Copy-Item -Recurse $rembgSrc (Join-Path $outDir "rembg")
|
||||
}
|
||||
$modelsSrc = Join-Path (Get-Location) "third_party\rembg-home"
|
||||
if (Test-Path $modelsSrc) {
|
||||
Copy-Item -Recurse $modelsSrc (Join-Path $outDir "rembg-home")
|
||||
}
|
||||
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 }
|
||||
|
|
@ -113,19 +137,110 @@ jobs:
|
|||
"zip_path=$zipPath" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
|
||||
Get-Item $zipPath | Format-List FullName, Length
|
||||
|
||||
- name: Publish GitHub release
|
||||
# Optional private artifact on GitHub (repo is private builder-only).
|
||||
- name: Publish private GitHub release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ steps.ver.outputs.tag }}
|
||||
name: Windows continuous (${{ steps.ver.outputs.asset_ver }})
|
||||
prerelease: true
|
||||
body: |
|
||||
Continuous Windows build from `main`.
|
||||
Continuous Windows build from `main` (private GitHub builder).
|
||||
|
||||
**Public download:** Forgejo release `windows-continuous`
|
||||
https://forgejo.fsociety00.cc/copilot/infinipaint/releases/tag/windows-continuous
|
||||
|
||||
- Version: **${{ steps.ver.outputs.version }}**
|
||||
- Commit: `${{ github.sha }}`
|
||||
- Asset: `${{ steps.ver.outputs.zip_name }}`
|
||||
|
||||
Updated on every push to `main`. Built on GitHub-hosted `windows-latest`.
|
||||
files: dist/${{ steps.ver.outputs.zip_name }}
|
||||
fail_on_unmatched_files: true
|
||||
|
||||
- name: Publish Forgejo release (public)
|
||||
shell: bash
|
||||
env:
|
||||
FORGEJO_TOKEN: ${{ secrets.FORGEJO_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_API: https://forgejo.fsociety00.cc/api/v1
|
||||
FORGEJO_REPO: copilot/infinipaint
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ -z "${FORGEJO_TOKEN:-}" ]; then
|
||||
echo "FORGEJO_TOKEN secret missing — cannot publish public Forgejo release" >&2
|
||||
exit 1
|
||||
fi
|
||||
zip_path="dist/${ZIP_NAME}"
|
||||
test -f "$zip_path"
|
||||
python3 - <<'PY'
|
||||
import json, os, ssl, urllib.error, urllib.parse, urllib.request
|
||||
|
||||
api = os.environ["FORGEJO_API"].rstrip("/")
|
||||
repo = os.environ["FORGEJO_REPO"]
|
||||
token = os.environ["FORGEJO_TOKEN"]
|
||||
tag = os.environ["VERSION_TAG"]
|
||||
name = f"Windows continuous ({os.environ['ASSET_VER']})"
|
||||
zip_name = os.environ["ZIP_NAME"]
|
||||
zip_path = f"dist/{zip_name}"
|
||||
body = "\n".join([
|
||||
"Continuous Windows build from `main` (built on private GitHub Actions).",
|
||||
"",
|
||||
f"- Version: **{os.environ['VERSION']}**",
|
||||
f"- Commit: `{os.environ['GITHUB_SHA']}`",
|
||||
f"- Asset: `{zip_name}`",
|
||||
"",
|
||||
"Updated on every push to `main`.",
|
||||
])
|
||||
ctx = ssl.create_default_context()
|
||||
if os.environ.get("FORGEJO_CURL_INSECURE", "").lower() in ("1", "true"):
|
||||
ctx = ssl._create_unverified_context()
|
||||
|
||||
def req(method, url, data=None, headers=None, raw=False, allow_404=False):
|
||||
h = {"Authorization": f"token {token}"}
|
||||
if headers:
|
||||
h.update(headers)
|
||||
body_data = data
|
||||
if data is not None and not raw:
|
||||
body_data = json.dumps(data).encode()
|
||||
h.setdefault("Content-Type", "application/json")
|
||||
r = urllib.request.Request(url, data=body_data, headers=h, method=method)
|
||||
try:
|
||||
with urllib.request.urlopen(r, context=ctx) as resp:
|
||||
raw_body = resp.read()
|
||||
return resp.status, (json.loads(raw_body) if raw_body else {})
|
||||
except urllib.error.HTTPError as e:
|
||||
err = e.read().decode(errors="replace")
|
||||
if allow_404 and e.code == 404:
|
||||
return 404, {}
|
||||
raise SystemExit(f"{method} {url} -> {e.code}: {err}") from e
|
||||
|
||||
base = f"{api}/repos/{repo}/releases"
|
||||
status, release = req("GET", f"{base}/tags/{urllib.parse.quote(tag)}", allow_404=True)
|
||||
payload = {
|
||||
"tag_name": tag,
|
||||
"name": name,
|
||||
"body": body,
|
||||
"draft": False,
|
||||
"prerelease": True,
|
||||
}
|
||||
if status == 404:
|
||||
_, release = req("POST", base, payload)
|
||||
else:
|
||||
release_id = release["id"]
|
||||
_, release = req("PATCH", f"{base}/{release_id}", payload)
|
||||
for asset in release.get("assets") or []:
|
||||
if asset.get("name") == zip_name:
|
||||
req("DELETE", f"{base}/{release_id}/assets/{asset['id']}")
|
||||
|
||||
release_id = release["id"]
|
||||
with open(zip_path, "rb") as f:
|
||||
data = f.read()
|
||||
upload_url = f"{base}/{release_id}/assets?name={urllib.parse.quote(zip_name)}"
|
||||
_, asset = req(
|
||||
"POST", upload_url, data=data, raw=True,
|
||||
headers={"Content-Type": "application/octet-stream"},
|
||||
)
|
||||
print(asset.get("browser_download_url") or asset.get("name") or asset)
|
||||
PY
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue