Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1882f54
ci: centralize Unity enrollment lifecycle
codex Jul 30, 2026
387368c
ci: align Unity provisioning with cleanup root
codex Jul 30, 2026
268cb55
ci: provision the managed Unity editor root
codex Jul 30, 2026
26133ed
ci: let central action own Unity return
codex Jul 30, 2026
8de6f39
ci: pin serial-redacting Unity return
codex Jul 30, 2026
70c3d3a
ci: centralize every final Unity return
codex Jul 30, 2026
934c1b8
ci: provision every trusted editor root
codex Jul 30, 2026
a99a6da
test(editor): reject PrintWindow capture automation
wallstop Jul 30, 2026
bba7442
Merge remote-tracking branch 'origin/master' into codex/issue-305-enr…
wallstop Jul 30, 2026
982f410
ci: serialize editor provisioning under lock
codex Jul 30, 2026
0792648
test: keep runner contracts within JS budget
codex Jul 30, 2026
774260e
ci: preflight bootstrap shared runner labels
codex Jul 30, 2026
ae8d957
ci: distinguish Unity CLI activity from silence
wallstop Jul 30, 2026
6e2c906
Merge remote-tracking branch 'origin/codex/issue-305-enrollment-remed…
wallstop Jul 30, 2026
87a1e60
test(ci): consolidate workflow contract checks
wallstop Jul 30, 2026
148de4e
docs(progress): record final provisioning validation
wallstop Jul 30, 2026
5cdcd2d
test(ci): classify second-reap Unity termination
wallstop Jul 30, 2026
b0d0190
test(ci): allow native pipe close spelling
wallstop Jul 30, 2026
e1dfee7
test: account for Windows detached pipe semantics
wallstop Jul 30, 2026
564af4c
test: classify editor heartbeat as static
codex Jul 30, 2026
591eb09
fix: preserve Unity lifecycle cleanup margin
codex Jul 30, 2026
378caa1
ci: reserve Unity cleanup timeout budget
wallstop Jul 30, 2026
9f0cdf1
Merge remote-tracking branch 'origin/codex/issue-305-enrollment-remed…
wallstop Jul 30, 2026
3f28a5e
Make Unity workflows validation-only
wallstop Jul 30, 2026
98fc555
docs(progress): record validation-only correction
wallstop Jul 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions .agents/skills/unity-editor-ci/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
---
name: unity-editor-ci
description: "Unity CI on self-hosted Windows runners: the unity-tests.yml
matrix of 3 Unity versions x {editmode, playmode, standalone}, the canonical
version list in .github/unity-versions.json enforced by npm run
validate:unity-versions, the organization build-lock and timeout invariants
that protect the two-seat Unity serial, the ensure-editor.ps1 standalone-CLI
bootstrap with its PATH refresh and module quarantine/reinstall repair,
Windows host prerequisites for 0xC0000135 startup failures, and repo-wide
GitHub Action version pins. Use when bumping a Unity version, adding a matrix
cell, triaging an IL2CPP-only or license or editor-provisioning failure, or
editing a Unity workflow."
matrix of 3 Unity versions x {editmode, playmode, standalone}, manual
administrator installation under RUNNER_TOOL_CACHE/u6-v3, validation-only
workflow checks with ensure-editor.ps1 -RequireHealthyExisting, the
organization build-lock and timeout invariants that protect the two-seat Unity
serial, Windows host prerequisites for 0xC0000135 startup failures, and
repo-wide GitHub Action version pins. Use when bumping a Unity version, adding
a matrix cell, triaging an IL2CPP-only, license, or editor-validation failure,
or editing a Unity workflow."
---

<!-- Generated by `npm run llm:index`. Do not edit by hand. -->
Expand Down
17 changes: 8 additions & 9 deletions .claude/skills/unity-editor-ci/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
---
name: unity-editor-ci
description: "Unity CI on self-hosted Windows runners: the unity-tests.yml
matrix of 3 Unity versions x {editmode, playmode, standalone}, the canonical
version list in .github/unity-versions.json enforced by npm run
validate:unity-versions, the organization build-lock and timeout invariants
that protect the two-seat Unity serial, the ensure-editor.ps1 standalone-CLI
bootstrap with its PATH refresh and module quarantine/reinstall repair,
Windows host prerequisites for 0xC0000135 startup failures, and repo-wide
GitHub Action version pins. Use when bumping a Unity version, adding a matrix
cell, triaging an IL2CPP-only or license or editor-provisioning failure, or
editing a Unity workflow."
matrix of 3 Unity versions x {editmode, playmode, standalone}, manual
administrator installation under RUNNER_TOOL_CACHE/u6-v3, validation-only
workflow checks with ensure-editor.ps1 -RequireHealthyExisting, the
organization build-lock and timeout invariants that protect the two-seat Unity
serial, Windows host prerequisites for 0xC0000135 startup failures, and
repo-wide GitHub Action version pins. Use when bumping a Unity version, adding
a matrix cell, triaging an IL2CPP-only, license, or editor-validation failure,
or editing a Unity workflow."
---

<!-- Generated by `npm run llm:index`. Do not edit by hand. -->
Expand Down
95 changes: 17 additions & 78 deletions .github/actions/assert-unity-host-prereqs/action.yml
Original file line number Diff line number Diff line change
@@ -1,71 +1,34 @@
name: Assert Unity host prerequisites
description: >-
Ensure the self-hosted Windows runner has every host-OS prerequisite Unity
Editor needs to launch successfully (Microsoft Visual C++ 2015-2022 x64
Redistributable, Windows long-path support, Windows Defender exclusions,
PowerShell 7, UCRT). Root cause: Unity.exe failed at startup with
Verify the self-hosted Windows runner has every host-OS prerequisite Unity
Editor needs to launch successfully (Microsoft Visual C++ 2010 SP1 and
2015-2022 x64 Redistributables, Windows long-path support, Windows Defender
exclusions, PowerShell 7, UCRT). Root cause: Unity.exe failed at startup with
-1073741515 / 0xC0000135 (STATUS_DLL_NOT_FOUND) on DAD-MACHINE because the
VC++ redist was missing. GitHub-hosted windows-2022 ships the redist
preinstalled; self-hosted runners do not. This action runs the bootstrap
script (auto-install by default) so every Unity job is preceded by a
resilient prereq check. Non-Windows callers (Linux/macOS) are no-ops --
the action emits a friendly ::notice:: skip and exits 0.

MODE RESOLUTION PRECEDENCE (highest wins):
1. Non-Windows host -> ::notice:: skip, exit 0
2. DXM_RUNNER_DISABLE_AUTO_BOOTSTRAP=1 -> force DetectOnly
3. inputs.auto-install is NOT truthy -> DetectOnly
4. inputs.auto-install IS truthy (default) -> auto-install
Truthy normalization (F4): true/True/1/yes/y all accepted; anything else
(including blank) is treated as false. Operators relying on the env-var
override see the same precedence rule on the workflow path (see
.github/workflows/runner-bootstrap.yml).

inputs:
auto-install:
description: >-
If truthy (default 'true'; accepts true/True/1/yes/y), bootstrap
auto-installs any missing prereq. Otherwise the script runs with
-DetectOnly and fails fast (exit 2) on any missing prereq. The env var
DXM_RUNNER_DISABLE_AUTO_BOOTSTRAP=1 forces DetectOnly regardless of
this input (operator escape hatch).
required: false
default: "true"
script with -DetectOnly. It never installs or repairs host software because
GitHub Actions does not have administrator credentials. This composite is
Windows-only because its first guard uses Windows PowerShell 5.1.

runs:
using: composite
steps:
# F14: PowerShell 5.1 preflight FIRST. The rest of the composite uses
# `shell: pwsh`; without this step a runner missing pwsh would fail
# with the cryptic "pwsh: command not found" before the bootstrap
# script gets a chance to install pwsh. Use Windows PowerShell 5.1
# (always built into Windows runners) so it executes regardless of
# whether pwsh exists. If pwsh is missing, point the operator at the
# runner-bootstrap.yml workflow_dispatch (which intentionally avoids
# `shell: pwsh` and CAN install pwsh; see that workflow's header for
# the chicken-and-egg rationale).
# with the cryptic "pwsh: command not found". Use Windows PowerShell 5.1
# (always built into Windows runners) so it can report the manual fix.
- name: Verify PowerShell 7 (pwsh) is available
shell: powershell
run: |
# Skip the preflight on non-Windows hosts (e.g. Linux callers that
# consume this composite by accident): pwsh is the default shell
# there, Windows PowerShell 5.1 does not exist, and the platform
# gate inside the main step is what actually emits the skip notice.
if ([System.IO.Path]::DirectorySeparatorChar -ne '\') {
Write-Output "::notice::PS 5.1 preflight: skipping (not Windows: $env:RUNNER_OS)"
exit 0
}
if ($null -eq (Get-Command pwsh -ErrorAction SilentlyContinue)) {
Write-Output ("::error title=pwsh missing on self-hosted runner::PowerShell 7 (pwsh) is not installed on runner '$env:RUNNER_NAME'. Dispatch " +
".github/workflows/runner-bootstrap.yml from the Actions UI to install it (the workflow uses Windows PowerShell 5.1 so it works even on a host " +
"missing pwsh). See docs/runbooks/unity-runners-after-transfer.md for the PowerShell 7 prerequisite.")
Write-Output ("::error title=pwsh missing on self-hosted runner::PowerShell 7 (pwsh) is not installed on runner '$env:RUNNER_NAME'. " +
"A runner administrator must install it manually. See docs/runbooks/unity-runners-after-transfer.md for the PowerShell 7 prerequisite.")
exit 1
}
Write-Output "pwsh found at: $((Get-Command pwsh).Source)"
- name: Probe + (optionally) install Unity host prerequisites
- name: Probe Unity host prerequisites
shell: pwsh
env:
DXM_PREREQ_AUTO_INSTALL: ${{ inputs.auto-install }}
run: |
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
Expand All @@ -85,27 +48,6 @@ runs:
exit 0
}

# Operator escape hatch: DXM_RUNNER_DISABLE_AUTO_BOOTSTRAP=1 forces
# -DetectOnly regardless of the input. Use it when an operator wants
# to inspect prereq state from a Unity job without mutating the
# runner host. The input 'auto-install' is the workflow-author-facing
# control; the env var is the operator-facing override.
# F4: normalize the input via natural truthy parsing so 'True',
# ' true ', '1', 'yes', 'y' all map to auto-install; anything else
# falls back to DetectOnly. The string-equality compare against the
# literal 'true' would case-sensitively miss those equivalents.
$rawInput = '' + $env:DXM_PREREQ_AUTO_INSTALL
$normalizedInput = $rawInput.Trim().ToLowerInvariant()
$autoInstall = ($normalizedInput -eq 'true' -or $normalizedInput -eq '1' -or $normalizedInput -eq 'yes' -or $normalizedInput -eq 'y')
$detectOnly = $false
if ($env:DXM_RUNNER_DISABLE_AUTO_BOOTSTRAP -eq '1') {
Write-Host "::notice::assert-unity-host-prereqs: DXM_RUNNER_DISABLE_AUTO_BOOTSTRAP=1 -> forcing DetectOnly"
$detectOnly = $true
} elseif (-not $autoInstall) {
Write-Host "::notice::assert-unity-host-prereqs: auto-install='$rawInput' (normalized='$normalizedInput') -> DetectOnly"
$detectOnly = $true
}

# F6: resolve via $GITHUB_WORKSPACE directly. Workflows always do
# `actions/checkout` before invoking this composite (it's a required
# precondition because the composite needs the bootstrap script),
Expand All @@ -128,12 +70,9 @@ runs:
exit 1
}

Write-Host "::notice::assert-unity-host-prereqs: invoking $scriptPath (DetectOnly=$detectOnly)"
if ($detectOnly) {
& $scriptPath -DetectOnly
} else {
& $scriptPath
}
$unityInstallRoot = Join-Path $env:RUNNER_TOOL_CACHE 'u6-v3'
Write-Host "::notice::assert-unity-host-prereqs: invoking $scriptPath (DetectOnly=True, UnityInstallRoot=$unityInstallRoot)"
& $scriptPath -DetectOnly -UnityInstallRoot $unityInstallRoot
$code = $LASTEXITCODE
$sw.Stop()
$elapsed = [int]$sw.Elapsed.TotalSeconds
Expand All @@ -146,9 +85,9 @@ runs:
# unset it falls back to the default "missing VC++ Redistributable
# is the most likely cause". Without this producer, the consumer
# branch is dead code and the annotation is misleading whenever the
# preflight just installed/confirmed VC++ but Unity still fails
# preflight just confirmed VC++ but Unity still fails
# 0xC0000135 for a different reason. Set on ANY exit-0 from the
# bootstrap (install path OR DetectOnly: both mean "host is OK").
# bootstrap validation (exit 0 means "host is OK").
# Skip when GITHUB_ENV is missing (local invocation outside Actions).
if ($code -eq 0 -and -not [string]::IsNullOrWhiteSpace($env:GITHUB_ENV)) {
Add-Content -Path $env:GITHUB_ENV -Value "DXM_RUNNER_PREREQ_INSTALLED=1" -Encoding utf8
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/compute-unity-assemblies/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ runs:
# SKIP, do not fail: the discovery succeeded but no DxMessaging-owned
# test assembly matched this target (for example a runtime-only
# standalone run when every DxMessaging test asmdef is editor-only).
# The caller gates its provision/run/verify steps on is-empty so the
# The caller gates its validate/run/verify steps on is-empty so the
# target is skipped cleanly instead of failing with "0 tests ran".
Write-Host "::notice::No DxMessaging test assemblies matched this target; the Unity run will be skipped."
Add-Content -Path $env:GITHUB_OUTPUT -Value "assemblies=" -Encoding utf8
Expand Down
14 changes: 2 additions & 12 deletions .github/actions/print-self-hosted-runner-diagnostics/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -171,22 +171,12 @@ runs:
}
# Assert Unity host prerequisites (VC++ redist, long-paths, Defender
# exclusions, pwsh, UCRT). Unity test jobs are detect-only: host/editor
# repair belongs to scripts/unity/maintain-windows-runner.ps1 or the
# operator-dispatched runner-bootstrap workflow.
# F8: the assert-unity-host-prereqs composite's own non-Windows skip
# ("if DirectorySeparatorChar -ne '\' -> ::notice:: + exit 0") is
# DEFENSE-IN-DEPTH only -- this parent composite is itself Windows-
# only by contract (every consumer pins `runs-on: [self-hosted,
# Windows, ...]`), so the inner skip never fires in production. The
# belt-and-suspenders gate stays because a future reuse of
# assert-unity-host-prereqs from a non-Windows context must remain a
# no-op rather than throw.
# repair requires a runner administrator working directly on the host.
# This parent and the prerequisite composite are Windows-only by contract.
# See scripts/unity/bootstrap-windows-runner.ps1 for the full prereq
# list and remediation logic; this step exists because Unity.exe
# failed with STATUS_DLL_NOT_FOUND (0xC0000135) on DAD-MACHINE when
# the VC++ redist was absent and ensure-editor.ps1 futilely retried
# Unity installs (the missing DLL is on the OS, not in Unity).
- name: Assert Unity host prerequisites
uses: ./.github/actions/assert-unity-host-prereqs
with:
auto-install: "false"
Loading
Loading