1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-11-24 20:06:55 +01:00

feat: allow 'instanceInfo' to be added to the version checker hook (#11018)

Allows the `checkLatestVersion` function in the `VersionService` to
accept an optional `instanceInfo` parameter. If provided, and if the
promise returns a value that is truthy, then it will add `instanceInfo`
to the versionPayload.

The license key may not contain a plan or a customer name, and while it
definitely won't contain a client id, it has been requested that we
report `self-hosted` as the client ID (will be handled in enterprise).

Adding a second, optional parameter seemed to be the most backwards
compatible way of doing this rather than changing the established method
/ callback types.
This commit is contained in:
Thomas Heartman 2025-11-24 15:52:59 +01:00 committed by GitHub
parent bbad97a9e4
commit 712cecf38d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 73 additions and 1 deletions

View File

@ -2,7 +2,7 @@ import nock from 'nock';
import createStores from '../../test/fixtures/store.js';
import version from '../util/version.js';
import getLogger from '../../test/fixtures/no-logger.js';
import VersionService from './version-service.js';
import VersionService, { type IInstanceInfo } from './version-service.js';
import { randomId } from '../util/random-id.js';
beforeAll(() => {
@ -347,3 +347,64 @@ test('Counts production changes', async () => {
expect(scope.isDone()).toEqual(true);
nock.cleanAll();
});
describe('instance info reading', () => {
test('it sets instance info if the instanceInfoProvider promise returns a truthy value', async () => {
const instanceInfo: IInstanceInfo = {
customerPlan: 'Test Plan',
customerName: 'Test Company',
clientId: 'Test Id',
};
const url = `https://${randomId()}.example.com`;
const scope = nock(url)
.post(
'/',
(body) =>
body.instanceInfo &&
body.instanceInfo.customerPlan ===
instanceInfo.customerPlan &&
body.instanceInfo.customerName ===
instanceInfo.customerName &&
body.instanceInfo.clientId === instanceInfo.clientId,
)
.reply(() => [200]);
const stores = createStores();
const service = new VersionService(stores, {
getLogger,
versionCheck: { url, enable: true },
telemetry: true,
});
await service.checkLatestVersion(
() => Promise.resolve(fakeTelemetryData),
() => Promise.resolve(instanceInfo),
);
expect(scope.isDone()).toEqual(true);
});
test.each([
['is undefined', undefined],
['returns undefined', () => Promise.resolve(undefined)],
])(
'it does not set instance info if the instanceInfoProvider promise %s',
async (_, instanceInfoProvider) => {
const url = `https://${randomId()}.example.com`;
const scope = nock(url)
.post('/', (body) => body.instanceInfo === undefined)
.reply(() => [200]);
const stores = createStores();
const service = new VersionService(stores, {
getLogger,
versionCheck: { url, enable: true },
telemetry: true,
});
await service.checkLatestVersion(
() => Promise.resolve(fakeTelemetryData),
instanceInfoProvider,
);
expect(scope.isDone()).toEqual(true);
},
);
});

View File

@ -58,6 +58,12 @@ export interface IFeatureUsageInfo {
edgeInstanceUsage?: EdgeInstanceUsage;
}
export type IInstanceInfo = Partial<{
customerPlan: string;
customerName: string;
clientId: string;
}>;
export default class VersionService {
private logger: Logger;
@ -131,6 +137,7 @@ export default class VersionService {
async checkLatestVersion(
telemetryDataProvider: () => Promise<IFeatureUsageInfo>,
instanceInfoProvider?: () => Promise<IInstanceInfo | undefined>,
): Promise<void> {
const instanceId = await this.getInstanceId();
this.logger.debug(
@ -145,6 +152,10 @@ export default class VersionService {
if (this.telemetryEnabled) {
versionPayload.featureInfo = await telemetryDataProvider();
const instanceInfo = await instanceInfoProvider?.();
if (instanceInfo) {
versionPayload.instanceInfo = instanceInfo;
}
}
if (this.versionCheckUrl) {
const res = await ky.post(this.versionCheckUrl, {