Skip to content

fix: Docker.run() ignored engine-supplied commands, breaking Godot/Unreal builds - #61

Merged
frostebite merged 1 commit into
mainfrom
engine-agnostic-docker-commands
Aug 13, 2026
Merged

frostebite merged 1 commit into
mainfrom
engine-agnostic-docker-commands

Conversation

@frostebite

Copy link
Copy Markdown
Member

Bug found while doing cli#51 phase 2/3 cleanup

Docker.run()'s getLinuxCommand/getWindowsCommand never referenced options.commands at all. Every container run always executed Unity's hardcoded /bin/bash /entrypoint.sh (which sources activate.sh/build.sh/return_license.sh — a Unity-license-activation-specific flow), regardless of options.engine.

godot-build-command.ts and unreal-build-command.ts both set commands on the options they pass to Docker.run(), expecting it to control what actually runs in the container (e.g. godot --headless --export-release ... or RunUAT.sh BuildCookRun ...). That value was silently discarded. In practice, game-ci build for Godot/Unreal projects was always running Unity's entrypoint script instead of the engine's real build command.

Fix

Added isUnityDefaultFlow = !commands || engine === 'unity' in both getLinuxCommand and getWindowsCommand:

  • When a non-Unity engine supplies commands, that string is now the actual container invocation.
  • Unity-only volumes/env vars (UNITY_SERIAL, default-build-script, platform steps, entrypoint.sh, unity-config, and on Windows the Visual Studio/registry-keys volumes) are skipped on that path.
  • Default behavior (no commands set, or engine === 'unity') is unchanged — verified via existing + new tests.

Also completes cli#51 phase 2/3 (engine-agnostic boundary cleanup)

  • image-environment-factory.ts no longer hardcodes UNITY_LICENSE/UNITY_SERIAL/ANDROID_*/etc. — those move to new src/logic/unity/environment.ts (UnityEnvironment.getVariables()), passed in as extraVariables only when engine === 'unity'.
  • docker.ts gets these via a small engineEnvVars(options) helper.

Phase 1 was already done via #50. This closes out phases 2 and 3.

Testing

  • Added tests in docker.test.ts covering: commands used verbatim for a non-Unity engine, and Unity's entrypoint still used when engine === 'unity' even if commands happens to be set.
  • Updated docker.test.ts/image-environment-factory.test.ts fixtures to explicitly pass engine: 'unity' / UnityEnvironment.getVariables() now that those vars aren't baked in by default — confirmed this matches how unity-build-command.ts already calls things (env is populated via yargs middleware in src/middleware/engine-detection/index.ts).
  • Full suite: bun test — 105 pass, 0 fail.
  • bun run build — builds clean.

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

…uilds

Bug: getLinuxCommand/getWindowsCommand never referenced options.commands,
so any non-Unity build always ran Unity's hardcoded
/bin/bash /entrypoint.sh (a pure license-activate/build/return-license
flow) instead of the command the Godot/Unreal build commands actually
set. Godot and Unreal builds via `game-ci build` were not running their
intended container command.

Fix adds an isUnityDefaultFlow = !commands || engine === 'unity' guard:
when a non-Unity engine supplies `commands`, that's now what actually
runs in the container, and Unity-only volumes/env vars (UNITY_SERIAL,
default-build-script, platform steps, entrypoint.sh, unity-config) are
skipped for that path.

Also completes cli#51 phase 2/3 (engine-agnostic boundary cleanup):
image-environment-factory.ts no longer hardcodes Unity/Android env vars
directly; they move to the new src/logic/unity/environment.ts and are
passed in as extraVariables, only for engine === 'unity'.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@frostebite, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 3 minutes

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

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 70b1f2d9-1ecc-4f7b-81a8-f0ad4c18e166

📥 Commits

Reviewing files that changed from the base of the PR and between 63d4e10 and c850f5e.

⛔ Files ignored due to path filters (1)
  • dist/index.js is excluded by !**/dist/**
📒 Files selected for processing (5)
  • src/logic/unity/environment.ts
  • src/model/docker.test.ts
  • src/model/docker.ts
  • src/model/image-environment-factory.test.ts
  • src/model/image-environment-factory.ts

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.

@frostebite
frostebite merged commit 99fbe74 into main Aug 13, 2026
8 checks passed
@frostebite
frostebite deleted the engine-agnostic-docker-commands branch August 13, 2026 03:58
frostebite added a commit that referenced this pull request Aug 13, 2026
Severity-1 bug found while auditing cli's build scripts against
unity-builder's real source (via unity-engine-core) for other
divergence, after finding and fixing the Docker `commands`-ignored
bug in #61.

MacBuilder.run() invoked entrypoint.sh via System.run() but never
converted any parsed option (--unity-serial, --project-path,
--target-platform, --build-name, licensing, Android signing, etc.)
into an environment variable. System.run()'s underlying spawn() call
had no `env` override at all, so it fell back to inheriting the cli
process's own environment - meaning `game-ci build` on macOS only
worked at all if a user separately, manually exported every setting
as a real shell env var outside of cli's own flags, silently ignoring
everything passed via CLI options.

Also found while confirming this: mac's entrypoint.sh/build.sh
reference $ACTION_FOLDER and $GITHUB_WORKSPACE, neither of which
ImageEnvironmentFactory produces (Docker builds get these via
explicit --env flags and volume-mount remapping instead) - added
both directly from options.cliDistPath/options.currentWorkDir.

And: mac's activate.sh had no Unity Licensing Server (floating
license) branch at all - UNITY_LICENSING_SERVER was silently ignored
and activation always attempted (likely empty) serial mode instead.
Linux and Windows already had this; ported the same structure real
unity-builder uses on mac.

Fix:
- System.run()'s RunOptions gains an `env` field, merged on top of
  the current process env when spawning.
- MacBuilder.run() now builds a full env var map from options (reusing
  the same ImageEnvironmentFactory/UnityEnvironment construction
  Docker builds already use and trust) and passes it through.
- mac activate.sh gets the missing UNITY_LICENSING_SERVER branch.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
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