Skip to content

fix: restore remote-cli-pre-build/log-stream/post-build after the -m CliFunction dispatcher was retired - #148

Merged
frostebite merged 2 commits into
mainfrom
fix/restore-remote-cli-subcommands
Aug 25, 2026
Merged

frostebite merged 2 commits into
mainfrom
fix/restore-remote-cli-subcommands

Conversation

@frostebite

@frostebite frostebite commented Aug 25, 2026 •

Copy link
Copy Markdown
Member

The bug

Every remote (AWS/K8s) orchestrator build has been broken on main for at least 2+ days (confirmed back to Aug 22). Integration Tests fails identically across the last 6+ runs, and only on AWS Provider Tests/K8s Provider Tests/Local Docker Provider Tests — not the MockAWS/Rclone jobs. I traced this independently, and a fresh audit agent (no shared context) converged on the exact same root cause from a different angle.

It is not a MiniStack flake — MiniStack starts and the S3 bucket creates successfully in every failing run (make_bucket: game-ci-team-pipelines). The real failure:

[WARN] Unknown argument: m
Build failed with exit code 1

[WARN] is game-ci/cli's own logger format (src/core/logger/index.ts), and Cli.handleFailure does exactly log.warning(message); process.exit(1) on any yargs failure — this is that failure, not some unrelated tool.

Root cause

build-automation-workflow.ts invokes node ${builderPath} -m remote-cli-pre-build (and 7 more call sites for -m remote-cli-log-stream / -m remote-cli-post-build) for every non-local-docker provider. -m <name> is a legacy dispatch protocol: a @CliFunction(name, ...) decorator registers a static method with CliFunctionsRepository, which some other file used to read process.argv's -m value and invoke the matching one.

That dispatcher is gone. CliFunctionsRepository is explicitly a "Bridge file — stub" that only stores registrations — nothing calls GetCliFunctions() against -m anywhere. This package's own bin entry (src/cli.ts) was independently rewritten to yargs subcommands too, with no -m support either.

start.sh runs under set -e, so this isn't a swallowed warning — it kills the entire remote build.

Why this needed real commands, not a deletion

remote-cli-pre-build isn't diagnostic-only: RemoteClient.setupRemoteClient() bootstraps the actual git workspace (full clone, incremental sync, or retained-workspace reuse) and runs before-build hooks — build-critical. remote-cli-post-build pushes the Library/Build caches. remote-cli-log-stream pipes build output into a log file (and, on K8s, echoes it to stdout for kubectl logs).

Fix

Three real yargs commands, matching this package's own existing command-per-file convention under cli/commands/, registered in src/cli.ts. All 9 call sites in build-automation-workflow.ts updated from -m <name> to the plain positional command. Each handler reads entirely from the environment via mapCliArgumentsToInput + BuildParameters.create() — the original bare invocations took no CLI flags at all (remote-cli-log-stream's one exception, --logFile, is preserved as a real yargs option).

A second bug found while verifying this under bun (not just tsc)

Three files imported SyncState/SyncStrategy (type-only exports) as regular values instead of import type: services/sync/index.ts, services/sync/sync-state-manager.ts, services/sync/incremental-sync-service.ts, and remote-client/index.ts itself. tsc erases type-only imports at compile time and never catches this; bun's isolated-module transpiler does not, and threw SyntaxError: export 'SyncStrategy' not found the moment these modules first actually loaded. This was a real, pre-existing latent bug — nothing in the old CLI's dependency graph ever loaded remote-client/index.ts, so it never surfaced until this fix made these modules load for the first time.

Verification

  • game-ci --help lists all three commands.
  • Invoking remote-cli-pre-build directly no longer hits Unknown argument: m and proceeds into real setup logic — reaches a genuine mkdir -p /data, which only fails here because this is a Windows dev sandbox, not the Linux container the code assumes (expected, not a bug).
  • tsc --noEmit clean.
  • 144 tests passing across the touched areas: 12 new command tests, plus the existing build-automation-workflow, sync, and mock-aws suites — the closest thing to the AWS integration path this environment can exercise without real AWS/Docker.
  • Full suite: same 2 pre-existing, unrelated flakes as before this change (cli-integration timing out under parallel load — passes 9/9 in isolation — and orchestrator-rclone-steps, which fails identically on a clean main checkout).

I don't have Docker/real AWS/K8s access in this environment, so I could not run the actual Integration Tests workflow end-to-end. Everything short of that has been verified directly.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added commands to initialize remote builds, stream build logs, and complete post-build processing.
    • Remote log streaming now requires a log-file path for reliable output collection.
  • Improvements

    • Updated build workflows to use the streamlined command format across supported execution environments.
    • Remote build initialization and post-build cache processing now run through dedicated commands.
  • Documentation

    • Updated command usage guidance to reflect the new invocation format.

…CliFunction dispatcher was retired

Every remote (AWS/K8s) orchestrator build has been broken since this
package's own CLI entrypoint (src/cli.ts) was rewritten to yargs -
confirmed independently by both my own trace and a fresh audit agent's,
converging on the same root cause from different angles.

Root cause, traced end to end:

  1. Integration Tests on main fail identically across the last 6+ runs
     (Aug 22-25), on AWS/K8s/Local Docker Provider Tests specifically -
     not the MockAWS/Rclone jobs, and not a MiniStack pull/readiness
     failure (MiniStack starts and the S3 bucket creates successfully in
     every failing run).
  2. The real failure: `[WARN] Unknown argument: m` immediately precedes
     `Build failed with exit code 1`. `[WARN]` is game-ci/cli's own
     logger format (src/core/logger/index.ts), and Cli.handleFailure
     (src/cli.ts) does exactly `log.warning(message); process.exit(1)`
     on any yargs failure - this is that failure, not a random tool.
  3. build-automation-workflow.ts invokes
     `node ${builderPath} -m remote-cli-pre-build` (and, at 7 more call
     sites, `-m remote-cli-log-stream` / `-m remote-cli-post-build`) for
     every non-local-docker provider. `-m <name>` is a legacy dispatch
     protocol: a `@CliFunction(name, ...)` decorator registers a static
     method with CliFunctionsRepository, which some *other* file used to
     read process.argv's `-m` value and invoke the matching one.
  4. That dispatcher is gone. CliFunctionsRepository
     (model/cli/cli-functions-repository.ts) is explicitly a "Bridge
     file - stub" that only stores registrations - nothing calls
     GetCliFunctions() against `-m` anywhere. This package's own bin
     entry (src/cli.ts, "game-ci": "./dist/cli.js") was independently
     rewritten to yargs subcommands too, with no `-m` support either.
  5. start.sh (docker/index.ts) runs under `set -e`, so this isn't a
     swallowed warning - it's fatal to the entire remote build.

remote-cli-pre-build isn't diagnostic-only, so simply deleting the call
site was never on the table: RemoteClient.setupRemoteClient() bootstraps
the actual git workspace (full clone, incremental sync, or
retained-workspace reuse) and runs before-build hooks - build-critical.
remote-cli-post-build pushes the Library/Build caches. remote-cli-log-stream
pipes build output into a log file (and, on K8s, echoes it to stdout for
kubectl logs).

Fix: three real yargs commands (matching this package's own existing
command-per-file convention under cli/commands/), registered in
src/cli.ts, replacing the `-m <name>` flag at all 9 call sites in
build-automation-workflow.ts with the plain positional command. Each
handler reads entirely from the environment via mapCliArgumentsToInput +
BuildParameters.create() - the original invocations took no CLI flags at
all (remote-cli-log-stream's one exception, --logFile, is preserved as a
real yargs option).

Also fixed, found while making the new commands' import chain actually
load under bun (not just tsc, which erases type-only imports at compile
time and never surfaces this): three files imported SyncState/SyncStrategy
(type-only exports) as regular values instead of `import type` -
services/sync/index.ts, services/sync/sync-state-manager.ts,
services/sync/incremental-sync-service.ts, and remote-client/index.ts
itself. This was a real, if previously dormant, bug - nothing in the old
CLI's dependency graph ever loaded remote-client/index.ts, so it never
surfaced until this fix made these modules load for the first time.

Verified: `game-ci --help` now lists all three commands; invoking
`remote-cli-pre-build` directly no longer hits "Unknown argument: m" and
proceeds into real setup logic (reaches a real `mkdir -p /data`, which
only fails here because this is a Windows dev sandbox, not the Linux
container the code assumes - expected, not a bug). tsc --noEmit clean.
144 tests passing across the touched areas (12 new command tests, plus
existing build-automation-workflow, sync, and mock-aws suites - the
closest thing to the AWS integration path this environment can exercise
without real AWS/Docker). Full suite: same 2 pre-existing, unrelated
flakes as before this change (cli-integration timing out under parallel
load - passes 9/9 in isolation - and orchestrator-rclone-steps, which
fails identically on a clean main checkout).
@coderabbitai

coderabbitai Bot commented Aug 25, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 48 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: 966fb148-c35d-4a30-84bc-e94a5675e1d4

📥 Commits

Reviewing files that changed from the base of the PR and between 56393a9 and 860097c.

📒 Files selected for processing (1)
  • plugins/orchestrator/src/cli/__tests__/cli-integration.test.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: 330dd2a9-a504-429a-8efe-04f8f82166c3

📥 Commits

Reviewing files that changed from the base of the PR and between 89b72dd and 56393a9.

📒 Files selected for processing (11)
  • plugins/orchestrator/src/cli.ts
  • plugins/orchestrator/src/cli/__tests__/commands.test.ts
  • plugins/orchestrator/src/cli/commands/remote-cli-log-stream.ts
  • plugins/orchestrator/src/cli/commands/remote-cli-post-build.ts
  • plugins/orchestrator/src/cli/commands/remote-cli-pre-build.ts
  • plugins/orchestrator/src/model/orchestrator/providers/local/index.ts
  • plugins/orchestrator/src/model/orchestrator/remote-client/index.ts
  • plugins/orchestrator/src/model/orchestrator/services/sync/incremental-sync-service.ts
  • plugins/orchestrator/src/model/orchestrator/services/sync/index.ts
  • plugins/orchestrator/src/model/orchestrator/services/sync/sync-state-manager.ts
  • plugins/orchestrator/src/model/orchestrator/workflows/build-automation-workflow.ts

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


📝 Walkthrough

Walkthrough

Changes

Remote CLI command flow

Layer / File(s) Summary
Remote command implementations
plugins/orchestrator/src/cli/commands/remote-cli-*.ts
Adds pre-build, log-stream, and post-build yargs commands. The log-stream command requires a log file.
CLI registration and command validation
plugins/orchestrator/src/cli.ts, plugins/orchestrator/src/cli/__tests__/commands.test.ts
Registers the commands and tests their metadata, handlers, and options.
Workflow invocation migration
plugins/orchestrator/src/model/orchestrator/workflows/build-automation-workflow.ts, plugins/orchestrator/src/model/orchestrator/providers/local/index.ts
Replaces -m dispatch with direct command invocation across build workflows and documentation.

Type-only sync imports

Layer / File(s) Summary
Sync type boundaries
plugins/orchestrator/src/model/orchestrator/remote-client/index.ts, plugins/orchestrator/src/model/orchestrator/services/sync/*
Converts SyncState and SyncStrategy imports and re-exports to type-only forms.

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

Merge Risk: ⚪ Minimal · up to 56393

The change restores the remote build commands without introducing an actionable merge-blocking risk; it is merge-ready after normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant BuildWorkflow
  participant RemoteCLI
  participant RemoteClient
  BuildWorkflow->>RemoteCLI: invoke remote-cli-pre-build
  RemoteCLI->>RemoteClient: initialize before engine build
  BuildWorkflow->>RemoteCLI: invoke remote-cli-log-stream with log file
  RemoteCLI->>RemoteClient: stream remote build output
  BuildWorkflow->>RemoteCLI: invoke remote-cli-post-build
  RemoteCLI->>RemoteClient: push post-build cache
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 11 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the restoration of the three remote CLI commands after the legacy -m dispatcher was retired. It accurately summarizes the primary change.
Description check ✅ Passed The description provides detailed bug context, root cause, implementation details, verification results, and test limitations. It does not use the exact Changes and Checklist headings, but it includes…
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.
Full details: Description check

Explanation

The description provides detailed bug context, root cause, implementation details, verification results, and test limitations. It does not use the exact Changes and Checklist headings, but it includes the required information in equivalent sections.

✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/restore-remote-cli-subcommands

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.

This suite has been the sole cause of flaky Integration Test failures on
several PRs today (#144, #147, and this one) - always the same signature,
just landing on a different parallel shard each run:

    FAIL src/cli/__tests__/cli-integration.test.ts > ... > exits 0 ...
    Error: Test timed out in 5000ms.

Root cause: every test spawns a real
`node --require ts-node/register/transpile-only` process to exercise the
actual CLI end to end - genuinely slow (full TS transpilation plus this
package's whole dependency graph), slower still under CI's parallel
test-shard contention. runCli()'s own execFile call already allows up to
60s for that child process. But vitest's *test*-level timeout defaults to
5000ms regardless of what the child process itself is allowed - so the
wrapping `it()` was timing out long before the process's real budget was
ever exhausted. A stale comment ("Per-test timeout configured via vitest
options at the file/describe level") describbrowsed an intent that was
never actually implemented.

Fix: describe(..., { timeout: 30_000 }, ...) applies a realistic
per-suite default. Verified the option is genuinely honored, not silently
ignored, by temporarily setting it to 1ms - all 9 tests failed instantly
(583ms total vs the normal ~30s), confirming this actually controls
vitest's timeout rather than being dead configuration. 30s comfortably
covers real CI contention without masking an actual hang, which would
still exceed it.

Passes reliably now; typecheck clean.
@frostebite
frostebite merged commit f7694e7 into main Aug 25, 2026
23 checks passed
@frostebite
frostebite deleted the fix/restore-remote-cli-subcommands branch August 25, 2026 10:45
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