CI: working Windows build workflow for self-hosted runner #7

Merged
jknapp merged 6 commits from ci/windows-build into main 2026-07-18 04:08:27 +00:00
Owner

Summary

Adds a working Windows-only build pipeline for the self-hosted org runner (windows-latest), and fixes the PyInstaller spec so the relay feature is bundled. Verified green end-to-end on the runner (macropad.exe, ~8.5 MB, uploaded as an artifact).

The previous .gitea/workflows/release.yml is left as-is (fully commented/disabled); it targeted GitHub-hosted ubuntu-latest/windows-latest and could not complete with only a self-hosted Windows runner.

What's here

  • .gitea/workflows/build-windows.yml — runs entirely on windows-latest:
    • preflight job: fast runner smoke-test (OS/PowerShell/Python) so a broken runner fails in seconds.
    • build-windows job: provisions Python 3.11, pip install -e . + PyInstaller, builds dist/macropad.exe, uploads it as an artifact, and on a v* tag creates/updates a Gitea release and attaches the exe via the Gitea API.
  • macropad.spec — declare relay_client + aiohttp as hidden imports (the relay client is imported lazily and was at risk of being dropped from the build); switch the EXE icon to a real .ico.
  • Macro Pad.ico — multi-size (16–256px) icon generated from Macro Pad.png.

Runner-specific hardening (each fixed after observing a real run)

  • actions/setup-python hangs inside its Windows tool-cache install on self-hosted runners → replaced with a standalone CPython from nuget (no registry/PATH side effects, idempotent, cached in LOCALAPPDATA; honours a pre-installed 3.11 if present).
  • Runner has Windows PowerShell 5.1, not pwsh → all steps use shell: powershell, with TLS 1.2 forced for HTTPS and BOM-free GITHUB_ENV writes.
  • PyInstaller needs an .ico on Windows → ship one.
  • upload-artifact@v4 needs a backend Gitea doesn't provide → pinned to @v3.
  • 30-minute job timeout so a hang can never run indefinitely.

How to release

Push a tag vX.Y.Z → the workflow builds and attaches macropad.exe to a Gitea release for that tag. Manual builds: run the workflow via Actions → Build Windows → Run workflow (or the API dispatch).

🤖 Generated with Claude Code

## Summary Adds a working **Windows-only** build pipeline for the self-hosted org runner (`windows-latest`), and fixes the PyInstaller spec so the relay feature is bundled. Verified green end-to-end on the runner (`macropad.exe`, ~8.5 MB, uploaded as an artifact). The previous `.gitea/workflows/release.yml` is left as-is (fully commented/disabled); it targeted GitHub-hosted `ubuntu-latest`/`windows-latest` and could not complete with only a self-hosted Windows runner. ## What's here - **`.gitea/workflows/build-windows.yml`** — runs entirely on `windows-latest`: - `preflight` job: fast runner smoke-test (OS/PowerShell/Python) so a broken runner fails in seconds. - `build-windows` job: provisions Python 3.11, `pip install -e .` + PyInstaller, builds `dist/macropad.exe`, uploads it as an artifact, and on a `v*` tag creates/updates a Gitea release and attaches the exe via the Gitea API. - **`macropad.spec`** — declare `relay_client` + `aiohttp` as hidden imports (the relay client is imported lazily and was at risk of being dropped from the build); switch the EXE icon to a real `.ico`. - **`Macro Pad.ico`** — multi-size (16–256px) icon generated from `Macro Pad.png`. ## Runner-specific hardening (each fixed after observing a real run) - `actions/setup-python` hangs inside its Windows tool-cache install on self-hosted runners → replaced with a standalone CPython from **nuget** (no registry/PATH side effects, idempotent, cached in `LOCALAPPDATA`; honours a pre-installed 3.11 if present). - Runner has Windows PowerShell 5.1, not `pwsh` → all steps use `shell: powershell`, with TLS 1.2 forced for HTTPS and BOM-free `GITHUB_ENV` writes. - PyInstaller needs an `.ico` on Windows → ship one. - `upload-artifact@v4` needs a backend Gitea doesn't provide → pinned to `@v3`. - 30-minute job timeout so a hang can never run indefinitely. ## How to release Push a tag `vX.Y.Z` → the workflow builds and attaches `macropad.exe` to a Gitea release for that tag. Manual builds: run the workflow via **Actions → Build Windows → Run workflow** (or the API dispatch). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jknapp added 6 commits 2026-07-18 03:49:29 +00:00
Adds .gitea/workflows/build-windows.yml targeting the org's self-hosted
`windows-latest` runner: sets up Python 3.11, installs the project +
PyInstaller, builds dist/macropad.exe, uploads it as an artifact, and on a
v* tag creates/updates a Gitea release and attaches the exe via the Gitea
API. Runs entirely on Windows (no Linux runner required).

Also declare relay_client + aiohttp as PyInstaller hidden imports so the
relay feature (lazily imported in the GUI) is bundled into the exe.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
actions/setup-python@v5 hangs inside its Windows tool-cache install script on
the self-hosted runner. Replace it with an "Ensure Python 3.11" step that uses
an existing py -3.11 / PATH python if present, otherwise silently installs
Python per-user (no elevation, cannot prompt). Invoke pip/PyInstaller via the
resolved interpreter path, and add a 30-minute job timeout so a hang can no
longer run indefinitely.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- The runner has Windows PowerShell 5.1, not pwsh/PowerShell 7 — switch all
  steps from `shell: pwsh` to `shell: powershell`.
- Make the scripts 5.1-safe: force TLS 1.2 for HTTPS, -UseBasicParsing on
  Invoke-WebRequest, and write GITHUB_ENV as ascii (no BOM).
- Add a fast `preflight` job that validates the runner (OS, PowerShell, Python
  availability) in seconds; build-windows now `needs: [preflight]`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PyInstaller on Windows requires an .ico (or .exe) for the executable icon and
its PNG->ICO auto-conversion did not engage on the runner. Add a multi-size
Macro Pad.ico (16-256px) generated from Macro Pad.png and point macropad.spec
at it. The PNG stays bundled for the runtime window/tray icon.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The per-user MSI installer is stateful across runs on a persistent VM: once a
version is registered, a later /quiet install no-ops and never lands at the new
TargetDir, so python.exe went missing. Switch to a standalone CPython from
nuget cached under LOCALAPPDATA — no registry/PATH changes, idempotent, reused
across runs. A pre-existing Python 3.11 on PATH is still honoured.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
upload-artifact@v4 uses the @actions/artifact v2 backend, which Gitea (reported
to the action as GHES) does not support. Pin to @v3, which uses the artifact
protocol Gitea implements. The exe itself now builds successfully; this was the
only remaining failure.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jknapp merged commit 8c3e5106d5 into main 2026-07-18 04:08:27 +00:00
jknapp deleted branch ci/windows-build 2026-07-18 04:08:27 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: MacroPad/MP-Server#7