-
-
Notifications
You must be signed in to change notification settings - Fork 5
feat(variants): add support for feature variants with distribution #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds support for feature variants by extending the feature flag mechanism. The key changes include:
- Adding a new composable (useFeatureVariant) to retrieve and select feature flag variants.
- Updating the vFeature directive to handle variant strings and control element visibility based on the selected variant.
- Modifying scheduled flags filtering and integrating variant examples in the playground.
Reviewed Changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/runtime/directives/v-feature.ts | Refactored the directive to support an optional variant string in the flag value. |
| src/runtime/composables/useFeatureVariant.ts | Introduced a new composable to determine the appropriate variant based on distribution. |
| src/runtime/composables/useFeatureFlag.ts | Updated the isEnabled logic to account for scheduled flags with optional active dates. |
| playground/pages/scheduled.vue | Adjusted filtering logic for scheduled flags to include timing properties. |
| playground/pages/index.vue | Added UI examples for displaying and resetting feature variants. |
| playground/nuxt.config.ts | Added configuration for the new feature variant (checkoutUI) with distribution. |
Comments suppressed due to low confidence (2)
src/runtime/composables/useFeatureFlag.ts:30
- The conditional check bypasses time-based activation when either 'activeFrom' or 'activeUntil' is missing. Ensure this behavior is intended, and consider adding inline documentation to clarify the design rationale.
if (typeof flag === 'object' && flag.name === flagName && ((!flag?.activeFrom || !flag?.activeUntil) ? true : isFlagActiveNow(flag))) return true
src/runtime/composables/useFeatureVariant.ts:57
- Ensure that the 'distribution' array provided in the configuration sums to 1; otherwise, the random variant selection may yield unexpected results. Consider normalizing the distribution values or adding a validation check.
for (let i = 0; i < variants.length; i++) {
nicokempe
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unrelated commit will be removed
| } | ||
|
|
||
| let selectedVariantIndex: number | null = null | ||
| const storedValue = localStorage.getItem(flagName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tylix localStorage works for client-side only, but it lacks SSR support and can’t be pre-evaluated on the server.
For more flexibility we could use:
useState()(https://nuxt.com/docs/getting-started/state-management) supports both SSR and client, scoped per session/render context.useCookie()(https://nuxt.com/docs/api/composables/use-cookie) would be ideal if we want persistent variants tied to a user (e.g. across sessions).
Might be worth making this configurable via a persistence: 'state' | 'cookie' | 'local' setting in the Nuxt config.
This way, integrators can choose the storage strategy depending on their use case (e.g. temporary testing, logged-in users, or full A/B testing persistence).
…r consistency in validation logic
|
@codex review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Codex Review: Here are some suggestions.
Reply with @codex fix comments to fix any unresolved comments.
About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you open a pull request for review, mark a draft as ready, or comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex fix this CI failure" or "@codex address that feedback".
| // 2. Retrieve flag configuration | ||
| const config: FeatureFlagsConfig = useRuntimeConfig().public.featureFlags | ||
| const env = config.environment | ||
| const flags: FeatureFlagInput[] = config.environments?.[env] || [] | ||
|
|
||
| // Find the specific flag configuration | ||
| const flag = flags.find( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P1] Variants never read from configured flag sets
The new useFeatureVariant composable is pulling declared flags from config.environments, but the rest of the codebase (and the updated type) now exposes them under flagSets. Because config.environments is undefined, the flags array is always empty and the subsequent search fails, so every call to isEnabled('feature:variant') will return false even when the flag is correctly configured. The code should reference config.flagSets[env] so that variants can be discovered.
Useful? React with 👍 / 👎.
Goal@codex make code changes to this PR (based on an old codebase) so it works on the latest Steps
Acceptance Criteria
Don’ts
|
For now, I can only help with PRs you've created. |
|
@codex review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // 2. Retrieve flag configuration | ||
| const config: FeatureFlagsConfig = useRuntimeConfig().public.featureFlags | ||
| const env = config.environment | ||
| const flags: FeatureFlagInput[] = config.environments?.[env] || [] | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolve variants from flagSets instead of environments
The new useFeatureVariant composable tries to load flags from config.environments, but the configuration object exposed at runtime uses the renamed flagSets key. As a result flags is always an empty array, flag becomes undefined, and every call to isEnabled('flag:variant') immediately warns that the flag has no variants and returns false, so variants never work. This should read from config.flagSets like the existing useFeatureFlag composable.
Useful? React with 👍 / 👎.
✅ PR Checklist
Please ensure the following before submitting your PR:
🔗 Linked Issue
No issue created
📖 Description
isEnabled('flag:variant')) and templates (v-feature="'flag:variant'").🚨 Breaking Changes
🧪 Type of Change
🧩 Additional Context
No additional context.