Skip to content

Commit f0aca9e

Browse files
frostebiteclaude
andcommitted
refactor(cli): reorganize commands — add test, alias orchestrate to o, extract shared options
- Add `test` / `t` command mirroring unity-test-runner (EditMode, PlayMode, All, code coverage, test filters) - Add `o` short alias for `orchestrate` command - Extract shared option builders (project, docker, android, orchestrator) to eliminate duplication across build/test/orchestrate - Make `build` local-only — remove --provider-strategy (use `orchestrate` for remote builds) - Absorb `cache` command into `status` (--cache-dir flag) — remove standalone cache command that was half-implemented - Fix `list-worfklow` typo in internal CLI → `list-workflow` - Add test-related fields to CliArguments input mapper - Update all unit and integration tests (64 passing) Command structure is now: game-ci build Local build (Docker/macOS) game-ci test / t Run Unity tests game-ci orchestrate / o Remote build (AWS/K8s/etc) game-ci activate License validation game-ci status Project info + cache status game-ci version Version info game-ci update Self-update Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 664cffa commit f0aca9e

File tree

13 files changed

+632
-582
lines changed

13 files changed

+632
-582
lines changed

dist/index.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cli.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import yargs from 'yargs';
44
// eslint-disable-next-line import/no-unresolved
55
import { hideBin } from 'yargs/helpers';
66
import buildCommand from './cli/commands/build';
7-
import activateCommand from './cli/commands/activate';
7+
import testCommand from './cli/commands/test';
88
import orchestrateCommand from './cli/commands/orchestrate';
9-
import cacheCommand from './cli/commands/cache';
9+
import activateCommand from './cli/commands/activate';
1010
import statusCommand from './cli/commands/status';
1111
import versionCommand from './cli/commands/version';
1212
import updateCommand from './cli/commands/update';
@@ -16,9 +16,9 @@ const cli = yargs(hideBin(process.argv))
1616
.scriptName('game-ci')
1717
.usage('$0 <command> [options]')
1818
.command(buildCommand)
19-
.command(activateCommand)
19+
.command(testCommand)
2020
.command(orchestrateCommand)
21-
.command(cacheCommand)
21+
.command(activateCommand)
2222
.command(statusCommand)
2323
.command(versionCommand)
2424
.command(updateCommand)

src/cli/__tests__/cli-integration.test.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ describe('CLI integration', () => {
3636
expect(result.code).toStrictEqual(0);
3737
expect(result.stdout).toContain('game-ci');
3838
expect(result.stdout).toContain('build');
39-
expect(result.stdout).toContain('activate');
39+
expect(result.stdout).toContain('test');
4040
expect(result.stdout).toContain('orchestrate');
41-
expect(result.stdout).toContain('cache');
41+
expect(result.stdout).toContain('activate');
4242
expect(result.stdout).toContain('status');
4343
expect(result.stdout).toContain('version');
4444
expect(result.stdout).toContain('update');
@@ -62,7 +62,24 @@ describe('CLI integration', () => {
6262
expect(result.stdout).toContain('--builds-path');
6363
expect(result.stdout).toContain('--build-method');
6464
expect(result.stdout).toContain('--custom-parameters');
65-
expect(result.stdout).toContain('--provider-strategy');
65+
expect(result.stdout).toContain('--versioning');
66+
});
67+
68+
it('exits 0 and shows test flags for test --help', async () => {
69+
const result = await runCli(['test', '--help']);
70+
71+
expect(result.code).toStrictEqual(0);
72+
expect(result.stdout).toContain('--target-platform');
73+
expect(result.stdout).toContain('--test-mode');
74+
expect(result.stdout).toContain('--test-results-path');
75+
expect(result.stdout).toContain('--enable-code-coverage');
76+
});
77+
78+
it('exits 0 for test alias t --help', async () => {
79+
const result = await runCli(['t', '--help']);
80+
81+
expect(result.code).toStrictEqual(0);
82+
expect(result.stdout).toContain('--test-mode');
6683
});
6784

6885
it('exits non-zero for an unknown command', async () => {
@@ -85,18 +102,26 @@ describe('CLI integration', () => {
85102
expect(result.stdout).toContain('--provider-strategy');
86103
});
87104

105+
it('exits 0 for orchestrate alias o --help', async () => {
106+
const result = await runCli(['o', '--help']);
107+
108+
expect(result.code).toStrictEqual(0);
109+
expect(result.stdout).toContain('--provider-strategy');
110+
});
111+
88112
it('exits 0 for activate --help', async () => {
89113
const result = await runCli(['activate', '--help']);
90114

91115
expect(result.code).toStrictEqual(0);
92116
expect(result.stdout).toContain('activate');
93117
});
94118

95-
it('exits 0 for cache --help', async () => {
96-
const result = await runCli(['cache', '--help']);
119+
it('exits 0 for status --help', async () => {
120+
const result = await runCli(['status', '--help']);
97121

98122
expect(result.code).toStrictEqual(0);
99-
expect(result.stdout).toContain('cache');
123+
expect(result.stdout).toContain('status');
124+
expect(result.stdout).toContain('--cache-dir');
100125
});
101126

102127
it('exits 0 for update --help', async () => {

src/cli/__tests__/commands.test.ts

Lines changed: 80 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import buildCommand from '../commands/build';
2+
import testCommand from '../commands/test';
23
import activateCommand from '../commands/activate';
34
import orchestrateCommand from '../commands/orchestrate';
4-
import cacheCommand from '../commands/cache';
55
import statusCommand from '../commands/status';
66
import versionCommand from '../commands/version';
77
import updateCommand from '../commands/update';
@@ -54,7 +54,7 @@ describe('CLI commands', () => {
5454

5555
(buildCommand.builder as Function)(yargs);
5656

57-
// Core build flags
57+
// Core build flags (from shared + build-specific)
5858
expect(options['target-platform']).toBeDefined();
5959
expect(options['target-platform'].demandOption).toStrictEqual(true);
6060
expect(options['unity-version']).toBeDefined();
@@ -88,10 +88,10 @@ describe('CLI commands', () => {
8888
expect(options['run-as-host-user']).toBeDefined();
8989
expect(options['chown-files-to']).toBeDefined();
9090

91-
// Provider flags
92-
expect(options['provider-strategy']).toBeDefined();
93-
expect(options['skip-activation']).toBeDefined();
94-
expect(options['unity-licensing-server']).toBeDefined();
91+
// Build should NOT have orchestrator-specific flags
92+
expect(options['provider-strategy']).toBeUndefined();
93+
expect(options['aws-stack-name']).toBeUndefined();
94+
expect(options['kube-config']).toBeUndefined();
9595
});
9696

9797
it('sets correct default values', () => {
@@ -107,7 +107,6 @@ describe('CLI commands', () => {
107107
expect(options['enable-gpu'].default).toStrictEqual(false);
108108
expect(options['android-export-type'].default).toStrictEqual('androidPackage');
109109
expect(options['android-symbol-type'].default).toStrictEqual('none');
110-
expect(options['provider-strategy'].default).toStrictEqual('local');
111110
});
112111

113112
it('provides camelCase aliases for kebab-case options', () => {
@@ -124,6 +123,62 @@ describe('CLI commands', () => {
124123
});
125124
});
126125

126+
describe('test command', () => {
127+
it('exports command with alias', () => {
128+
expect(testCommand.command).toStrictEqual(['test', 't']);
129+
});
130+
131+
it('has a description', () => {
132+
expect(testCommand.describe).toBeTruthy();
133+
});
134+
135+
it('has a builder function', () => {
136+
expect(typeof testCommand.builder).toStrictEqual('function');
137+
});
138+
139+
it('has a handler function', () => {
140+
expect(typeof testCommand.handler).toStrictEqual('function');
141+
});
142+
143+
it('defines test-specific flags', () => {
144+
const { yargs, options } = createFakeYargs();
145+
146+
(testCommand.builder as Function)(yargs);
147+
148+
expect(options['test-mode']).toBeDefined();
149+
expect(options['test-mode'].default).toStrictEqual('All');
150+
expect(options['test-mode'].choices).toStrictEqual(['EditMode', 'PlayMode', 'All']);
151+
expect(options['test-results-path']).toBeDefined();
152+
expect(options['test-category']).toBeDefined();
153+
expect(options['test-filter']).toBeDefined();
154+
expect(options['enable-code-coverage']).toBeDefined();
155+
expect(options['coverage-options']).toBeDefined();
156+
});
157+
158+
it('includes shared project options', () => {
159+
const { yargs, options } = createFakeYargs();
160+
161+
(testCommand.builder as Function)(yargs);
162+
163+
expect(options['target-platform']).toBeDefined();
164+
expect(options['target-platform'].demandOption).toStrictEqual(true);
165+
expect(options['unity-version']).toBeDefined();
166+
expect(options['project-path']).toBeDefined();
167+
expect(options['custom-image']).toBeDefined();
168+
});
169+
170+
it('includes docker options but not orchestrator options', () => {
171+
const { yargs, options } = createFakeYargs();
172+
173+
(testCommand.builder as Function)(yargs);
174+
175+
expect(options['docker-cpu-limit']).toBeDefined();
176+
expect(options['docker-memory-limit']).toBeDefined();
177+
expect(options['provider-strategy']).toBeUndefined();
178+
expect(options['aws-stack-name']).toBeUndefined();
179+
});
180+
});
181+
127182
describe('activate command', () => {
128183
it('exports the correct command name', () => {
129184
expect(activateCommand.command).toStrictEqual('activate');
@@ -143,8 +198,8 @@ describe('CLI commands', () => {
143198
});
144199

145200
describe('orchestrate command', () => {
146-
it('exports the correct command name', () => {
147-
expect(orchestrateCommand.command).toStrictEqual('orchestrate');
201+
it('exports command with alias', () => {
202+
expect(orchestrateCommand.command).toStrictEqual(['orchestrate', 'o']);
148203
});
149204

150205
it('has a description', () => {
@@ -175,23 +230,16 @@ describe('CLI commands', () => {
175230
expect(options['watch-to-end']).toBeDefined();
176231
expect(options['clone-depth']).toBeDefined();
177232
});
178-
});
179-
180-
describe('cache command', () => {
181-
it('exports the correct command name', () => {
182-
expect(cacheCommand.command).toStrictEqual('cache <action>');
183-
});
184233

185-
it('has a description', () => {
186-
expect(cacheCommand.describe).toBeTruthy();
187-
});
234+
it('does not include build-only options', () => {
235+
const { yargs, options } = createFakeYargs();
188236

189-
it('has a builder function', () => {
190-
expect(typeof cacheCommand.builder).toStrictEqual('function');
191-
});
237+
(orchestrateCommand.builder as Function)(yargs);
192238

193-
it('has a handler function', () => {
194-
expect(typeof cacheCommand.handler).toStrictEqual('function');
239+
expect(options['build-profile']).toBeUndefined();
240+
expect(options['manual-exit']).toBeUndefined();
241+
expect(options['enable-gpu']).toBeUndefined();
242+
expect(options['android-version-code']).toBeUndefined();
195243
});
196244
});
197245

@@ -207,6 +255,15 @@ describe('CLI commands', () => {
207255
it('has a handler function', () => {
208256
expect(typeof statusCommand.handler).toStrictEqual('function');
209257
});
258+
259+
it('includes cache-dir option', () => {
260+
const { yargs, options } = createFakeYargs();
261+
262+
(statusCommand.builder as Function)(yargs);
263+
264+
expect(options['cache-dir']).toBeDefined();
265+
expect(options['project-path']).toBeDefined();
266+
});
210267
});
211268

212269
describe('version command', () => {

0 commit comments

Comments
 (0)