feat(windows-ci): self-provisioning toolchain for the shared unom/infra runner
windows-drivers / driver-build (push) Failing after 14s
windows-host / package (push) Failing after 7s
windows-drivers / probe-and-proto (push) Successful in 39s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Failing after 7s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Failing after 7s
android / android (push) Successful in 4m20s
ci / web (push) Successful in 54s
deb / build-publish (push) Successful in 3m30s
decky / build-publish (push) Successful in 25s
apple / swift (push) Successful in 1m8s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m15s
ci / rust (push) Successful in 4m48s
ci / docs-site (push) Successful in 58s
apple / screenshots (push) Successful in 5m36s
ci / bench (push) Successful in 4m39s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 32s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 2m38s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m54s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 54s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m23s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m18s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 15s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m14s
docker / deploy-docs (push) Successful in 21s
windows-drivers / driver-build (push) Failing after 14s
windows-host / package (push) Failing after 7s
windows-drivers / probe-and-proto (push) Successful in 39s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Failing after 7s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Failing after 7s
android / android (push) Successful in 4m20s
ci / web (push) Successful in 54s
deb / build-publish (push) Successful in 3m30s
decky / build-publish (push) Successful in 25s
apple / swift (push) Successful in 1m8s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m15s
ci / rust (push) Successful in 4m48s
ci / docs-site (push) Successful in 58s
apple / screenshots (push) Successful in 5m36s
ci / bench (push) Successful in 4m39s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 32s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 2m38s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m54s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 54s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m23s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m18s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 15s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m14s
docker / deploy-docs (push) Successful in 21s
The Windows CI runner (home-windows-runner-1, vmid 210) is now provisioned/owned by unom/infra and can be rebuilt or joined by additional windows-amd64-labeled runners at any time - a manually-dispatched provisioning workflow has no way to target a specific runner instance, so it could land on an already-provisioned box instead of the one that needed it. Replace windows-drivers-provision.yml / windows-punktfunk-provision.yml with scripts/ci/ensure-windows-toolchain.ps1, a shared idempotent pre-flight (WDK/cargo-wdk, FFmpeg, Inno Setup, ARM64 rustup target) that every Windows workflow now runs at job start - a fast no-op once already provisioned, so any runner self-heals on first real use. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,27 +0,0 @@
|
|||||||
# One-shot provisioning of the WDK + cargo-wdk onto the persistent self-hosted windows-amd64 runner, so
|
|
||||||
# the all-Rust UMDF drivers can build there (design/windows-host-rewrite.md, M0). The runner has the base
|
|
||||||
# Windows SDK + MSVC + LLVM + Rust but NOT the WDK (no km/wdf/iddcx headers) or cargo-wdk.
|
|
||||||
#
|
|
||||||
# Dispatch manually (workflow_dispatch). Idempotent: re-running is a near no-op once provisioned. The
|
|
||||||
# install persists on the runner (real box, not an ephemeral container), so this runs once, not per build.
|
|
||||||
name: windows-drivers-provision
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
paths:
|
|
||||||
- 'scripts/ci/provision-windows-wdk.ps1'
|
|
||||||
- '.gitea/workflows/windows-drivers-provision.yml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
provision:
|
|
||||||
runs-on: windows-amd64
|
|
||||||
timeout-minutes: 60
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: pwsh
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install WDK + cargo-wdk on the runner
|
|
||||||
run: ./scripts/ci/provision-windows-wdk.ps1
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# Windows driver workspace CI — runs on the self-hosted Windows runner (home-windows-1, host mode;
|
# Windows driver workspace CI — runs on a self-hosted Windows runner (home-windows-runner-1, host
|
||||||
# label windows-amd64). Part of the Windows-host rewrite (design/windows-host-rewrite.md, M0).
|
# mode; label windows-amd64). Part of the Windows-host rewrite (design/windows-host-rewrite.md, M0).
|
||||||
#
|
#
|
||||||
# Stage 1 (this file): PROBE the runner's driver toolchain (WDK / EWDK / cargo-make / LLVM / the
|
# Stage 1 (this file): PROBE the runner's driver toolchain (WDK / EWDK / cargo-make / LLVM / the
|
||||||
# inf2cat/stampinf/devgen/signtool tools) so we know what's provisioned BEFORE writing driver code,
|
# inf2cat/stampinf/devgen/signtool tools) so we know what's provisioned BEFORE writing driver code,
|
||||||
@@ -26,7 +26,8 @@ on:
|
|||||||
- 'crates/pf-driver-proto/**'
|
- 'crates/pf-driver-proto/**'
|
||||||
- 'packaging/windows/drivers/**'
|
- 'packaging/windows/drivers/**'
|
||||||
|
|
||||||
# Driver builds need the WDK on the runner (provision once via windows-drivers-provision.yml).
|
# Driver builds need the WDK on the runner - the driver-build job below self-provisions it via
|
||||||
|
# scripts/ci/ensure-windows-toolchain.ps1, a fast no-op once already present.
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
probe-and-proto:
|
probe-and-proto:
|
||||||
@@ -124,11 +125,12 @@ jobs:
|
|||||||
# retired that — see design/windows-build-and-packaging.md.
|
# retired that — see design/windows-build-and-packaging.md.
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Ensure WDK + cargo-wdk (idempotent self-provision)
|
- name: Ensure Windows toolchain (WDK, FFmpeg, Inno Setup, ARM64 target)
|
||||||
# Run the provisioning script here too so driver-build is self-sufficient and never races a
|
# Shared self-provision step (also used by windows.yml/windows-msix.yml/windows-host.yml) so
|
||||||
# separate provision run on the single runner. Path is relative to the job working-directory
|
# driver-build is self-sufficient on any windows-amd64 runner and never races a manually
|
||||||
# (packaging/windows/drivers). Near-noop once the toolchain is present.
|
# dispatched provisioning workflow landing on a different one. Path is relative to the job
|
||||||
run: ../../../scripts/ci/provision-windows-wdk.ps1
|
# working-directory (packaging/windows/drivers). Near-noop once the toolchain is present.
|
||||||
|
run: ../../../scripts/ci/ensure-windows-toolchain.ps1
|
||||||
- name: cargo build the driver workspace (wdk-probe + wdk-iddcx + pf-vdisplay)
|
- name: cargo build the driver workspace (wdk-probe + wdk-iddcx + pf-vdisplay)
|
||||||
# Whole workspace: wdk-probe (toolchain/surface-assert probe) + wdk-iddcx (DDI wrappers) +
|
# Whole workspace: wdk-probe (toolchain/surface-assert probe) + wdk-iddcx (DDI wrappers) +
|
||||||
# pf-vdisplay (the real IddCx driver). pf-vdisplay linking proves the IddCx call sites resolve
|
# pf-vdisplay (the real IddCx driver). pf-vdisplay linking proves the IddCx call sites resolve
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# Build the punktfunk Windows HOST as a signed Inno Setup installer and publish it to Gitea's generic
|
# Build the punktfunk Windows HOST as a signed Inno Setup installer and publish it to Gitea's generic
|
||||||
# package registry, so a Windows GPU box can install the streaming host (SYSTEM service + bundled
|
# package registry, so a Windows GPU box can install the streaming host (SYSTEM service + bundled
|
||||||
# pf-vdisplay virtual-display driver + the web management console, run by a scheduled task on a bundled
|
# pf-vdisplay virtual-display driver + the web management console, run by a scheduled task on a bundled
|
||||||
# bun) from one signed setup.exe. Runs on the self-hosted Windows runner
|
# bun) from one signed setup.exe. Runs on a self-hosted windows-amd64 runner
|
||||||
# (host mode; scripts/ci/setup-windows-runner.ps1) — same MSVC/Windows-SDK/LLVM env as windows.yml.
|
# (host mode; same MSVC/Windows-SDK/LLVM env as windows.yml — generic from unom/infra's
|
||||||
|
# windows-runner/, FFmpeg/Inno Setup self-provision via the "Ensure Windows toolchain" step below).
|
||||||
#
|
#
|
||||||
# Why an installer and not MSIX (like the client): the host installs a LocalSystem SCM service that
|
# Why an installer and not MSIX (like the client): the host installs a LocalSystem SCM service that
|
||||||
# CreateProcessAsUserW's into the interactive session for secure-desktop capture, and bundles a
|
# CreateProcessAsUserW's into the interactive session for secure-desktop capture, and bundles a
|
||||||
@@ -57,6 +58,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Ensure Windows toolchain (WDK, FFmpeg, Inno Setup, ARM64 target)
|
||||||
|
shell: pwsh
|
||||||
|
run: ./scripts/ci/ensure-windows-toolchain.ps1
|
||||||
|
|
||||||
- name: Locale-safety gate (installer-run scripts must be ASCII)
|
- name: Locale-safety gate (installer-run scripts must be ASCII)
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
# The installer runs these via powershell.exe (Windows PowerShell 5.1) and cmd.exe on the END
|
# The installer runs these via powershell.exe (Windows PowerShell 5.1) and cmd.exe on the END
|
||||||
@@ -82,7 +87,7 @@ jobs:
|
|||||||
"CARGO_TARGET_DIR=C:\t" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
"CARGO_TARGET_DIR=C:\t" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||||
"CARGO_WORKSPACE_DIR=$env:GITHUB_WORKSPACE" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
"CARGO_WORKSPACE_DIR=$env:GITHUB_WORKSPACE" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||||
# FFMPEG_DIR: the same BtbN lgpl-shared x64 tree the Windows CLIENT links against (provisioned
|
# FFMPEG_DIR: the same BtbN lgpl-shared x64 tree the Windows CLIENT links against (provisioned
|
||||||
# by scripts/ci/setup-windows-runner.ps1). The host's AMD/Intel AMF/QSV encode backend
|
# by scripts/ci/provision-windows-punktfunk-extras.ps1). The host's AMD/Intel AMF/QSV encode backend
|
||||||
# (--features amf-qsv) link-imports avcodec/avutil/swscale from it; pack-host-installer.ps1
|
# (--features amf-qsv) link-imports avcodec/avutil/swscale from it; pack-host-installer.ps1
|
||||||
# then bundles its bin\*.dll into the installer. LIBCLANG_PATH is in the runner daemon env.
|
# then bundles its bin\*.dll into the installer. LIBCLANG_PATH is in the runner daemon env.
|
||||||
if (-not $env:FFMPEG_DIR) {
|
if (-not $env:FFMPEG_DIR) {
|
||||||
@@ -125,14 +130,6 @@ jobs:
|
|||||||
cargo clippy --release -- -D warnings; if ($LASTEXITCODE) { throw "pf-vkhdr-layer clippy" }
|
cargo clippy --release -- -D warnings; if ($LASTEXITCODE) { throw "pf-vkhdr-layer clippy" }
|
||||||
Pop-Location
|
Pop-Location
|
||||||
|
|
||||||
- name: Ensure Inno Setup
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
if (-not (Test-Path 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe') -and -not (Get-Command iscc -ErrorAction SilentlyContinue)) {
|
|
||||||
Write-Output "installing Inno Setup via choco"
|
|
||||||
choco install innosetup -y --no-progress
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Fetch portable bun runtime (build tool + bundled to run the console)
|
- name: Fetch portable bun runtime (build tool + bundled to run the console)
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# Build the punktfunk Windows client as signed MSIX packages (x64 + ARM64) and publish them to
|
# Build the punktfunk Windows client as signed MSIX packages (x64 + ARM64) and publish them to
|
||||||
# Gitea's generic package registry, so Windows boxes can download + install a real package (Start
|
# Gitea's generic package registry, so Windows boxes can download + install a real package (Start
|
||||||
# tile, clean install/uninstall) instead of a loose exe. Runs on the self-hosted Windows runner
|
# tile, clean install/uninstall) instead of a loose exe. Runs on a self-hosted windows-amd64
|
||||||
# (host mode; scripts/ci/setup-windows-runner.ps1) — the MSVC/WinUI/FFmpeg toolchain + the Windows
|
# runner (host mode; the MSVC/WinUI toolchain comes from unom/infra's windows-runner/, FFmpeg
|
||||||
# SDK's makeappx/signtool are baked into the runner's daemon env, same as windows.yml.
|
# self-provisions via the "Ensure Windows toolchain" step below, same as windows.yml) — the
|
||||||
|
# Windows SDK's makeappx/signtool are baked into the runner's daemon env.
|
||||||
#
|
#
|
||||||
# Both arches come off the ONE x64 runner: x86_64 natively, aarch64 cross-compiled (the x64 MSVC
|
# Both arches come off the ONE x64 runner: x86_64 natively, aarch64 cross-compiled (the x64 MSVC
|
||||||
# toolset has the ARM64 cross compiler; the matrix points FFMPEG_DIR at the ARM64 FFmpeg tree). See
|
# toolset has the ARM64 cross compiler; the matrix points FFMPEG_DIR at the ARM64 FFmpeg tree). See
|
||||||
@@ -62,6 +63,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Ensure Windows toolchain (WDK, FFmpeg, Inno Setup, ARM64 target)
|
||||||
|
shell: pwsh
|
||||||
|
run: ./scripts/ci/ensure-windows-toolchain.ps1
|
||||||
|
|
||||||
- name: Configure + version
|
- name: Configure + version
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
# Windows client CI — runs on the self-hosted Windows runner (home-windows-1, host mode; see
|
# Windows client CI — runs on a self-hosted windows-amd64 runner (host mode; the generic runner +
|
||||||
# scripts/ci/setup-windows-runner.ps1). Build + clippy + fmt + test the WinUI 3 client
|
# toolchain come from unom/infra's windows-runner/; punktfunk's own extras - FFmpeg, WDK, Inno
|
||||||
|
# Setup, the ARM64 rustup target - self-provision via the "Ensure Windows toolchain" step below, a
|
||||||
|
# fast no-op once already present, so any runner with that label works with no manual dispatch
|
||||||
|
# step first). Build + clippy + fmt + test the WinUI 3 client
|
||||||
# (windows-reactor + D3D11/SwapChainPanel + WASAPI + SDL3).
|
# (windows-reactor + D3D11/SwapChainPanel + WASAPI + SDL3).
|
||||||
#
|
#
|
||||||
# Two architectures from ONE x64 runner: x86_64-pc-windows-msvc natively and
|
# Two architectures from ONE x64 runner: x86_64-pc-windows-msvc natively and
|
||||||
@@ -61,6 +64,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Ensure Windows toolchain (WDK, FFmpeg, Inno Setup, ARM64 target)
|
||||||
|
shell: pwsh
|
||||||
|
run: ./scripts/ci/ensure-windows-toolchain.ps1
|
||||||
|
|
||||||
- name: Configure + toolchain versions
|
- name: Configure + toolchain versions
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
@@ -68,7 +75,7 @@ jobs:
|
|||||||
# Per-arch short target root (dodges MAX_PATH; keeps the two legs from sharing target\).
|
# Per-arch short target root (dodges MAX_PATH; keeps the two legs from sharing target\).
|
||||||
$td = if ('${{ matrix.target }}' -eq 'aarch64-pc-windows-msvc') { 'C:\t-a64' } else { 'C:\t' }
|
$td = if ('${{ matrix.target }}' -eq 'aarch64-pc-windows-msvc') { 'C:\t-a64' } else { 'C:\t' }
|
||||||
"CARGO_TARGET_DIR=$td" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
"CARGO_TARGET_DIR=$td" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||||
# Per-arch FFmpeg import libs (the runner provisions both — setup-windows-runner.ps1).
|
# Per-arch FFmpeg import libs (provision-windows-punktfunk-extras.ps1 fetches both).
|
||||||
$ff = if ('${{ matrix.target }}' -eq 'aarch64-pc-windows-msvc') { 'C:\Users\Public\ffmpeg-arm64' } else { 'C:\Users\Public\ffmpeg' }
|
$ff = if ('${{ matrix.target }}' -eq 'aarch64-pc-windows-msvc') { 'C:\Users\Public\ffmpeg-arm64' } else { 'C:\Users\Public\ffmpeg' }
|
||||||
"FFMPEG_DIR=$ff" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
"FFMPEG_DIR=$ff" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||||
rustup target add ${{ matrix.target }}
|
rustup target add ${{ matrix.target }}
|
||||||
|
|||||||
@@ -285,7 +285,25 @@ clients are deliberately NOT containerized); `apple.yml` builds the xcframework
|
|||||||
provisioned by `scripts/ci/setup-macos-runner.sh`). Per-client/host release workflows:
|
provisioned by `scripts/ci/setup-macos-runner.sh`). Per-client/host release workflows:
|
||||||
`deb.yml`/`rpm.yml`/`flatpak.yml` (Linux client), `android.yml` (Google Play), `windows-msix.yml`
|
`deb.yml`/`rpm.yml`/`flatpak.yml` (Linux client), `android.yml` (Google Play), `windows-msix.yml`
|
||||||
(Windows client), `windows-host.yml` (Windows host installer), `release.yml` (Apple notarized DMG +
|
(Windows client), `windows-host.yml` (Windows host installer), `release.yml` (Apple notarized DMG +
|
||||||
TestFlight), `decky.yml` (Steam Deck plugin); Windows builds run on a self-hosted Windows runner.
|
TestFlight), `decky.yml` (Steam Deck plugin); Windows builds run on a self-hosted Windows runner
|
||||||
|
(`home-windows-runner-1`, vmid 210, `windows-amd64:host` label). The runner is reproducible and
|
||||||
|
**owned by `unom/infra`**, not this repo, since it's shared across unom Windows projects going
|
||||||
|
forward: `unom/infra`'s `windows-runner/` Packer template bakes a generic Windows 11 template (OS
|
||||||
|
install + OpenSSH Server + VS Build Tools/NASM/CMake/LLVM + the act_runner/Node/rustup base, no
|
||||||
|
registration) on Proxmox once; `proxmox/windows-runner/` (Terraform, `bpg/proxmox`) full-clones it
|
||||||
|
(agent-based IP discovery, no pre-provisioned DHCP reservation needed) and registers the instance
|
||||||
|
over SSH remote-exec — the same bake-once/clone-fast split `proxmox/unom-1` uses for the Linux CI
|
||||||
|
host, just without a native Windows cloud-init (registration goes over `remote-exec`/SSH instead of
|
||||||
|
`initialization{}`; WinRM was tried first but is deprecated in OpenTofu, so this moved to SSH via
|
||||||
|
Windows' in-box OpenSSH Server). punktfunk layers its own extras on top of that generic runner:
|
||||||
|
`scripts/ci/provision-windows-wdk.ps1` (WDK + cargo-wdk for the UMDF drivers) and
|
||||||
|
`scripts/ci/provision-windows-punktfunk-extras.ps1` (FFmpeg x64/ARM64 trees, Inno Setup, the
|
||||||
|
`aarch64-pc-windows-msvc` rustup target) — both idempotent, and both run automatically at the start
|
||||||
|
of every Windows CI job via the shared `scripts/ci/ensure-windows-toolchain.ps1` step (a fast no-op
|
||||||
|
once already provisioned), rather than a separate manually-dispatched provisioning workflow — that
|
||||||
|
avoided a real footgun once there could be more than one `windows-amd64` runner: a manually
|
||||||
|
dispatched provisioning workflow has no way to target a *specific* runner instance, so it could
|
||||||
|
land on an already-provisioned box instead of the one that actually needed it.
|
||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
|
|||||||
@@ -178,16 +178,21 @@ forest. (`build-web.ps1` is the dev-box rebuild-and-restart helper.)
|
|||||||
|
|
||||||
## 8. CI workflows (`.gitea/workflows/`)
|
## 8. CI workflows (`.gitea/workflows/`)
|
||||||
|
|
||||||
All run on the single self-hosted `windows-amd64` runner (`home-windows-1`), which **serializes** the
|
All run on a self-hosted `windows-amd64` runner (provisioned by unom/infra's `windows-runner/`
|
||||||
whole Windows fleet - a `Cargo.lock`/`packaging/windows/**` touch queues several builds back-to-back.
|
Packer template + Terraform clone, `home-windows-runner-1`), which **serializes** the whole
|
||||||
|
Windows fleet - a `Cargo.lock`/`packaging/windows/**` touch queues several builds back-to-back.
|
||||||
|
|
||||||
| Workflow | Trigger | Does |
|
| Workflow | Trigger | Does |
|
||||||
|----------|---------|------|
|
|----------|---------|------|
|
||||||
| `windows-host.yml` | `crates/punktfunk-host`, `packaging/windows`, `scripts/windows`, `web`, tags `v*` | build host + clippy + HDR layer + web smoke-boot -> pack + sign installer -> publish (canary/latest) |
|
| `windows-host.yml` | `crates/punktfunk-host`, `packaging/windows`, `scripts/windows`, `web`, tags `v*` | build host + clippy + HDR layer + web smoke-boot -> pack + sign installer -> publish (canary/latest) |
|
||||||
| `windows-drivers.yml` | `packaging/windows/drivers`, `crates/pf-driver-proto` | probe the driver toolchain + build/test/clippy `pf-driver-proto` + `cargo build` the driver workspace + inspect FORCE_INTEGRITY (the fast driver-only gate; coverage the pack lacks) |
|
| `windows-drivers.yml` | `packaging/windows/drivers`, `crates/pf-driver-proto` | probe the driver toolchain + build/test/clippy `pf-driver-proto` + `cargo build` the driver workspace + inspect FORCE_INTEGRITY (the fast driver-only gate; coverage the pack lacks) |
|
||||||
| `windows-drivers-provision.yml` | `provision-windows-wdk.ps1` | one-shot WDK + cargo-wdk provisioning onto the persistent runner |
|
|
||||||
| `windows.yml` / `windows-msix.yml` | client | build the Windows *client* + its signed MSIX (x64 + ARM64) |
|
| `windows.yml` / `windows-msix.yml` | client | build the Windows *client* + its signed MSIX (x64 + ARM64) |
|
||||||
|
|
||||||
|
Every workflow above self-provisions its own toolchain at job start via `scripts/ci/
|
||||||
|
ensure-windows-toolchain.ps1` (WDK/cargo-wdk, FFmpeg, Inno Setup, the ARM64 rustup target) - a
|
||||||
|
fast no-op once already present, so no separate one-shot provisioning workflow/dispatch step is
|
||||||
|
needed, and it works the same on any runner sharing the `windows-amd64` label.
|
||||||
|
|
||||||
`windows-host.yml` also builds the drivers from source (in pack), so it overlaps `windows-drivers.yml` on
|
`windows-host.yml` also builds the drivers from source (in pack), so it overlaps `windows-drivers.yml` on
|
||||||
a `drivers/**` edit (two driver builds on the serialized runner). They're kept separate on purpose -
|
a `drivers/**` edit (two driver builds on the serialized runner). They're kept separate on purpose -
|
||||||
`windows-drivers.yml` is the fast pre-pack gate. **CI builds, never launches the exe** (no GPU on the
|
`windows-drivers.yml` is the fast pre-pack gate. **CI builds, never launches the exe** (no GPU on the
|
||||||
|
|||||||
@@ -250,9 +250,10 @@ then restore + `git worktree remove`. Drive over ssh via `powershell -EncodedCom
|
|||||||
The persistent build validator is the **windows-amd64 CI runner** (no GPU — fine for builds / `iddcx`
|
The persistent build validator is the **windows-amd64 CI runner** (no GPU — fine for builds / `iddcx`
|
||||||
link / `/INTEGRITYCHECK` self-sign / the surface-asserts; live NVENC encode + on-glass defers to the RTX
|
link / `/INTEGRITYCHECK` self-sign / the surface-asserts; live NVENC encode + on-glass defers to the RTX
|
||||||
box). Workflows: `windows-host.yml` (the host installer), `windows-drivers.yml` (the driver workspace
|
box). Workflows: `windows-host.yml` (the host installer), `windows-drivers.yml` (the driver workspace
|
||||||
build + FORCE_INTEGRITY clear), `windows-drivers-provision.yml` (WDK/LLVM toolchain), `windows-msix.yml`
|
build + FORCE_INTEGRITY clear; self-provisions the WDK/LLVM toolchain via `scripts/ci/
|
||||||
(the client). A single Windows runner serializes the whole fleet; a `Cargo.toml` touch costs ~25 min of
|
ensure-windows-toolchain.ps1`), `windows-msix.yml` (the client). A single Windows runner serializes
|
||||||
queue, so driver pushes that avoid `Cargo.toml` skip the fleet serialization.
|
the whole fleet; a `Cargo.toml` touch costs ~25 min of queue, so driver pushes that avoid
|
||||||
|
`Cargo.toml` skip the fleet serialization.
|
||||||
|
|
||||||
Local pre-push checks (this Linux box can't compile the Windows paths):
|
Local pre-push checks (this Linux box can't compile the Windows paths):
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Idempotent pre-flight for punktfunk's Windows CI dependencies: WDK + cargo-wdk (driver builds),
|
||||||
|
# FFmpeg x64/ARM64 trees, Inno Setup, and the aarch64-pc-windows-msvc rustup target. Run at the
|
||||||
|
# start of every Windows CI job so ANY runner - freshly built from unom/infra's windows-runner/
|
||||||
|
# template, rebuilt, or a new one added later - self-provisions on first real use, instead of
|
||||||
|
# needing a human to remember to dispatch a separate provisioning workflow first (and instead of
|
||||||
|
# racing which runner a manually-dispatched provisioning workflow happens to land on, when more
|
||||||
|
# than one Windows runner shares the windows-amd64 label).
|
||||||
|
#
|
||||||
|
# Each underlying script already does its own existence checks (Test-Path/Get-Command) before
|
||||||
|
# installing anything, so this is a fast no-op on a runner that's already fully provisioned - the
|
||||||
|
# only cost is on a genuinely fresh box, where it's the first job's problem to pay once.
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
trap {
|
||||||
|
Write-Host "FATAL: $_"
|
||||||
|
Write-Host $_.ScriptStackTrace
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$ciDir = $PSScriptRoot
|
||||||
|
& "$ciDir\provision-windows-wdk.ps1"
|
||||||
|
& "$ciDir\provision-windows-punktfunk-extras.ps1"
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# Layers punktfunk-specific tooling onto the shared unom Windows CI runner: per-arch FFmpeg
|
||||||
|
# (host + client native builds), Inno Setup (the host installer), and the aarch64-pc-windows-msvc
|
||||||
|
# rustup target (windows-msix.yml's ARM64 leg). The runner itself - act_runner, Node, rustup,
|
||||||
|
# VS Build Tools/NASM/CMake/LLVM - is provisioned generically by unom/infra
|
||||||
|
# (windows-runner/windows-runner.pkr.hcl + proxmox/windows-runner's Terraform clone); this script
|
||||||
|
# is what punktfunk adds on top, since FFmpeg/Inno Setup/the ARM64 target aren't every project's
|
||||||
|
# concern. See also provision-windows-wdk.ps1 for the driver-build toolchain (also punktfunk-only).
|
||||||
|
#
|
||||||
|
# Idempotent - safe to re-run. Run ELEVATED (admin) on the runner.
|
||||||
|
[CmdletBinding()]
|
||||||
|
param()
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
function info($m) { Write-Host "[provision-punktfunk-extras] $m" }
|
||||||
|
|
||||||
|
$env:RUSTUP_HOME = "C:\Users\Public\.rustup"
|
||||||
|
$env:CARGO_HOME = "C:\Users\Public\.cargo"
|
||||||
|
|
||||||
|
# --- ARM64 cross-compile target (windows.yml / windows-msix.yml build aarch64-pc-windows-msvc off
|
||||||
|
# this x64 box; the ARM64 MSVC cross compiler itself comes from unom/infra's generic VS Build
|
||||||
|
# Tools provisioning, which already includes the ARM64 component). ---
|
||||||
|
$rustup = "C:\Users\Public\.cargo\bin\rustup.exe"
|
||||||
|
if (Test-Path $rustup) {
|
||||||
|
info "rustup target add aarch64-pc-windows-msvc"
|
||||||
|
& $rustup target add aarch64-pc-windows-msvc
|
||||||
|
} else {
|
||||||
|
Write-Warning "rustup not found at $rustup - has unom/infra's setup-gitea-runner-base.ps1 run on this box yet?"
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- FFmpeg shared trees for the host (amf-qsv encode) + clients (decode). BtbN **lgpl-shared**
|
||||||
|
# builds: the AMD/Intel AMF + Intel QSV encoders, swscale, and the HEVC decoder are all present in
|
||||||
|
# the LGPL build, and punktfunk never calls the GPL-only encoders (x264/x265 - software encode is
|
||||||
|
# the separate BSD-2 openh264 crate; NVENC is the direct NVIDIA SDK). lgpl-shared keeps the
|
||||||
|
# bundled DLLs LGPL-2.1+ (dynamic linking satisfies the relink duty) rather than GPL, so the
|
||||||
|
# shipped installer/MSIX stay consistent with punktfunk's MIT OR Apache-2.0 posture.
|
||||||
|
# MIGRATION: a runner previously provisioned with the old *gpl-shared* trees must be
|
||||||
|
# re-provisioned - delete C:\Users\Public\ffmpeg and C:\Users\Public\ffmpeg-arm64, then re-run.
|
||||||
|
function Get-BtbnFfmpeg {
|
||||||
|
param([string]$Dir, [string]$ZipTag) # ZipTag: 'win64' (x64) or 'winarm64' (ARM64 cross tree)
|
||||||
|
if (Test-Path (Join-Path $Dir 'lib\avcodec.lib')) { info "FFmpeg ($ZipTag) already present at $Dir"; return }
|
||||||
|
info "fetching FFmpeg ($ZipTag, BtbN lgpl-shared)"
|
||||||
|
$url = "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n7.1-latest-$ZipTag-lgpl-shared-7.1.zip"
|
||||||
|
$zip = "$Dir.zip"; $tmp = "$Dir-extract"
|
||||||
|
Invoke-WebRequest -Uri $url -OutFile $zip -UseBasicParsing
|
||||||
|
if (Test-Path $tmp) { Remove-Item -Recurse -Force $tmp }
|
||||||
|
Expand-Archive -Path $zip -DestinationPath $tmp -Force # BtbN zips have one top-level folder
|
||||||
|
$inner = Get-ChildItem $tmp -Directory | Select-Object -First 1
|
||||||
|
if (Test-Path $Dir) { Remove-Item -Recurse -Force $Dir }
|
||||||
|
Move-Item -Path $inner.FullName -Destination $Dir
|
||||||
|
Remove-Item -Force $zip; Remove-Item -Recurse -Force $tmp -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
Get-BtbnFfmpeg -Dir "C:\Users\Public\ffmpeg" -ZipTag 'win64'
|
||||||
|
Get-BtbnFfmpeg -Dir "C:\Users\Public\ffmpeg-arm64" -ZipTag 'winarm64'
|
||||||
|
|
||||||
|
# --- Inno Setup (ISCC.exe) for the host installer build (windows-host.yml). pack-host-installer.ps1
|
||||||
|
# locates it at its fixed Program Files path, so it need not be on PATH - just present. ---
|
||||||
|
if (-not (Test-Path "C:\Program Files (x86)\Inno Setup 6\ISCC.exe")) {
|
||||||
|
if (Get-Command choco -ErrorAction SilentlyContinue) {
|
||||||
|
info "installing Inno Setup (ISCC)"
|
||||||
|
choco install innosetup -y --no-progress
|
||||||
|
} else { Write-Warning "Inno Setup not found and choco unavailable - install it for windows-host.yml." }
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Drop punktfunk's env vars into the generic runner's daemon wrapper extension point (see
|
||||||
|
# unom/infra's scripts/setup-gitea-runner-base.ps1) so the act_runner daemon - and therefore every
|
||||||
|
# job it runs - sees FFMPEG_DIR without unom/infra needing to know punktfunk exists. ---
|
||||||
|
$projectEnv = "C:\Users\Public\act-runner\project-env.ps1"
|
||||||
|
@'
|
||||||
|
$env:FFMPEG_DIR = "C:\Users\Public\ffmpeg"
|
||||||
|
$env:PATH = "C:\Users\Public\ffmpeg\bin;" + $env:PATH
|
||||||
|
'@ | Set-Content -Encoding UTF8 $projectEnv
|
||||||
|
info "wrote $projectEnv (FFMPEG_DIR) - restart the gitea-act-runner scheduled task to pick it up"
|
||||||
|
|
||||||
|
info "punktfunk extras provisioned OK."
|
||||||
@@ -7,8 +7,11 @@
|
|||||||
# Idempotent: skips the WDK install if the km/wdf headers are already present, and cargo-wdk if already
|
# Idempotent: skips the WDK install if the km/wdf headers are already present, and cargo-wdk if already
|
||||||
# installed. Safe to run repeatedly. Runs non-interactively (/q /norestart) — never auto-reboots.
|
# installed. Safe to run repeatedly. Runs non-interactively (/q /norestart) — never auto-reboots.
|
||||||
#
|
#
|
||||||
# Invoked by .gitea/workflows/windows-drivers-provision.yml (workflow_dispatch) and referenced by
|
# Invoked by scripts/ci/ensure-windows-toolchain.ps1, the shared self-provision step every Windows
|
||||||
# scripts/ci/setup-windows-runner.ps1. Run as the runner's account (SYSTEM) with admin rights.
|
# CI workflow runs at job start (windows-drivers.yml, windows.yml, windows-msix.yml,
|
||||||
|
# windows-host.yml), on top of the generic runner unom/infra provisions (windows-runner/) and
|
||||||
|
# provision-windows-punktfunk-extras.ps1's FFmpeg/Inno Setup/ARM64-target layer. Run as the
|
||||||
|
# runner's account (SYSTEM) with admin rights.
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
# WDK 26100 standalone bootstrapper. Source: https://learn.microsoft.com/windows-hardware/drivers/download-the-wdk
|
# WDK 26100 standalone bootstrapper. Source: https://learn.microsoft.com/windows-hardware/drivers/download-the-wdk
|
||||||
|
|||||||
@@ -1,180 +0,0 @@
|
|||||||
# Provision this Windows box as the Gitea Actions runner for the Windows client + host CI/packaging.
|
|
||||||
# The Windows analogue of scripts/ci/setup-macos-runner.sh. Idempotent — safe to re-run. Run
|
|
||||||
# ELEVATED (admin) on the box, e.g. over SSH:
|
|
||||||
#
|
|
||||||
# ssh "<box>" 'powershell -NoProfile -ExecutionPolicy Bypass -File C:\path\setup-windows-runner.ps1 -Token <registration token>'
|
|
||||||
#
|
|
||||||
# Installs: the act_runner (gitea-runner) binary in **host mode** (jobs run directly on Windows,
|
|
||||||
# no containers — MSVC/WinUI builds need the host toolchain), Node 20 via the box's nvm4w (JS
|
|
||||||
# actions like actions/checkout run via node on PATH), and a SYSTEM scheduled task that keeps the
|
|
||||||
# daemon alive across reboots with nobody logged in. Registration happens once (.runner file); the
|
|
||||||
# token is NOT persisted.
|
|
||||||
#
|
|
||||||
# Get a **GLOBAL** registration token: Gitea **Site Administration -> Actions -> Runners** (the
|
|
||||||
# registration token shown there). The runner MUST be global/instance-scoped to pick up org-repo
|
|
||||||
# jobs like unom/punktfunk — an org- or repo-scoped token leaves it registered but unmatchable
|
|
||||||
# ("no fitting runner for windows-amd64", even though the runner shows idle). Mirrors the Linux
|
|
||||||
# runner's scope.
|
|
||||||
#
|
|
||||||
# Env/param knobs: -Instance (default https://git.unom.io), -Token (GITEA_RUNNER_TOKEN; required
|
|
||||||
# for first registration), -RunnerName (default COMPUTERNAME), -Labels (default windows-amd64:host
|
|
||||||
# — match the Windows job's runs-on), -Version (act_runner, default 1.0.8).
|
|
||||||
#
|
|
||||||
# The daemon's env wrapper hard-codes this box's MSVC build paths (cargo/rustup, NASM, CMake, LLVM,
|
|
||||||
# FFmpeg, the ASCII CARGO_HOME that SDL3's PCH needs) so the Windows workflow inherits a working
|
|
||||||
# toolchain without re-deriving dev-box specifics. Per-checkout vars (CARGO_WORKSPACE_DIR for the
|
|
||||||
# windows-reactor build.rs) are set by the workflow, not here.
|
|
||||||
param(
|
|
||||||
[string]$Instance = $(if ($env:GITEA_INSTANCE) { $env:GITEA_INSTANCE } else { "https://git.unom.io" }),
|
|
||||||
[string]$Version = $(if ($env:ACT_RUNNER_VERSION) { $env:ACT_RUNNER_VERSION } else { "1.0.8" }),
|
|
||||||
[string]$RunnerName = $(if ($env:RUNNER_NAME) { $env:RUNNER_NAME } else { $env:COMPUTERNAME }),
|
|
||||||
[string]$Labels = $(if ($env:RUNNER_LABELS) { $env:RUNNER_LABELS } else { "windows-amd64:host" }),
|
|
||||||
[string]$Token = $env:GITEA_RUNNER_TOKEN
|
|
||||||
)
|
|
||||||
$ErrorActionPreference = "Stop"
|
|
||||||
$RunnerHome = "C:\Users\Public\act-runner"
|
|
||||||
$Exe = "$RunnerHome\act_runner.exe"
|
|
||||||
New-Item -ItemType Directory -Force -Path $RunnerHome | Out-Null
|
|
||||||
|
|
||||||
# --- act_runner binary (gitea-runner; CLI surface unchanged from act_runner) ---
|
|
||||||
$need = $true
|
|
||||||
if (Test-Path $Exe) { try { $need = -not ((& $Exe --version 2>$null) -match [regex]::Escape($Version)) } catch { } }
|
|
||||||
if ($need) {
|
|
||||||
$url = "https://dl.gitea.com/gitea-runner/$Version/gitea-runner-$Version-windows-amd64.exe"
|
|
||||||
Write-Host "==> downloading act_runner $Version"
|
|
||||||
Invoke-WebRequest -Uri $url -OutFile "$Exe.tmp" -UseBasicParsing
|
|
||||||
Move-Item -Force "$Exe.tmp" $Exe
|
|
||||||
}
|
|
||||||
& $Exe --version
|
|
||||||
|
|
||||||
# --- Node 20 (actions/checkout@v4 demands node20) via the box's nvm4w ---
|
|
||||||
if (Get-Command nvm -ErrorAction SilentlyContinue) {
|
|
||||||
if (-not ((node --version 2>$null) -match "^v20")) {
|
|
||||||
nvm install 20.18.0 | Out-Null
|
|
||||||
nvm use 20.18.0 | Out-Null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Write-Host "node $(node --version)"
|
|
||||||
|
|
||||||
# --- config + host-mode labels (empty the docker defaults so .runner's labels rule) ---
|
|
||||||
Push-Location $RunnerHome
|
|
||||||
if (-not (Test-Path config.yaml)) { & $Exe generate-config | Set-Content -Encoding ASCII config.yaml }
|
|
||||||
(Get-Content config.yaml) |
|
|
||||||
Where-Object { $_ -notmatch "docker.gitea.com/runner-images" } |
|
|
||||||
ForEach-Object { $_ -replace '^(\s*)labels:\s*$', '${1}labels: []' } |
|
|
||||||
Set-Content -Encoding ASCII config.yaml
|
|
||||||
Pop-Location
|
|
||||||
|
|
||||||
# --- one-time registration (from $RunnerHome: register writes .runner to the CWD) ---
|
|
||||||
if (-not (Test-Path "$RunnerHome\.runner")) {
|
|
||||||
if (-not $Token) {
|
|
||||||
Write-Warning "Not registered yet. Re-run with -Token <GLOBAL registration token>."
|
|
||||||
Write-Host " (Gitea: Site Administration -> Actions -> Runners -> registration token; must be GLOBAL scope)"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
Push-Location $RunnerHome
|
|
||||||
& $Exe register --no-interactive --instance $Instance --token $Token --name $RunnerName --labels $Labels
|
|
||||||
Pop-Location
|
|
||||||
}
|
|
||||||
|
|
||||||
# rustup toolchains under an ASCII path so nothing in the daemon env carries the non-ASCII
|
|
||||||
# username (the same hazard that breaks SDL3's PCH; here it also keeps this script ASCII-clean).
|
|
||||||
if (-not (Test-Path "C:\Users\Public\.rustup\settings.toml")) {
|
|
||||||
Write-Host "==> copying rustup toolchains to an ASCII path"
|
|
||||||
robocopy "$env:USERPROFILE\.rustup" "C:\Users\Public\.rustup" /E /NFL /NDL /NJH /NJS /MT:16 | Out-Null
|
|
||||||
}
|
|
||||||
|
|
||||||
# --- ARM64 cross-compile support (windows.yml / windows-msix.yml build aarch64-pc-windows-msvc off
|
|
||||||
# this x64 box; no ARM64 runner needed). Two pieces beyond the x64 toolchain:
|
|
||||||
# 1. the rustup std for the target;
|
|
||||||
# 2. an ARM64 FFmpeg import-lib/DLL tree at C:\Users\Public\ffmpeg-arm64 (the workflow matrix
|
|
||||||
# points FFMPEG_DIR here for the aarch64 leg; the x64 tree stays at C:\Users\Public\ffmpeg).
|
|
||||||
# The x64 MSVC toolset already ships the ARM64 cross compiler — if
|
|
||||||
# VC\Tools\MSVC\<ver>\bin\Hostx64\arm64\cl.exe is missing, add the VS "MSVC v143+ ARM64/ARM64EC
|
|
||||||
# build tools" + "C++ ARM64 build tools" workload components (the cc/cmake crates need it to
|
|
||||||
# cross-build SDL3 + libopus).
|
|
||||||
$env:RUSTUP_HOME = "C:\Users\Public\.rustup"
|
|
||||||
$env:CARGO_HOME = "C:\Users\Public\.cargo"
|
|
||||||
$rustup = (Get-Command rustup -ErrorAction SilentlyContinue).Source
|
|
||||||
if (-not $rustup) { $rustup = "C:\Users\Public\.cargo\bin\rustup.exe" }
|
|
||||||
if (Test-Path $rustup) {
|
|
||||||
Write-Host "==> rustup target add aarch64-pc-windows-msvc"
|
|
||||||
& $rustup target add aarch64-pc-windows-msvc
|
|
||||||
} else { Write-Warning "rustup not found - install rustup then re-run (needed for the aarch64 target)." }
|
|
||||||
|
|
||||||
# FFmpeg shared trees for the host (amf-qsv encode) + clients (decode). We use BtbN **lgpl-shared**
|
|
||||||
# builds: the AMD/Intel AMF + Intel QSV encoders, swscale, and the HEVC decoder are all present in the
|
|
||||||
# LGPL build, and punktfunk never calls the GPL-only encoders (x264/x265 — software encode is the
|
|
||||||
# separate BSD-2 openh264 crate; NVENC is the direct NVIDIA SDK). lgpl-shared keeps the bundled DLLs
|
|
||||||
# LGPL-2.1+ (dynamic linking satisfies the relink duty) rather than GPL, so the shipped installer/MSIX
|
|
||||||
# stay consistent with punktfunk's MIT OR Apache-2.0 posture.
|
|
||||||
# MIGRATION: a runner previously provisioned with the old *gpl-shared* trees must be re-provisioned —
|
|
||||||
# delete C:\Users\Public\ffmpeg and C:\Users\Public\ffmpeg-arm64, then re-run this script.
|
|
||||||
function Get-BtbnFfmpeg {
|
|
||||||
param([string]$Dir, [string]$ZipTag) # ZipTag: 'win64' (x64) or 'winarm64' (ARM64 cross tree)
|
|
||||||
if (Test-Path (Join-Path $Dir 'lib\avcodec.lib')) { return }
|
|
||||||
# FFmpeg 7.x (avcodec-61); MSVC-linkable .lib import libs + headers + bin\*.dll — exactly what
|
|
||||||
# ffmpeg-sys-next + pack-host-installer.ps1 + pack-msix.ps1 consume. The extracted top-level folder
|
|
||||||
# also carries FFmpeg's own LICENSE/COPYING text, preserved in $Dir for the packagers to bundle.
|
|
||||||
Write-Host "==> fetching FFmpeg ($ZipTag, BtbN lgpl-shared)"
|
|
||||||
$url = "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n7.1-latest-$ZipTag-lgpl-shared-7.1.zip"
|
|
||||||
$zip = "$Dir.zip"; $tmp = "$Dir-extract"
|
|
||||||
Invoke-WebRequest -Uri $url -OutFile $zip -UseBasicParsing
|
|
||||||
if (Test-Path $tmp) { Remove-Item -Recurse -Force $tmp }
|
|
||||||
Expand-Archive -Path $zip -DestinationPath $tmp -Force # BtbN zips have one top-level folder
|
|
||||||
$inner = Get-ChildItem $tmp -Directory | Select-Object -First 1
|
|
||||||
if (Test-Path $Dir) { Remove-Item -Recurse -Force $Dir }
|
|
||||||
Move-Item -Path $inner.FullName -Destination $Dir
|
|
||||||
Remove-Item -Force $zip; Remove-Item -Recurse -Force $tmp -ErrorAction SilentlyContinue
|
|
||||||
}
|
|
||||||
# x64 host+client tree (the workflow's default FFMPEG_DIR = C:\Users\Public\ffmpeg) and the ARM64 cross
|
|
||||||
# tree (the aarch64 leg points FFMPEG_DIR at C:\Users\Public\ffmpeg-arm64).
|
|
||||||
Get-BtbnFfmpeg -Dir "C:\Users\Public\ffmpeg" -ZipTag 'win64'
|
|
||||||
Get-BtbnFfmpeg -Dir "C:\Users\Public\ffmpeg-arm64" -ZipTag 'winarm64'
|
|
||||||
|
|
||||||
# Inno Setup (ISCC.exe) for the host installer build (windows-host.yml). pack-host-installer.ps1
|
|
||||||
# locates it at its fixed Program Files path, so it need not be on PATH — just present.
|
|
||||||
if (-not (Test-Path "C:\Program Files (x86)\Inno Setup 6\ISCC.exe")) {
|
|
||||||
if (Get-Command choco -ErrorAction SilentlyContinue) {
|
|
||||||
Write-Host "==> installing Inno Setup (ISCC)"
|
|
||||||
choco install innosetup -y --no-progress
|
|
||||||
}
|
|
||||||
else { Write-Warning "Inno Setup not found and choco unavailable - install it for windows-host.yml." }
|
|
||||||
}
|
|
||||||
|
|
||||||
# --- daemon env wrapper (the box's MSVC/WinUI/FFmpeg toolchain) ---
|
|
||||||
$wrapper = "$RunnerHome\run-runner.ps1"
|
|
||||||
@'
|
|
||||||
$env:NO_COLOR = "1"
|
|
||||||
$env:CARGO_HOME = "C:\Users\Public\.cargo"
|
|
||||||
$env:RUSTUP_HOME = "C:\Users\Public\.rustup"
|
|
||||||
$env:CMAKE_POLICY_VERSION_MINIMUM = "3.5"
|
|
||||||
$env:LIBCLANG_PATH = "C:\Program Files\LLVM\bin"
|
|
||||||
$env:FFMPEG_DIR = "C:\Users\Public\ffmpeg"
|
|
||||||
$env:PATH = "C:\Program Files\PowerShell\7;C:\Users\Public\.cargo\bin;C:\nvm4w\nodejs;C:\Program Files\NASM;C:\Program Files\CMake\bin;C:\Program Files\LLVM\bin;C:\Users\Public\ffmpeg\bin;" + $env:PATH
|
|
||||||
Set-Location "C:\Users\Public\act-runner"
|
|
||||||
# cmd-level redirect (>>, 2>&1) keeps the daemon's native stderr out of PowerShell's error stream.
|
|
||||||
& cmd /c "act_runner.exe daemon --config config.yaml >> runner.log 2>&1"
|
|
||||||
'@ | Set-Content -Encoding UTF8 $wrapper
|
|
||||||
|
|
||||||
# --- SYSTEM scheduled task: keep the daemon alive across reboots, no login needed ---
|
|
||||||
$taskName = "gitea-act-runner"
|
|
||||||
if (schtasks /Query /TN $taskName 2>$null) {
|
|
||||||
schtasks /End /TN $taskName 2>$null | Out-Null
|
|
||||||
schtasks /Delete /TN $taskName /F | Out-Null
|
|
||||||
}
|
|
||||||
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
|
|
||||||
-Argument "-NoProfile -ExecutionPolicy Bypass -File `"$wrapper`""
|
|
||||||
$trigger = New-ScheduledTaskTrigger -AtStartup
|
|
||||||
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
|
|
||||||
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries `
|
|
||||||
-RestartCount 999 -RestartInterval (New-TimeSpan -Minutes 1) -ExecutionTimeLimit ([TimeSpan]::Zero)
|
|
||||||
Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger `
|
|
||||||
-Principal $principal -Settings $settings -Force | Out-Null
|
|
||||||
Start-ScheduledTask -TaskName $taskName
|
|
||||||
Start-Sleep -Seconds 4
|
|
||||||
|
|
||||||
Write-Host "==> runner '$RunnerName' labels=$Labels instance=$Instance"
|
|
||||||
$p = Get-Process act_runner -ErrorAction SilentlyContinue
|
|
||||||
if ($p) { Write-Host "daemon running (pid $($p.Id), session $($p.SessionId))" }
|
|
||||||
else { Write-Warning "daemon not running yet - check the gitea-act-runner task" }
|
|
||||||
Reference in New Issue
Block a user