1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-25 00:07:47 +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:
Jaanus Sellin 2024-05-20 12:58:30 +03:00 committed by GitHub
parent 50ee7fa779
commit a204f2c615
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 80 additions and 1 deletions

View File

@ -218,6 +218,22 @@ export default class ClientInstanceStore implements IClientInstanceStore {
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[]> {
const rows = await this.db

View File

@ -275,6 +275,17 @@ export default class ClientInstanceService {
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(
sdkName: string,
sdkVersion: string,

View File

@ -18,6 +18,8 @@ import {
createResponseSchema,
type DeprecatedProjectOverviewSchema,
deprecatedProjectOverviewSchema,
outdatedSdksSchema,
type OutdatedSdksSchema,
type ProjectDoraMetricsSchema,
projectDoraMetricsSchema,
projectOverviewSchema,
@ -41,17 +43,21 @@ import { projectApplicationsQueryParameters } from '../../openapi/spec/project-a
import { normalizeQueryParams } from '../feature-search/search-utils';
import ProjectInsightsController from '../project-insights/project-insights-controller';
import FeatureLifecycleController from '../feature-lifecycle/feature-lifecycle-controller';
import type ClientInstanceService from '../metrics/instance/instance-service';
export default class ProjectController extends Controller {
private projectService: ProjectService;
private openApiService: OpenApiService;
private clientInstanceService: ClientInstanceService;
private flagResolver: IFlagResolver;
constructor(config: IUnleashConfig, services: IUnleashServices, db: Db) {
super(config);
this.projectService = services.projectService;
this.clientInstanceService = services.clientInstanceService;
this.openApiService = services.openApiService;
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(
'/',
new ProjectFeaturesController(
@ -310,4 +336,21 @@ export default class ProjectController extends Controller {
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 },
);
}
}

View File

@ -29,6 +29,9 @@ export interface IClientInstanceStore
groupApplicationsBySdk(): Promise<
{ sdkVersion: string; applications: string[] }[]
>;
groupApplicationsBySdkAndProject(
projectId: string,
): Promise<{ sdkVersion: string; applications: string[] }[]>;
getDistinctApplications(): Promise<string[]>;
getDistinctApplicationsCount(daysBefore?: number): Promise<number>;
deleteForApplication(appName: string): Promise<void>;

View File

@ -158,7 +158,7 @@ test('should show correct application metrics', async () => {
]);
const { body: outdatedSdks } = await app.request
.get(`/api/admin/metrics/sdks/outdated`)
.get(`/api/admin/projects/default/sdks/outdated`)
.expect(200);
expect(outdatedSdks).toMatchObject({

View File

@ -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> {
this.instances = [];
}