diff --git a/src/lib/routes/admin-api/project/variants.ts b/src/lib/routes/admin-api/project/variants.ts index 1c003fdc36c..48ec317d5f2 100644 --- a/src/lib/routes/admin-api/project/variants.ts +++ b/src/lib/routes/admin-api/project/variants.ts @@ -65,6 +65,10 @@ export default class VariantsController extends Controller { handler: this.getVariants, middleware: [ openApiService.validPath({ + summary: 'Retrieve variants for a feature (deprecated) ', + description: + '(deprecated from 4.21) Retrieve the variants for the specified feature. From Unleash 4.21 onwards, this endpoint will attempt to choose a [production-type environment](https://docs.getunleash.io/reference/environments) as the source of truth. If more than one production environment is found, the first one will be used.', + deprecated: true, tags: ['Features'], operationId: 'getFeatureVariants', responses: { @@ -80,6 +84,11 @@ export default class VariantsController extends Controller { handler: this.patchVariants, middleware: [ openApiService.validPath({ + summary: + "Apply a patch to a feature's variants (in all environments).", + description: `Apply a list of patches patch to the specified feature's variants. The patch objects should conform to the [JSON-patch format (RFC 6902)](https://www.rfc-editor.org/rfc/rfc6902). + + ⚠️ **Warning**: This method is not atomic. If something fails in the middle of applying the patch, you can be left with a half-applied patch. We recommend that you instead [patch variants on a per-environment basis](/docs/reference/api/unleash/patch-environments-feature-variants.api.mdx), which **is** an atomic operation.`, tags: ['Features'], operationId: 'patchFeatureVariants', requestBody: createRequestSchema('patchesSchema'), @@ -96,6 +105,16 @@ export default class VariantsController extends Controller { handler: this.overwriteVariants, middleware: [ openApiService.validPath({ + summary: + 'Create (overwrite) variants for a feature toggle in all environments', + description: `This overwrites the current variants for the feature specified in the :featureName parameter in all environments. + + The backend will validate the input for the following invariants + + * If there are variants, there needs to be at least one variant with \`weightType: variable\` + * The sum of the weights of variants with \`weightType: fix\` must be strictly less than 1000 (< 1000) + + The backend will also distribute remaining weight up to 1000 after adding the variants with \`weightType: fix\` together amongst the variants of \`weightType: variable\``, tags: ['Features'], operationId: 'overwriteFeatureVariants', requestBody: createRequestSchema('variantsSchema'), @@ -112,6 +131,8 @@ export default class VariantsController extends Controller { handler: this.getVariantsOnEnv, middleware: [ openApiService.validPath({ + summary: 'Get variants for a feature in an environment', + description: `Returns the variants for a feature in a specific environment. If the feature has no variants it will return an empty array of variants`, tags: ['Features'], operationId: 'getEnvironmentFeatureVariants', responses: { @@ -127,6 +148,8 @@ export default class VariantsController extends Controller { handler: this.patchVariantsOnEnv, middleware: [ openApiService.validPath({ + summary: "Patch a feature's variants in an environment", + description: `Apply a list of patches to the features environments in the specified environment. The patch objects should conform to the [JSON-patch format (RFC 6902)](https://www.rfc-editor.org/rfc/rfc6902).`, tags: ['Features'], operationId: 'patchEnvironmentsFeatureVariants', requestBody: createRequestSchema('patchesSchema'), @@ -143,6 +166,16 @@ export default class VariantsController extends Controller { handler: this.overwriteVariantsOnEnv, middleware: [ openApiService.validPath({ + summary: + 'Create (overwrite) variants for a feature in an environment', + description: `This overwrites the current variants for the feature toggle in the :featureName parameter for the :environment parameter. + + The backend will validate the input for the following invariants: + + * If there are variants, there needs to be at least one variant with \`weightType: variable\` + * The sum of the weights of variants with \`weightType: fix\` must be strictly less than 1000 (< 1000) + + The backend will also distribute remaining weight up to 1000 after adding the variants with \`weightType: fix\` together amongst the variants of \`weightType: variable\``, tags: ['Features'], operationId: 'overwriteEnvironmentFeatureVariants', requestBody: createRequestSchema('variantsSchema'), diff --git a/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap b/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap index 0627af1cdb6..0fcae1d5e75 100644 --- a/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap +++ b/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap @@ -6815,6 +6815,7 @@ If the provided project does not exist, the list of events will be empty.", }, "/api/admin/projects/{projectId}/features/{featureName}/environments/{environment}/variants": { "get": { + "description": "Returns the variants for a feature in a specific environment. If the feature has no variants it will return an empty array of variants", "operationId": "getEnvironmentFeatureVariants", "parameters": [ { @@ -6854,11 +6855,13 @@ If the provided project does not exist, the list of events will be empty.", "description": "featureVariantsSchema", }, }, + "summary": "Get variants for a feature in an environment", "tags": [ "Features", ], }, "patch": { + "description": "Apply a list of patches to the features environments in the specified environment. The patch objects should conform to the [JSON-patch format (RFC 6902)](https://www.rfc-editor.org/rfc/rfc6902).", "operationId": "patchEnvironmentsFeatureVariants", "parameters": [ { @@ -6909,11 +6912,20 @@ If the provided project does not exist, the list of events will be empty.", "description": "featureVariantsSchema", }, }, + "summary": "Patch a feature's variants in an environment", "tags": [ "Features", ], }, "put": { + "description": "This overwrites the current variants for the feature toggle in the :featureName parameter for the :environment parameter. + + The backend will validate the input for the following invariants: + + * If there are variants, there needs to be at least one variant with \`weightType: variable\` + * The sum of the weights of variants with \`weightType: fix\` must be strictly less than 1000 (< 1000) + + The backend will also distribute remaining weight up to 1000 after adding the variants with \`weightType: fix\` together amongst the variants of \`weightType: variable\`", "operationId": "overwriteEnvironmentFeatureVariants", "parameters": [ { @@ -6964,6 +6976,7 @@ If the provided project does not exist, the list of events will be empty.", "description": "featureVariantsSchema", }, }, + "summary": "Create (overwrite) variants for a feature in an environment", "tags": [ "Features", ], @@ -7031,6 +7044,8 @@ If the provided project does not exist, the list of events will be empty.", }, "/api/admin/projects/{projectId}/features/{featureName}/variants": { "get": { + "deprecated": true, + "description": "(deprecated from 4.21) Retrieve the variants for the specified feature. From Unleash 4.21 onwards, this endpoint will attempt to choose a [production-type environment](https://docs.getunleash.io/reference/environments) as the source of truth. If more than one production environment is found, the first one will be used.", "operationId": "getFeatureVariants", "parameters": [ { @@ -7062,11 +7077,15 @@ If the provided project does not exist, the list of events will be empty.", "description": "featureVariantsSchema", }, }, + "summary": "Retrieve variants for a feature (deprecated) ", "tags": [ "Features", ], }, "patch": { + "description": "Apply a list of patches patch to the specified feature's variants. The patch objects should conform to the [JSON-patch format (RFC 6902)](https://www.rfc-editor.org/rfc/rfc6902). + + ⚠️ **Warning**: This method is not atomic. If something fails in the middle of applying the patch, you can be left with a half-applied patch. We recommend that you instead [patch variants on a per-environment basis](/docs/reference/api/unleash/patch-environments-feature-variants.api.mdx), which **is** an atomic operation.", "operationId": "patchFeatureVariants", "parameters": [ { @@ -7109,11 +7128,20 @@ If the provided project does not exist, the list of events will be empty.", "description": "featureVariantsSchema", }, }, + "summary": "Apply a patch to a feature's variants (in all environments).", "tags": [ "Features", ], }, "put": { + "description": "This overwrites the current variants for the feature specified in the :featureName parameter in all environments. + + The backend will validate the input for the following invariants + + * If there are variants, there needs to be at least one variant with \`weightType: variable\` + * The sum of the weights of variants with \`weightType: fix\` must be strictly less than 1000 (< 1000) + + The backend will also distribute remaining weight up to 1000 after adding the variants with \`weightType: fix\` together amongst the variants of \`weightType: variable\`", "operationId": "overwriteFeatureVariants", "parameters": [ { @@ -7156,6 +7184,7 @@ If the provided project does not exist, the list of events will be empty.", "description": "featureVariantsSchema", }, }, + "summary": "Create (overwrite) variants for a feature toggle in all environments", "tags": [ "Features", ], diff --git a/website/docs/reference/api/legacy/unleash/admin/features-v2.md b/website/docs/reference/api/legacy/unleash/admin/features-v2.md index 721cc621eda..8df9c22ebbb 100644 --- a/website/docs/reference/api/legacy/unleash/admin/features-v2.md +++ b/website/docs/reference/api/legacy/unleash/admin/features-v2.md @@ -611,7 +611,15 @@ Transfer-Encoding: chunked ### Put variants for Feature Toggle {#update-variants} - - Feature toggle variants were introduced in Unleash v3.2.0. - -
+:::info Availability + +**Feature toggle variants** were first introduced in Unleash 3.2. +In Unleash 4.21, variants were updated to be **environment-dependent**, meaning the same feature could have different variant configurations in different environments. + +::: Every toggle in Unleash can have something called _variants_. Where _feature toggles_ allow you to decide which users get access to a feature, _toggle variants_ allow you to further split those users into segments. Say, for instance, that you're testing out a new feature, such as an alternate sign-up form. The feature toggle would expose the form only to a select group of users. The variants could decide whether the user sees a blue or a green submit button on that form. @@ -12,12 +14,12 @@ Variants facilitate A/B testing and experimentation by letting you create contro ## What are variants? -Whenever you create a feature toggle, you can assign it any number of _variants_. This is commonly done in cases where you want to serve your users different versions of a feature to see which performs better. +Whenever you create a feature toggle, you can assign it any number of _variants_. This is commonly done in cases where you want to serve your users different versions of a feature to see which performs better. A feature can have different variants in each of its environments. A variant has four components that define it: - a **name**: - This must be unique among the toggle's variants. When working with a toggle with variants in a client, you will typically use the variant's name to find out which variant it is. + This must be unique among the toggle's variants in the specified environment. When working with a feature with variants in a client, you will typically use the variant's name to find out which variant it is. - a **weight**: diff --git a/website/static/img/create-toggle-add-variants.png b/website/static/img/create-toggle-add-variants.png index d792cf8b8f3..f7b8c13fa32 100644 Binary files a/website/static/img/create-toggle-add-variants.png and b/website/static/img/create-toggle-add-variants.png differ diff --git a/website/static/img/variant-creation-form.png b/website/static/img/variant-creation-form.png index 7f5a8145690..1ab87a0edf1 100644 Binary files a/website/static/img/variant-creation-form.png and b/website/static/img/variant-creation-form.png differ