1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-25 00:07:47 +01:00

fix: don't create duplicate tags on import (#3688)

This commit is contained in:
Mateusz Kwasniewski 2023-05-04 22:19:00 +02:00 committed by GitHub
parent c21fafc8aa
commit 108e15940e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 11 deletions

View File

@ -280,17 +280,17 @@ export default class ExportImportService {
await this.importTogglesStore.deleteTagsForFeatures( await this.importTogglesStore.deleteTagsForFeatures(
dto.data.features.map((feature) => feature.name), dto.data.features.map((feature) => feature.name),
); );
return Promise.all(
(dto.data.featureTags || []).map((tag) => { const featureTags = dto.data.featureTags || [];
return tag.tagType for (const tag of featureTags) {
? this.featureTagService.addTag( if (tag.tagType) {
tag.featureName, await this.featureTagService.addTag(
{ type: tag.tagType, value: tag.tagValue }, tag.featureName,
extractUsernameFromUser(user), { type: tag.tagType, value: tag.tagValue },
) extractUsernameFromUser(user),
: Promise.resolve(); );
}), }
); }
} }
private async importContextFields(dto: ImportTogglesSchema, user: User) { private async importContextFields(dto: ImportTogglesSchema, user: User) {

View File

@ -14,6 +14,7 @@ import {
IProjectStore, IProjectStore,
ISegment, ISegment,
IStrategyConfig, IStrategyConfig,
ITagStore,
IVariant, IVariant,
} from '../../types'; } from '../../types';
import { DEFAULT_ENV } from '../../util'; import { DEFAULT_ENV } from '../../util';
@ -33,6 +34,7 @@ let environmentStore: IEnvironmentStore;
let contextFieldStore: IContextFieldStore; let contextFieldStore: IContextFieldStore;
let projectStore: IProjectStore; let projectStore: IProjectStore;
let toggleStore: IFeatureToggleStore; let toggleStore: IFeatureToggleStore;
let tagStore: ITagStore;
const defaultStrategy: IStrategyConfig = { const defaultStrategy: IStrategyConfig = {
name: 'default', name: 'default',
@ -150,6 +152,7 @@ beforeAll(async () => {
projectStore = db.stores.projectStore; projectStore = db.stores.projectStore;
contextFieldStore = db.stores.contextFieldStore; contextFieldStore = db.stores.contextFieldStore;
toggleStore = db.stores.featureToggleStore; toggleStore = db.stores.featureToggleStore;
tagStore = db.stores.tagStore;
}); });
beforeEach(async () => { beforeEach(async () => {
@ -157,6 +160,7 @@ beforeEach(async () => {
await toggleStore.deleteAll(); await toggleStore.deleteAll();
await projectStore.deleteAll(); await projectStore.deleteAll();
await environmentStore.deleteAll(); await environmentStore.deleteAll();
await tagStore.deleteAll();
await contextFieldStore.deleteAll(); await contextFieldStore.deleteAll();
await app.createContextField({ name: 'appName' }); await app.createContextField({ name: 'appName' });
@ -544,6 +548,10 @@ const exportedFeature: ImportTogglesSchema['data']['features'][0] = {
project: 'old_project', project: 'old_project',
name: 'first_feature', name: 'first_feature',
}; };
const anotherExportedFeature: ImportTogglesSchema['data']['features'][0] = {
project: 'old_project',
name: 'second_feature',
};
const constraints: ImportTogglesSchema['data']['featureStrategies'][0]['constraints'] = const constraints: ImportTogglesSchema['data']['featureStrategies'][0]['constraints'] =
[ [
{ {
@ -614,6 +622,31 @@ const defaultImportPayload: ImportTogglesSchema = {
environment: DEFAULT_ENV, environment: DEFAULT_ENV,
}; };
const importWithMultipleFeatures: ImportTogglesSchema = {
data: {
features: [exportedFeature, anotherExportedFeature],
featureStrategies: [],
featureEnvironments: [],
featureTags: [
{
featureName: exportedFeature.name,
tagType: 'simple',
tagValue: 'tag1',
},
{
featureName: anotherExportedFeature.name,
tagType: 'simple',
tagValue: 'tag1',
},
],
tagTypes,
contextFields: [],
segments: [],
},
project: DEFAULT_PROJECT,
environment: DEFAULT_ENV,
};
const getFeature = async (feature: string) => const getFeature = async (feature: string) =>
app.request app.request
.get(`/api/admin/projects/${DEFAULT_PROJECT}/features/${feature}`) .get(`/api/admin/projects/${DEFAULT_PROJECT}/features/${feature}`)
@ -672,6 +705,24 @@ test('import features to existing project and environment', async () => {
}); });
}); });
test('import multiple features with same tag', async () => {
await createProjects();
await app.importToggles(importWithMultipleFeatures);
const { body: tags1 } = await getTags(exportedFeature.name);
const { body: tags2 } = await getTags(anotherExportedFeature.name);
expect(tags1).toMatchObject({
version: 1,
tags: [{ value: 'tag1', type: 'simple' }],
});
expect(tags2).toMatchObject({
version: 1,
tags: [{ value: 'tag1', type: 'simple' }],
});
});
test('importing same JSON should work multiple times in a row', async () => { test('importing same JSON should work multiple times in a row', async () => {
await createProjects(); await createProjects();
await app.importToggles(defaultImportPayload); await app.importToggles(defaultImportPayload);