acdream/.gitea/workflows/ci.yml
Erik c5492984ef
Some checks failed
CI / linux-portable (push) Successful in 3m26s
CI / windows-gate (push) Failing after 5m2s
CI / release (push) Has been skipped
ci: tag DAT-dependent tests into the InstalledDat lane; drop invariant workaround
Three tests reached the CI gate needing the installed retail DATs, which no
build machine has, and failed with FileNotFoundException on client_cell_1.dat:
  - Issue127FloodFlipReplayTests (both facts replay via ResolveDatDir)
  - FindCellListConformanceTests.FindCellList_DoorwayThreshold_IndoorPicks_
    MatchRetail, the one untagged method among already-tagged siblings
They now carry [Trait("Lane", "InstalledDat")] like every other DAT test, so
the gate filter excludes them and the local DAT lane still runs them.

Also reverts the DOTNET_SYSTEM_GLOBALIZATION_INVARIANT pin from the previous
commit. It was too blunt: it fixed the 40 decimal-comma failures but broke
ChatLogTests.FormatTimestampPrefix_UsesLiteralColons_RegardlessOfCurrentCulture,
which legitimately constructs a culture and cannot under invariant mode. The
runner's HKCU locale (LocaleName=en-SE, sDecimal=',') was corrected to en-US
instead, which is the actual defect.
2026-08-19 11:19:14 +02:00

161 lines
7 KiB
YAML

# Gitea Actions CI gate for the self-hosted runners.
#
# Deliberately does NOT use actions/setup-dotnet: data.forgejo.org (the mirror
# Gitea resolves actions from) does not host that action at all, and the
# self-hosted runners carry the pinned SDK band from global.json already.
# actions/checkout IS mirrored, so it is used normally.
#
# The suite runs through tools/run-release-gate.ps1 rather than a bare
# `dotnet test`: that script owns the xUnit trait-lane filter which excludes
# the InstalledDat / Live / Manual / OS-specific lanes. A bare `dotnet test`
# fails ~36 tests by design because those lanes assert their own preconditions.
name: CI
on:
push:
branches: [main]
workflow_dispatch:
jobs:
windows-gate:
runs-on: windows-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v6
- name: Verify the pinned SDK band resolves
shell: pwsh
run: |
dotnet --version
dotnet --list-sdks
# NOT tools/run-release-gate.ps1 here. That script redirects every child
# process to its own log file, so the step emits nothing for minutes at a
# time; Forgejo treats a task that stops reporting as a zombie and fails
# it while the work is still running (observed: job marked failed with 20
# dotnet processes still alive and a complete 8.7 MB TRX on disk). Running
# the projects directly keeps output streaming. The script stays the
# canonical LOCAL gate; the trait filter below is copied from its default.
- name: Build
shell: pwsh
run: dotnet build AcDream.slnx -c Release --nologo
- name: Test (lane-filtered, streaming)
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$filter = 'Lane!=InstalledDat&Lane!=PreparedPackage&Lane!=Live&Lane!=Manual&Lane!=Windows&Lane!=Linux&Lane!=SystemFont&Purpose!=Diagnostic&Status!=KnownFailure'
$failed = @()
foreach ($proj in Get-ChildItem tests -Directory | Sort-Object Name) {
$csproj = Join-Path $proj.FullName "$($proj.Name).csproj"
if (-not (Test-Path $csproj)) { continue }
Write-Host "::group::$($proj.Name)"
dotnet test $csproj -c Release --no-build --nologo --filter $filter
if ($LASTEXITCODE -ne 0) { $failed += $proj.Name }
Write-Host "::endgroup::"
}
if ($failed.Count) { throw "Failed test projects: $($failed -join ', ')" }
linux-portable:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v6
- name: Portable closure (Linux lanes run here, not on Windows)
run: |
set -e
dotnet --version
for p in \
tests/AcDream.Platform.Tests \
tests/AcDream.Core.Tests \
tests/AcDream.Core.Net.Tests \
tests/AcDream.Content.Tests \
tests/AcDream.Runtime.Tests \
tests/AcDream.Headless.Tests \
tests/AcDream.Launcher.Core.Tests \
tests/AcDream.UI.Abstractions.Tests ; do
echo "::group::$p"
# MaxParallelThreads is capped because this runner is a small
# container. Under full-assembly parallel load
# FakeAceTransportTests.PausedSelector_SeededDroppedServerReady_
# RecoversOnIdleSweep took 37 s and missed its 2 s real-time wait,
# while passing 5/5 in ~350 ms in isolation. Timing-sensitive, not
# broken: starve it less rather than edit Campaign N transport code.
dotnet test "$p" -c Release --nologo \
--filter 'Lane!=InstalledDat&Lane!=PreparedPackage&Lane!=Live&Lane!=Manual&Lane!=Windows&Lane!=SystemFont&Purpose!=Diagnostic&Status!=KnownFailure' \
-- xUnit.MaxParallelThreads=2
echo "::endgroup::"
done
release:
# Same workflow rather than a workflow_run trigger: workflow_run is a
# GitHub feature whose Forgejo support is unreliable, while `needs` is
# guaranteed. A red gate therefore cannot publish.
needs: [windows-gate, linux-portable]
runs-on: windows-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v6
- name: Compute release version
id: ver
shell: pwsh
run: |
$v = '0.1.0-build.{0}' -f ([DateTime]::UtcNow.ToString('yyyyMMddHHmm'))
"version=$v" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
Write-Host "release version: $v"
- name: Build payloads with release-attachment URLs
shell: pwsh
env:
TAG: ${{ steps.ver.outputs.version }}
run: |
./tools/publish-bin.ps1 -Version $env:TAG -BaseUrl "${{ github.server_url }}/${{ github.repository }}/releases/download/$env:TAG"
- name: Create the release and upload payloads
shell: pwsh
env:
TAG: ${{ steps.ver.outputs.version }}
TOKEN: ${{ secrets.GITEA_TOKEN }}
run: |
$ErrorActionPreference = 'Stop'
$api = "${{ github.server_url }}/api/v1/repos/${{ github.repository }}"
$headers = @{ Authorization = "token $env:TOKEN" }
$body = @{
tag_name = $env:TAG
name = "acdream alpha $env:TAG"
body = "Automated alpha build from ${{ github.sha }}."
draft = $false
prerelease = $true
target_commitish = 'main'
} | ConvertTo-Json
$release = Invoke-RestMethod -Method Post -Uri "$api/releases" -Headers $headers -ContentType 'application/json' -Body $body
Write-Host "created release id=$($release.id)"
foreach ($f in Get-ChildItem bin -File) {
Write-Host ("uploading {0} ({1:N1} MB)" -f $f.Name, ($f.Length/1MB))
Invoke-RestMethod -Method Post -Headers $headers -Uri "$api/releases/$($release.id)/assets?name=$($f.Name)" -Form @{ attachment = Get-Item $f.FullName } | Out-Null
}
- name: Point the launcher manifest at the new release
shell: pwsh
env:
TAG: ${{ steps.ver.outputs.version }}
TOKEN: ${{ secrets.GITEA_TOKEN }}
run: |
$ErrorActionPreference = 'Stop'
# dist carries ONLY manifest.json (~500 bytes), force-replaced each
# publish, never pushed to GitHub. Payloads stay in release
# attachments, outside git history entirely.
$url = "${{ github.server_url }}/${{ github.repository }}.git" -replace '^https://', "https://x:$env:TOKEN@"
git config --global user.email 'ci@acdream.local'
git config --global user.name 'acdream CI'
New-Item -ItemType Directory -Force dist-branch/bin | Out-Null
Copy-Item bin/manifest.json dist-branch/bin/manifest.json
Push-Location dist-branch
git init -q
git checkout -q -b dist
git add -f bin/manifest.json
git commit -q -m "release: manifest for $env:TAG"
git push -q --force $url dist:dist
Pop-Location
Write-Host "manifest published for $env:TAG"