mirror of
https://github.com/Unleash/unleash.git
synced 2025-09-05 17:53:12 +02:00
feat: feature environments variants usage ui flag
This commit is contained in:
parent
668cb81384
commit
80049c2fa9
@ -490,4 +490,12 @@ export class FeatureEnvironmentStore implements IFeatureEnvironmentStore {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async variantExists(): Promise<boolean> {
|
||||
const result = await this.db.raw(
|
||||
`SELECT EXISTS (SELECT 1 FROM ${T.featureEnvs} WHERE variants <> '[]'::jsonb) AS present`,
|
||||
);
|
||||
const { present } = result.rows[0];
|
||||
return present;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import FakeClientMetricsStoreV2 from '../client-metrics/fake-client-metrics-stor
|
||||
import FakeStrategiesStore from '../../../../test/fixtures/fake-strategies-store';
|
||||
import FakeFeatureToggleStore from '../../feature-toggle/fakes/fake-feature-toggle-store';
|
||||
import type { IApplicationOverview } from './models';
|
||||
import FakeFeatureEnvironmentStore from '../../../../test/fixtures/fake-feature-environment-store';
|
||||
|
||||
let config: IUnleashConfig;
|
||||
beforeAll(() => {
|
||||
@ -29,6 +30,7 @@ test('Multiple registrations of same appname and instanceid within same time per
|
||||
featureToggleStore: new FakeFeatureToggleStore(),
|
||||
clientApplicationsStore,
|
||||
clientInstanceStore,
|
||||
featureEnvironmentStore: new FakeFeatureEnvironmentStore(),
|
||||
eventStore: new FakeEventStore(),
|
||||
},
|
||||
config,
|
||||
@ -79,6 +81,7 @@ test('Multiple unique clients causes multiple registrations', async () => {
|
||||
featureToggleStore: new FakeFeatureToggleStore(),
|
||||
clientApplicationsStore,
|
||||
clientInstanceStore,
|
||||
featureEnvironmentStore: new FakeFeatureEnvironmentStore(),
|
||||
eventStore: new FakeEventStore(),
|
||||
},
|
||||
config,
|
||||
@ -129,6 +132,7 @@ test('Same client registered outside of dedup interval will be registered twice'
|
||||
featureToggleStore: new FakeFeatureToggleStore(),
|
||||
clientApplicationsStore,
|
||||
clientInstanceStore,
|
||||
featureEnvironmentStore: new FakeFeatureEnvironmentStore(),
|
||||
eventStore: new FakeEventStore(),
|
||||
},
|
||||
config,
|
||||
@ -179,6 +183,7 @@ test('No registrations during a time period will not call stores', async () => {
|
||||
featureToggleStore: new FakeFeatureToggleStore(),
|
||||
clientApplicationsStore,
|
||||
clientInstanceStore,
|
||||
featureEnvironmentStore: new FakeFeatureEnvironmentStore(),
|
||||
eventStore: new FakeEventStore(),
|
||||
},
|
||||
config,
|
||||
|
@ -1,6 +1,9 @@
|
||||
import { APPLICATION_CREATED, CLIENT_REGISTER } from '../../../types/events';
|
||||
import type { IApplication, IApplicationOverview } from './models';
|
||||
import type { IUnleashStores } from '../../../types/stores';
|
||||
import type {
|
||||
IFeatureEnvironmentStore,
|
||||
IUnleashStores,
|
||||
} from '../../../types/stores';
|
||||
import type { IUnleashConfig } from '../../../types/option';
|
||||
import type { IEventStore } from '../../../types/stores/event-store';
|
||||
import type {
|
||||
@ -46,6 +49,8 @@ export default class ClientInstanceService {
|
||||
|
||||
private privateProjectChecker: IPrivateProjectChecker;
|
||||
|
||||
private featureEnvironmentStore: IFeatureEnvironmentStore;
|
||||
|
||||
private flagResolver: IFlagResolver;
|
||||
|
||||
constructor(
|
||||
@ -55,6 +60,7 @@ export default class ClientInstanceService {
|
||||
featureToggleStore,
|
||||
clientInstanceStore,
|
||||
clientApplicationsStore,
|
||||
featureEnvironmentStore,
|
||||
eventStore,
|
||||
}: Pick<
|
||||
IUnleashStores,
|
||||
@ -63,6 +69,7 @@ export default class ClientInstanceService {
|
||||
| 'featureToggleStore'
|
||||
| 'clientApplicationsStore'
|
||||
| 'clientInstanceStore'
|
||||
| 'featureEnvironmentStore'
|
||||
| 'eventStore'
|
||||
>,
|
||||
{
|
||||
@ -78,6 +85,7 @@ export default class ClientInstanceService {
|
||||
this.clientInstanceStore = clientInstanceStore;
|
||||
this.eventStore = eventStore;
|
||||
this.privateProjectChecker = privateProjectChecker;
|
||||
this.featureEnvironmentStore = featureEnvironmentStore;
|
||||
this.flagResolver = flagResolver;
|
||||
this.logger = getLogger(
|
||||
'/services/client-metrics/client-instance-service.ts',
|
||||
@ -294,4 +302,8 @@ export default class ClientInstanceService {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async usesFeatureEnvironmentVariants() {
|
||||
return this.featureEnvironmentStore.variantExists();
|
||||
}
|
||||
}
|
||||
|
@ -98,3 +98,39 @@ describe('displayUpgradeEdgeBanner', () => {
|
||||
expect(body.flags.displayUpgradeEdgeBanner).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('displayFeatureEnvironmentVariants', () => {
|
||||
test('ui config should have displayFeatureEnvironmentVariants flag disabled if no env variants are used', async () => {
|
||||
const { body } = await request
|
||||
.get(`${base}/api/admin/ui-config`)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200);
|
||||
expect(body.flags).toBeTruthy();
|
||||
expect(body.flags.displayFeatureEnvironmentVariants).toEqual(false);
|
||||
});
|
||||
test('ui config should have displayFeatureEnvironmentVariants flag enabled if env variants are used', async () => {
|
||||
await stores.featureEnvironmentStore.addEnvironmentToFeature(
|
||||
'test',
|
||||
'default',
|
||||
true,
|
||||
);
|
||||
await stores.featureEnvironmentStore.addVariantsToFeatureEnvironment(
|
||||
'test',
|
||||
'default',
|
||||
[
|
||||
{
|
||||
name: 'a',
|
||||
weight: 1,
|
||||
weightType: 'fix',
|
||||
stickiness: 'default',
|
||||
},
|
||||
],
|
||||
);
|
||||
const { body } = await request
|
||||
.get(`${base}/api/admin/ui-config`)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200);
|
||||
expect(body.flags).toBeTruthy();
|
||||
expect(body.flags.displayFeatureEnvironmentVariants).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
@ -44,6 +44,8 @@ class ConfigController extends Controller {
|
||||
|
||||
private usesOldEdgeFunction: () => Promise<boolean>;
|
||||
|
||||
private usesFeatureEnvironmentVariants: () => Promise<boolean>;
|
||||
|
||||
private readonly openApiService: OpenApiService;
|
||||
|
||||
constructor(
|
||||
@ -86,6 +88,14 @@ class ConfigController extends Controller {
|
||||
maxAge: minutesToMilliseconds(10),
|
||||
},
|
||||
);
|
||||
this.usesFeatureEnvironmentVariants = memoizee(
|
||||
async () =>
|
||||
this.clientInstanceService.usesFeatureEnvironmentVariants(),
|
||||
{
|
||||
promise: true,
|
||||
maxAge: minutesToMilliseconds(10),
|
||||
},
|
||||
);
|
||||
|
||||
this.route({
|
||||
method: 'get',
|
||||
@ -134,11 +144,13 @@ class ConfigController extends Controller {
|
||||
simpleAuthSettings,
|
||||
maintenanceMode,
|
||||
usesOldEdge,
|
||||
usesFeatureEnvironmentVariants,
|
||||
] = await Promise.all([
|
||||
this.frontendApiService.getFrontendSettings(false),
|
||||
this.settingService.get<SimpleAuthSettings>(simpleAuthSettingsKey),
|
||||
this.maintenanceService.isMaintenanceMode(),
|
||||
this.usesOldEdgeFunction(),
|
||||
this.usesFeatureEnvironmentVariants(),
|
||||
]);
|
||||
|
||||
const disablePasswordAuth =
|
||||
@ -155,6 +167,7 @@ class ConfigController extends Controller {
|
||||
displayUpgradeEdgeBanner:
|
||||
usesOldEdge ||
|
||||
this.config.flagResolver.isEnabled('displayEdgeBanner'),
|
||||
displayFeatureEnvironmentVariants: usesFeatureEnvironmentVariants,
|
||||
};
|
||||
|
||||
const response: UiConfigSchema = {
|
||||
|
@ -86,4 +86,6 @@ export interface IFeatureEnvironmentStore
|
||||
): Promise<void>;
|
||||
|
||||
clonePreviousVariants(environment: string, project: string): Promise<void>;
|
||||
|
||||
variantExists(): Promise<boolean>;
|
||||
}
|
||||
|
@ -98,3 +98,12 @@ test('sets ui config with frontendSettings', async () => {
|
||||
expect(res.body.frontendApiOrigins).toEqual(frontendApiOrigins),
|
||||
);
|
||||
});
|
||||
|
||||
test('ui config should have displayFeatureEnvironmentVariants flag disabled if no env variants are used', async () => {
|
||||
const { body } = await app.request
|
||||
.get('/api/admin/ui-config')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200);
|
||||
expect(body.flags).toBeTruthy();
|
||||
expect(body.flags.displayFeatureEnvironmentVariants).toEqual(false);
|
||||
});
|
||||
|
@ -245,4 +245,12 @@ export default class FakeFeatureEnvironmentStore
|
||||
features.includes(featureEnv.featureName),
|
||||
);
|
||||
}
|
||||
|
||||
async variantExists() {
|
||||
return this.featureEnvironments.some(
|
||||
(featureEnvironment) =>
|
||||
featureEnvironment.variants &&
|
||||
featureEnvironment.variants.length > 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user