Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rage-against-the-pixel/unity-cli",
"version": "1.6.8",
"version": "1.6.9",
"description": "A command line utility for the Unity Game Engine.",
"author": "RageAgainstThePixel",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ program.command('activate-license')
.option('-e, --email <email>', 'Email associated with the Unity account. Required when activating a personal or professional license.')
.option('-p, --password <password>', 'Password for the Unity account. Required when activating a personal or professional license.')
.option('-s, --serial <serial>', 'License serial number. Required when activating a professional license.')
.option('-c, --config <config>', 'Path to the configuration file, or base64 encoded JSON string. Required when activating a floating license.')
.option('-c, --config <config>', 'Path to the configuration file, raw JSON, or base64 encoded JSON string. Required when activating a floating license.')
.option('--verbose', 'Enable verbose logging.')
.option('--json', 'Prints the last line of output as JSON string.')
.action(async (options) => {
Expand Down
10 changes: 7 additions & 3 deletions src/license-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,8 @@ export class LicensingClient {
}
catch (error) {
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
this.logger.debug(`Failed to inspect licensing client log: ${error}`);
this.logger.error(`Failed to inspect licensing client log: ${error}`);
continue;
}
}

Expand All @@ -531,11 +532,12 @@ export class LicensingClient {
}

if (notConfiguredPattern.test(line)) {
this.logger.warn('Floating license server is not configured. Waiting for configuration...');
this.logger.debug('Floating license server is not configured. Waiting for configuration...');
}
}
}

await this.exec(['--showContext'], true);
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
}

Expand All @@ -561,6 +563,9 @@ export class LicensingClient {
this.logger.debug(`Using services config at: ${servicesConfigPath}`);
}

// For floating licenses, skip the entitlement check
skipEntitlementCheck = options.licenseType === LicenseType.floating;

if (!skipEntitlementCheck) {
const activeLicenses = await this.GetActiveEntitlements();

Expand All @@ -572,7 +577,6 @@ export class LicensingClient {

switch (options.licenseType) {
case LicenseType.floating: {
await this.Context();
await this.waitForLicenseServerConfiguration();
const output = await this.exec([`--acquire-floating`], true);
const tokenMatch = output.match(/with token:\s*"(?<token>[\w-]+)"/);
Expand Down
14 changes: 9 additions & 5 deletions tests/license-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,24 @@ describe('LicensingClient services config handling', () => {
});

describe('LicensingClient floating activation order', () => {
it('prepares services config before checking entitlements', async () => {
it('prepares services config without checking entitlements', async () => {
const client = new LicensingClient();
const setupSpy = jest.spyOn(client as any, 'setupServicesConfig').mockResolvedValue('/tmp/services-config.json');
const entitlementsSpy = jest.spyOn(client, 'GetActiveEntitlements').mockResolvedValue([]);
jest.spyOn(client, 'Context').mockResolvedValue();
jest.spyOn(client as any, 'waitForLicenseServerConfiguration').mockResolvedValue(undefined);
jest.spyOn(client as any, 'exec').mockResolvedValue('Successfully acquired with token: "token-123"');
const waitSpy = jest.spyOn(client as any, 'waitForLicenseServerConfiguration').mockResolvedValue(undefined);
const execSpy = jest.spyOn(client as any, 'exec').mockResolvedValue('Successfully acquired with token: "token-123"');

await client.Activate({
licenseType: LicenseType.floating,
servicesConfig: '{"floatingServer":"https://example.com"}'
});

expect(setupSpy).toHaveBeenCalledTimes(1);
expect(entitlementsSpy).toHaveBeenCalledTimes(1);
expect(entitlementsSpy.mock.invocationCallOrder[0]).toBeGreaterThan(setupSpy.mock.invocationCallOrder[0]);
expect(entitlementsSpy).not.toHaveBeenCalled();
expect(waitSpy).toHaveBeenCalledTimes(1);
expect(execSpy).toHaveBeenCalledTimes(1);
expect(execSpy.mock.invocationCallOrder[0]).toBeGreaterThan(waitSpy.mock.invocationCallOrder[0]);
});
});

Expand All @@ -69,6 +71,7 @@ describe('LicensingClient waitForLicenseServerConfiguration', () => {
const client = new LicensingClient();
const tempLog = createTempLog();
jest.spyOn(LicensingClient, 'ClientLogPath').mockReturnValue(tempLog);
jest.spyOn(client as any, 'exec').mockResolvedValue('');

setTimeout(() => {
fs.appendFileSync(tempLog, '\nFloating license server URL is: https://example.com (via config file)\n');
Expand All @@ -82,6 +85,7 @@ describe('LicensingClient waitForLicenseServerConfiguration', () => {
const client = new LicensingClient();
const tempLog = createTempLog();
jest.spyOn(LicensingClient, 'ClientLogPath').mockReturnValue(tempLog);
jest.spyOn(client as any, 'exec').mockResolvedValue('');

await expect((client as any).waitForLicenseServerConfiguration(200, 10)).rejects.toThrow(/Timed out waiting for floating license server configuration/);
fs.rmSync(tempLog, { force: true });
Expand Down
Loading