1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-05 17:53:12 +02:00

feat: update backend to include technicalDebt field (#10088)

Deprecate `health` for a more descriptive `technicalDebt` in project-related services and schemas.
This commit is contained in:
Tymoteusz Czech 2025-06-06 16:27:41 +02:00 committed by GitHub
parent c739ea71cf
commit a5e5ea0436
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 183 additions and 15 deletions

View File

@ -13,9 +13,13 @@ export type BasePersonalProject = {
export type PersonalProject = BasePersonalProject & {
owners?: ProjectOwners;
} & {
health: number;
technicalDebt: number;
memberCount: number;
featureCount: number;
/**
* @deprecated
*/
health: number;
};
export interface IPersonalDashboardReadModel {

View File

@ -96,6 +96,7 @@ export class PersonalDashboardService {
id: project.id,
name: project.name,
health: project.health,
technicalDebt: 100 - (project.health || 0),
memberCount: project.memberCount,
featureCount: project.featureCount,
}));
@ -193,6 +194,7 @@ export class PersonalDashboardService {
projectInsights?.potentiallyStaleFeatureCount || 0;
const staleFlags = projectInsights?.staleFeatureCount || 0;
const currentHealth = projectInsights?.health || 0;
const technicalDebt = projectInsights?.technicalDebt || 0;
return {
latestEvents,
@ -206,6 +208,10 @@ export class PersonalDashboardService {
potentiallyStaleFlags,
staleFlags,
activeFlags: totalFlags - staleFlags - potentiallyStaleFlags,
technicalDebt,
/**
* @deprecated
*/
health: currentHealth,
},
};

View File

@ -47,6 +47,12 @@ test('Return basic insights', async () => {
staleCount: 0,
rating: 100,
},
technicalDebt: {
activeCount: 0,
potentiallyStaleCount: 0,
staleCount: 0,
rating: 0,
},
leadTime: { features: [], projectAverage: 0 },
members: { currentMembers: 0, change: 0 },
});

View File

@ -93,6 +93,10 @@ export class ProjectInsightsService {
activeCount,
potentiallyStaleCount,
staleCount,
technicalDebt: overview.technicalDebt,
/**
* @deprecated
*/
rating: overview.health,
};
}
@ -101,7 +105,14 @@ export class ProjectInsightsService {
projectId: string,
archived: boolean = false,
userId?: number,
): Promise<{ health: number; features: IFeatureOverview[] }> {
): Promise<{
technicalDebt: number;
features: IFeatureOverview[];
/**
* @deprecated
*/
health: number;
}> {
const [project, features] = await Promise.all([
this.projectStore.get(projectId),
this.featureStrategiesStore.getFeatureOverview({
@ -113,6 +124,7 @@ export class ProjectInsightsService {
return {
health: project?.health || 0,
technicalDebt: 100 - (project?.health || 0),
features: features,
};
}
@ -151,9 +163,23 @@ export class ProjectInsightsService {
return {
stats,
featureTypeCounts,
health,
technicalDebt: {
rating: health.technicalDebt,
activeCount: health.activeCount,
potentiallyStaleCount: health.potentiallyStaleCount,
staleCount: health.staleCount,
},
leadTime,
members,
/**
* @deprecated
*/
health: {
rating: health.rating,
activeCount: health.activeCount,
potentiallyStaleCount: health.potentiallyStaleCount,
staleCount: health.staleCount,
},
};
}
}

View File

@ -88,6 +88,9 @@ export class ProjectStatusService {
health: {
current: currentHealth,
},
technicalDebt: {
current: 100 - currentHealth,
},
lifecycleSummary,
staleFlags: {
total: staleFlagCount,

View File

@ -18,12 +18,16 @@ export type ProjectForUi = {
export type ProjectForInsights = {
id: string;
health: number;
technicalDebt: number;
memberCount: number;
featureCount: number;
staleFeatureCount: number;
potentiallyStaleFeatureCount: number;
avgTimeToProduction: number;
/**
* @deprecated
*/
health: number;
};
export interface IProjectReadModel {

View File

@ -42,6 +42,7 @@ const mapProjectForInsights = (row): ProjectForInsights => {
Number(row.potentially_stale_feature_count) || 0,
memberCount: Number(row.number_of_users) || 0,
avgTimeToProduction: row.avg_time_to_prod_current_window || 0,
technicalDebt: 100 - (row.health || 0),
};
};

View File

@ -1280,6 +1280,7 @@ export default class ProjectService {
featureNaming: project.featureNaming,
defaultStickiness: project.defaultStickiness,
health: project.health || 0,
technicalDebt: 100 - (project.health || 0),
favorite: favorite,
updatedAt: project.updatedAt,
createdAt: project.createdAt,
@ -1338,6 +1339,7 @@ export default class ProjectService {
linkTemplates: project.linkTemplates,
defaultStickiness: project.defaultStickiness,
health: project.health || 0,
technicalDebt: 100 - (project.health || 0),
favorite: favorite,
updatedAt: project.updatedAt,
archivedAt: project.archivedAt,

View File

@ -26,6 +26,7 @@ export const healthOverviewSchema = {
'mode',
'members',
'health',
'technicalDebt',
'environments',
'features',
],
@ -75,9 +76,17 @@ export const healthOverviewSchema = {
},
health: {
type: 'integer',
description:
'The overall [health rating](https://docs.getunleash.io/reference/technical-debt#project-status) of the project.',
description: 'Use `technicalDebt` instead.',
example: 95,
deprecated: true,
},
technicalDebt: {
type: 'number',
example: 25,
minimum: 0,
maximum: 100,
description:
"An indicator of the [project's technical debt](https://docs.getunleash.io/reference/technical-debt#project-status) on a scale from 0 to 100",
},
environments: {
type: 'array',

View File

@ -28,6 +28,7 @@ export const personalDashboardProjectDetailsSchema = {
'staleFlags',
'potentiallyStaleFlags',
'health',
'technicalDebt',
],
properties: {
avgHealthCurrentWindow: {
@ -76,8 +77,17 @@ export const personalDashboardProjectDetailsSchema = {
health: {
type: 'integer',
minimum: 0,
description: "The project's current health score",
description: 'Use `technicalDebt` instead.',
example: 80,
deprecated: true,
},
technicalDebt: {
type: 'integer',
example: 25,
minimum: 0,
maximum: 100,
description:
"An indicator of the [project's technical debt](https://docs.getunleash.io/reference/technical-debt#project-status) on a scale from 0 to 100",
},
},
},

View File

@ -84,6 +84,7 @@ export const personalDashboardSchema = {
'id',
'name',
'health',
'technicalDebt',
'memberCount',
'featureCount',
],
@ -102,8 +103,16 @@ export const personalDashboardSchema = {
type: 'integer',
example: 50,
minimum: 0,
deprecated: true,
description: 'Use `technicalDebt` instead.',
},
technicalDebt: {
type: 'integer',
example: 25,
minimum: 0,
maximum: 100,
description:
"An indicator of the [project's health](https://docs.getunleash.io/reference/technical-debt#project-status) on a scale from 0 to 100",
"An indicator of the [project's technical debt](https://docs.getunleash.io/reference/technical-debt#project-status) on a scale from 0 to 100",
},
memberCount: {
type: 'integer',

View File

@ -8,7 +8,14 @@ export const projectInsightsSchema = {
$id: '#/components/schemas/projectInsightsSchema',
type: 'object',
additionalProperties: false,
required: ['stats', 'leadTime', 'featureTypeCounts', 'health', 'members'],
required: [
'stats',
'leadTime',
'featureTypeCounts',
'health',
'technicalDebt',
'members',
],
description:
'A high-level overview of a project insights. It contains information such as project statistics, overall health, types of flags, members overview, change requests overview.',
properties: {
@ -18,6 +25,7 @@ export const projectInsightsSchema = {
},
health: {
type: 'object',
deprecated: true,
required: [
'rating',
'activeCount',
@ -28,7 +36,7 @@ export const projectInsightsSchema = {
rating: {
type: 'integer',
description:
"An indicator of the [project's health](https://docs.getunleash.io/reference/technical-debt#project-status) on a scale from 0 to 100",
"An indicator of the [project's technical debt](https://docs.getunleash.io/reference/technical-debt#project-status) on a scale from 0 to 100",
example: 95,
},
activeCount: {
@ -48,7 +56,44 @@ export const projectInsightsSchema = {
example: 10,
},
},
description: 'Health summary of the project',
description:
'Use `technicalDebt` instead. Summary of the project health',
},
technicalDebt: {
type: 'object',
required: [
'rating',
'activeCount',
'potentiallyStaleCount',
'staleCount',
],
properties: {
rating: {
type: 'integer',
description:
"An indicator of the [project's technical debt](https://docs.getunleash.io/reference/technical-debt#project-status) on a scale from 0 to 100",
example: 25,
minimum: 0,
maximum: 100,
},
activeCount: {
type: 'number',
description: 'The number of active feature flags.',
example: 12,
},
potentiallyStaleCount: {
type: 'number',
description:
'The number of potentially stale feature flags.',
example: 5,
},
staleCount: {
type: 'number',
description: 'The number of stale feature flags.',
example: 10,
},
},
description: 'Summary of the projects technical debt',
},
leadTime: {
type: 'object',

View File

@ -84,8 +84,16 @@ export const projectOverviewSchema = {
health: {
type: 'number',
example: 50,
deprecated: true,
description: 'Use `technicalDebt` instead.',
},
technicalDebt: {
type: 'number',
example: 25,
minimum: 0,
maximum: 100,
description:
"An indicator of the [project's health](https://docs.getunleash.io/reference/technical-debt#project-status) on a scale from 0 to 100",
"An indicator of the [project's technical debt](https://docs.getunleash.io/reference/technical-debt#project-status) on a scale from 0 to 100",
},
environments: {
type: 'array',

View File

@ -28,8 +28,16 @@ export const projectSchema = {
health: {
type: 'number',
example: 50,
description: 'Use `technicalDebt` instead.',
deprecated: true,
},
technicalDebt: {
type: 'number',
example: 25,
minimum: 0,
maximum: 100,
description:
"An indicator of the [project's health](https://docs.getunleash.io/reference/technical-debt#project-status) on a scale from 0 to 100",
"An indicator of the [project's technical debt](https://docs.getunleash.io/reference/technical-debt#project-status) on a scale from 0 to 100",
},
featureCount: {
type: 'number',

View File

@ -6,6 +6,9 @@ test('projectStatusSchema', () => {
health: {
current: 50,
},
technicalDebt: {
current: 50,
},
lifecycleSummary: {
initial: {
currentFlags: 0,

View File

@ -32,6 +32,7 @@ export const projectStatusSchema = {
'activityCountByDate',
'resources',
'health',
'technicalDebt',
'lifecycleSummary',
'staleFlags',
],
@ -57,6 +58,21 @@ export const projectStatusSchema = {
},
},
},
technicalDebt: {
type: 'object',
additionalProperties: false,
required: ['current'],
description: "Information about the project's health rating",
properties: {
current: {
type: 'integer',
minimum: 0,
maximum: 100,
description: `The project's current health score, based on the ratio of healthy flags to stale and potentially stale flags.`,
example: 100,
},
},
},
resources: {
type: 'object',
additionalProperties: false,

View File

@ -342,7 +342,7 @@ export interface IProjectHealth {
features: IFeatureOverview[];
members: number;
version: number;
health: number;
technicalDebt: number;
favorite?: boolean;
updatedAt?: Date;
createdAt: Date | undefined;
@ -351,6 +351,10 @@ export interface IProjectHealth {
featureLimit?: number;
featureNaming?: IFeatureNaming;
defaultStickiness: string;
/**
* @deprecated
*/
health: number;
}
export type ProjectOnboardingStatus =
@ -366,7 +370,7 @@ export interface IProjectOverview {
featureTypeCounts: IFeatureTypeCount[];
members: number;
version: number;
health: number;
technicalDebt: number;
favorite?: boolean;
updatedAt?: Date;
archivedAt?: Date;
@ -378,6 +382,10 @@ export interface IProjectOverview {
defaultStickiness: string;
onboardingStatus: ProjectOnboardingStatus;
linkTemplates?: IProjectLinkTemplate[];
/**
* @deprecated
*/
health: number;
}
export interface IProjectHealthReport extends IProjectHealth {