mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: dependant flag on feature search (#6684)
This commit is contained in:
		
							parent
							
								
									d4f52cdb54
								
							
						
					
					
						commit
						283a8f4d8b
					
				@ -137,6 +137,11 @@ class FeatureSearchStore implements IFeatureSearchStore {
 | 
			
		||||
                    this.db.raw(
 | 
			
		||||
                        'EXISTS (SELECT 1 FROM feature_strategies WHERE feature_strategies.feature_name = features.name AND feature_strategies.environment = feature_environments.environment AND (feature_strategies.disabled IS NULL OR feature_strategies.disabled = false)) as has_enabled_strategies',
 | 
			
		||||
                    ),
 | 
			
		||||
                    this.db.raw(`CASE
 | 
			
		||||
                            WHEN dependent_features.parent = features.name THEN 'parent'
 | 
			
		||||
                            WHEN dependent_features.child = features.name THEN 'child'
 | 
			
		||||
                            ELSE null
 | 
			
		||||
                            END AS dependency`),
 | 
			
		||||
                ];
 | 
			
		||||
 | 
			
		||||
                applyQueryParams(query, queryParams);
 | 
			
		||||
@ -197,6 +202,17 @@ class FeatureSearchStore implements IFeatureSearchStore {
 | 
			
		||||
                        'feature_strategy_segment.segment_id',
 | 
			
		||||
                        'segments.id',
 | 
			
		||||
                    )
 | 
			
		||||
                    .leftJoin('dependent_features', (qb) => {
 | 
			
		||||
                        qb.on(
 | 
			
		||||
                            'dependent_features.parent',
 | 
			
		||||
                            '=',
 | 
			
		||||
                            'features.name',
 | 
			
		||||
                        ).orOn(
 | 
			
		||||
                            'dependent_features.child',
 | 
			
		||||
                            '=',
 | 
			
		||||
                            'features.name',
 | 
			
		||||
                        );
 | 
			
		||||
                    })
 | 
			
		||||
                    .leftJoin('client_metrics_env', (qb) => {
 | 
			
		||||
                        qb.on(
 | 
			
		||||
                            'client_metrics_env.environment',
 | 
			
		||||
@ -335,6 +351,7 @@ class FeatureSearchStore implements IFeatureSearchStore {
 | 
			
		||||
                    stale: row.stale,
 | 
			
		||||
                    impressionData: row.impression_data,
 | 
			
		||||
                    lastSeenAt: row.last_seen_at,
 | 
			
		||||
                    dependencyType: row.dependency,
 | 
			
		||||
                    environments: [],
 | 
			
		||||
                    segments: row.segment_name ? [row.segment_name] : [],
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
@ -977,3 +977,57 @@ test('should return environment usage metrics', async () => {
 | 
			
		||||
        ],
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test('should return dependencyType', async () => {
 | 
			
		||||
    await app.createFeature({
 | 
			
		||||
        name: 'my_feature_a',
 | 
			
		||||
        createdAt: '2023-01-29T15:21:39.975Z',
 | 
			
		||||
    });
 | 
			
		||||
    await app.createFeature({
 | 
			
		||||
        name: 'my_feature_b',
 | 
			
		||||
        createdAt: '2023-01-29T15:21:39.975Z',
 | 
			
		||||
    });
 | 
			
		||||
    await app.createFeature({
 | 
			
		||||
        name: 'my_feature_c',
 | 
			
		||||
        createdAt: '2023-01-29T15:21:39.975Z',
 | 
			
		||||
    });
 | 
			
		||||
    await app.createFeature({
 | 
			
		||||
        name: 'my_feature_d',
 | 
			
		||||
        createdAt: '2023-01-29T15:21:39.975Z',
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    await stores.dependentFeaturesStore.upsert({
 | 
			
		||||
        child: 'my_feature_b',
 | 
			
		||||
        parent: 'my_feature_a',
 | 
			
		||||
        enabled: true,
 | 
			
		||||
    });
 | 
			
		||||
    await stores.dependentFeaturesStore.upsert({
 | 
			
		||||
        child: 'my_feature_c',
 | 
			
		||||
        parent: 'my_feature_a',
 | 
			
		||||
        enabled: true,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const { body } = await searchFeatures({
 | 
			
		||||
        query: 'my_feature',
 | 
			
		||||
    });
 | 
			
		||||
    expect(body).toMatchObject({
 | 
			
		||||
        features: [
 | 
			
		||||
            {
 | 
			
		||||
                name: 'my_feature_a',
 | 
			
		||||
                dependencyType: 'parent',
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                name: 'my_feature_b',
 | 
			
		||||
                dependencyType: 'child',
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                name: 'my_feature_c',
 | 
			
		||||
                dependencyType: 'child',
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                name: 'my_feature_d',
 | 
			
		||||
                dependencyType: null,
 | 
			
		||||
            },
 | 
			
		||||
        ],
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,18 @@ export const featureSearchResponseSchema = {
 | 
			
		||||
    $id: '#/components/schemas/featureSearchResponseSchema',
 | 
			
		||||
    type: 'object',
 | 
			
		||||
    additionalProperties: false,
 | 
			
		||||
    required: ['name'],
 | 
			
		||||
    required: [
 | 
			
		||||
        'name',
 | 
			
		||||
        'dependencyType',
 | 
			
		||||
        'type',
 | 
			
		||||
        'project',
 | 
			
		||||
        'stale',
 | 
			
		||||
        'favorite',
 | 
			
		||||
        'impressionData',
 | 
			
		||||
        'createdAt',
 | 
			
		||||
        'environments',
 | 
			
		||||
        'segments',
 | 
			
		||||
    ],
 | 
			
		||||
    description: 'A feature toggle definition',
 | 
			
		||||
    properties: {
 | 
			
		||||
        name: {
 | 
			
		||||
@ -33,6 +44,14 @@ export const featureSearchResponseSchema = {
 | 
			
		||||
                'Controls disabling of the comments section in case of an incident',
 | 
			
		||||
            description: 'Detailed description of the feature',
 | 
			
		||||
        },
 | 
			
		||||
        dependencyType: {
 | 
			
		||||
            type: 'string',
 | 
			
		||||
            enum: ['parent', 'child', null],
 | 
			
		||||
            nullable: true,
 | 
			
		||||
            example: 'parent',
 | 
			
		||||
            description:
 | 
			
		||||
                "The type of dependency. 'parent' means that the feature is a parent feature, 'child' means that the feature is a child feature.",
 | 
			
		||||
        },
 | 
			
		||||
        archived: {
 | 
			
		||||
            type: 'boolean',
 | 
			
		||||
            example: true,
 | 
			
		||||
@ -43,11 +62,6 @@ export const featureSearchResponseSchema = {
 | 
			
		||||
            example: 'dx-squad',
 | 
			
		||||
            description: 'Name of the project the feature belongs to',
 | 
			
		||||
        },
 | 
			
		||||
        enabled: {
 | 
			
		||||
            type: 'boolean',
 | 
			
		||||
            example: true,
 | 
			
		||||
            description: '`true` if the feature is enabled, otherwise `false`.',
 | 
			
		||||
        },
 | 
			
		||||
        stale: {
 | 
			
		||||
            type: 'boolean',
 | 
			
		||||
            example: false,
 | 
			
		||||
@ -129,47 +143,6 @@ export const featureSearchResponseSchema = {
 | 
			
		||||
            nullable: true,
 | 
			
		||||
            description: 'The list of feature tags',
 | 
			
		||||
        },
 | 
			
		||||
        children: {
 | 
			
		||||
            type: 'array',
 | 
			
		||||
            description:
 | 
			
		||||
                'The list of child feature names. This is an experimental field and may change.',
 | 
			
		||||
            items: {
 | 
			
		||||
                type: 'string',
 | 
			
		||||
                example: 'some-feature',
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
        dependencies: {
 | 
			
		||||
            type: 'array',
 | 
			
		||||
            items: {
 | 
			
		||||
                type: 'object',
 | 
			
		||||
                additionalProperties: false,
 | 
			
		||||
                required: ['feature'],
 | 
			
		||||
                properties: {
 | 
			
		||||
                    feature: {
 | 
			
		||||
                        description: 'The name of the parent feature',
 | 
			
		||||
                        type: 'string',
 | 
			
		||||
                        example: 'some-feature',
 | 
			
		||||
                    },
 | 
			
		||||
                    enabled: {
 | 
			
		||||
                        description:
 | 
			
		||||
                            'Whether the parent feature is enabled or not',
 | 
			
		||||
                        type: 'boolean',
 | 
			
		||||
                        example: true,
 | 
			
		||||
                    },
 | 
			
		||||
                    variants: {
 | 
			
		||||
                        description:
 | 
			
		||||
                            'The list of variants the parent feature should resolve to. Only valid when feature is enabled.',
 | 
			
		||||
                        type: 'array',
 | 
			
		||||
                        items: {
 | 
			
		||||
                            example: 'some-feature-blue-variant',
 | 
			
		||||
                            type: 'string',
 | 
			
		||||
                        },
 | 
			
		||||
                    },
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
            description:
 | 
			
		||||
                'The list of parent dependencies. This is an experimental field and may change.',
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    components: {
 | 
			
		||||
        schemas: {
 | 
			
		||||
 | 
			
		||||
@ -223,6 +223,7 @@ export type IFeatureSearchOverview = Exclude<
 | 
			
		||||
    IFeatureOverview,
 | 
			
		||||
    'environments'
 | 
			
		||||
> & {
 | 
			
		||||
    dependencyType: 'parent' | 'child' | null;
 | 
			
		||||
    environments: FeatureSearchEnvironmentSchema[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user