feat: use lifecycles API#7793
Conversation
…ification Conform the project lifecycle page to the new backend API (#7789): - Add lifecycle-status-counts RTK query for sidebar counts in one call - Add lifecycle_stage + evaluation_period_days params to getProjectFlags and a lifecycle_stage field on ProjectFlag - Each section now fetches only its own stage, classified server-side - Remove client-side tag/code-reference/evaluation classification, the per-flag EvaluationChecker and useEvaluationCounts hook - Single environment (name-matched "prod" by default, switchable in the left nav, persisted per project in a new redux slice) and a single evaluation_period_days replace the multi-env + dual-period controls - Drop the non-functional "LIFECYCLE STAGES" sidebar header/Add button Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Docker builds report
|
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Failed testsfirefox › tests/environment-permission-test.pw.ts › Environment Permission Tests › Environment-level permissions control access to features, identities, and segments @enterprise Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
|
Visual Regression19 screenshots compared. See report for details. |
This comment was marked as spam.
This comment was marked as spam.
Match the feature-lifecycle endpoints introduced in PR #7789: - lowercase LifecycleStage values + SECTION_TO_STAGE mapping - env-scoped counts URL (environments/{env}/feature-lifecycle-counts/) - read lowercase count keys; drop unsupported filter + evaluation_period params from the counts query - remove the orphaned evaluation-period selector (backend derives the window from project.stale_flags_limit_days) Extract prod-environment prediction into predictProdEnvironment(). Add frontend context doc for running an unmerged backend PR's Docker image. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Fix loading state: use isFetching in addition to isLoading for proper loading indicator when switching between lifecycle sections - Change environment picker from tag chips to dropdown select - Add tooltip explaining environment selection affects evaluations only - Remove checkbox selection from Stale and Remove sections for visual consistency with other sections - Fix MONITOR_TOOLTIP type error by converting JSX to HTML string - Add spacing before "Why am I seeing this?" link - Fix FeatureImport.tsx type error with proper ternary for existingFlags Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Clicking a feature row in the lifecycle page now opens a side modal with Usage and Settings tabs, matching the main feature modal styling. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR replaces client-side feature lifecycle evaluation and counting with backend-driven lifecycle counts and stage classification. It adds lifecycle request/response types, a new lifecycle counts query, a persisted per-project environment selection slice and hook, and refactors the feature lifecycle page and section components to use environment-scoped data. It also adds row click handling and a feature usage modal, and updates the lifecycle sidebar and labels. Estimated code review effort: 4 (Complex) | ~60 minutes Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontend/web/components/pages/feature-lifecycle/components/FeatureUsageModal.tsx (1)
1-44: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winNew component doesn't follow the mandated folder structure.
FeatureUsageModal.tsxis a brand-new component placed flat incomponents/, rather than in its ownFeatureUsageModal/FeatureUsageModal.tsxwith a co-located barrelindex.ts.As per coding guidelines, "Each new component must live in its own folder with a barrel
index.ts, aComponentName/ComponentName.tsxfile, co-locatedComponentName.scss, any subcomponents, and imports should use the component folder path rather than the inner file."#!/bin/bash # Description: Verify current placement/structure of the new component. fd FeatureUsageModal frontend/web/components/pages/feature-lifecycleSource: Coding guidelines
♻️ Duplicate comments (1)
frontend/web/components/pages/feature-lifecycle/hooks/useLifecycleData.ts (1)
52-90: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicated
FeatureListStoresubscribe/unsubscribe block across both hooks.The identical
useEffectwiringFeatureListStore.on/off('saved'|'removed', refetch)is repeated verbatim inuseLifecycleCountsanduseLifecycleSectionFlags. This is also the direct-store-coupling pattern previously flagged as making the hook hard to test (no seam to inject/mock the event source). Extracting a small shared hook (e.g.useRefetchOnFeatureListEvents(refetch)) would remove the duplication and provide the seam needed for testability.♻️ Proposed refactor
+function useRefetchOnFeatureListEvents(refetch: () => void) { + useEffect(() => { + FeatureListStore.on('saved', refetch) + FeatureListStore.on('removed', refetch) + return () => { + FeatureListStore.off('saved', refetch) + FeatureListStore.off('removed', refetch) + } + }, [refetch]) +} + export function useLifecycleCounts({ environmentId, }: { environmentId: number | undefined }) { const query = useGetLifecycleStatusCountsQuery( environmentId ? { environment: environmentId } : skipToken, { refetchOnMountOrArgChange: true }, ) - const { refetch } = query - useEffect(() => { - FeatureListStore.on('saved', refetch) - FeatureListStore.on('removed', refetch) - return () => { - FeatureListStore.off('saved', refetch) - FeatureListStore.off('removed', refetch) - } - }, [refetch]) + useRefetchOnFeatureListEvents(query.refetch)Apply the equivalent replacement in
useLifecycleSectionFlags.Also applies to: 93-132
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 79bdbfe8-b1bb-4457-8851-b653e1dfa56e
📒 Files selected for processing (23)
frontend/common/lifecycleEnvironmentSlice.tsfrontend/common/services/useProjectFlag.tsfrontend/common/store.tsfrontend/common/types/requests.tsfrontend/common/types/responses.tsfrontend/web/components/feature-summary/ProjectFeatureRow.tsxfrontend/web/components/pages/feature-lifecycle/FeatureLifecyclePage.tsxfrontend/web/components/pages/feature-lifecycle/components/EvaluationChecker.tsxfrontend/web/components/pages/feature-lifecycle/components/FeatureUsageModal.tsxfrontend/web/components/pages/feature-lifecycle/components/LifecycleSidebar.tsxfrontend/web/components/pages/feature-lifecycle/components/LiveSection.tsxfrontend/web/components/pages/feature-lifecycle/components/MonitorSection.tsxfrontend/web/components/pages/feature-lifecycle/components/NewSection.tsxfrontend/web/components/pages/feature-lifecycle/components/PermanentSection.tsxfrontend/web/components/pages/feature-lifecycle/components/RemoveSection.tsxfrontend/web/components/pages/feature-lifecycle/components/SectionShell.tsxfrontend/web/components/pages/feature-lifecycle/components/StaleSection.tsxfrontend/web/components/pages/feature-lifecycle/constants.tsxfrontend/web/components/pages/feature-lifecycle/hooks/predictProdEnvironment.tsfrontend/web/components/pages/feature-lifecycle/hooks/useEvaluationCounts.tsfrontend/web/components/pages/feature-lifecycle/hooks/useLifecycleData.tsfrontend/web/components/pages/feature-lifecycle/hooks/useLifecycleEnvironment.tsfrontend/web/components/pages/feature-lifecycle/types.ts
💤 Files with no reviewable changes (3)
- frontend/web/components/pages/feature-lifecycle/components/EvaluationChecker.tsx
- frontend/web/components/pages/feature-lifecycle/types.ts
- frontend/web/components/pages/feature-lifecycle/hooks/useEvaluationCounts.ts
talissoncosta
left a comment
There was a problem hiding this comment.
Looks good on my view! Thanks for addressing the feedback.
- Invalidate LifecycleCounts on flag update and delete so sidebar counts stay fresh - Make clickable feature rows keyboard-operable (role, tabIndex, Enter/Space handler) - Remove stale 'and period' copy from the remove section empty state Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontend/common/services/useProjectFlag.ts (1)
142-150: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueConsider scoping
LifecycleCountstag per environment.
providesTags/invalidatesTagsuse a single global'LifecycleCounts'tag rather than one keyed by environment id. This is consistent between the query and the mutations, so it's not a bug, but any flag mutation in one project/environment will invalidate cached counts for every environment currently held in the cache, causing extra refetches for unrelated environments in multi-tab or multi-environment scenarios.♻️ Optional: scope the tag by environment id
getLifecycleStatusCounts: builder.query< Res['lifecycleStatusCounts'], Req['getLifecycleStatusCounts'] >({ - providesTags: ['LifecycleCounts'], + providesTags: (_res, _err, req) => [ + { id: req.environment, type: 'LifecycleCounts' }, + ], query: ({ environment }) => ({ url: `environments/${environment}/feature-lifecycle-counts/`, }), }),Note: this would also require updating the
invalidatesTagsarrays oncreateProjectFlag,updateProjectFlag, andremoveProjectFlagto target the relevant environment id (if available in their args/response) instead of the bare tag type.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 27595980-170d-45e1-b285-0e26d5542aae
📒 Files selected for processing (3)
frontend/common/services/useProjectFlag.tsfrontend/web/components/feature-summary/ProjectFeatureRow.tsxfrontend/web/components/pages/feature-lifecycle/components/RemoveSection.tsx
Conform the project lifecycle page to the new backend API (#7789):
Thanks for submitting a PR! Please check the boxes below:
docs/if required so people know about the feature.Changes
Hooks up API for feature lifecycle
How did you test this code?
Go to lifecycle page as in the Flagsmith project