mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: tag feature on creation (#7664)
Now it is possible to tag feature on creation.
This commit is contained in:
		
							parent
							
								
									369518cd7d
								
							
						
					
					
						commit
						1e3c690185
					
				| @ -1256,7 +1256,7 @@ class FeatureToggleService { | ||||
|         await this.validateName(value.name); | ||||
|         await this.validateFeatureFlagNameAgainstPattern(value.name, projectId); | ||||
| 
 | ||||
|         const exists = await this.projectStore.hasProject(projectId); | ||||
|         const projectExists = await this.projectStore.hasProject(projectId); | ||||
| 
 | ||||
|         if (await this.projectStore.isFeatureLimitReached(projectId)) { | ||||
|             throw new InvalidOperationError( | ||||
| @ -1266,7 +1266,7 @@ class FeatureToggleService { | ||||
| 
 | ||||
|         await this.validateFeatureFlagLimit(); | ||||
| 
 | ||||
|         if (exists) { | ||||
|         if (projectExists) { | ||||
|             let featureData: FeatureToggleInsert; | ||||
|             if (isValidated) { | ||||
|                 featureData = { createdByUserId: auditUser.id, ...value }; | ||||
| @ -1301,6 +1301,16 @@ class FeatureToggleService { | ||||
|                 ); | ||||
|             } | ||||
| 
 | ||||
|             if (value.tags && value.tags.length > 0) { | ||||
|                 const mapTagsToFeatureTagInserts = value.tags.map((tag) => ({ | ||||
|                     tagValue: tag.value, | ||||
|                     tagType: tag.type, | ||||
|                     createdByUserId: auditUser.id, | ||||
|                     featureName: featureName, | ||||
|                 })); | ||||
|                 await this.tagStore.tagFeatures(mapTagsToFeatureTagInserts); | ||||
|             } | ||||
| 
 | ||||
|             await this.eventService.storeEvent( | ||||
|                 new FeatureCreatedEvent({ | ||||
|                     featureName, | ||||
|  | ||||
| @ -8,7 +8,10 @@ test('createFeatureSchema', () => { | ||||
|         description: | ||||
|             'Controls disabling of the comments section in case of an incident', | ||||
|         impressionData: false, | ||||
|         tags: ['simple:test', 'simple:test2'], | ||||
|         tags: [ | ||||
|             { type: 'simple', value: 'tag' }, | ||||
|             { type: 'simple', value: 'mytag' }, | ||||
|         ], | ||||
|     }; | ||||
| 
 | ||||
|     expect( | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| import type { FromSchema } from 'json-schema-to-ts'; | ||||
| import { tagSchema } from './tag-schema'; | ||||
| 
 | ||||
| export const createFeatureSchema = { | ||||
|     $id: '#/components/schemas/createFeatureSchema', | ||||
| @ -32,14 +33,17 @@ export const createFeatureSchema = { | ||||
|         }, | ||||
|         tags: { | ||||
|             type: 'array', | ||||
|             description: 'Tags to add to the feature.', | ||||
|             items: { | ||||
|                 type: 'string', | ||||
|                 example: 'simple:test', | ||||
|                 $ref: '#/components/schemas/tagSchema', | ||||
|             }, | ||||
|             description: 'List of tags associated with the feature', | ||||
|         }, | ||||
|     }, | ||||
|     components: {}, | ||||
|     components: { | ||||
|         schemas: { | ||||
|             tagSchema, | ||||
|         }, | ||||
|     }, | ||||
| } as const; | ||||
| 
 | ||||
| export type CreateFeatureSchema = FromSchema<typeof createFeatureSchema>; | ||||
|  | ||||
| @ -14,6 +14,7 @@ import { tagTypeSchema } from './tag-type-schema'; | ||||
| import { strategyVariantSchema } from './strategy-variant-schema'; | ||||
| import { featureDependenciesSchema } from './feature-dependencies-schema'; | ||||
| import { dependentFeatureSchema } from './dependent-feature-schema'; | ||||
| import { tagSchema } from './tag-schema'; | ||||
| 
 | ||||
| export const exportResultSchema = { | ||||
|     $id: '#/components/schemas/exportResultSchema', | ||||
| @ -194,6 +195,7 @@ export const exportResultSchema = { | ||||
|             tagTypeSchema, | ||||
|             featureDependenciesSchema, | ||||
|             dependentFeatureSchema, | ||||
|             tagSchema, | ||||
|         }, | ||||
|     }, | ||||
| } as const; | ||||
|  | ||||
| @ -8,6 +8,7 @@ import { featureStrategySchema } from './feature-strategy-schema'; | ||||
| import { environmentSchema } from './environment-schema'; | ||||
| import { featureEnvironmentSchema } from './feature-environment-schema'; | ||||
| import { strategyVariantSchema } from './strategy-variant-schema'; | ||||
| import { tagSchema } from './tag-schema'; | ||||
| 
 | ||||
| export const featuresSchema = { | ||||
|     $id: '#/components/schemas/featuresSchema', | ||||
| @ -40,6 +41,7 @@ export const featuresSchema = { | ||||
|             strategyVariantSchema, | ||||
|             parametersSchema, | ||||
|             variantSchema, | ||||
|             tagSchema, | ||||
|         }, | ||||
|     }, | ||||
| } as const; | ||||
|  | ||||
| @ -104,6 +104,15 @@ export const featureMetadataSchema = joi | ||||
|             .unique((a, b) => a.name === b.name) | ||||
|             .optional() | ||||
|             .items(variantsSchema), | ||||
|         tags: joi | ||||
|             .array() | ||||
|             .optional() | ||||
|             .items( | ||||
|                 joi.object().keys({ | ||||
|                     type: joi.string().required(), | ||||
|                     value: joi.string().required(), | ||||
|                 }), | ||||
|             ), | ||||
|         createdByUserId: joi.number(), | ||||
|     }) | ||||
|     .options({ allowUnknown: false, stripUnknown: true, abortEarly: false }); | ||||
|  | ||||
| @ -63,6 +63,7 @@ export interface FeatureToggleDTO { | ||||
|     createdAt?: Date; | ||||
|     impressionData?: boolean; | ||||
|     variants?: IVariant[]; | ||||
|     tags?: ITag[]; | ||||
|     createdByUserId?: number; | ||||
|     createdBy?: { | ||||
|         id: number; | ||||
|  | ||||
| @ -358,3 +358,25 @@ test('returns a feature flags impression data for a different project', async () | ||||
|             expect(projectFlag.impressionData).toBe(true); | ||||
|         }); | ||||
| }); | ||||
| 
 | ||||
| test('Can add tags while creating feature flag', async () => { | ||||
|     const featureName = 'test.feature.with.tagss'; | ||||
|     const tags = [{ value: 'tag1', type: 'simple' }]; | ||||
| 
 | ||||
|     await app.request.post('/api/admin/tags').send(tags[0]); | ||||
| 
 | ||||
|     await app.request.post('/api/admin/projects/default/features').send({ | ||||
|         name: featureName, | ||||
|         type: 'killswitch', | ||||
|         tags, | ||||
|     }); | ||||
| 
 | ||||
|     const { body } = await app.request | ||||
|         .get(`/api/admin/features/${featureName}/tags`) | ||||
|         .expect('Content-Type', /json/) | ||||
|         .expect(200); | ||||
| 
 | ||||
|     expect(body).toMatchObject({ | ||||
|         tags, | ||||
|     }); | ||||
| }); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user