@rage-against-the-pixel/unity-cli 3.0.2 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +86 -224
  2. package/dist/android-sdk.js +8 -1
  3. package/dist/android-sdk.js.map +1 -1
  4. package/dist/cli.js +180 -505
  5. package/dist/cli.js.map +1 -1
  6. package/dist/failure-markers.d.ts +17 -0
  7. package/dist/failure-markers.js +46 -0
  8. package/dist/failure-markers.js.map +1 -0
  9. package/dist/github-actions-ci.d.ts +1 -0
  10. package/dist/github-actions-ci.js +17 -3
  11. package/dist/github-actions-ci.js.map +1 -1
  12. package/dist/index.d.ts +2 -2
  13. package/dist/index.js +2 -2
  14. package/dist/index.js.map +1 -1
  15. package/dist/license-client.d.ts +113 -2
  16. package/dist/license-client.js +715 -54
  17. package/dist/license-client.js.map +1 -1
  18. package/dist/logger-provider.d.ts +2 -0
  19. package/dist/logger-provider.js +3 -0
  20. package/dist/logger-provider.js.map +1 -1
  21. package/dist/logging.d.ts +5 -0
  22. package/dist/logging.js +47 -0
  23. package/dist/logging.js.map +1 -1
  24. package/dist/process-tracker.d.ts +71 -0
  25. package/dist/process-tracker.js +213 -0
  26. package/dist/process-tracker.js.map +1 -0
  27. package/dist/unity-cli.d.ts +97 -0
  28. package/dist/unity-cli.js +587 -0
  29. package/dist/unity-cli.js.map +1 -0
  30. package/dist/unity-editor.d.ts +25 -16
  31. package/dist/unity-editor.js +204 -107
  32. package/dist/unity-editor.js.map +1 -1
  33. package/dist/unity-installer.d.ts +134 -0
  34. package/dist/unity-installer.js +963 -0
  35. package/dist/unity-installer.js.map +1 -0
  36. package/dist/unity-logging.d.ts +16 -1
  37. package/dist/unity-logging.js +55 -3
  38. package/dist/unity-logging.js.map +1 -1
  39. package/dist/unity-project.d.ts +15 -0
  40. package/dist/unity-project.js +80 -0
  41. package/dist/unity-project.js.map +1 -1
  42. package/dist/upm-cli.d.ts +8 -8
  43. package/dist/upm-cli.js +8 -8
  44. package/dist/upm-cli.js.map +1 -1
  45. package/dist/utilities.d.ts +27 -7
  46. package/dist/utilities.js +119 -63
  47. package/dist/utilities.js.map +1 -1
  48. package/package.json +10 -11
  49. package/dist/unity-hub.d.ts +0 -140
  50. package/dist/unity-hub.js +0 -1425
  51. package/dist/unity-hub.js.map +0 -1
package/dist/cli.js CHANGED
@@ -40,101 +40,33 @@ Object.defineProperty(exports, "__esModule", { value: true });
40
40
  require("source-map-support/register");
41
41
  const fs = __importStar(require("fs"));
42
42
  const os = __importStar(require("os"));
43
- const tar = __importStar(require("tar"));
44
43
  const path = __importStar(require("path"));
45
44
  const commander_1 = require("commander");
46
- const unity_hub_1 = require("./unity-hub");
47
- const unity_editor_1 = require("./unity-editor");
48
45
  const update_notifier_1 = __importDefault(require("update-notifier"));
49
46
  const logging_1 = require("./logging");
47
+ const unity_cli_1 = require("./unity-cli");
48
+ const unity_editor_1 = require("./unity-editor");
49
+ const unity_installer_1 = require("./unity-installer");
50
50
  const unity_version_1 = require("./unity-version");
51
51
  const unity_project_1 = require("./unity-project");
52
- const child_process_1 = require("child_process");
53
52
  const android_sdk_1 = require("./android-sdk");
54
53
  const license_client_1 = require("./license-client");
55
54
  const utilities_1 = require("./utilities");
56
55
  const upm_cli_1 = require("./upm-cli");
56
+ const failure_markers_1 = require("./failure-markers");
57
57
  const pkgPath = path.join(__dirname, '..', 'package.json');
58
58
  const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
59
59
  (0, update_notifier_1.default)({ pkg }).notify();
60
60
  const program = new commander_1.Command();
61
61
  program.name('unity-cli')
62
- .description('A powerful all-in-one command line utility for the Unity Game Engine.')
63
- .version(pkg.version);
64
- program.command('install-all-tools')
65
- .description('Install the Unity Hub and the Unity Package Manager cli (pack/sign). Runs hub-install and upm-install in parallel.')
66
- .option('--verbose', 'Enable verbose logging.')
67
- .option('--auto-update', 'If any tools are installed, they\'re automatically updated to the latest versions. Cannot be used with --hub-version or --upm-version.')
68
- .option('--hub-version <version>', 'Specify to install a specific version of Unity Hub. Cannot be used with --auto-update.')
69
- .option('--upm-version <version>', 'Specify to install a specific version of the Unity Package Manager cli. Cannot be used with --auto-update.')
70
- .option('--json', 'Print hub path, UPM CLI version, and resolved UPM CLI path as JSON.')
71
- .action(async (options) => {
72
- if (options.verbose) {
73
- logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
74
- }
75
- logging_1.Logger.instance.debugOptions(options);
76
- if (options.autoUpdate === true && options.hubVersion) {
77
- logging_1.Logger.instance.error('Cannot use --auto-update with --hub-version.');
78
- process.exit(1);
79
- }
80
- if (options.autoUpdate === true && options.upmVersion) {
81
- logging_1.Logger.instance.error('Cannot use --auto-update with --upm-version.');
82
- process.exit(1);
83
- }
84
- try {
85
- const unityHub = new unity_hub_1.UnityHub();
86
- const upm = new upm_cli_1.UpmCli();
87
- let upmRequestedVersion = options.upmVersion?.toString()?.trim();
88
- if (options.autoUpdate === true) {
89
- const currentVersion = upm.GetInstalledReleaseTag();
90
- const latestVersion = await upm.GetLatestReleaseTag();
91
- if (currentVersion && !upm.IsUpdateAvailable(latestVersion)) {
92
- logging_1.Logger.instance.info(`Upm cli is already up to date (${currentVersion}).`);
93
- upmRequestedVersion = currentVersion;
94
- }
95
- else {
96
- if (currentVersion) {
97
- logging_1.Logger.instance.info(`Updating upm cli ${currentVersion} -> ${latestVersion}...`);
98
- }
99
- upmRequestedVersion = latestVersion;
100
- }
101
- }
102
- const [hubPath, upmVer] = await Promise.all([
103
- unityHub.Install(options.autoUpdate === true, options.hubVersion),
104
- upm.Install({
105
- version: upmRequestedVersion,
106
- skipIfInstalled: true
107
- }),
108
- ]);
109
- logging_1.Logger.instance.CI_setEnvironmentVariable('UNITY_HUB_PATH', hubPath);
110
- let upmCliPath;
111
- try {
112
- await upm.Version(upmVer);
113
- upmCliPath = upm.executable;
114
- }
115
- catch (verifyError) {
116
- logging_1.Logger.instance.warn(`Upm cli version check failed after install: ${verifyError}`);
117
- if (process.env.CI === 'true') {
118
- logging_1.Logger.instance.error('Failing in CI because the installed UPM CLI did not match the expected release.');
119
- process.exit(1);
120
- }
121
- upmCliPath = upm.ResolveManagedPrimaryPath();
122
- }
123
- if (options.json) {
124
- process.stdout.write(`\n${JSON.stringify({
125
- UNITY_HUB_PATH: hubPath,
126
- UPM_VERSION: upmVer,
127
- UPM_CLI_PATH: upmCliPath,
128
- })}\n`);
129
- }
130
- else {
131
- process.stdout.write(`Unity Hub: ${hubPath}\nUpm cli: ${upmVer}\n${upmCliPath ?? ''}\n`);
132
- }
133
- process.exit(0);
134
- }
135
- catch (error) {
136
- logging_1.Logger.instance.error(`${error}`);
137
- process.exit(1);
62
+ .description('Bridges the gaps in the official Unity CLI (unity) for CI: Unity ID licensing, Unity 4.x and 5.x editors, Android SDK setup and Editor log annotations.')
63
+ .version(pkg.version)
64
+ .option('--unity-cli-version <version>', 'The official Unity CLI version to use (e.g. 1.0.0-beta.14). Defaults to the UNITY_CLI_VERSION environment variable, then the latest release. Commands install it on first use.')
65
+ .hook('preAction', (command) => {
66
+ const version = command.opts().unityCliVersion?.toString()?.trim();
67
+ if (version) {
68
+ // every command resolves the official CLI through UnityCli.Get(), which reads the request from here
69
+ process.env.UNITY_CLI_VERSION = version;
138
70
  }
139
71
  });
140
72
  program.commandsGroup('Auth:');
@@ -146,51 +78,49 @@ program.command('license-version')
146
78
  process.exit(0);
147
79
  });
148
80
  program.command('activate-license')
149
- .description('Activate a Unity license.')
81
+ .description('Activate a Unity license. Tries the official Unity CLI first, then the Unity Licensing Client with your Unity ID email and password.')
150
82
  .option('-l, --license <license>', 'License type (personal, professional, floating). Required.')
151
- .option('-e, --email <email>', 'Email associated with the Unity account. Required when activating a personal or professional license.')
152
- .option('-p, --password <password>', 'Password for the Unity account. Required when activating a personal or professional license.')
153
- .option('-s, --serial <serial>', 'License serial number. Required when activating a professional license.')
83
+ .option('-e, --email <email>', 'Email associated with the Unity account. Used when the Unity CLI cannot activate a personal or professional license. Defaults to the UNITY_USERNAME environment variable.')
84
+ .option('-p, --password <password>', 'Password for the Unity account. Used when the Unity CLI cannot activate a personal or professional license. Defaults to the UNITY_PASSWORD environment variable, which keeps it off the command line.')
85
+ .option('-s, --serial <serial>', 'License serial number. Required when activating a professional license. Defaults to the UNITY_SERIAL environment variable.')
154
86
  .option('-c, --config <config>', 'Path to the configuration file, raw JSON, or base64 encoded JSON string. Required when activating a floating license.')
87
+ .option('-f, --license-file <licenseFile>', 'A cached license file (Unity_lic.ulf) from an earlier activation on a machine with the same identity: a path, the raw XML, or base64. Defaults to the UNITY_LICENSE environment variable. Falls back to the email and password when it cannot be used.')
155
88
  .option('--verbose', 'Enable verbose logging.')
156
89
  .option('--json', 'Prints the last line of output as JSON string.')
157
90
  .action(async (options) => {
158
91
  if (options.verbose) {
159
92
  logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
160
93
  }
94
+ // environment variables keep credentials out of the process command line
95
+ options.email ??= process.env.UNITY_USERNAME || undefined;
96
+ options.password ??= process.env.UNITY_PASSWORD || undefined;
97
+ options.serial ??= process.env.UNITY_SERIAL || undefined;
98
+ // Mask credentials in CI environments before any potential logging
99
+ logging_1.Logger.instance.maskCredential(options.email);
100
+ logging_1.Logger.instance.maskCredential(options.password);
101
+ logging_1.Logger.instance.maskCredential(options.serial);
161
102
  logging_1.Logger.instance.debugOptions(options);
162
- const client = new license_client_1.LicensingClient();
163
103
  const licenseStr = options.license?.toString()?.trim();
164
104
  if (!licenseStr || licenseStr.length === 0) {
165
105
  logging_1.Logger.instance.error('License type is required. Use -l or --license to specify it.');
166
106
  process.exit(1);
167
107
  }
168
- const licenseType = options.license.toLowerCase();
108
+ const licenseType = licenseStr.toLowerCase();
169
109
  if (![license_client_1.LicenseType.personal, license_client_1.LicenseType.professional, license_client_1.LicenseType.floating].includes(licenseType)) {
170
110
  logging_1.Logger.instance.error(`Invalid license type: ${licenseType}`);
171
111
  process.exit(1);
172
112
  }
173
- if (licenseType !== license_client_1.LicenseType.floating) {
174
- if (!options.email) {
175
- options.email = await (0, utilities_1.PromptForSecretInput)('Email: ');
176
- }
177
- if (!options.password) {
178
- options.password = await (0, utilities_1.PromptForSecretInput)('Password: ');
179
- }
180
- if (licenseType === license_client_1.LicenseType.professional && !options.serial) {
181
- options.serial = await (0, utilities_1.PromptForSecretInput)('Serial: ');
182
- }
183
- // Mask credentials in CI environments before any potential logging
184
- logging_1.Logger.instance.maskCredential(options.email);
185
- logging_1.Logger.instance.maskCredential(options.password);
113
+ if (licenseType === license_client_1.LicenseType.professional && !options.serial) {
114
+ options.serial = await (0, utilities_1.PromptForSecretInput)('Serial: ');
186
115
  logging_1.Logger.instance.maskCredential(options.serial);
187
116
  }
188
- const token = await client.Activate({
117
+ const token = await (0, license_client_1.ActivateLicense)({
189
118
  licenseType,
190
119
  servicesConfig: options.config,
191
120
  serial: options.serial,
192
121
  username: options.email,
193
- password: options.password
122
+ password: options.password,
123
+ ...(options.licenseFile ? { licenseFile: options.licenseFile } : {}),
194
124
  });
195
125
  if (licenseType === license_client_1.LicenseType.floating && token && options.json) {
196
126
  process.stdout.write(`\n${JSON.stringify({ token: token })}\n`);
@@ -198,16 +128,24 @@ program.command('activate-license')
198
128
  process.exit(0);
199
129
  });
200
130
  program.command('return-license')
201
- .description('Return a Unity license.')
131
+ .description('Return a Unity license. Tries the official Unity CLI first, then the Unity Licensing Client.')
202
132
  .option('-l, --license <license>', 'License type (personal, professional, floating)')
203
- .option('-t, --token <token>', 'Floating license token. Required when returning a floating license.')
133
+ .option('-t, --token <token>', 'Floating license token from activation. When given, the floating license is returned with the Unity Licensing Client.')
134
+ .option('--when <when>', 'auto, always or never. auto skips returning a personal or professional license on GitHub-hosted macOS and Linux runners, which share one machine identity: a return there revokes the license for every job and repo on that identity. Defaults to auto.', 'auto')
204
135
  .option('--verbose', 'Enable verbose logging.')
205
136
  .action(async (options) => {
206
137
  if (options.verbose) {
207
138
  logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
208
139
  }
140
+ const when = options.when?.toString()?.trim().toLowerCase();
141
+ if (!['auto', 'always', 'never'].includes(when)) {
142
+ logging_1.Logger.instance.error(`Invalid --when value: ${when}. Expected auto, always or never.`);
143
+ process.exit(1);
144
+ }
145
+ const token = options.token?.toString()?.trim() || undefined;
146
+ // Mask token in CI environments before any potential logging
147
+ logging_1.Logger.instance.maskCredential(token);
209
148
  logging_1.Logger.instance.debugOptions(options);
210
- const client = new license_client_1.LicensingClient();
211
149
  const licenseStr = options.license?.toString()?.trim();
212
150
  if (!licenseStr || licenseStr.length === 0) {
213
151
  logging_1.Logger.instance.error('License type is required. Use -l or --license to specify it.');
@@ -218,26 +156,19 @@ program.command('return-license')
218
156
  logging_1.Logger.instance.error(`Invalid license type: ${licenseType}`);
219
157
  process.exit(1);
220
158
  }
221
- let token = options.token;
222
- if (licenseType === license_client_1.LicenseType.floating) {
223
- if (!token || token.length === 0) {
224
- token = await (0, utilities_1.PromptForSecretInput)('Token: ');
225
- }
226
- if (!token || token.length === 0) {
227
- logging_1.Logger.instance.error('Token is required when returning a floating license. Use -t or --token to specify it.');
228
- process.exit(1);
229
- }
230
- // Mask token in CI environments before any potential logging
231
- logging_1.Logger.instance.maskCredential(token);
232
- }
233
- await client.Deactivate(licenseType, token);
159
+ await (0, license_client_1.ReturnLicense)(licenseType, token, when);
234
160
  process.exit(0);
235
161
  });
236
162
  program.command('license-context')
237
- .description('Print the current license context information.')
163
+ .description('Print the current license state from the Unity CLI and the Unity Licensing Client.')
238
164
  .action(async () => {
239
- const client = new license_client_1.LicensingClient();
240
- await client.Context();
165
+ await (0, license_client_1.PrintLicenseContext)();
166
+ process.exit(0);
167
+ });
168
+ program.command('license-file-path')
169
+ .description('Prints the path to the machine\'s Unity license file (Unity_lic.ulf).')
170
+ .action(async () => {
171
+ process.stdout.write(`${(0, license_client_1.GetLicenseFilePath)()}\n`);
241
172
  process.exit(0);
242
173
  });
243
174
  program.command('licensing-client-logs')
@@ -252,94 +183,9 @@ program.command('licensing-audit-logs')
252
183
  process.stdout.write(`${license_client_1.LicensingClient.ClientAuditLogPath()}\n`);
253
184
  process.exit(0);
254
185
  });
255
- program.commandsGroup('Unity Hub:');
256
- program.command('hub-version')
257
- .description('Print the Unity Hub version.')
258
- .action(async () => {
259
- const unityHub = new unity_hub_1.UnityHub();
260
- try {
261
- const version = await unityHub.Version();
262
- process.stdout.write(`${version}\n`);
263
- }
264
- catch (error) {
265
- process.stdout.write(`${error}\n`);
266
- }
267
- finally {
268
- process.exit(0);
269
- }
270
- });
271
- program.command('hub-path')
272
- .description('Print the path to the Unity Hub executable.')
273
- .option('--json', 'Prints the last line of output as JSON string.')
274
- .action(async (options) => {
275
- const hub = new unity_hub_1.UnityHub();
276
- logging_1.Logger.instance.CI_setEnvironmentVariable('UNITY_HUB_PATH', hub.executable);
277
- if (options.json) {
278
- process.stdout.write(`\n${JSON.stringify({ UNITY_HUB_PATH: hub.executable })}\n`);
279
- }
280
- else {
281
- process.stdout.write(`${hub.executable}\n`);
282
- }
283
- process.exit(0);
284
- });
285
- program.command('hub-logs')
286
- .description('Prints the path to the Unity Hub log file.')
287
- .action(async () => {
288
- process.stdout.write(`${unity_hub_1.UnityHub.LogPath()}\n`);
289
- process.exit(0);
290
- });
291
- program.command('package-manager-logs')
292
- .description('Prints the path to the Unity Package Manager log file.')
293
- .action(async () => {
294
- process.stdout.write(`${unity_hub_1.UnityHub.PackageManagerLogsPath()}\n`);
295
- process.exit(0);
296
- });
297
- program.command('hub-install')
298
- .description('Install or update the Unity Hub.')
299
- .option('--verbose', 'Enable verbose logging.')
300
- .option('--auto-update', 'Automatically updates the Unity Hub if it is already installed. Cannot be used with --hub-version.')
301
- .option('--hub-version <version>', 'Specify to install a specific version of Unity Hub. Cannot be used with --auto-update.')
302
- .option('--json', 'Prints the last line of output as JSON string.')
303
- .action(async (options) => {
304
- if (options.verbose) {
305
- logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
306
- }
307
- logging_1.Logger.instance.debugOptions(options);
308
- if (options.autoUpdate === true && options.hubVersion) {
309
- logging_1.Logger.instance.error('Cannot use --auto-update with --hub-version.');
310
- process.exit(1);
311
- }
312
- const unityHub = new unity_hub_1.UnityHub();
313
- const hubPath = await unityHub.Install(options.autoUpdate === true, options.hubVersion);
314
- logging_1.Logger.instance.CI_setEnvironmentVariable('UNITY_HUB_PATH', hubPath);
315
- if (options.json) {
316
- process.stdout.write(`\n${JSON.stringify({ UNITY_HUB_PATH: hubPath })}\n`);
317
- }
318
- else {
319
- process.stdout.write(`${hubPath}\n`);
320
- }
321
- process.exit(0);
322
- });
323
- program.command('hub')
324
- .description('Run commands directly to the Unity Hub. (You need not to pass --headless or -- to this command).')
325
- .option('--verbose', 'Enable verbose logging.')
326
- .option('--json', 'Prints the last line of output as a json string, which contains the operation results.')
327
- .allowUnknownOption(true)
328
- .argument('<args...>', 'Arguments to pass to the Unity Hub executable.')
329
- .action(async (args, options) => {
330
- if (options.verbose) {
331
- logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
332
- }
333
- logging_1.Logger.instance.debugOptions({ args, options });
334
- const unityHub = new unity_hub_1.UnityHub();
335
- const output = await unityHub.Exec(args, { silent: false, showCommand: logging_1.Logger.instance.logLevel === logging_1.LogLevel.DEBUG });
336
- if (options.json) {
337
- process.stdout.write(`\n${JSON.stringify({ output })}\n`);
338
- }
339
- process.exit(0);
340
- });
186
+ program.commandsGroup('Unity Editor:');
341
187
  program.command('setup-unity')
342
- .description('Find or install the Unity Editor for a project or specific version.')
188
+ .description('Find or install the Unity Editor for a project or specific version. 2017.4 and newer install with the official Unity CLI; 4.x and 5.x install from Unity\'s archives.')
343
189
  .option('-p, --unity-project <unityProject>', 'The path to a Unity project or "none" to skip project detection.')
344
190
  .option('-u, --unity-version <unityVersion>', 'The Unity version to get (e.g. 2020.3.1f1, 2021.x, 2022.1.*, 6000). If specified, it will override the version read from the project.')
345
191
  .option('-c, --changeset <changeset>', 'The Unity changeset to get (e.g. 1234567890ab).')
@@ -347,7 +193,7 @@ program.command('setup-unity')
347
193
  .option('-a, --arch <arch>', 'The Unity architecture to get (e.g. x86_64, arm64). Defaults to the architecture of the current process.')
348
194
  .option('-b, --build-targets <buildTargets>', 'The Unity build target to get/install as comma-separated values (e.g. iOS,Android).')
349
195
  .option('-m, --modules <modules>', 'The Unity module to get/install as comma-separated values (e.g. ios,android).')
350
- .option('-i, --install-path <installPath>', 'The path to install the Unity Editor to. By default, it will be installed to the default Unity Hub location.')
196
+ .option('-i, --install-path <installPath>', 'The path to install the Unity Editor to. By default, it will be installed to the Unity CLI install path.')
351
197
  .option('--verbose', 'Enable verbose logging.')
352
198
  .option('--json', 'Prints the last line of output as JSON string.')
353
199
  .action(async (options) => {
@@ -365,14 +211,23 @@ program.command('setup-unity')
365
211
  }
366
212
  let unityVersion;
367
213
  if (options.unityVersion) {
368
- unityVersion = new unity_version_1.UnityVersion(options.unityVersion, options.changeset, options.arch);
214
+ const arch = options.arch?.toString()?.trim().toLowerCase();
215
+ const architecture = arch === 'arm64' ? 'ARM64' : arch === 'x86_64' || arch === 'x64' ? 'X86_64' : undefined;
216
+ unityVersion = new unity_version_1.UnityVersion(options.unityVersion, options.changeset, architecture);
369
217
  }
370
218
  else {
371
219
  unityVersion = unityProject.version;
372
220
  }
373
221
  const modules = options.modules ? options.modules.split(/[ ,]+/).filter(Boolean) : [];
374
222
  const buildTargets = options.buildTargets ? options.buildTargets.split(/[ ,]+/).filter(Boolean) : [];
375
- const moduleBuildTargetMap = unity_hub_1.UnityHub.GetPlatformTargetModuleMap();
223
+ // with only a project, its saved build profiles pick the modules; --modules or --build-targets override them
224
+ if (unityProject && modules.length === 0 && buildTargets.length === 0) {
225
+ buildTargets.push(...unityProject.GetBuildProfileTargets());
226
+ if (buildTargets.length > 0) {
227
+ logging_1.Logger.instance.info(`Installing modules for the project's build profiles: ${buildTargets.join(', ')}`);
228
+ }
229
+ }
230
+ const moduleBuildTargetMap = unity_installer_1.UnityInstaller.GetPlatformTargetModuleMap();
376
231
  for (const target of buildTargets) {
377
232
  const module = moduleBuildTargetMap[target];
378
233
  if (module === undefined) {
@@ -389,7 +244,6 @@ program.command('setup-unity')
389
244
  modules.includes('None')) {
390
245
  modules.length = 0;
391
246
  }
392
- const unityHub = new unity_hub_1.UnityHub();
393
247
  const channels = options.channel
394
248
  ? String(options.channel).split(/[ ,]+/).map((c) => c.trim().toLowerCase()).filter(Boolean)
395
249
  : ['f'];
@@ -400,9 +254,14 @@ program.command('setup-unity')
400
254
  process.exit(1);
401
255
  }
402
256
  }
403
- const unityEditor = await unityHub.GetEditor(unityVersion, modules, channels);
257
+ const unityCli = await unity_cli_1.UnityCli.Get();
258
+ const installer = new unity_installer_1.UnityInstaller(unityCli);
259
+ if (options.installPath) {
260
+ await installer.SetInstallPath(options.installPath);
261
+ }
262
+ const unityEditor = await installer.GetEditor(unityVersion, modules, channels);
404
263
  const output = {
405
- 'UNITY_HUB_PATH': unityHub.executable,
264
+ 'UNITY_CLI_PATH': unityCli.executable,
406
265
  'UNITY_EDITOR_PATH': unityEditor.editorPath,
407
266
  'UNITY_EDITOR_VERSION': unityEditor.version.version,
408
267
  'UNITY_EDITOR_CHANGESET': unityEditor.version.changeset ?? '',
@@ -432,56 +291,8 @@ program.command('setup-unity')
432
291
  }
433
292
  process.exit(0);
434
293
  });
435
- program.command('uninstall-unity')
436
- .description('Uninstall a Unity Editor version.')
437
- .option('-e, --unity-editor <unityEditor>', 'The path to the Unity Editor executable. If unspecified, -u, --unity-version or the UNITY_EDITOR_PATH environment variable must be set.')
438
- .option('-u, --unity-version <unityVersion>', 'The Unity version to get (e.g. 2020.3.1f1, 2021.x, 2022.1.*, 6000). If unspecified, then --unity-editor must be specified.')
439
- .option('-c, --changeset <changeset>', 'The Unity changeset to get (e.g. 1234567890ab).')
440
- .option('-a, --arch <arch>', 'The Unity architecture to get (e.g. x86_64, arm64). Defaults to the architecture of the current process.')
441
- .option('--verbose', 'Enable verbose logging.')
442
- .action(async (options) => {
443
- if (options.verbose) {
444
- logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
445
- }
446
- logging_1.Logger.instance.debugOptions(options);
447
- let unityEditor;
448
- const unityVersionStr = options.unityVersion?.toString()?.trim();
449
- if (unityVersionStr) {
450
- const unityVersion = new unity_version_1.UnityVersion(unityVersionStr, options.changeset, options.arch);
451
- const unityHub = new unity_hub_1.UnityHub();
452
- const installedEditors = await unityHub.ListInstalledEditors();
453
- if (unityVersion.isLegacy()) {
454
- const installPath = await unityHub.GetInstallPath();
455
- unityEditor = new unity_editor_1.UnityEditor(path.join(installPath, `Unity ${unityVersion.toString()}`, 'Unity.exe'));
456
- }
457
- else {
458
- unityEditor = installedEditors.find(e => e.version.equals(unityVersion));
459
- }
460
- }
461
- else {
462
- const editorPath = options.unityEditor?.toString()?.trim() || process.env.UNITY_EDITOR_PATH || undefined;
463
- if (!editorPath || editorPath.length === 0) {
464
- logging_1.Logger.instance.error('You must specify a Unity version or editor path with -u, --unity-version, -e, --unity-editor.');
465
- process.exit(1);
466
- }
467
- try {
468
- unityEditor = new unity_editor_1.UnityEditor(editorPath);
469
- }
470
- catch {
471
- // ignored
472
- }
473
- }
474
- if (!unityEditor) {
475
- logging_1.Logger.instance.info('The specified Unity Editor was not found.');
476
- }
477
- else {
478
- await unityEditor.Uninstall();
479
- }
480
- process.exit(0);
481
- });
482
- program.commandsGroup('Unity Editor:');
483
294
  program.command('run')
484
- .description('Run Unity Editor command line arguments (passes args directly to the editor).')
295
+ .description('Run Unity Editor command line arguments with live Editor log and UTP annotations. Runs with a project go through the official CLI\'s unity run.')
485
296
  .option('--unity-editor <unityEditor>', 'The path to the Unity Editor executable. If unspecified, --unity-project or the UNITY_EDITOR_PATH environment variable must be set.')
486
297
  .option('--unity-project <unityProject>', 'The path to a Unity project. If unspecified, the UNITY_PROJECT_PATH environment variable will be used, otherwise no project will be specified.')
487
298
  .option('--log-name <logName>', 'The name of the log file.')
@@ -559,9 +370,8 @@ program.command('run')
559
370
  process.exit(1);
560
371
  }
561
372
  if (!unityEditor) {
562
- const unityHub = new unity_hub_1.UnityHub();
563
373
  try {
564
- unityEditor = await unityHub.GetEditor(unityProject.version);
374
+ unityEditor = await new unity_installer_1.UnityInstaller().GetEditor(unityProject.version);
565
375
  }
566
376
  catch {
567
377
  logging_1.Logger.instance.error(`Could not find Unity Editor version ${unityProject.version.version} installed for project at ${unityProject.projectPath}. Please specify the editor path with --unity-editor or set the UNITY_EDITOR_PATH environment variable.`);
@@ -583,127 +393,99 @@ program.command('run')
583
393
  });
584
394
  process.exit(0);
585
395
  });
586
- program.command('list-project-templates')
587
- .description('List available Unity project templates for an editor.')
588
- .option('-u, --unity-version <unityVersion>', 'The Unity version to get (e.g. 2020.3.1f1, 2021.x, 2022.1.*, 6000). If unspecified, then --unity-editor must be specified.')
396
+ program.command('editor-logs')
397
+ .description('Prints the path to the Unity Editor log files.')
398
+ .action(async () => {
399
+ const unityEditorLogsPath = unity_editor_1.UnityEditor.GetEditorLogsDirectory();
400
+ process.stdout.write(`${unityEditorLogsPath}\n`);
401
+ process.exit(0);
402
+ });
403
+ program.commandsGroup('Deprecated, forwarded to the official Unity CLI:');
404
+ program.command('uninstall-unity')
405
+ .description('[Deprecated] Uninstall a Unity Editor version. Forwards to: unity uninstall <version> --yes')
589
406
  .option('-e, --unity-editor <unityEditor>', 'The path to the Unity Editor executable. If unspecified, -u, --unity-version or the UNITY_EDITOR_PATH environment variable must be set.')
407
+ .option('-u, --unity-version <unityVersion>', 'The Unity version to uninstall (e.g. 2020.3.1f1, 6000.2). If unspecified, then --unity-editor must be specified.')
408
+ .option('-c, --changeset <changeset>', 'Ignored; the official CLI uninstalls by version.')
409
+ .option('-a, --arch <arch>', 'The Unity architecture to uninstall (x86_64, arm64).')
590
410
  .option('--verbose', 'Enable verbose logging.')
591
- .option('--json', 'Prints the last line of output as JSON string.')
592
411
  .action(async (options) => {
593
412
  if (options.verbose) {
594
413
  logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
595
414
  }
596
415
  logging_1.Logger.instance.debugOptions(options);
597
- const unityVersionStr = options.unityVersion?.toString()?.trim();
598
- const editorFromEnv = process.env.UNITY_EDITOR_PATH?.trim();
599
- if (!unityVersionStr && !options.unityEditor?.toString()?.trim() && !editorFromEnv) {
600
- logging_1.Logger.instance.error('You must specify a Unity version or editor path with -u, --unity-version, -e, --unity-editor, or set UNITY_EDITOR_PATH.');
416
+ const version = await forwardedEditorVersion(options);
417
+ if (!version) {
418
+ logging_1.Logger.instance.error('You must specify the Unity version or editor path with -u, --unity-version, -e, --unity-editor or UNITY_EDITOR_PATH.');
601
419
  process.exit(1);
602
420
  }
603
- let unityEditor;
604
- if (unityVersionStr) {
605
- const unityVersion = new unity_version_1.UnityVersion(unityVersionStr);
606
- unityEditor = await new unity_hub_1.UnityHub().GetEditor(unityVersion);
607
- }
608
- else {
609
- const editorPath = options.unityEditor?.toString()?.trim() || editorFromEnv;
610
- if (!editorPath || editorPath.length === 0) {
611
- throw new Error('The Unity Editor path was not specified. Use -e or --unity-editor to specify it, or set the UNITY_EDITOR_PATH environment variable.');
612
- }
613
- unityEditor = new unity_editor_1.UnityEditor(editorPath);
421
+ const args = ['uninstall', version, '--yes'];
422
+ const arch = options.arch?.toString()?.trim();
423
+ if (arch) {
424
+ args.push('--architecture', arch);
614
425
  }
615
- const templates = unityEditor.GetAvailableTemplates();
616
- if (templates.length > 0) {
617
- if (options.json) {
618
- process.stdout.write(`\n${JSON.stringify({ templates })}\n`);
619
- }
620
- else {
621
- process.stdout.write(`Available project templates:\n${templates.map(t => ` - ${path.basename(t)}`).join('\n')}\n`);
622
- }
623
- }
624
- else {
625
- process.stdout.write('No project templates found for this Unity Editor.\n');
426
+ await forwardToUnityCli('uninstall-unity', args);
427
+ });
428
+ program.command('list-project-templates')
429
+ .description('[Deprecated] List available Unity project templates for an editor. Forwards to: unity templates list --editor <version>')
430
+ .option('-u, --unity-version <unityVersion>', 'The Unity version to list templates for (e.g. 2022.3.1f1, 6000.2). If unspecified, then --unity-editor must be specified.')
431
+ .option('-e, --unity-editor <unityEditor>', 'The path to the Unity Editor executable. If unspecified, -u, --unity-version or the UNITY_EDITOR_PATH environment variable must be set.')
432
+ .option('--verbose', 'Enable verbose logging.')
433
+ .option('--json', 'Prints the output as JSON.')
434
+ .action(async (options) => {
435
+ if (options.verbose) {
436
+ logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
626
437
  }
627
- process.exit(0);
438
+ logging_1.Logger.instance.debugOptions(options);
439
+ const version = await forwardedEditorVersion(options, true);
440
+ await forwardToUnityCli('list-project-templates', ['templates', 'list', ...(version ? ['--editor', version] : [])], options.json === true);
628
441
  });
629
442
  program.command('create-project')
630
- .description('Create a new Unity project.')
443
+ .description('[Deprecated] Create a new Unity project. Forwards to: unity projects create <name> --path <path> --editor-version <version> --template <id> --no-cloud')
631
444
  .option('-n, --name <projectName>', 'The name of the new Unity project. If unspecified, the project will be created in the specified path or the current working directory.')
632
445
  .option('-p, --path <projectPath>', 'The path to create the new Unity project. If unspecified, the current working directory will be used.')
633
- .option('-t, --template <projectTemplate>', 'The name of the template package to use for creating the unity project. Supports regex patterns.', 'com.unity.template.3d(-cross-platform)?')
634
- .option('-u, --unity-version <unityVersion>', 'The Unity version to get (e.g. 2020.3.1f1, 2021.x, 2022.1.*, 6000). If unspecified, then --unity-editor must be specified.')
446
+ .option('-t, --template <projectTemplate>', 'The template package id to create the project from; an id prefix picks the first matching template.', 'com.unity.template.3d')
447
+ .option('-u, --unity-version <unityVersion>', 'The Unity version to create the project with (e.g. 2022.3.1f1, 6000.2). If unspecified, then --unity-editor must be specified.')
635
448
  .option('-e, --unity-editor <unityEditor>', 'The path to the Unity Editor executable. If unspecified, -u, --unity-version, or the UNITY_EDITOR_PATH environment variable must be set.')
636
449
  .option('--verbose', 'Enable verbose logging.')
637
- .option('--json', 'Prints the last line of output as JSON string.')
450
+ .option('--json', 'Prints the output as JSON.')
638
451
  .action(async (options) => {
639
452
  if (options.verbose) {
640
453
  logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
641
454
  }
642
455
  logging_1.Logger.instance.debugOptions(options);
643
- const unityVersionStr = options.unityVersion?.toString()?.trim();
644
- const editorFromEnv = process.env.UNITY_EDITOR_PATH?.trim();
645
- if (!unityVersionStr && !options.unityEditor?.toString()?.trim() && !editorFromEnv) {
646
- logging_1.Logger.instance.error('You must specify a Unity version or editor path with -u, --unity-version, -e, --unity-editor, or set UNITY_EDITOR_PATH.');
456
+ const version = await forwardedEditorVersion(options, true);
457
+ const target = path.resolve(options.path?.toString()?.trim() || process.cwd());
458
+ const name = options.name?.toString()?.trim();
459
+ const args = ['projects', 'create', name || path.basename(target), '--path', name ? target : path.dirname(target)];
460
+ if (version) {
461
+ args.push('--editor-version', version);
462
+ }
463
+ const template = options.template.toString().trim();
464
+ // v3 took a regex here; a pattern is never compiled from the argument, so its leading literal part
465
+ // (com.unity.template.3d for the v3 default) is matched as an exact id, then as an id prefix
466
+ const prefix = /^[\w.-]+/.exec(template)?.[0];
467
+ if (!prefix) {
468
+ logging_1.Logger.instance.error(`Invalid project template: ${template}. Use a template id such as com.unity.template.3d.`);
647
469
  process.exit(1);
648
470
  }
649
- let unityEditor;
650
- if (unityVersionStr) {
651
- const unityVersion = new unity_version_1.UnityVersion(unityVersionStr);
652
- unityEditor = await new unity_hub_1.UnityHub().GetEditor(unityVersion);
653
- }
654
- else {
655
- const editorPath = options.unityEditor?.toString()?.trim() || editorFromEnv;
656
- if (!editorPath || editorPath.length === 0) {
657
- logging_1.Logger.instance.error('The Unity Editor path was not specified. Use -e or --unity-editor to specify it, or set the UNITY_EDITOR_PATH environment variable.');
658
- process.exit(1);
659
- }
660
- unityEditor = new unity_editor_1.UnityEditor(editorPath);
661
- }
662
- let args = [
663
- '-quit',
664
- '-nographics',
665
- '-batchmode'
666
- ];
667
- const projectName = options.name?.toString()?.trim();
668
- let projectPath = options.path?.toString()?.trim() || process.cwd();
669
- if (projectName && projectName.length > 0) {
670
- projectPath = path.join(projectPath, projectName);
671
- }
672
- args.push('-createProject', projectPath);
673
- if (options.template && options.template.length > 0) {
674
- const availableTemplates = unityEditor.GetAvailableTemplates();
675
- if (availableTemplates.length === 0) {
676
- if (unityEditor.version.isLessThan('2019.0.0')) {
677
- logging_1.Logger.instance.info(`Skipping template selection for Unity ${unityEditor.version.toString()} because project templates are not supported.`);
678
- }
679
- else {
680
- throw new Error(`No Unity project templates found for ${unityEditor.version.toString()}`);
681
- }
682
- }
683
- else {
684
- const templatePath = unityEditor.GetTemplatePath(options.template) ??
685
- unityEditor.GetTemplatePath('com\\.unity\\.template\\.urp-[\\w-]+') ??
686
- availableTemplates[0];
687
- if (!templatePath) {
688
- throw new Error(`No Unity project template found for ${options.template}`);
689
- }
690
- args.push('-cloneFromTemplate', templatePath);
691
- }
692
- }
693
- await unityEditor.Run({ projectPath, args });
694
- logging_1.Logger.instance.CI_setEnvironmentVariable('UNITY_PROJECT_PATH', projectPath);
695
- if (options.json) {
696
- process.stdout.write(`\n${JSON.stringify({ UNITY_PROJECT_PATH: projectPath })}\n`);
471
+ if (prefix !== template) {
472
+ logging_1.Logger.instance.warn(`Template patterns are no longer supported; matching templates that start with ${prefix}.`);
697
473
  }
698
- else {
699
- process.stdout.write(`Unity project created at: ${projectPath}\n`);
474
+ const cli = await unity_cli_1.UnityCli.Get();
475
+ const { envelope } = await cli.RunJson(['templates', 'list', ...(version ? ['--editor', version] : [])]);
476
+ const ids = (envelope?.data ?? []).map(t => t.name || t.id).filter((id) => !!id);
477
+ const templateId = ids.find(id => id === prefix) ?? ids.find(id => id.startsWith(prefix));
478
+ if (!templateId) {
479
+ logging_1.Logger.instance.error(`No project template matches ${prefix}. Available: ${ids.join(', ')}`);
480
+ process.exit(1);
700
481
  }
701
- process.exit(0);
482
+ args.push('--template', templateId, '--no-cloud');
483
+ await forwardToUnityCli('create-project', args, options.json === true);
702
484
  });
703
485
  program.command('open-project')
704
- .description('Open a Unity project in the Unity Editor.')
486
+ .description('[Deprecated] Open a Unity project in the Unity Editor. Forwards to: unity open <project>')
705
487
  .option('-p, --unity-project <unityProject>', 'The path to a Unity project. If unspecified, the UNITY_PROJECT_PATH environment variable or the current working directory will be used.')
706
- .option('-u, --unity-version <unityVersion>', 'The Unity version to get (e.g. 2020.3.1f1, 2021.x, 2022.1.*, 6000). If specified, it will override the version read from the project.')
488
+ .option('-u, --unity-version <unityVersion>', 'The Unity version to open the project with. If specified, it will override the version read from the project.')
707
489
  .option('-t, --build-target <buildTarget>', 'The Unity build target to switch the project to (e.g. StandaloneWindows64, StandaloneOSX, iOS, Android).')
708
490
  .option('--verbose', 'Enable verbose logging.')
709
491
  .action(async (options) => {
@@ -711,47 +493,48 @@ program.command('open-project')
711
493
  logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
712
494
  }
713
495
  logging_1.Logger.instance.debugOptions(options);
714
- const projectPath = options.unityProject?.toString()?.trim() ||
715
- process.env.UNITY_PROJECT_PATH ||
716
- undefined;
717
- const unityProject = await unity_project_1.UnityProject.GetProject(projectPath);
718
- if (!unityProject) {
719
- logging_1.Logger.instance.error(`The specified path is not a valid Unity project: ${projectPath}`);
720
- process.exit(1);
721
- }
722
- let unityVersion = unityProject?.version;
723
- if (options.unityVersion) {
724
- unityVersion = new unity_version_1.UnityVersion(options.unityVersion);
725
- }
496
+ const projectPath = options.unityProject?.toString()?.trim() || process.env.UNITY_PROJECT_PATH || process.cwd();
497
+ const args = ['open', projectPath];
498
+ const version = options.unityVersion?.toString()?.trim();
726
499
  const buildTarget = options.buildTarget?.toString()?.trim();
727
- let module = undefined;
728
- if (buildTarget && buildTarget.length > 0) {
729
- const moduleBuildTargetMap = unity_hub_1.UnityHub.GetPlatformTargetModuleMap();
730
- module = moduleBuildTargetMap[buildTarget] ? [moduleBuildTargetMap[buildTarget]] : undefined;
731
- }
732
- const unityHub = new unity_hub_1.UnityHub();
733
- const unityEditor = await unityHub.GetEditor(unityVersion, module);
734
- logging_1.Logger.instance.info(`Opening "${unityProject.projectPath}" with Unity ${unityEditor.version}${buildTarget ? ` - ${buildTarget}` : ''}...`);
735
- const openArgs = ['-projectPath', unityProject.projectPath];
736
- if (buildTarget && buildTarget.length > 0) {
737
- openArgs.push('-buildTarget', buildTarget);
738
- }
739
- let child = null;
740
- try {
741
- child = (0, child_process_1.spawn)(unityEditor.editorPath, openArgs, { detached: true });
742
- child.unref();
500
+ if (version) {
501
+ args.push('--editor-version', version);
743
502
  }
744
- finally {
745
- process.exit(child?.pid !== undefined ? 0 : 1);
503
+ if (buildTarget) {
504
+ args.push('--build-target', buildTarget);
746
505
  }
506
+ await forwardToUnityCli('open-project', args);
747
507
  });
748
- program.command('editor-logs')
749
- .description('Prints the path to the Unity Editor log files.')
750
- .action(async () => {
751
- const unityEditorLogsPath = unity_editor_1.UnityEditor.GetEditorLogsDirectory();
752
- process.stdout.write(`${unityEditorLogsPath}\n`);
753
- process.exit(0);
754
- });
508
+ /**
509
+ * The editor version a forwarded v3 command names, from --unity-version or the editor at --unity-editor / UNITY_EDITOR_PATH.
510
+ * Partial versions such as 2021.3.x become 2021.3, the short form `unity uninstall` accepts; with `exact`, they resolve
511
+ * to the newest matching release instead, because `unity templates list` and `unity projects create` need a full version.
512
+ */
513
+ async function forwardedEditorVersion(options, exact = false) {
514
+ const version = options.unityVersion?.toString()?.trim();
515
+ if (version) {
516
+ if (!exact) {
517
+ return version.replace(/\.[x*]$/i, '');
518
+ }
519
+ const unityVersion = new unity_version_1.UnityVersion(version);
520
+ if (unityVersion.isFullyQualified()) {
521
+ return unityVersion.version;
522
+ }
523
+ return (await new unity_installer_1.UnityInstaller(await unity_cli_1.UnityCli.Get()).resolveVersion(unityVersion)).version;
524
+ }
525
+ const editorPath = options.unityEditor?.toString()?.trim() || process.env.UNITY_EDITOR_PATH;
526
+ return editorPath ? new unity_editor_1.UnityEditor(editorPath).version.version : undefined;
527
+ }
528
+ /** Warns that a v3 command is deprecated, runs its official Unity CLI replacement and exits with that exit code. */
529
+ async function forwardToUnityCli(command, args, json = false) {
530
+ logging_1.Logger.instance.warn(`unity-cli ${command} is deprecated and will be removed. Use the official Unity CLI instead: unity ${args.join(' ')}`);
531
+ const cli = await unity_cli_1.UnityCli.Get();
532
+ const result = await cli.Run(json ? [...args, '--json'] : args, { stream: !json });
533
+ if (json) {
534
+ process.stdout.write(`${result.stdout.trim()}\n`);
535
+ }
536
+ process.exit(result.exitCode);
537
+ }
755
538
  program.commandsGroup("Unity Package Manager:");
756
539
  program.command('upm-install')
757
540
  .description('Download and install the Unity Package Manager cli (pack/sign).')
@@ -805,7 +588,7 @@ program.command('upm-install')
805
588
  process.exit(0);
806
589
  }
807
590
  catch (error) {
808
- logging_1.Logger.instance.error(`${error}`);
591
+ (0, failure_markers_1.ReportFailure)(error);
809
592
  process.exit(1);
810
593
  }
811
594
  });
@@ -819,7 +602,7 @@ program.command('upm-version')
819
602
  process.exit(0);
820
603
  }
821
604
  catch (error) {
822
- logging_1.Logger.instance.error(`${error}`);
605
+ (0, failure_markers_1.ReportFailure)(error);
823
606
  process.exit(1);
824
607
  }
825
608
  });
@@ -884,120 +667,12 @@ program.command('upm-pack')
884
667
  process.exit(0);
885
668
  }
886
669
  catch (error) {
887
- logging_1.Logger.instance.error(`${error}`);
670
+ (0, failure_markers_1.ReportFailure)(error);
888
671
  process.exit(1);
889
672
  }
890
673
  });
891
- program.command('sign-package')
892
- .description('[Deprecated] Sign a Unity package using Unity Editor 6000.3+ batch mode (-upmPack). Use unity-cli upm-pack with organization and service account credentials for new workflows.')
893
- .option('--package <package>', 'Required. The fully qualified path to the folder that contains the package.json file for the package you want to sign. Note: Don\'t include package.json in this parameter value.')
894
- .option('--output <output>', 'Optional. The output directory where you want to save the signed tarball file (.tgz). If unspecified, the package contents will be updated in place with the signed .attestation.p7m file.')
895
- .option('--email <email>', 'Email associated with the Unity account. If unspecified, the UNITY_USERNAME environment variable will be used.')
896
- .option('--password <password>', 'The password of the Unity account. If unspecified, the UNITY_PASSWORD environment variable will be used.')
897
- .option('--organization <organization>', 'The Organization ID you copied from the Unity Cloud Dashboard. If unspecified, the UNITY_ORGANIZATION_ID environment variable will be used.')
898
- .option('--verbose', 'Enable verbose logging.')
899
- .action(async (options) => {
900
- logging_1.Logger.instance.warn('The sign-package command is deprecated. Use unity-cli upm-pack --source <path-to-package-folder> --destination <output-path> with UNITY_ORGANIZATION_ID or UNITY_ORG_ID, UPM_SERVICE_ACCOUNT_KEY_ID, and UPM_SERVICE_ACCOUNT_KEY_SECRET (or secure prompts).');
901
- if (options.verbose) {
902
- logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
903
- }
904
- logging_1.Logger.instance.debugOptions(options);
905
- const packagePath = path.normalize(options.package?.toString()?.trim());
906
- if (!packagePath || packagePath.length === 0) {
907
- logging_1.Logger.instance.error('The package path is required. Use --package to specify it.');
908
- process.exit(1);
909
- }
910
- const packageJsonPath = path.join(packagePath, 'package.json');
911
- try {
912
- await fs.promises.access(packageJsonPath, fs.constants.R_OK);
913
- }
914
- catch {
915
- logging_1.Logger.instance.error(`Failed to find a valid package.json file at: ${packageJsonPath}`);
916
- process.exit(1);
917
- }
918
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
919
- let outputPath = options.output?.toString()?.trim();
920
- if (outputPath && outputPath.length > 0) {
921
- outputPath = path.resolve(outputPath);
922
- if (outputPath.endsWith('.tgz')) {
923
- // remove .tgz if present
924
- outputPath = outputPath.substring(0, outputPath.length - 4);
925
- }
926
- }
927
- else {
928
- outputPath = path.join(path.resolve(packagePath, '..'));
929
- }
930
- let username = options.email?.toString()?.trim() || process.env.UNITY_USERNAME || undefined;
931
- if (!username || username.length === 0) {
932
- username = await (0, utilities_1.PromptForSecretInput)('Email: ');
933
- }
934
- if (!username || username.length === 0) {
935
- logging_1.Logger.instance.error('The email is required. Use --email to specify it.');
936
- process.exit(1);
937
- }
938
- let password = options.password?.toString()?.trim() || process.env.UNITY_PASSWORD || undefined;
939
- if (!password || password.length === 0) {
940
- password = await (0, utilities_1.PromptForSecretInput)('Password: ');
941
- }
942
- if (!password || password.length === 0) {
943
- logging_1.Logger.instance.error('The password is required. Use --password to specify it.');
944
- process.exit(1);
945
- }
946
- let organization = options.organization?.toString()?.trim() || process.env.UNITY_ORGANIZATION_ID || undefined;
947
- if (!organization || organization.length === 0) {
948
- organization = await (0, utilities_1.PromptForSecretInput)('Organization ID: ');
949
- }
950
- if (!organization || organization.length === 0) {
951
- logging_1.Logger.instance.error('The organization ID is required. Use --organization to specify it.');
952
- process.exit(1);
953
- }
954
- // Mask credentials in CI environments before any potential logging
955
- logging_1.Logger.instance.maskCredential(username);
956
- logging_1.Logger.instance.maskCredential(password);
957
- logging_1.Logger.instance.maskCredential(organization);
958
- // must use a unity editor 6000.3 or newer
959
- const unityVersion = new unity_version_1.UnityVersion('6000.3');
960
- const unityHub = new unity_hub_1.UnityHub();
961
- const unityEditor = await unityHub.GetEditor(unityVersion, undefined, ['f', 'b']);
962
- try {
963
- await unityEditor.Run({
964
- args: [
965
- '-batchmode',
966
- '-username', username,
967
- '-password', password,
968
- '-upmPack', packagePath, path.normalize(outputPath),
969
- '-cloudOrganization', organization
970
- ]
971
- });
972
- }
973
- catch (error) {
974
- // currently the editor returns exit code 1 even on success
975
- }
976
- finally {
977
- if (fs.existsSync(outputPath)) {
978
- const pkg = await (0, utilities_1.ResolveGlobToPath)([outputPath, `${path.basename(packageJson.name)}*.tgz`]);
979
- logging_1.Logger.instance.info(`Package signed successfully: ${pkg}`);
980
- // if the output directory was not specified in the command options,
981
- // then unpack the .tgz file and overwrite the package contents.
982
- if (!options.output || options.output.length === 0) {
983
- await tar.x({
984
- file: pkg,
985
- cwd: packagePath,
986
- strip: 1
987
- });
988
- logging_1.Logger.instance.info(`Package contents extracted to: ${packagePath}`);
989
- fs.unlinkSync(pkg);
990
- }
991
- process.exit(0);
992
- }
993
- else {
994
- logging_1.Logger.instance.error('Failed to sign the package.');
995
- process.exit(1);
996
- }
997
- }
998
- });
999
674
  void program.parseAsync(process.argv).catch((err) => {
1000
- logging_1.Logger.instance.error(err instanceof Error ? err.message : String(err));
675
+ (0, failure_markers_1.ReportFailure)(err);
1001
676
  process.exit(1);
1002
677
  });
1003
678
  //# sourceMappingURL=cli.js.map