mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-04 00:18:01 +01:00
feat: outdated sdks project level (#7080)
This adds project level endpoint to catch outdated SDKs only for that project.
This commit is contained in:
parent
50ee7fa779
commit
a204f2c615
@ -218,6 +218,22 @@ export default class ClientInstanceStore implements IClientInstanceStore {
|
|||||||
|
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
async groupApplicationsBySdkAndProject(
|
||||||
|
projectId: string,
|
||||||
|
): Promise<{ sdkVersion: string; applications: string[] }[]> {
|
||||||
|
const rows = await this.db
|
||||||
|
.select([
|
||||||
|
'ci.sdk_version as sdkVersion',
|
||||||
|
this.db.raw('ARRAY_AGG(DISTINCT cme.app_name) as applications'),
|
||||||
|
])
|
||||||
|
.from('client_metrics_env as cme')
|
||||||
|
.leftJoin('features as f', 'f.name', 'cme.feature_name')
|
||||||
|
.leftJoin('client_instances as ci', 'ci.app_name', 'cme.app_name')
|
||||||
|
.where('f.project', projectId)
|
||||||
|
.groupBy('ci.sdk_version');
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
async getDistinctApplications(): Promise<string[]> {
|
async getDistinctApplications(): Promise<string[]> {
|
||||||
const rows = await this.db
|
const rows = await this.db
|
||||||
|
@ -275,6 +275,17 @@ export default class ClientInstanceService {
|
|||||||
return sdkApps.filter((sdkApp) => isOutdatedSdk(sdkApp.sdkVersion));
|
return sdkApps.filter((sdkApp) => isOutdatedSdk(sdkApp.sdkVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getOutdatedSdksByProject(
|
||||||
|
projectId: string,
|
||||||
|
): Promise<OutdatedSdksSchema['sdks']> {
|
||||||
|
const sdkApps =
|
||||||
|
await this.clientInstanceStore.groupApplicationsBySdkAndProject(
|
||||||
|
projectId,
|
||||||
|
);
|
||||||
|
|
||||||
|
return sdkApps.filter((sdkApp) => isOutdatedSdk(sdkApp.sdkVersion));
|
||||||
|
}
|
||||||
|
|
||||||
async usesSdkOlderThan(
|
async usesSdkOlderThan(
|
||||||
sdkName: string,
|
sdkName: string,
|
||||||
sdkVersion: string,
|
sdkVersion: string,
|
||||||
|
@ -18,6 +18,8 @@ import {
|
|||||||
createResponseSchema,
|
createResponseSchema,
|
||||||
type DeprecatedProjectOverviewSchema,
|
type DeprecatedProjectOverviewSchema,
|
||||||
deprecatedProjectOverviewSchema,
|
deprecatedProjectOverviewSchema,
|
||||||
|
outdatedSdksSchema,
|
||||||
|
type OutdatedSdksSchema,
|
||||||
type ProjectDoraMetricsSchema,
|
type ProjectDoraMetricsSchema,
|
||||||
projectDoraMetricsSchema,
|
projectDoraMetricsSchema,
|
||||||
projectOverviewSchema,
|
projectOverviewSchema,
|
||||||
@ -41,17 +43,21 @@ import { projectApplicationsQueryParameters } from '../../openapi/spec/project-a
|
|||||||
import { normalizeQueryParams } from '../feature-search/search-utils';
|
import { normalizeQueryParams } from '../feature-search/search-utils';
|
||||||
import ProjectInsightsController from '../project-insights/project-insights-controller';
|
import ProjectInsightsController from '../project-insights/project-insights-controller';
|
||||||
import FeatureLifecycleController from '../feature-lifecycle/feature-lifecycle-controller';
|
import FeatureLifecycleController from '../feature-lifecycle/feature-lifecycle-controller';
|
||||||
|
import type ClientInstanceService from '../metrics/instance/instance-service';
|
||||||
|
|
||||||
export default class ProjectController extends Controller {
|
export default class ProjectController extends Controller {
|
||||||
private projectService: ProjectService;
|
private projectService: ProjectService;
|
||||||
|
|
||||||
private openApiService: OpenApiService;
|
private openApiService: OpenApiService;
|
||||||
|
|
||||||
|
private clientInstanceService: ClientInstanceService;
|
||||||
|
|
||||||
private flagResolver: IFlagResolver;
|
private flagResolver: IFlagResolver;
|
||||||
|
|
||||||
constructor(config: IUnleashConfig, services: IUnleashServices, db: Db) {
|
constructor(config: IUnleashConfig, services: IUnleashServices, db: Db) {
|
||||||
super(config);
|
super(config);
|
||||||
this.projectService = services.projectService;
|
this.projectService = services.projectService;
|
||||||
|
this.clientInstanceService = services.clientInstanceService;
|
||||||
this.openApiService = services.openApiService;
|
this.openApiService = services.openApiService;
|
||||||
this.flagResolver = config.flagResolver;
|
this.flagResolver = config.flagResolver;
|
||||||
|
|
||||||
@ -160,6 +166,26 @@ export default class ProjectController extends Controller {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.route({
|
||||||
|
method: 'get',
|
||||||
|
path: '/:projectId/sdks/outdated',
|
||||||
|
handler: this.getOutdatedProjectSdks,
|
||||||
|
permission: NONE,
|
||||||
|
middleware: [
|
||||||
|
this.openApiService.validPath({
|
||||||
|
tags: ['Unstable'],
|
||||||
|
operationId: 'getOutdatedProjectSdks',
|
||||||
|
summary: 'Get outdated project SDKs',
|
||||||
|
description:
|
||||||
|
'Returns a list of the outdated SDKS with the applications using them.',
|
||||||
|
responses: {
|
||||||
|
200: createResponseSchema('outdatedSdksSchema'),
|
||||||
|
...getStandardResponses(404),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
this.use(
|
this.use(
|
||||||
'/',
|
'/',
|
||||||
new ProjectFeaturesController(
|
new ProjectFeaturesController(
|
||||||
@ -310,4 +336,21 @@ export default class ProjectController extends Controller {
|
|||||||
serializeDates(applications),
|
serializeDates(applications),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
async getOutdatedProjectSdks(
|
||||||
|
req: IAuthRequest<IProjectParam>,
|
||||||
|
res: Response<OutdatedSdksSchema>,
|
||||||
|
) {
|
||||||
|
const { projectId } = req.params;
|
||||||
|
const outdatedSdks =
|
||||||
|
await this.clientInstanceService.getOutdatedSdksByProject(
|
||||||
|
projectId,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.openApiService.respondWithValidation(
|
||||||
|
200,
|
||||||
|
res,
|
||||||
|
outdatedSdksSchema.$id,
|
||||||
|
{ sdks: outdatedSdks },
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,9 @@ export interface IClientInstanceStore
|
|||||||
groupApplicationsBySdk(): Promise<
|
groupApplicationsBySdk(): Promise<
|
||||||
{ sdkVersion: string; applications: string[] }[]
|
{ sdkVersion: string; applications: string[] }[]
|
||||||
>;
|
>;
|
||||||
|
groupApplicationsBySdkAndProject(
|
||||||
|
projectId: string,
|
||||||
|
): Promise<{ sdkVersion: string; applications: string[] }[]>;
|
||||||
getDistinctApplications(): Promise<string[]>;
|
getDistinctApplications(): Promise<string[]>;
|
||||||
getDistinctApplicationsCount(daysBefore?: number): Promise<number>;
|
getDistinctApplicationsCount(daysBefore?: number): Promise<number>;
|
||||||
deleteForApplication(appName: string): Promise<void>;
|
deleteForApplication(appName: string): Promise<void>;
|
||||||
|
@ -158,7 +158,7 @@ test('should show correct application metrics', async () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const { body: outdatedSdks } = await app.request
|
const { body: outdatedSdks } = await app.request
|
||||||
.get(`/api/admin/metrics/sdks/outdated`)
|
.get(`/api/admin/projects/default/sdks/outdated`)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
expect(outdatedSdks).toMatchObject({
|
expect(outdatedSdks).toMatchObject({
|
||||||
|
@ -49,6 +49,12 @@ export default class FakeClientInstanceStore implements IClientInstanceStore {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async groupApplicationsBySdkAndProject(
|
||||||
|
projectId: string,
|
||||||
|
): Promise<{ sdkVersion: string; applications: string[] }[]> {
|
||||||
|
throw new Error('Not implemented in mock');
|
||||||
|
}
|
||||||
|
|
||||||
async deleteAll(): Promise<void> {
|
async deleteAll(): Promise<void> {
|
||||||
this.instances = [];
|
this.instances = [];
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user