@rage-against-the-pixel/unity-cli 3.0.1 → 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.
- package/README.md +89 -223
- package/dist/android-sdk.js +8 -1
- package/dist/android-sdk.js.map +1 -1
- package/dist/cli.js +195 -506
- package/dist/cli.js.map +1 -1
- package/dist/failure-markers.d.ts +17 -0
- package/dist/failure-markers.js +46 -0
- package/dist/failure-markers.js.map +1 -0
- package/dist/github-actions-ci.d.ts +1 -0
- package/dist/github-actions-ci.js +17 -3
- package/dist/github-actions-ci.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/license-client.d.ts +113 -2
- package/dist/license-client.js +715 -54
- package/dist/license-client.js.map +1 -1
- package/dist/logger-provider.d.ts +2 -0
- package/dist/logger-provider.js +3 -0
- package/dist/logger-provider.js.map +1 -1
- package/dist/logging.d.ts +6 -1
- package/dist/logging.js +66 -5
- package/dist/logging.js.map +1 -1
- package/dist/process-tracker.d.ts +71 -0
- package/dist/process-tracker.js +213 -0
- package/dist/process-tracker.js.map +1 -0
- package/dist/unity-cli.d.ts +97 -0
- package/dist/unity-cli.js +587 -0
- package/dist/unity-cli.js.map +1 -0
- package/dist/unity-editor.d.ts +25 -16
- package/dist/unity-editor.js +204 -107
- package/dist/unity-editor.js.map +1 -1
- package/dist/unity-installer.d.ts +134 -0
- package/dist/unity-installer.js +963 -0
- package/dist/unity-installer.js.map +1 -0
- package/dist/unity-logging.d.ts +16 -1
- package/dist/unity-logging.js +79 -40
- package/dist/unity-logging.js.map +1 -1
- package/dist/unity-project.d.ts +15 -0
- package/dist/unity-project.js +80 -0
- package/dist/unity-project.js.map +1 -1
- package/dist/unity-version.d.ts +4 -0
- package/dist/unity-version.js +40 -2
- package/dist/unity-version.js.map +1 -1
- package/dist/upm-cli.d.ts +8 -8
- package/dist/upm-cli.js +8 -8
- package/dist/upm-cli.js.map +1 -1
- package/dist/utilities.d.ts +27 -7
- package/dist/utilities.js +119 -63
- package/dist/utilities.js.map +1 -1
- package/dist/utp-benign.d.ts +13 -0
- package/dist/utp-benign.js +41 -0
- package/dist/utp-benign.js.map +1 -0
- package/dist/utp.d.ts +11 -2
- package/dist/utp.js +40 -3
- package/dist/utp.js.map +1 -1
- package/package.json +14 -15
- package/dist/unity-hub.d.ts +0 -127
- package/dist/unity-hub.js +0 -1327
- 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('
|
|
63
|
-
.version(pkg.version)
|
|
64
|
-
|
|
65
|
-
.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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.
|
|
152
|
-
.option('-p, --password <password>', 'Password for the Unity account.
|
|
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 =
|
|
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
|
|
174
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
|
163
|
+
.description('Print the current license state from the Unity CLI and the Unity Licensing Client.')
|
|
238
164
|
.action(async () => {
|
|
239
|
-
|
|
240
|
-
|
|
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,101 +183,17 @@ 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
|
|
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).')
|
|
192
|
+
.option('--channel <channels>', 'Release channel letter(s) to accept when resolving partial versions: f,p,b,a,x (comma-separated). Default: f (stable only).')
|
|
346
193
|
.option('-a, --arch <arch>', 'The Unity architecture to get (e.g. x86_64, arm64). Defaults to the architecture of the current process.')
|
|
347
194
|
.option('-b, --build-targets <buildTargets>', 'The Unity build target to get/install as comma-separated values (e.g. iOS,Android).')
|
|
348
195
|
.option('-m, --modules <modules>', 'The Unity module to get/install as comma-separated values (e.g. ios,android).')
|
|
349
|
-
.option('-i, --install-path <installPath>', 'The path to install the Unity Editor to. By default, it will be installed to the
|
|
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.')
|
|
350
197
|
.option('--verbose', 'Enable verbose logging.')
|
|
351
198
|
.option('--json', 'Prints the last line of output as JSON string.')
|
|
352
199
|
.action(async (options) => {
|
|
@@ -364,14 +211,23 @@ program.command('setup-unity')
|
|
|
364
211
|
}
|
|
365
212
|
let unityVersion;
|
|
366
213
|
if (options.unityVersion) {
|
|
367
|
-
|
|
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);
|
|
368
217
|
}
|
|
369
218
|
else {
|
|
370
219
|
unityVersion = unityProject.version;
|
|
371
220
|
}
|
|
372
221
|
const modules = options.modules ? options.modules.split(/[ ,]+/).filter(Boolean) : [];
|
|
373
222
|
const buildTargets = options.buildTargets ? options.buildTargets.split(/[ ,]+/).filter(Boolean) : [];
|
|
374
|
-
|
|
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();
|
|
375
231
|
for (const target of buildTargets) {
|
|
376
232
|
const module = moduleBuildTargetMap[target];
|
|
377
233
|
if (module === undefined) {
|
|
@@ -388,11 +244,28 @@ program.command('setup-unity')
|
|
|
388
244
|
modules.includes('None')) {
|
|
389
245
|
modules.length = 0;
|
|
390
246
|
}
|
|
391
|
-
const
|
|
392
|
-
|
|
247
|
+
const channels = options.channel
|
|
248
|
+
? String(options.channel).split(/[ ,]+/).map((c) => c.trim().toLowerCase()).filter(Boolean)
|
|
249
|
+
: ['f'];
|
|
250
|
+
const allowedChannels = new Set(['f', 'p', 'b', 'a', 'x']);
|
|
251
|
+
for (const ch of channels) {
|
|
252
|
+
if (!allowedChannels.has(ch)) {
|
|
253
|
+
logging_1.Logger.instance.error(`Invalid --channel '${ch}'. Expected one of: f, p, b, a, x.`);
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
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);
|
|
393
263
|
const output = {
|
|
394
|
-
'
|
|
395
|
-
'UNITY_EDITOR_PATH': unityEditor.editorPath
|
|
264
|
+
'UNITY_CLI_PATH': unityCli.executable,
|
|
265
|
+
'UNITY_EDITOR_PATH': unityEditor.editorPath,
|
|
266
|
+
'UNITY_EDITOR_VERSION': unityEditor.version.version,
|
|
267
|
+
'UNITY_EDITOR_CHANGESET': unityEditor.version.changeset ?? '',
|
|
268
|
+
'UNITY_EDITOR_CHANNELS': channels.join(','),
|
|
396
269
|
};
|
|
397
270
|
if (unityProject) {
|
|
398
271
|
output['UNITY_PROJECT_PATH'] = unityProject.projectPath;
|
|
@@ -418,56 +291,8 @@ program.command('setup-unity')
|
|
|
418
291
|
}
|
|
419
292
|
process.exit(0);
|
|
420
293
|
});
|
|
421
|
-
program.command('uninstall-unity')
|
|
422
|
-
.description('Uninstall a Unity Editor version.')
|
|
423
|
-
.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.')
|
|
424
|
-
.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.')
|
|
425
|
-
.option('-c, --changeset <changeset>', 'The Unity changeset to get (e.g. 1234567890ab).')
|
|
426
|
-
.option('-a, --arch <arch>', 'The Unity architecture to get (e.g. x86_64, arm64). Defaults to the architecture of the current process.')
|
|
427
|
-
.option('--verbose', 'Enable verbose logging.')
|
|
428
|
-
.action(async (options) => {
|
|
429
|
-
if (options.verbose) {
|
|
430
|
-
logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
|
|
431
|
-
}
|
|
432
|
-
logging_1.Logger.instance.debugOptions(options);
|
|
433
|
-
let unityEditor;
|
|
434
|
-
const unityVersionStr = options.unityVersion?.toString()?.trim();
|
|
435
|
-
if (unityVersionStr) {
|
|
436
|
-
const unityVersion = new unity_version_1.UnityVersion(unityVersionStr, options.changeset, options.arch);
|
|
437
|
-
const unityHub = new unity_hub_1.UnityHub();
|
|
438
|
-
const installedEditors = await unityHub.ListInstalledEditors();
|
|
439
|
-
if (unityVersion.isLegacy()) {
|
|
440
|
-
const installPath = await unityHub.GetInstallPath();
|
|
441
|
-
unityEditor = new unity_editor_1.UnityEditor(path.join(installPath, `Unity ${unityVersion.toString()}`, 'Unity.exe'));
|
|
442
|
-
}
|
|
443
|
-
else {
|
|
444
|
-
unityEditor = installedEditors.find(e => e.version.equals(unityVersion));
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
else {
|
|
448
|
-
const editorPath = options.unityEditor?.toString()?.trim() || process.env.UNITY_EDITOR_PATH || undefined;
|
|
449
|
-
if (!editorPath || editorPath.length === 0) {
|
|
450
|
-
logging_1.Logger.instance.error('You must specify a Unity version or editor path with -u, --unity-version, -e, --unity-editor.');
|
|
451
|
-
process.exit(1);
|
|
452
|
-
}
|
|
453
|
-
try {
|
|
454
|
-
unityEditor = new unity_editor_1.UnityEditor(editorPath);
|
|
455
|
-
}
|
|
456
|
-
catch {
|
|
457
|
-
// ignored
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
if (!unityEditor) {
|
|
461
|
-
logging_1.Logger.instance.info('The specified Unity Editor was not found.');
|
|
462
|
-
}
|
|
463
|
-
else {
|
|
464
|
-
await unityEditor.Uninstall();
|
|
465
|
-
}
|
|
466
|
-
process.exit(0);
|
|
467
|
-
});
|
|
468
|
-
program.commandsGroup('Unity Editor:');
|
|
469
294
|
program.command('run')
|
|
470
|
-
.description('Run Unity Editor command line arguments
|
|
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.')
|
|
471
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.')
|
|
472
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.')
|
|
473
298
|
.option('--log-name <logName>', 'The name of the log file.')
|
|
@@ -545,9 +370,8 @@ program.command('run')
|
|
|
545
370
|
process.exit(1);
|
|
546
371
|
}
|
|
547
372
|
if (!unityEditor) {
|
|
548
|
-
const unityHub = new unity_hub_1.UnityHub();
|
|
549
373
|
try {
|
|
550
|
-
unityEditor = await
|
|
374
|
+
unityEditor = await new unity_installer_1.UnityInstaller().GetEditor(unityProject.version);
|
|
551
375
|
}
|
|
552
376
|
catch {
|
|
553
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.`);
|
|
@@ -569,127 +393,99 @@ program.command('run')
|
|
|
569
393
|
});
|
|
570
394
|
process.exit(0);
|
|
571
395
|
});
|
|
572
|
-
program.command('
|
|
573
|
-
.description('
|
|
574
|
-
.
|
|
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')
|
|
575
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).')
|
|
576
410
|
.option('--verbose', 'Enable verbose logging.')
|
|
577
|
-
.option('--json', 'Prints the last line of output as JSON string.')
|
|
578
411
|
.action(async (options) => {
|
|
579
412
|
if (options.verbose) {
|
|
580
413
|
logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
|
|
581
414
|
}
|
|
582
415
|
logging_1.Logger.instance.debugOptions(options);
|
|
583
|
-
const
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
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.');
|
|
587
419
|
process.exit(1);
|
|
588
420
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
}
|
|
594
|
-
else {
|
|
595
|
-
const editorPath = options.unityEditor?.toString()?.trim() || editorFromEnv;
|
|
596
|
-
if (!editorPath || editorPath.length === 0) {
|
|
597
|
-
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.');
|
|
598
|
-
}
|
|
599
|
-
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);
|
|
600
425
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
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;
|
|
612
437
|
}
|
|
613
|
-
|
|
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);
|
|
614
441
|
});
|
|
615
442
|
program.command('create-project')
|
|
616
|
-
.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')
|
|
617
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.')
|
|
618
445
|
.option('-p, --path <projectPath>', 'The path to create the new Unity project. If unspecified, the current working directory will be used.')
|
|
619
|
-
.option('-t, --template <projectTemplate>', 'The
|
|
620
|
-
.option('-u, --unity-version <unityVersion>', 'The Unity version to
|
|
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.')
|
|
621
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.')
|
|
622
449
|
.option('--verbose', 'Enable verbose logging.')
|
|
623
|
-
.option('--json', 'Prints the
|
|
450
|
+
.option('--json', 'Prints the output as JSON.')
|
|
624
451
|
.action(async (options) => {
|
|
625
452
|
if (options.verbose) {
|
|
626
453
|
logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
|
|
627
454
|
}
|
|
628
455
|
logging_1.Logger.instance.debugOptions(options);
|
|
629
|
-
const
|
|
630
|
-
const
|
|
631
|
-
|
|
632
|
-
|
|
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.`);
|
|
633
469
|
process.exit(1);
|
|
634
470
|
}
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
const unityVersion = new unity_version_1.UnityVersion(unityVersionStr);
|
|
638
|
-
unityEditor = await new unity_hub_1.UnityHub().GetEditor(unityVersion);
|
|
639
|
-
}
|
|
640
|
-
else {
|
|
641
|
-
const editorPath = options.unityEditor?.toString()?.trim() || editorFromEnv;
|
|
642
|
-
if (!editorPath || editorPath.length === 0) {
|
|
643
|
-
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.');
|
|
644
|
-
process.exit(1);
|
|
645
|
-
}
|
|
646
|
-
unityEditor = new unity_editor_1.UnityEditor(editorPath);
|
|
647
|
-
}
|
|
648
|
-
let args = [
|
|
649
|
-
'-quit',
|
|
650
|
-
'-nographics',
|
|
651
|
-
'-batchmode'
|
|
652
|
-
];
|
|
653
|
-
const projectName = options.name?.toString()?.trim();
|
|
654
|
-
let projectPath = options.path?.toString()?.trim() || process.cwd();
|
|
655
|
-
if (projectName && projectName.length > 0) {
|
|
656
|
-
projectPath = path.join(projectPath, projectName);
|
|
657
|
-
}
|
|
658
|
-
args.push('-createProject', projectPath);
|
|
659
|
-
if (options.template && options.template.length > 0) {
|
|
660
|
-
const availableTemplates = unityEditor.GetAvailableTemplates();
|
|
661
|
-
if (availableTemplates.length === 0) {
|
|
662
|
-
if (unityEditor.version.isLessThan('2019.0.0')) {
|
|
663
|
-
logging_1.Logger.instance.info(`Skipping template selection for Unity ${unityEditor.version.toString()} because project templates are not supported.`);
|
|
664
|
-
}
|
|
665
|
-
else {
|
|
666
|
-
throw new Error(`No Unity project templates found for ${unityEditor.version.toString()}`);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
else {
|
|
670
|
-
const templatePath = unityEditor.GetTemplatePath(options.template) ??
|
|
671
|
-
unityEditor.GetTemplatePath('com\\.unity\\.template\\.urp-[\\w-]+') ??
|
|
672
|
-
availableTemplates[0];
|
|
673
|
-
if (!templatePath) {
|
|
674
|
-
throw new Error(`No Unity project template found for ${options.template}`);
|
|
675
|
-
}
|
|
676
|
-
args.push('-cloneFromTemplate', templatePath);
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
await unityEditor.Run({ projectPath, args });
|
|
680
|
-
logging_1.Logger.instance.CI_setEnvironmentVariable('UNITY_PROJECT_PATH', projectPath);
|
|
681
|
-
if (options.json) {
|
|
682
|
-
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}.`);
|
|
683
473
|
}
|
|
684
|
-
|
|
685
|
-
|
|
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);
|
|
686
481
|
}
|
|
687
|
-
|
|
482
|
+
args.push('--template', templateId, '--no-cloud');
|
|
483
|
+
await forwardToUnityCli('create-project', args, options.json === true);
|
|
688
484
|
});
|
|
689
485
|
program.command('open-project')
|
|
690
|
-
.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>')
|
|
691
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.')
|
|
692
|
-
.option('-u, --unity-version <unityVersion>', 'The Unity version to
|
|
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.')
|
|
693
489
|
.option('-t, --build-target <buildTarget>', 'The Unity build target to switch the project to (e.g. StandaloneWindows64, StandaloneOSX, iOS, Android).')
|
|
694
490
|
.option('--verbose', 'Enable verbose logging.')
|
|
695
491
|
.action(async (options) => {
|
|
@@ -697,47 +493,48 @@ program.command('open-project')
|
|
|
697
493
|
logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
|
|
698
494
|
}
|
|
699
495
|
logging_1.Logger.instance.debugOptions(options);
|
|
700
|
-
const projectPath = options.unityProject?.toString()?.trim() ||
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
const unityProject = await unity_project_1.UnityProject.GetProject(projectPath);
|
|
704
|
-
if (!unityProject) {
|
|
705
|
-
logging_1.Logger.instance.error(`The specified path is not a valid Unity project: ${projectPath}`);
|
|
706
|
-
process.exit(1);
|
|
707
|
-
}
|
|
708
|
-
let unityVersion = unityProject?.version;
|
|
709
|
-
if (options.unityVersion) {
|
|
710
|
-
unityVersion = new unity_version_1.UnityVersion(options.unityVersion);
|
|
711
|
-
}
|
|
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();
|
|
712
499
|
const buildTarget = options.buildTarget?.toString()?.trim();
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
const moduleBuildTargetMap = unity_hub_1.UnityHub.GetPlatformTargetModuleMap();
|
|
716
|
-
module = moduleBuildTargetMap[buildTarget] ? [moduleBuildTargetMap[buildTarget]] : undefined;
|
|
717
|
-
}
|
|
718
|
-
const unityHub = new unity_hub_1.UnityHub();
|
|
719
|
-
const unityEditor = await unityHub.GetEditor(unityVersion, module);
|
|
720
|
-
logging_1.Logger.instance.info(`Opening "${unityProject.projectPath}" with Unity ${unityEditor.version}${buildTarget ? ` - ${buildTarget}` : ''}...`);
|
|
721
|
-
const openArgs = ['-projectPath', unityProject.projectPath];
|
|
722
|
-
if (buildTarget && buildTarget.length > 0) {
|
|
723
|
-
openArgs.push('-buildTarget', buildTarget);
|
|
724
|
-
}
|
|
725
|
-
let child = null;
|
|
726
|
-
try {
|
|
727
|
-
child = (0, child_process_1.spawn)(unityEditor.editorPath, openArgs, { detached: true });
|
|
728
|
-
child.unref();
|
|
500
|
+
if (version) {
|
|
501
|
+
args.push('--editor-version', version);
|
|
729
502
|
}
|
|
730
|
-
|
|
731
|
-
|
|
503
|
+
if (buildTarget) {
|
|
504
|
+
args.push('--build-target', buildTarget);
|
|
732
505
|
}
|
|
506
|
+
await forwardToUnityCli('open-project', args);
|
|
733
507
|
});
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
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
|
+
}
|
|
741
538
|
program.commandsGroup("Unity Package Manager:");
|
|
742
539
|
program.command('upm-install')
|
|
743
540
|
.description('Download and install the Unity Package Manager cli (pack/sign).')
|
|
@@ -791,7 +588,7 @@ program.command('upm-install')
|
|
|
791
588
|
process.exit(0);
|
|
792
589
|
}
|
|
793
590
|
catch (error) {
|
|
794
|
-
|
|
591
|
+
(0, failure_markers_1.ReportFailure)(error);
|
|
795
592
|
process.exit(1);
|
|
796
593
|
}
|
|
797
594
|
});
|
|
@@ -805,7 +602,7 @@ program.command('upm-version')
|
|
|
805
602
|
process.exit(0);
|
|
806
603
|
}
|
|
807
604
|
catch (error) {
|
|
808
|
-
|
|
605
|
+
(0, failure_markers_1.ReportFailure)(error);
|
|
809
606
|
process.exit(1);
|
|
810
607
|
}
|
|
811
608
|
});
|
|
@@ -870,120 +667,12 @@ program.command('upm-pack')
|
|
|
870
667
|
process.exit(0);
|
|
871
668
|
}
|
|
872
669
|
catch (error) {
|
|
873
|
-
|
|
874
|
-
process.exit(1);
|
|
875
|
-
}
|
|
876
|
-
});
|
|
877
|
-
program.command('sign-package')
|
|
878
|
-
.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.')
|
|
879
|
-
.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.')
|
|
880
|
-
.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.')
|
|
881
|
-
.option('--email <email>', 'Email associated with the Unity account. If unspecified, the UNITY_USERNAME environment variable will be used.')
|
|
882
|
-
.option('--password <password>', 'The password of the Unity account. If unspecified, the UNITY_PASSWORD environment variable will be used.')
|
|
883
|
-
.option('--organization <organization>', 'The Organization ID you copied from the Unity Cloud Dashboard. If unspecified, the UNITY_ORGANIZATION_ID environment variable will be used.')
|
|
884
|
-
.option('--verbose', 'Enable verbose logging.')
|
|
885
|
-
.action(async (options) => {
|
|
886
|
-
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).');
|
|
887
|
-
if (options.verbose) {
|
|
888
|
-
logging_1.Logger.instance.logLevel = logging_1.LogLevel.DEBUG;
|
|
889
|
-
}
|
|
890
|
-
logging_1.Logger.instance.debugOptions(options);
|
|
891
|
-
const packagePath = path.normalize(options.package?.toString()?.trim());
|
|
892
|
-
if (!packagePath || packagePath.length === 0) {
|
|
893
|
-
logging_1.Logger.instance.error('The package path is required. Use --package to specify it.');
|
|
894
|
-
process.exit(1);
|
|
895
|
-
}
|
|
896
|
-
const packageJsonPath = path.join(packagePath, 'package.json');
|
|
897
|
-
try {
|
|
898
|
-
await fs.promises.access(packageJsonPath, fs.constants.R_OK);
|
|
899
|
-
}
|
|
900
|
-
catch {
|
|
901
|
-
logging_1.Logger.instance.error(`Failed to find a valid package.json file at: ${packageJsonPath}`);
|
|
902
|
-
process.exit(1);
|
|
903
|
-
}
|
|
904
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
905
|
-
let outputPath = options.output?.toString()?.trim();
|
|
906
|
-
if (outputPath && outputPath.length > 0) {
|
|
907
|
-
outputPath = path.resolve(outputPath);
|
|
908
|
-
if (outputPath.endsWith('.tgz')) {
|
|
909
|
-
// remove .tgz if present
|
|
910
|
-
outputPath = outputPath.substring(0, outputPath.length - 4);
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
else {
|
|
914
|
-
outputPath = path.join(path.resolve(packagePath, '..'));
|
|
915
|
-
}
|
|
916
|
-
let username = options.email?.toString()?.trim() || process.env.UNITY_USERNAME || undefined;
|
|
917
|
-
if (!username || username.length === 0) {
|
|
918
|
-
username = await (0, utilities_1.PromptForSecretInput)('Email: ');
|
|
919
|
-
}
|
|
920
|
-
if (!username || username.length === 0) {
|
|
921
|
-
logging_1.Logger.instance.error('The email is required. Use --email to specify it.');
|
|
922
|
-
process.exit(1);
|
|
923
|
-
}
|
|
924
|
-
let password = options.password?.toString()?.trim() || process.env.UNITY_PASSWORD || undefined;
|
|
925
|
-
if (!password || password.length === 0) {
|
|
926
|
-
password = await (0, utilities_1.PromptForSecretInput)('Password: ');
|
|
927
|
-
}
|
|
928
|
-
if (!password || password.length === 0) {
|
|
929
|
-
logging_1.Logger.instance.error('The password is required. Use --password to specify it.');
|
|
930
|
-
process.exit(1);
|
|
931
|
-
}
|
|
932
|
-
let organization = options.organization?.toString()?.trim() || process.env.UNITY_ORGANIZATION_ID || undefined;
|
|
933
|
-
if (!organization || organization.length === 0) {
|
|
934
|
-
organization = await (0, utilities_1.PromptForSecretInput)('Organization ID: ');
|
|
935
|
-
}
|
|
936
|
-
if (!organization || organization.length === 0) {
|
|
937
|
-
logging_1.Logger.instance.error('The organization ID is required. Use --organization to specify it.');
|
|
670
|
+
(0, failure_markers_1.ReportFailure)(error);
|
|
938
671
|
process.exit(1);
|
|
939
672
|
}
|
|
940
|
-
// Mask credentials in CI environments before any potential logging
|
|
941
|
-
logging_1.Logger.instance.maskCredential(username);
|
|
942
|
-
logging_1.Logger.instance.maskCredential(password);
|
|
943
|
-
logging_1.Logger.instance.maskCredential(organization);
|
|
944
|
-
// must use a unity editor 6000.3 or newer
|
|
945
|
-
const unityVersion = new unity_version_1.UnityVersion('6000.3');
|
|
946
|
-
const unityHub = new unity_hub_1.UnityHub();
|
|
947
|
-
const unityEditor = await unityHub.GetEditor(unityVersion, undefined, ['f', 'b']);
|
|
948
|
-
try {
|
|
949
|
-
await unityEditor.Run({
|
|
950
|
-
args: [
|
|
951
|
-
'-batchmode',
|
|
952
|
-
'-username', username,
|
|
953
|
-
'-password', password,
|
|
954
|
-
'-upmPack', packagePath, path.normalize(outputPath),
|
|
955
|
-
'-cloudOrganization', organization
|
|
956
|
-
]
|
|
957
|
-
});
|
|
958
|
-
}
|
|
959
|
-
catch (error) {
|
|
960
|
-
// currently the editor returns exit code 1 even on success
|
|
961
|
-
}
|
|
962
|
-
finally {
|
|
963
|
-
if (fs.existsSync(outputPath)) {
|
|
964
|
-
const pkg = await (0, utilities_1.ResolveGlobToPath)([outputPath, `${path.basename(packageJson.name)}*.tgz`]);
|
|
965
|
-
logging_1.Logger.instance.info(`Package signed successfully: ${pkg}`);
|
|
966
|
-
// if the output directory was not specified in the command options,
|
|
967
|
-
// then unpack the .tgz file and overwrite the package contents.
|
|
968
|
-
if (!options.output || options.output.length === 0) {
|
|
969
|
-
await tar.x({
|
|
970
|
-
file: pkg,
|
|
971
|
-
cwd: packagePath,
|
|
972
|
-
strip: 1
|
|
973
|
-
});
|
|
974
|
-
logging_1.Logger.instance.info(`Package contents extracted to: ${packagePath}`);
|
|
975
|
-
fs.unlinkSync(pkg);
|
|
976
|
-
}
|
|
977
|
-
process.exit(0);
|
|
978
|
-
}
|
|
979
|
-
else {
|
|
980
|
-
logging_1.Logger.instance.error('Failed to sign the package.');
|
|
981
|
-
process.exit(1);
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
673
|
});
|
|
985
674
|
void program.parseAsync(process.argv).catch((err) => {
|
|
986
|
-
|
|
675
|
+
(0, failure_markers_1.ReportFailure)(err);
|
|
987
676
|
process.exit(1);
|
|
988
677
|
});
|
|
989
678
|
//# sourceMappingURL=cli.js.map
|