mirror of
https://github.com/Unleash/unleash.git
synced 2025-09-19 17:52:45 +02:00
chore(AI): releasePlans flag cleanup (#10537)
This PR cleans up the releasePlans flag. These changes were automatically generated by AI and should be reviewed carefully. Fixes #10536 ## 🧹 AI Flag Cleanup Summary The `releasePlans` feature flag has been removed, making the feature permanently available for Enterprise customers. All conditional logic and checks related to this flag have been removed from the codebase. This change ensures that Release Plans are an integral part of the Unleash Enterprise offering. ### 🚮 Removed - **Flag Definitions** - `releasePlans` flag from `experimental.ts` in the backend. - `releasePlans` flag from `uiConfig.ts` in the frontend. - `releasePlans` flag from `server-dev.ts` development config. - **Conditional Logic** - Removed checks for `releasePlansEnabled` in components and hooks, including `ReleaseManagement.tsx`, `FeatureStrategyMenu.tsx`, and `NewInUnleash.tsx`. - Removed `useUiFlag('releasePlans')` calls from all frontend files. - Removed the `flag: 'releasePlans'` property from route definitions in `routes.ts`. ### 🛠 Kept - **Feature Functionality** - All UI and logic related to Release Plans and Release Templates are now unconditionally enabled for Enterprise users. ### 📝 Why The `releasePlans` feature has been successfully rolled out and is now a stable part of the product. This cleanup removes the artık feature flag to simplify the codebase and reduce complexity. --------- Co-authored-by: unleash-bot <194219037+unleash-bot[bot]@users.noreply.github.com> Co-authored-by: Nuno Góis <github@nunogois.com>
This commit is contained in:
parent
f375ae4694
commit
0792125bb7
@ -18,7 +18,6 @@ import {
|
||||
} from 'utils/permissions';
|
||||
import { RolePermissionEnvironment } from './RolePermissionEnvironment.tsx';
|
||||
import { useMemo } from 'react';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import { RolePermissionProject } from './RolePermissionProject.tsx';
|
||||
import { RolePermissionCategoryAccordion } from './RolePermissionCategoryAccordion.tsx';
|
||||
|
||||
@ -43,8 +42,6 @@ export const RolePermissionCategories = ({
|
||||
revalidateOnFocus: false,
|
||||
});
|
||||
|
||||
const releasePlansEnabled = useUiFlag('releasePlans');
|
||||
|
||||
const isProjectRole = PROJECT_ROLE_TYPES.includes(type);
|
||||
|
||||
const categories = useMemo(
|
||||
@ -81,23 +78,14 @@ export const RolePermissionCategories = ({
|
||||
return useMemo(
|
||||
() => (
|
||||
<>
|
||||
{categories
|
||||
.filter(
|
||||
({ label }) =>
|
||||
releasePlansEnabled ||
|
||||
label !== 'Release plan templates',
|
||||
)
|
||||
.map(({ label, type, permissions }) => (
|
||||
{categories.map(({ label, type, permissions }) => (
|
||||
<RolePermissionCategoryAccordion
|
||||
key={label}
|
||||
title={label}
|
||||
context={label.toLowerCase()}
|
||||
Icon={
|
||||
type === PROJECT_PERMISSION_TYPE ? (
|
||||
<TopicIcon
|
||||
color='disabled'
|
||||
sx={{ mr: 1 }}
|
||||
/>
|
||||
<TopicIcon color='disabled' sx={{ mr: 1 }} />
|
||||
) : type === ENVIRONMENT_PERMISSION_TYPE ? (
|
||||
<CloudCircleIcon
|
||||
color='disabled'
|
||||
|
@ -77,10 +77,8 @@ export const FeatureStrategyMenu = ({
|
||||
const { addReleasePlanToFeature } = useReleasePlansApi();
|
||||
const { isEnterprise } = useUiConfig();
|
||||
const addConfigurationEnabled = useUiFlag('addConfiguration');
|
||||
const releasePlansEnabled = useUiFlag('releasePlans');
|
||||
const displayReleasePlanButton = isEnterprise() && releasePlansEnabled;
|
||||
const crProtected =
|
||||
releasePlansEnabled && isChangeRequestConfigured(environmentId);
|
||||
const displayReleasePlanButton = isEnterprise();
|
||||
const crProtected = isChangeRequestConfigured(environmentId);
|
||||
|
||||
const onClose = () => {
|
||||
setIsStrategyMenuDialogOpen(false);
|
||||
|
@ -8,7 +8,6 @@ import { useNavigate } from 'react-router-dom';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import FactCheckOutlinedIcon from '@mui/icons-material/FactCheckOutlined';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig.ts';
|
||||
import { useUiFlag } from 'hooks/useUiFlag.ts';
|
||||
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon.tsx';
|
||||
|
||||
interface IFeatureStrategyMenuCardsProps {
|
||||
@ -124,7 +123,6 @@ export const FeatureStrategyMenuCards = ({
|
||||
onClose,
|
||||
}: IFeatureStrategyMenuCardsProps) => {
|
||||
const { isEnterprise } = useUiConfig();
|
||||
const releasePlansEnabled = useUiFlag('releasePlans');
|
||||
|
||||
const { strategies } = useStrategies();
|
||||
const { templates } = useReleasePlanTemplates();
|
||||
@ -150,7 +148,7 @@ export const FeatureStrategyMenuCards = ({
|
||||
};
|
||||
|
||||
const renderReleasePlanTemplates = () => {
|
||||
if (!isEnterprise() || !releasePlansEnabled) {
|
||||
if (!isEnterprise()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@ import type { FC } from 'react';
|
||||
import { styled, Link } from '@mui/material';
|
||||
import type { Link as RouterLink } from 'react-router-dom';
|
||||
import { RELEASE_TEMPLATE_FEEDBACK } from 'constants/links';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
|
||||
const StyledLink = styled(Link<typeof RouterLink | 'a'>)(({ theme }) => ({
|
||||
@ -17,9 +16,8 @@ const StyledLink = styled(Link<typeof RouterLink | 'a'>)(({ theme }) => ({
|
||||
|
||||
export const ReleaseTemplatesFeedback: FC = () => {
|
||||
const { isEnterprise } = useUiConfig();
|
||||
const releaseTemplatesEnabled = useUiFlag('releasePlans');
|
||||
|
||||
if (!isEnterprise() || !releaseTemplatesEnabled) {
|
||||
if (!isEnterprise()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@ import { ReleasePlanRemoveDialog } from './ReleasePlanRemoveDialog.tsx';
|
||||
import { ReleasePlanMilestone } from './ReleasePlanMilestone/ReleasePlanMilestone.tsx';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
||||
import { usePendingChangeRequests } from 'hooks/api/getters/usePendingChangeRequests/usePendingChangeRequests';
|
||||
import { RemoveReleasePlanChangeRequestDialog } from './ChangeRequest/RemoveReleasePlanChangeRequestDialog.tsx';
|
||||
@ -120,8 +119,6 @@ export const ReleasePlan = ({
|
||||
const { refetch: refetchChangeRequests } =
|
||||
usePendingChangeRequests(projectId);
|
||||
|
||||
const releasePlansEnabled = useUiFlag('releasePlans');
|
||||
|
||||
const onAddRemovePlanChangesConfirm = async () => {
|
||||
await addChange(projectId, environment, {
|
||||
feature: featureName,
|
||||
@ -162,7 +159,7 @@ export const ReleasePlan = ({
|
||||
};
|
||||
|
||||
const confirmRemoveReleasePlan = () => {
|
||||
if (releasePlansEnabled && isChangeRequestConfigured(environment)) {
|
||||
if (isChangeRequestConfigured(environment)) {
|
||||
setChangeRequestDialogRemoveOpen(true);
|
||||
} else {
|
||||
setRemoveOpen(true);
|
||||
@ -197,7 +194,7 @@ export const ReleasePlan = ({
|
||||
};
|
||||
|
||||
const onStartMilestone = async (milestone: IReleasePlanMilestone) => {
|
||||
if (releasePlansEnabled && isChangeRequestConfigured(environment)) {
|
||||
if (isChangeRequestConfigured(environment)) {
|
||||
setMilestoneForChangeRequestDialog(milestone);
|
||||
setChangeRequestDialogStartMilestoneOpen(true);
|
||||
} else {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import { useUiFlag } from 'hooks/useUiFlag.ts';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { useLocalStorageState } from 'hooks/useLocalStorageState';
|
||||
import {
|
||||
@ -102,7 +102,6 @@ export const NewInUnleash = ({
|
||||
);
|
||||
const { isEnterprise } = useUiConfig();
|
||||
const signalsEnabled = useUiFlag('signals');
|
||||
const releasePlansEnabled = useUiFlag('releasePlans');
|
||||
|
||||
const items: NewInUnleashItemDetails[] = [
|
||||
{
|
||||
@ -175,7 +174,7 @@ export const NewInUnleash = ({
|
||||
),
|
||||
onCheckItOut: () => navigate('/release-templates'),
|
||||
docsLink: 'https://docs.getunleash.io/reference/release-templates',
|
||||
show: isEnterprise() && releasePlansEnabled,
|
||||
show: isEnterprise(),
|
||||
beta: false,
|
||||
popout: true,
|
||||
},
|
||||
|
@ -46,6 +46,10 @@ exports[`order of items in navigation > menu for enterprise plan 1`] = `
|
||||
"icon": "StopRoundedIcon",
|
||||
"text": "Environments",
|
||||
},
|
||||
{
|
||||
"icon": "StopRoundedIcon",
|
||||
"text": "Release templates",
|
||||
},
|
||||
{
|
||||
"icon": "StopRoundedIcon",
|
||||
"text": "Tag types",
|
||||
@ -168,6 +172,10 @@ exports[`order of items in navigation > menu for pro plan 1`] = `
|
||||
"icon": "StopRoundedIcon",
|
||||
"text": "Environments",
|
||||
},
|
||||
{
|
||||
"icon": "StopRoundedIcon",
|
||||
"text": "Release templates",
|
||||
},
|
||||
{
|
||||
"icon": "StopRoundedIcon",
|
||||
"text": "Tag types",
|
||||
|
@ -282,7 +282,6 @@ exports[`returns all baseRoutes 1`] = `
|
||||
},
|
||||
{
|
||||
"component": [Function],
|
||||
"flag": "releasePlans",
|
||||
"menu": {
|
||||
"main": true,
|
||||
"mode": [
|
||||
@ -296,7 +295,6 @@ exports[`returns all baseRoutes 1`] = `
|
||||
{
|
||||
"component": [Function],
|
||||
"enterprise": true,
|
||||
"flag": "releasePlans",
|
||||
"menu": {
|
||||
"mode": [
|
||||
"enterprise",
|
||||
@ -310,7 +308,6 @@ exports[`returns all baseRoutes 1`] = `
|
||||
{
|
||||
"component": [Function],
|
||||
"enterprise": true,
|
||||
"flag": "releasePlans",
|
||||
"menu": {
|
||||
"mode": [
|
||||
"enterprise",
|
||||
|
@ -304,7 +304,6 @@ export const routes: IRoute[] = [
|
||||
component: ReleaseManagement,
|
||||
type: 'protected',
|
||||
menu: { main: true, mode: ['enterprise'] },
|
||||
flag: 'releasePlans',
|
||||
},
|
||||
{
|
||||
path: '/release-templates/create-template',
|
||||
@ -313,7 +312,6 @@ export const routes: IRoute[] = [
|
||||
component: CreateReleasePlanTemplate,
|
||||
type: 'protected',
|
||||
menu: { mode: ['enterprise'] },
|
||||
flag: 'releasePlans',
|
||||
enterprise: true,
|
||||
},
|
||||
{
|
||||
@ -323,7 +321,6 @@ export const routes: IRoute[] = [
|
||||
component: EditReleasePlanTemplate,
|
||||
type: 'protected',
|
||||
menu: { mode: ['enterprise'] },
|
||||
flag: 'releasePlans',
|
||||
enterprise: true,
|
||||
},
|
||||
|
||||
|
@ -9,7 +9,6 @@ import { useNavigate } from 'react-router-dom';
|
||||
import { useReleasePlanTemplates } from 'hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplates';
|
||||
import { EmptyTemplatesListMessage } from './EmptyTemplatesListMessage.tsx';
|
||||
import { ReleasePlanTemplateList } from './ReleasePlanTemplateList.tsx';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature';
|
||||
import { RELEASE_PLAN_TEMPLATE_CREATE } from '@server/types/permissions';
|
||||
@ -57,11 +56,6 @@ export const ReleaseManagement = () => {
|
||||
const data = useReleasePlanTemplates();
|
||||
|
||||
const { isEnterprise } = useUiConfig();
|
||||
const releasePlansEnabled = useUiFlag('releasePlans');
|
||||
if (!releasePlansEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isEnterprise()) {
|
||||
return <PremiumFeature feature='releaseManagement' page />;
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import useReleasePlanTemplatesApi from 'hooks/api/actions/useReleasePlanTemplate
|
||||
import { scrollToTop } from 'component/common/util';
|
||||
import useToast from 'hooks/useToast';
|
||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||
import { Limit } from 'component/common/Limit/Limit.tsx';
|
||||
@ -28,7 +27,6 @@ const StyledCancelButton = styled(Button)(({ theme }) => ({
|
||||
|
||||
export const CreateReleasePlanTemplate = () => {
|
||||
const { uiConfig, isEnterprise } = useUiConfig();
|
||||
const releasePlansEnabled = useUiFlag('releasePlans');
|
||||
const { setToastApiError, setToastData } = useToast();
|
||||
const navigate = useNavigate();
|
||||
const { createReleasePlanTemplate } = useReleasePlanTemplatesApi();
|
||||
@ -92,7 +90,7 @@ export const CreateReleasePlanTemplate = () => {
|
||||
--header 'Content-Type: application/json' \\
|
||||
--data-raw '${JSON.stringify(getTemplatePayload(), undefined, 2)}'`;
|
||||
|
||||
if (!releasePlansEnabled || !isEnterprise()) {
|
||||
if (!isEnterprise()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import { usePageTitle } from 'hooks/usePageTitle';
|
||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||
import { useReleasePlanTemplate } from 'hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplate';
|
||||
@ -26,7 +25,6 @@ const StyledCancelButton = styled(Button)(({ theme }) => ({
|
||||
|
||||
export const EditReleasePlanTemplate = () => {
|
||||
const { uiConfig, isEnterprise } = useUiConfig();
|
||||
const releasePlansEnabled = useUiFlag('releasePlans');
|
||||
const templateId = useRequiredPathParam('templateId');
|
||||
const { template, loading, error, refetch } =
|
||||
useReleasePlanTemplate(templateId);
|
||||
@ -92,7 +90,7 @@ export const EditReleasePlanTemplate = () => {
|
||||
--header 'Content-Type: application/json' \\
|
||||
--data-raw '${JSON.stringify(getTemplatePayload(), undefined, 2)}'`;
|
||||
|
||||
if (!releasePlansEnabled || !isEnterprise()) {
|
||||
if (!isEnterprise()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ import useUiConfig from '../useUiConfig/useUiConfig.js';
|
||||
import { formatApiPath } from 'utils/formatPath';
|
||||
import handleErrorResponses from '../httpErrorResponseHandler.js';
|
||||
import { useConditionalSWR } from '../useConditionalSWR/useConditionalSWR.js';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import type { IReleasePlanTemplate } from 'interfaces/releasePlans';
|
||||
|
||||
const path = (templateId: string) =>
|
||||
@ -20,10 +19,9 @@ const DEFAULT_DATA: IReleasePlanTemplate = {
|
||||
|
||||
export const useReleasePlanTemplate = (templateId: string) => {
|
||||
const { isEnterprise } = useUiConfig();
|
||||
const releasePlansEnabled = useUiFlag('releasePlans');
|
||||
|
||||
const { data, error, mutate } = useConditionalSWR<IReleasePlanTemplate>(
|
||||
isEnterprise() && releasePlansEnabled,
|
||||
isEnterprise(),
|
||||
DEFAULT_DATA,
|
||||
formatApiPath(path(templateId)),
|
||||
fetcher,
|
||||
|
@ -3,7 +3,6 @@ import useUiConfig from '../useUiConfig/useUiConfig.js';
|
||||
import { formatApiPath } from 'utils/formatPath';
|
||||
import handleErrorResponses from '../httpErrorResponseHandler.js';
|
||||
import { useConditionalSWR } from '../useConditionalSWR/useConditionalSWR.js';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import type { IReleasePlanTemplate } from 'interfaces/releasePlans';
|
||||
|
||||
const ENDPOINT = 'api/admin/release-plan-templates';
|
||||
@ -12,10 +11,9 @@ const DEFAULT_DATA: IReleasePlanTemplate[] = [];
|
||||
|
||||
export const useReleasePlanTemplates = () => {
|
||||
const { isEnterprise } = useUiConfig();
|
||||
const releasePlansEnabled = useUiFlag('releasePlans');
|
||||
|
||||
const { data, error, mutate } = useConditionalSWR<IReleasePlanTemplate[]>(
|
||||
isEnterprise() && releasePlansEnabled,
|
||||
isEnterprise(),
|
||||
DEFAULT_DATA,
|
||||
formatApiPath(ENDPOINT),
|
||||
fetcher,
|
||||
|
@ -3,7 +3,6 @@ import useUiConfig from '../useUiConfig/useUiConfig.js';
|
||||
import { formatApiPath } from 'utils/formatPath';
|
||||
import handleErrorResponses from '../httpErrorResponseHandler.js';
|
||||
import { useConditionalSWR } from '../useConditionalSWR/useConditionalSWR.js';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import type { IReleasePlan } from 'interfaces/releasePlans';
|
||||
|
||||
const DEFAULT_DATA: IReleasePlan[] = [];
|
||||
@ -14,10 +13,9 @@ export const useReleasePlans = (
|
||||
environment?: string,
|
||||
) => {
|
||||
const { isEnterprise } = useUiConfig();
|
||||
const releasePlansEnabled = useUiFlag('releasePlans');
|
||||
|
||||
const { data, error, mutate } = useConditionalSWR<IReleasePlan[]>(
|
||||
isEnterprise() && releasePlansEnabled && Boolean(environment),
|
||||
isEnterprise() && Boolean(environment),
|
||||
DEFAULT_DATA,
|
||||
formatApiPath(
|
||||
`api/admin/projects/${projectId}/features/${featureName}/environments/${environment}/release_plans`,
|
||||
|
@ -79,7 +79,6 @@ export type UiFlags = {
|
||||
manyStrategiesPagination?: boolean;
|
||||
enableLegacyVariants?: boolean;
|
||||
flagCreator?: boolean;
|
||||
releasePlans?: boolean;
|
||||
productivityReportEmail?: boolean;
|
||||
showUserDeviceCount?: boolean;
|
||||
consumptionModel?: boolean;
|
||||
|
@ -41,7 +41,6 @@ export type IFlagKey =
|
||||
| 'projectRoleAssignment'
|
||||
| 'originMiddlewareRequestLogging'
|
||||
| 'webhookDomainLogging'
|
||||
| 'releasePlans'
|
||||
| 'productivityReportEmail'
|
||||
| 'productivityReportUnsubscribers'
|
||||
| 'showUserDeviceCount'
|
||||
@ -209,10 +208,6 @@ const flags: IFlags = {
|
||||
process.env.UNLEASH_EXPERIMENT_WEBHOOK_DOMAIN_LOGGING,
|
||||
false,
|
||||
),
|
||||
releasePlans: parseEnvVarBoolean(
|
||||
process.env.UNLEASH_EXPERIMENTAL_RELEASE_PLANS,
|
||||
false,
|
||||
),
|
||||
productivityReportEmail: parseEnvVarBoolean(
|
||||
process.env.UNLEASH_EXPERIMENTAL_PRODUCTIVITY_REPORT_EMAIL,
|
||||
false,
|
||||
|
@ -46,7 +46,6 @@ process.nextTick(async () => {
|
||||
extendedMetrics: true,
|
||||
originMiddlewareRequestLogging: true,
|
||||
webhookDomainLogging: true,
|
||||
releasePlans: false,
|
||||
showUserDeviceCount: true,
|
||||
deltaApi: true,
|
||||
uniqueSdkTracking: true,
|
||||
|
Loading…
Reference in New Issue
Block a user