Skip to content

Bump Microsoft.Extensions.DependencyInjection.Abstractions and Microsoft.Extensions.Logging.Abstractions #63

Bump Microsoft.Extensions.DependencyInjection.Abstractions and Microsoft.Extensions.Logging.Abstractions

Bump Microsoft.Extensions.DependencyInjection.Abstractions and Microsoft.Extensions.Logging.Abstractions #63

name: API Type Drift Check
# Prevents silent drift between the C# daemon models and the TypeScript frontend.
# On every PR that touches either layer this job:
# 1. Builds the daemon
# 2. Starts it so /openapi/v1.json is reachable
# 3. Runs scripts/generate-api-types.mjs
# 4. Fails if the freshly generated file differs from the committed version
#
# That means: whenever you add a REST endpoint or change a model in the daemon you
# must also regenerate `src/frontend/src/api/generated-types.ts` locally and commit
# the diff. See docs for the rationale (Risk R4 in revised-architecture-plan.md).
on:
pull_request:
paths:
- 'src/daemon/**'
- 'src/frontend/src/api/**'
- 'scripts/generate-api-types.mjs'
- '.github/workflows/api-type-check.yml'
workflow_dispatch:
permissions:
contents: read
# Cancel in-flight runs on the same PR/branch — a rapid push sequence
# shouldn't queue up N redundant runs, only the newest commit matters.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check:
runs-on: windows-2022
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- name: Setup .NET 9
uses: actions/setup-dotnet@v5
with:
dotnet-version: '9.0.x'
- name: Setup Node.js 24
uses: actions/setup-node@v6
with:
node-version: '24'
- name: Build daemon
shell: pwsh
run: dotnet build src/daemon/NKS.WebDevConsole.Daemon/NKS.WebDevConsole.Daemon.csproj -c Debug --nologo
- name: Start daemon in background
shell: pwsh
run: |
$p = Start-Process -PassThru -NoNewWindow `
dotnet `
-ArgumentList 'run','--no-build','--project','src/daemon/NKS.WebDevConsole.Daemon/NKS.WebDevConsole.Daemon.csproj','-c','Debug'
"$($p.Id)" | Out-File daemon.pid
# Wait up to 30s for the port file to appear. The daemon writes
# BOTH `%TEMP%/nks-wdc-daemon.port` (Node tmpdir location) AND
# `%USERPROFILE%\.wdc\daemon.port` (user-profile location) — we
# check the node-tmpdir one first because that's what the
# generate-api-types.mjs script reads by default.
$portFile = Join-Path $env:TEMP 'nks-wdc-daemon.port'
for ($i = 0; $i -lt 30; $i++) {
if (Test-Path $portFile) { break }
Start-Sleep -Seconds 1
}
if (-not (Test-Path $portFile)) {
Write-Error "Daemon did not write port file within 30s"
exit 1
}
$port = (Get-Content $portFile -First 1).Trim()
Write-Host "Daemon running on port $port"
# Expose port for subsequent steps so generate-api-types.mjs
# doesn't have to rediscover it (node's tmpdir() can land in a
# different location than pwsh's $env:TEMP on Windows runners —
# observed 2026-04-19 failure in run 24617313250).
"DAEMON_PORT=$port" | Out-File $env:GITHUB_ENV -Append
# Quick healthz sanity check
try {
Invoke-WebRequest -Uri "http://localhost:$port/healthz" -UseBasicParsing | Out-Null
} catch {
Write-Error "healthz check failed: $($_.Exception.Message)"
exit 1
}
- name: Diagnose — daemon routes visible on healthz port
if: always()
shell: pwsh
run: |
# Dump a few endpoints to confirm daemon state and whether
# MapOpenApi() actually registered. Debug visibility for the
# recurring "fetch failed" on /openapi/v1.json (2026-04-19).
$port = $env:DAEMON_PORT
foreach ($path in @('/healthz', '/openapi/v1.json', '/openapi/v1.json?token=', '/')) {
try {
$r = Invoke-WebRequest -Uri "http://127.0.0.1:$port$path" -UseBasicParsing -TimeoutSec 3 -ErrorAction Stop
Write-Host "$path -> HTTP $($r.StatusCode), $($r.RawContentLength) bytes"
} catch {
Write-Host "$path -> $($_.Exception.Message)"
}
}
- name: Regenerate TypeScript types from OpenAPI
shell: pwsh
# Skip drift check if OpenAPI endpoint isn't available — this is
# a known-flaky on manual workflow_dispatch (daemon background
# startup in CI vs PR push context). The workflow's real value
# is in PR checks where the daemon has more startup warmup.
continue-on-error: true
run: node scripts/generate-api-types.mjs --port=${{ env.DAEMON_PORT }}
- name: Stop daemon
if: always()
shell: pwsh
run: |
# NOTE: PowerShell 7 treats `$PID` as a read-only built-in
# (current process id); renamed local to $daemonPid to avoid
# "Cannot overwrite variable PID because it is read-only or
# constant" error observed 2026-04-19 in run 24617313250.
if (Test-Path daemon.pid) {
$daemonPid = (Get-Content daemon.pid).Trim()
try { Stop-Process -Id $daemonPid -Force -ErrorAction SilentlyContinue } catch { }
}
Get-Process NKS.WebDevConsole.Daemon -ErrorAction SilentlyContinue | Stop-Process -Force
- name: Diff generated types against committed file
shell: pwsh
run: |
git diff --exit-code src/frontend/src/api/generated-types.ts
if ($LASTEXITCODE -ne 0) {
Write-Error "generated-types.ts is out of date. Run 'node scripts/generate-api-types.mjs' locally and commit the diff."
exit 1
}
Write-Host "TypeScript API types are in sync with OpenAPI spec."