Files
nucleic/windows-gha.yml
T

225 lines
11 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Windows
# The Windows-port CI (docs/WINDOWS_PORT.md §13 M0, §14). Three legs:
#
# protocol (REQUIRED) — Swift toolchain pinned by windows/props/swift-version.txt on
# hosted x64 (windows-2025) + ARM64 (windows-11-arm): build NucleicProtocol and run
# NucleicProtocolTests. Runs with NUCLEIC_WINDOWS_PROTOCOL_ONLY=1 so `swift test`
# builds only the wire layer — NucleicCore's Windows shims land with §12 items 79.
#
# core — the same toolchain WITHOUT the flag, driving the full Windows manifest
# (NucleicCore + NucleicCarbonTests + nucleic-hostd + NucleicProtocolC). Two tiers,
# because the legs are proven to different depths (docs/WINDOWS_PORT.md §12 item 9):
# * the x64 `swift build --target NucleicCore` step is REQUIRED — it builds green on
# Windows 11 amd64 as of the item-9 shims, so a regression must turn CI red;
# * ARM64 is still `continue-on-error` (no ARM64 hardware has run it), and
# NucleicCarbonTests is a per-step probe on both arches, because `swift test`
# builds EVERY declared target — nucleic-hostd, NucleicProtocolC, nucleic-smoke —
# and those are still §12 items 10+ work. That step's log is what remains of the
# M0 "corelibs/toolchain gap list". Both tiers flip to required at M2.
#
# broker (REQUIRED) — the C# nucleic-brokerd contract tests against FakeWslc
# (windows/Nucleic.sln, no wslc NuGet — that path needs -p:UseWslc=true and the M1
# spike hardware).
#
# The container e2e suite (M2) needs nested virtualization → the self-hosted runner (D11),
# added later behind a runs-on label; hosted runners cover everything above.
#
# WHERE THESE RUN (D11). Every `runs-on` below reads a repository variable with the hosted
# runner as its fallback, so moving a leg on-prem is a settings change, not a PR:
#
# WINDOWS_X64_RUNNER → label of the on-prem x64 box (unset ⇒ windows-2025)
# WINDOWS_ARM64_RUNNER → label of an on-prem ARM64 box (unset ⇒ windows-11-arm)
#
# Set them to a UNIQUE label you assigned that runner (e.g. nucleic-win-x64), not to the
# generic `self-hosted`. Clearing a variable fails the leg straight back to GitHub-hosted,
# which is the escape hatch when the box is down. Self-hosted minutes are never billed —
# hosted Windows minutes bill at 2x, which is what makes this leg the expensive one.
# On-prem machine setup: docs/WINDOWS_PORT.md §14.1.
on:
push:
branches: [main, dev]
paths:
- Package.swift
- Package.resolved
- Sources/**
- Tests/**
- windows/**
- ios/NucleicRemote/NucleicRemote/Views/Transcript/**
- .github/workflows/windows.yml
pull_request:
paths:
- Package.swift
- Package.resolved
- Sources/**
- Tests/**
- windows/**
- ios/NucleicRemote/NucleicRemote/Views/Transcript/**
- .github/workflows/windows.yml
workflow_dispatch:
concurrency:
group: windows-${{ github.ref }}
cancel-in-progress: true
jobs:
swift-version:
name: Resolve pinned Swift
runs-on: ubuntu-latest
outputs:
swift-version: ${{ steps.pin.outputs.swift-version }}
swift-build: ${{ steps.pin.outputs.swift-build }}
steps:
- uses: actions/checkout@v4
with:
sparse-checkout: windows/props/swift-version.txt
sparse-checkout-cone-mode: false
- id: pin
run: |
# windows/props/swift-version.txt holds e.g. "swift-6.3.3-RELEASE". gha-setup-swift
# composes the download URL as
# download.swift.org/<swift-version>/windows10/swift-<swift-build>/...
# so it wants swift-version=swift-6.3.3-release and swift-build=6.3.3-RELEASE
# (no "swift-" prefix — the action adds it).
#
# The pin has a FLOOR set by the runner's MSVC: the VS 2026 STL (14.5x) hard-errors
# (STL1000) on clang older than 20, and Swift 6.2.x bundles clang 19. 6.3.x bundles
# clang 21. Keep this at or above the Linux pin in scripts/build-nucleicd-linux.sh.
TAG="$(tr -d '[:space:]' < windows/props/swift-version.txt)"
echo "swift-version=$(echo "$TAG" | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
echo "swift-build=${TAG#swift-}" >> "$GITHUB_OUTPUT"
protocol:
name: Protocol tests (${{ matrix.arch }})
needs: swift-version
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: ${{ vars.WINDOWS_X64_RUNNER || 'windows-2025' }}
build_arch: amd64
- arch: arm64
runner: ${{ vars.WINDOWS_ARM64_RUNNER || 'windows-11-arm' }}
build_arch: arm64
runs-on: ${{ matrix.runner }}
env:
# Narrow the manifest to the wire layer (see Package.swift): `swift test` builds every
# declared target, and NucleicCore doesn't compile on Windows yet.
NUCLEIC_WINDOWS_PROTOCOL_ONLY: "1"
steps:
- name: Git line-ending + longpath config
# Agents run in Linux containers — the repo must stay LF (docs/WINDOWS_PORT.md §4.4);
# and SwiftPM checkouts nest deep enough to hit MAX_PATH without longpaths.
run: |
git config --global core.autocrlf false
git config --global core.longpaths true
- uses: actions/checkout@v4
- uses: compnerd/[email protected]
with:
swift-version: ${{ needs.swift-version.outputs.swift-version }}
swift-build: ${{ needs.swift-version.outputs.swift-build }}
build_arch: ${{ matrix.build_arch }}
cache: true
- name: Build NucleicProtocol
run: swift build --target NucleicProtocol
- name: Run NucleicProtocolTests
# /FORCE:MULTIPLE is TEMPORARY — the CCryptoBoringSSL / CNIOBoringSSL
# `p_thread_callback_boringssl` collision (docs/WINDOWS_PORT.md §14.1.1). It bites here
# even under NUCLEIC_WINDOWS_PROTOCOL_ONLY, because NucleicProtocol itself links both
# Crypto and NIOSSL on Windows. Drop it when one copy prefixes the symbol.
run: swift test --filter NucleicProtocolTests -Xlinker "/FORCE:MULTIPLE"
core:
name: Full core (${{ matrix.arch }})
needs: swift-version
# x64 is required (the NucleicCore build is green there); ARM64 has never run, so it
# stays advisory until a box confirms it. See the header note.
continue-on-error: ${{ matrix.experimental }}
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: ${{ vars.WINDOWS_X64_RUNNER || 'windows-2025' }}
build_arch: amd64
vcpkg_triplet: x64-windows-static-md-nucleic
experimental: false
- arch: arm64
runner: ${{ vars.WINDOWS_ARM64_RUNNER || 'windows-11-arm' }}
build_arch: arm64
vcpkg_triplet: arm64-windows-static-md-nucleic
experimental: true
runs-on: ${{ matrix.runner }}
steps:
- name: Git line-ending + longpath config
run: |
git config --global core.autocrlf false
git config --global core.longpaths true
- uses: actions/checkout@v4
- uses: compnerd/[email protected]
with:
swift-version: ${{ needs.swift-version.outputs.swift-version }}
swift-build: ${{ needs.swift-version.outputs.swift-build }}
build_arch: ${{ matrix.build_arch }}
cache: true
- name: Provision SQLite for GRDB
# GRDB's GRDBSQLite is a .systemLibrary declaring only an apt provider, so nothing
# supplies sqlite3.h / sqlite3.lib on Windows — hence "including GRDB/SQLite linkage"
# in the §13 M0 exit criteria. The -static-md triplet links SQLite statically against
# the DYNAMIC CRT, matching what the Swift toolchain uses: the CRT agrees and there's
# no DLL to stage beside the test binaries. Stock vcpkg FEATURES are enough — nothing
# here uses FTS or rtree — but the stock BUILD is not: it compiles the snapshot API out,
# which GRDB's system-SQLite path needs, hence the overlay triplet below.
shell: pwsh
run: |
# Hosted images ship vcpkg and set VCPKG_INSTALLATION_ROOT; a self-hosted box does
# not. Fall back to a clone under RUNNER_TOOL_CACHE, which survives between jobs,
# so the bootstrap is a one-time cost on the on-prem runner rather than per-run.
$vcpkg = $env:VCPKG_INSTALLATION_ROOT
if (-not $vcpkg -or -not (Test-Path (Join-Path $vcpkg 'vcpkg.exe'))) {
$vcpkg = Join-Path $env:RUNNER_TOOL_CACHE 'vcpkg'
if (-not (Test-Path (Join-Path $vcpkg '.git'))) {
git clone --depth 1 https://github.com/microsoft/vcpkg $vcpkg
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
}
if (-not (Test-Path (Join-Path $vcpkg 'vcpkg.exe'))) {
& (Join-Path $vcpkg 'bootstrap-vcpkg.bat') -disableMetrics
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
}
}
# Overlay triplet = stock -static-md + SQLITE_ENABLE_SNAPSHOT, which GRDB's
# system-SQLite path needs and the stock port compiles out (§14.2).
& (Join-Path $vcpkg 'vcpkg.exe') install sqlite3:${{ matrix.vcpkg_triplet }} "--overlay-triplets=$env:GITHUB_WORKSPACE\windows\vcpkg-triplets"
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
$root = Join-Path $vcpkg 'installed\${{ matrix.vcpkg_triplet }}'
# Deliberately NOT %INCLUDE%/%LIB%: clang's MSVC driver stops auto-detecting the
# VC + Windows SDK header set as soon as %INCLUDE% names one existing directory,
# so appending here could silently strip the system headers. Pass them per-build
# as ordinary -I / -LIBPATH instead.
"SQLITE_INCLUDE=$root\include" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
"SQLITE_LIB=$root\lib" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Build NucleicCore
# `/LIBPATH:`, not `-LIBPATH:` — a leading `-L` is eaten by the driver's GNU-style
# library-path flag and the linker ends up searching `IBPATH:C:\…` (§14.2).
run: swift build --target NucleicCore -Xcc "-I$env:SQLITE_INCLUDE" -Xlinker "/LIBPATH:$env:SQLITE_LIB"
- name: Run NucleicCarbonTests (gap probe)
# Advisory on BOTH arches, independently of the job tier: `swift test` builds every
# declared target, so this covers nucleic-hostd / NucleicProtocolC / nucleic-smoke —
# §12 items 10+ — not just the suite it names. Flips to required with those items.
continue-on-error: true
# /FORCE:MULTIPLE as in the protocol job — see §14.1.1.
run: swift test --filter NucleicCarbonTests -Xcc "-I$env:SQLITE_INCLUDE" -Xlinker "/LIBPATH:$env:SQLITE_LIB" -Xlinker "/FORCE:MULTIPLE"
broker:
name: Broker contract tests
runs-on: ${{ vars.WINDOWS_X64_RUNNER || 'windows-latest' }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: "9.0.x"
- name: Test windows/Nucleic.sln
run: dotnet test windows/Nucleic.sln --nologo