Skip to content

feat: support game-ci test --docker on Windows containers - #140

Merged
frostebite merged 2 commits into
mainfrom
feat/windows-docker-test-support
Aug 24, 2026
Merged

feat: support game-ci test --docker on Windows containers#140
frostebite merged 2 commits into
mainfrom
feat/windows-docker-test-support

Conversation

@frostebite

@frostebite frostebite commented Aug 24, 2026

Copy link
Copy Markdown
Member

What

game-ci test --docker rejected every non-Linux host outright:

--docker's classic batchmode test flow is currently only supported on Linux hosts/containers (got hostPlatform=win32). Windows Docker test support is tracked separately (the container-side scripts only handle builds so far).

That guard was correct for the code as it stooddist/platforms/windows/entrypoint.ps1 had no RUN_TESTS branch and unconditionally ran build.ps1, so letting a test run through would have silently performed a build and reported success.

This is what fails every Windows job on game-ci/unity-test-runner#310 (each dies in ~25s, well before Unity starts).

Why it regressed

The original unity-test-runner action did support this, via its own dist/platforms/windows/run_tests.ps1. The capability was lost in the port to this CLI — not deliberately dropped.

Approach

Rather than resurrect run_tests.ps1, entrypoint.ps1 now reuses steps/test.ps1 — the "native host" Windows test script — which is already container-safe. The only container/host difference that ever mattered is how the Unity Editor is located, and resolve_unity_path.ps1's Get-UnityEditorRoot already returns the image-baked $Env:UNITY_PATH when set, before falling back to the Unity Hub default.

Docker.getWindowsCommand already mounts the whole platforms/windows tree at c:\steps, so the shared script is reachable at c:\steps\steps\test.ps1 with no new volume.

This also keeps the strictly better implementation — package mode, coverageEnabled gating, array-based argv — instead of the original's string-interpolated one, and avoids a ~250-line duplicate.

Two further bugs found while verifying end to end

1. --testPlatforms=standalone was broken in Docker mode — on Linux too.
dist/test-standalone-scripts was never mounted into the container, so ubuntu/steps/test.sh's cp -R "/UnityTestRunnerAction/Assets/..." failed outright. The scripts survived the port; the mount didn't (the original action mounted the same directory as /UnityStandaloneScripts). Now mounted on both platforms, and only for test runs.

2. The Windows container never propagated its exit code.
entrypoint.ps1 just fell off the end, so the container's status was whatever return_license.ps1 happened to leave behind. Builds were shielded by UnityBuildValidation parsing the log output, but a test run has no equivalent output check — a failing suite could have reported success.

macOS stays rejected, with a clearer message: there are no Unity Editor Docker images for macOS at all, so there is nothing to run the container scripts in.

Verification

  • PowerShell scripts parse cleanly under Windows PowerShell 5.1 — what the container actually runs (powershell, not pwsh 7). Both runtimes were also checked for the [int]"" coercion the new exit-code casts rely on.
  • steps/test.ps1 was executed against a stubbed UNITY_PATH to confirm it resolves its sibling resolve_unity_path.ps1 via $PSScriptRoot, honours $Env:UNITY_PATH (it attempted exactly the container's <UNITY_PATH>\Editor\Unity.exe shape), and surfaces $global:TEST_RUNNER_EXIT_CODE across the dot-source boundary entrypoint.ps1 consumes it through.
  • 5 new unit tests (Windows test dispatch resolves a windows-il2cpp image; standalone mount present for test runs and absent for builds, both platforms).
  • Full suite: 244 pre-existing failures before and after — no regression. (Those are unrelated: the orchestrator plugin's tests use vitest vi.mock under bun's runner.)

Note on unity-test-runner#310

This unblocks the Windows half of that PR's matrix. The Linux half fails for an unrelated reason — Unity licensing (Code 500 ... No ULF license found / Code 10 while verifying Licensing Client signature), i.e. an expired or invalid UNITY_LICENSE secret, not a code defect. Both halves need to be resolved for that matrix to go green.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for running Unity tests in Windows Docker containers.
    • Standalone test-player builds can now run tests in both Linux and Windows containers.
    • Test helper scripts are automatically included when running Unity tests in Docker.
  • Documentation

    • Clarified Windows native and container-based test execution behavior.

`game-ci test --docker` rejected every non-Linux host outright. The
container-side Windows entrypoint.ps1 had no RUN_TESTS branch (it always
ran build.ps1), so allowing it through would have silently run a BUILD
instead of a test - the guard was correct for the code as it stood.

The original unity-test-runner action did support this, via its own
dist/platforms/windows/run_tests.ps1; the capability was lost in the port
to this CLI, not deliberately dropped.

Rather than resurrect that script, entrypoint.ps1 now reuses
steps/test.ps1 - the "native host" Windows test script - which is already
container-safe: the only container/host difference that ever mattered is
how the Unity Editor is located, and resolve_unity_path.ps1's
Get-UnityEditorRoot already returns the image-baked $Env:UNITY_PATH when
set. Docker.getWindowsCommand mounts the whole platforms/windows tree at
c:\steps, so it needs no new volume. That also keeps the far better
implementation (package mode, coverage gating, array-based argv) instead
of the original's string-interpolated one, and avoids a ~250-line
duplicate.

Two further bugs found and fixed while verifying this end to end:

- dist/test-standalone-scripts was never mounted into the container, so
  --testPlatforms=standalone died on `cp -R /UnityTestRunnerAction/...`.
  This affected LINUX too, not just Windows - the scripts survived the
  port but the mount didn't. Now mounted on both platforms, and only for
  test runs.

- The Windows container entrypoint never exited with the build/test step's
  exit code; it just fell off the end, so the container's status was
  whatever return_license.ps1 happened to leave. Builds were shielded by
  UnityBuildValidation parsing the log, but a test run has no equivalent
  output check, so a failing test suite could have reported success.

macOS stays rejected, with a clearer message - there are no Unity Editor
Docker images for macOS at all, so there is nothing to run in.

Verified: the PowerShell scripts parse under Windows PowerShell 5.1 (what
the container actually runs, not pwsh 7), and steps/test.ps1 was executed
against a stubbed UNITY_PATH to confirm it resolves its sibling
resolve_unity_path.ps1 via $PSScriptRoot, honours $Env:UNITY_PATH, and
surfaces $global:TEST_RUNNER_EXIT_CODE across the dot-source boundary the
way entrypoint.ps1 consumes it. Full suite: 244 pre-existing failures
before and after, +5 new passing tests.
@coderabbitai

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 35 minutes.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c1d40293-0df9-4088-b20a-f1e203780f52

📥 Commits

Reviewing files that changed from the base of the PR and between 6dd4c54 and 1d51bb8.

📒 Files selected for processing (2)
  • src/model/docker.test.ts
  • src/model/docker.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 16a17b65-9793-484d-a567-dc65a9a6487b

📥 Commits

Reviewing files that changed from the base of the PR and between 704286e and 6dd4c54.

⛔ Files ignored due to path filters (3)
  • dist/platforms/windows/entrypoint.ps1 is excluded by !**/dist/**
  • dist/platforms/windows/steps/runsteps.ps1 is excluded by !**/dist/**
  • dist/platforms/windows/steps/test.ps1 is excluded by !**/dist/**
📒 Files selected for processing (5)
  • src/command/test/unity-test-command.test.ts
  • src/command/test/unity-test-command.ts
  • src/model/docker.test.ts
  • src/model/docker.ts
  • src/model/host-runner.ts

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

Docker-based Unity test execution now supports Windows containers. Linux and Windows commands mount standalone test scripts when runTests is enabled. macOS remains unsupported for Docker test execution.

Changes

Windows Docker test execution

Layer / File(s) Summary
Docker test-script mounts
src/model/docker.ts, src/model/docker.test.ts
Linux and Windows Docker commands mount test-standalone-scripts only for test runs. Tests verify the mount paths and build omission behavior.
Windows container test flow
src/command/test/unity-test-command.ts, src/command/test/unity-test-command.test.ts, src/model/host-runner.ts
Windows hosts proceed through Docker test execution, macOS hosts are rejected, and the Windows batchmode flow is tested with the windows-il2cpp image and runTests. Windows script documentation describes the shared test path.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 6dd4c

The PR adds Windows container test execution and related mounting and exit-code handling; no actionable merge-blocking risk remains based on the supplied evidence.

Sequence Diagram(s)

sequenceDiagram
  participant UnityTestCommand
  participant Docker.run
  participant WindowsContainer
  UnityTestCommand->>Docker.run: run windows-il2cpp with runTests
  Docker.run->>WindowsContainer: mount test-standalone-scripts
  WindowsContainer->>WindowsContainer: execute batchmode tests
  WindowsContainer-->>UnityTestCommand: return execution result
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: enabling Docker-based Unity tests on Windows containers.
Description check ✅ Passed The description thoroughly explains the changes, rationale, fixes, implementation approach, tests, and verification results.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 5 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/windows-docker-test-support

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

game-ci/unity-test-runner#310's Linux jobs ran their tests successfully -
the log ends with `<test-run id="2" result="Passed" total="5" passed="5">` -
and the CLI then reported:

    [ERROR] Error: There was an error building the project.
        at validateBuild (...)
        at async executeDocker (...)

validateBuild() scrapes the container log for a "# Build results #"
section, which only a real build ever emits. `game-ci test --docker`
produces NUnit XML instead, so every passing test run was turned into a
build failure.

This is the same defect already fixed for activate-only runs
(game-ci/unity-activate#111) - the guard just never learned about
runTests. Test outcomes are validated from the results XML by the caller,
so there is nothing for validateBuild to do on this path.
@frostebite

Copy link
Copy Markdown
Member Author

Added: a third bug, found by running this against a real matrix

After fixing the stale Unity license on unity-test-runner#310, its Linux jobs got far enough to actually run the tests and pass them:

</test-run><test-run id="2" testcasecount="5" result="Passed" total="5" passed="5" ...

…and the CLI then reported the run as a failure:

[ERROR] Error: There was an error building the project.
    at validateBuild (...)
    at async executeDocker (...)

validateBuild() scrapes the container log for a # Build results # section, which only a real build emits. game-ci test --docker produces NUnit XML instead, so every passing test run was being turned into a build failure.

This is the same defect already fixed for activate-only runs (game-ci/unity-activate#111) — the guard simply never learned about runTests. Test outcomes are validated from the results XML by the caller, so there is nothing for validateBuild to do on this path.

Fixed in 1d51bb8, with a regression test.

Note on rollout

unity-test-runner consumes the released CLI binary (cliVersion: latest → currently v0.1.14), so #310 cannot go green from this PR alone — it needs this merged and a new CLI release cut before the fix reaches it.

@frostebite
frostebite merged commit 8f0a814 into main Aug 24, 2026
22 checks passed
@frostebite
frostebite deleted the feat/windows-docker-test-support branch August 24, 2026 21:35
frostebite added a commit that referenced this pull request Aug 24, 2026
Releases the fixes from #140, which game-ci/unity-test-runner cannot pick
up until a release exists - it downloads the published binary
(cliVersion: latest), so it is still running v0.1.14.

Both of unity-test-runner#310's remaining failure modes are fixed by
this release, and nothing else:

  - Linux: `game-ci test --docker` ran the tests, passed them
    (<test-run result="Passed" total="5" passed="5">), and then failed
    the run anyway - validateBuild() scrapes the log for a
    "# Build results #" section that only a real build emits.

  - Windows: rejected outright by the hostPlatform guard, which existed
    because the container entrypoint.ps1 had no RUN_TESTS branch. It has
    one now, reusing the shared steps/test.ps1.

Also carries the missing /UnityTestRunnerAction mount, without which
--testPlatforms=standalone fails on `cp -R` (on Linux too, not just
Windows).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant