mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-09 00:18:00 +01:00
feat: dependencies import validation (#5023)
This commit is contained in:
parent
b6d945befc
commit
2263a1f062
@ -340,7 +340,7 @@ test('validate import data', async () => {
|
||||
errors: [
|
||||
{
|
||||
message:
|
||||
'We detected the following custom strategy in the import file that needs to be created first:',
|
||||
'We detected the following custom strategy that needs to be created first:',
|
||||
affectedItems: ['customStrategy'],
|
||||
},
|
||||
{
|
||||
@ -351,7 +351,7 @@ test('validate import data', async () => {
|
||||
{
|
||||
affectedItems: ['customSegment'],
|
||||
message:
|
||||
'We detected the following segments in the import file that need to be created first:',
|
||||
'We detected the following segments that need to be created first:',
|
||||
},
|
||||
],
|
||||
warnings: [
|
||||
|
@ -52,6 +52,7 @@ import { FeatureNameCheckResultWithFeaturePattern } from '../feature-toggle/feat
|
||||
import { IDependentFeaturesReadModel } from '../dependent-features/dependent-features-read-model-type';
|
||||
import groupBy from 'lodash.groupby';
|
||||
import { ISegmentService } from '../../segments/segment-service-interface';
|
||||
import { FeatureDependenciesSchema } from '../../openapi/spec/feature-dependencies-schema';
|
||||
|
||||
export type IImportService = {
|
||||
validate(
|
||||
@ -194,6 +195,7 @@ export default class ExportImportService
|
||||
featureNameCheckResult,
|
||||
featureLimitResult,
|
||||
unsupportedSegments,
|
||||
unsupportedDependencies,
|
||||
] = await Promise.all([
|
||||
this.getUnsupportedStrategies(dto),
|
||||
this.getUsedCustomStrategies(dto),
|
||||
@ -210,6 +212,7 @@ export default class ExportImportService
|
||||
this.getInvalidFeatureNames(dto),
|
||||
this.getFeatureLimit(dto),
|
||||
this.getUnsupportedSegments(dto),
|
||||
this.getMissingDependencies(dto),
|
||||
]);
|
||||
|
||||
const errors = ImportValidationMessages.compileErrors({
|
||||
@ -221,6 +224,7 @@ export default class ExportImportService
|
||||
featureNameCheckResult,
|
||||
featureLimitResult,
|
||||
segments: unsupportedSegments,
|
||||
dependencies: unsupportedDependencies,
|
||||
});
|
||||
const warnings = ImportValidationMessages.compileWarnings({
|
||||
archivedFeatures,
|
||||
@ -250,6 +254,7 @@ export default class ExportImportService
|
||||
this.importPermissionsService.verifyPermissions(dto, user, mode),
|
||||
this.verifyFeatures(dto),
|
||||
this.verifySegments(dto),
|
||||
this.verifyDependencies(dto),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -459,6 +464,32 @@ export default class ExportImportService
|
||||
: [];
|
||||
}
|
||||
|
||||
private async getMissingDependencies(
|
||||
dto: ImportTogglesSchema,
|
||||
): Promise<string[]> {
|
||||
const dependentFeatures =
|
||||
dto.data.dependencies?.flatMap((dependency) =>
|
||||
dependency.dependencies.map((d) => d.feature),
|
||||
) || [];
|
||||
const importedFeatures = dto.data.features.map((f) => f.name);
|
||||
|
||||
const missingFromImported = dependentFeatures.filter(
|
||||
(feature) => !importedFeatures.includes(feature),
|
||||
);
|
||||
|
||||
let missingFeatures: string[] = [];
|
||||
|
||||
if (missingFromImported.length) {
|
||||
const featuresFromStore = (
|
||||
await this.toggleStore.getAllByNames(missingFromImported)
|
||||
).map((f) => f.name);
|
||||
missingFeatures = missingFromImported.filter(
|
||||
(feature) => !featuresFromStore.includes(feature),
|
||||
);
|
||||
}
|
||||
return missingFeatures;
|
||||
}
|
||||
|
||||
private async verifySegments(dto: ImportTogglesSchema) {
|
||||
const unsupportedSegments = await this.getUnsupportedSegments(dto);
|
||||
if (unsupportedSegments.length > 0) {
|
||||
@ -468,6 +499,17 @@ export default class ExportImportService
|
||||
}
|
||||
}
|
||||
|
||||
private async verifyDependencies(dto: ImportTogglesSchema) {
|
||||
const unsupportedDependencies = await this.getMissingDependencies(dto);
|
||||
if (unsupportedDependencies.length > 0) {
|
||||
throw new BadDataError(
|
||||
`The following dependent features are missing: ${unsupportedDependencies.join(
|
||||
', ',
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async verifyContextFields(dto: ImportTogglesSchema) {
|
||||
const unsupportedContextFields = await this.getUnsupportedContextFields(
|
||||
dto,
|
||||
|
@ -1006,6 +1006,16 @@ test('validate import data', async () => {
|
||||
},
|
||||
createdContextField,
|
||||
],
|
||||
dependencies: [
|
||||
{
|
||||
feature: 'childFeature',
|
||||
dependencies: [
|
||||
{
|
||||
feature: 'parentFeature',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@ -1023,7 +1033,7 @@ test('validate import data', async () => {
|
||||
errors: [
|
||||
{
|
||||
message:
|
||||
'We detected the following custom strategy in the import file that needs to be created first:',
|
||||
'We detected the following custom strategy that needs to be created first:',
|
||||
affectedItems: ['customStrategy'],
|
||||
},
|
||||
{
|
||||
@ -1051,9 +1061,14 @@ test('validate import data', async () => {
|
||||
},
|
||||
{
|
||||
message:
|
||||
'We detected the following segments in the import file that need to be created first:',
|
||||
'We detected the following segments that need to be created first:',
|
||||
affectedItems: ['customSegment'],
|
||||
},
|
||||
{
|
||||
affectedItems: ['parentFeature'],
|
||||
message:
|
||||
'We detected the following dependencies that need to be created first:',
|
||||
},
|
||||
],
|
||||
warnings: [
|
||||
{
|
||||
|
@ -15,6 +15,7 @@ export interface IErrorsParams {
|
||||
featureNameCheckResult: FeatureNameCheckResultWithFeaturePattern;
|
||||
featureLimitResult: ProjectFeaturesLimit;
|
||||
segments: string[];
|
||||
dependencies: string[];
|
||||
}
|
||||
|
||||
export interface IWarningParams {
|
||||
@ -48,13 +49,14 @@ export class ImportValidationMessages {
|
||||
featureNameCheckResult,
|
||||
featureLimitResult,
|
||||
segments,
|
||||
dependencies,
|
||||
}: IErrorsParams): ImportTogglesValidateItemSchema[] {
|
||||
const errors: ImportTogglesValidateItemSchema[] = [];
|
||||
|
||||
if (strategies.length > 0) {
|
||||
errors.push({
|
||||
message:
|
||||
'We detected the following custom strategy in the import file that needs to be created first:',
|
||||
'We detected the following custom strategy that needs to be created first:',
|
||||
affectedItems: strategies.map((strategy) => strategy.name),
|
||||
});
|
||||
}
|
||||
@ -111,11 +113,19 @@ export class ImportValidationMessages {
|
||||
if (segments.length > 0) {
|
||||
errors.push({
|
||||
message:
|
||||
'We detected the following segments in the import file that need to be created first:',
|
||||
'We detected the following segments that need to be created first:',
|
||||
affectedItems: segments,
|
||||
});
|
||||
}
|
||||
|
||||
if (dependencies.length > 0) {
|
||||
errors.push({
|
||||
message:
|
||||
'We detected the following dependencies that need to be created first:',
|
||||
affectedItems: dependencies,
|
||||
});
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,8 @@ import { legalValueSchema } from './legal-value-schema';
|
||||
import { tagTypeSchema } from './tag-type-schema';
|
||||
import { featureEnvironmentSchema } from './feature-environment-schema';
|
||||
import { strategyVariantSchema } from './strategy-variant-schema';
|
||||
import { featureDependenciesSchema } from './feature-dependencies-schema';
|
||||
import { dependentFeatureSchema } from './dependent-feature-schema';
|
||||
|
||||
export const importTogglesSchema = {
|
||||
$id: '#/components/schemas/importTogglesSchema',
|
||||
@ -56,6 +58,8 @@ export const importTogglesSchema = {
|
||||
parametersSchema,
|
||||
legalValueSchema,
|
||||
tagTypeSchema,
|
||||
featureDependenciesSchema,
|
||||
dependentFeatureSchema,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
@ -163,3 +163,4 @@ export * from './update-feature-strategy-segments-schema';
|
||||
export * from './dependent-feature-schema';
|
||||
export * from './create-dependent-feature-schema';
|
||||
export * from './parent-feature-options-schema';
|
||||
export * from './feature-dependencies-schema';
|
||||
|
Loading…
Reference in New Issue
Block a user