mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
chore: deprecate custom strategies (#7186)
This commit is contained in:
parent
0c4d4643bd
commit
f16f8594f5
@ -10,6 +10,7 @@ import {
|
|||||||
Box,
|
Box,
|
||||||
Divider,
|
Divider,
|
||||||
Typography,
|
Typography,
|
||||||
|
Link,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import type {
|
import type {
|
||||||
IFeatureStrategy,
|
IFeatureStrategy,
|
||||||
@ -42,7 +43,7 @@ import { useHasProjectEnvironmentAccess } from 'hooks/useHasAccess';
|
|||||||
import { FeatureStrategyTitle } from './FeatureStrategyTitle/FeatureStrategyTitle';
|
import { FeatureStrategyTitle } from './FeatureStrategyTitle/FeatureStrategyTitle';
|
||||||
import { FeatureStrategyEnabledDisabled } from './FeatureStrategyEnabledDisabled/FeatureStrategyEnabledDisabled';
|
import { FeatureStrategyEnabledDisabled } from './FeatureStrategyEnabledDisabled/FeatureStrategyEnabledDisabled';
|
||||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
import { formatStrategyName } from 'utils/strategyNames';
|
import { BuiltInStrategies, formatStrategyName } from 'utils/strategyNames';
|
||||||
import { Badge } from 'component/common/Badge/Badge';
|
import { Badge } from 'component/common/Badge/Badge';
|
||||||
import EnvironmentIcon from 'component/common/EnvironmentIcon/EnvironmentIcon';
|
import EnvironmentIcon from 'component/common/EnvironmentIcon/EnvironmentIcon';
|
||||||
|
|
||||||
@ -389,6 +390,29 @@ export const FeatureStrategyForm = ({
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={
|
||||||
|
!BuiltInStrategies.includes(strategy.name || 'default')
|
||||||
|
}
|
||||||
|
show={
|
||||||
|
<Alert severity='warning'>
|
||||||
|
Custom strategies are deprecated. We recommend not
|
||||||
|
adding them to any flags going forward and using the
|
||||||
|
predefined strategies like Gradual rollout with{' '}
|
||||||
|
<Link
|
||||||
|
href={
|
||||||
|
'https://docs.getunleash.io/reference/strategy-constraints'
|
||||||
|
}
|
||||||
|
target='_blank'
|
||||||
|
variant='body2'
|
||||||
|
>
|
||||||
|
constraints
|
||||||
|
</Link>{' '}
|
||||||
|
instead.
|
||||||
|
</Alert>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<FeatureStrategyEnabled
|
<FeatureStrategyEnabled
|
||||||
projectId={feature.project}
|
projectId={feature.project}
|
||||||
featureId={feature.name}
|
featureId={feature.name}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Fragment, useMemo, type VFC } from 'react';
|
import { Fragment, useMemo, type VFC } from 'react';
|
||||||
import { Box, Chip, styled } from '@mui/material';
|
import { Alert, Box, Chip, Link, styled } from '@mui/material';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
|
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
|
||||||
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
||||||
@ -17,6 +17,7 @@ import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
|||||||
import { Badge } from 'component/common/Badge/Badge';
|
import { Badge } from 'component/common/Badge/Badge';
|
||||||
import type { CreateFeatureStrategySchema } from 'openapi';
|
import type { CreateFeatureStrategySchema } from 'openapi';
|
||||||
import type { IFeatureStrategyPayload } from 'interfaces/strategy';
|
import type { IFeatureStrategyPayload } from 'interfaces/strategy';
|
||||||
|
import { BuiltInStrategies } from 'utils/strategyNames';
|
||||||
|
|
||||||
interface IStrategyExecutionProps {
|
interface IStrategyExecutionProps {
|
||||||
strategy: IFeatureStrategyPayload | CreateFeatureStrategySchema;
|
strategy: IFeatureStrategyPayload | CreateFeatureStrategySchema;
|
||||||
@ -41,6 +42,20 @@ const StyledContainer = styled(Box, {
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const CustomStrategyDeprecationWarning = () => (
|
||||||
|
<Alert severity='warning' sx={{ mb: 2 }}>
|
||||||
|
Custom strategies are deprecated and may be removed in a future major
|
||||||
|
version. Consider rewriting this strategy as a predefined strategy with{' '}
|
||||||
|
<Link
|
||||||
|
href={'https://docs.getunleash.io/reference/strategy-constraints'}
|
||||||
|
target='_blank'
|
||||||
|
variant='body2'
|
||||||
|
>
|
||||||
|
constraints.
|
||||||
|
</Link>
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
|
|
||||||
const NoItems: VFC = () => (
|
const NoItems: VFC = () => (
|
||||||
<Box sx={{ px: 3, color: 'text.disabled' }}>
|
<Box sx={{ px: 3, color: 'text.disabled' }}>
|
||||||
This strategy does not have constraints or parameters.
|
This strategy does not have constraints or parameters.
|
||||||
@ -299,22 +314,31 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
|
|||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConditionallyRender
|
<>
|
||||||
condition={listItems.length > 0}
|
<ConditionallyRender
|
||||||
show={
|
condition={
|
||||||
<StyledContainer disabled={Boolean(strategy.disabled)}>
|
!BuiltInStrategies.includes(strategy.name || 'default')
|
||||||
{listItems.map((item, index) => (
|
}
|
||||||
<Fragment key={index}>
|
show={<CustomStrategyDeprecationWarning />}
|
||||||
<ConditionallyRender
|
/>
|
||||||
condition={index > 0}
|
|
||||||
show={<StrategySeparator text='AND' />}
|
<ConditionallyRender
|
||||||
/>
|
condition={listItems.length > 0}
|
||||||
{item}
|
show={
|
||||||
</Fragment>
|
<StyledContainer disabled={Boolean(strategy.disabled)}>
|
||||||
))}
|
{listItems.map((item, index) => (
|
||||||
</StyledContainer>
|
<Fragment key={index}>
|
||||||
}
|
<ConditionallyRender
|
||||||
elseShow={<NoItems />}
|
condition={index > 0}
|
||||||
/>
|
show={<StrategySeparator text='AND' />}
|
||||||
|
/>
|
||||||
|
{item}
|
||||||
|
</Fragment>
|
||||||
|
))}
|
||||||
|
</StyledContainer>
|
||||||
|
}
|
||||||
|
elseShow={<NoItems />}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,15 +1,5 @@
|
|||||||
import type { PlaygroundFeatureSchema } from 'openapi';
|
import type { PlaygroundFeatureSchema } from 'openapi';
|
||||||
|
import { BuiltInStrategies } from 'utils/strategyNames';
|
||||||
export const DEFAULT_STRATEGIES = [
|
|
||||||
'default',
|
|
||||||
'applicationHostname',
|
|
||||||
'flexibleRollout',
|
|
||||||
'gradualRolloutRandom',
|
|
||||||
'gradualRolloutSessionId',
|
|
||||||
'gradualRolloutUserId',
|
|
||||||
'remoteAddress',
|
|
||||||
'userWithId',
|
|
||||||
];
|
|
||||||
|
|
||||||
export function checkForEmptyValues(object?: Object): boolean {
|
export function checkForEmptyValues(object?: Object): boolean {
|
||||||
if (object === undefined) {
|
if (object === undefined) {
|
||||||
@ -22,7 +12,7 @@ export function checkForEmptyValues(object?: Object): boolean {
|
|||||||
|
|
||||||
export const hasCustomStrategies = (feature: PlaygroundFeatureSchema) => {
|
export const hasCustomStrategies = (feature: PlaygroundFeatureSchema) => {
|
||||||
return feature.strategies?.data?.find(
|
return feature.strategies?.data?.find(
|
||||||
(strategy) => !DEFAULT_STRATEGIES.includes(strategy.name),
|
(strategy) => !BuiltInStrategies.includes(strategy.name),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,7 +20,7 @@ export const hasOnlyCustomStrategies = (feature: PlaygroundFeatureSchema) => {
|
|||||||
return (
|
return (
|
||||||
feature.strategies?.data?.length > 0 &&
|
feature.strategies?.data?.length > 0 &&
|
||||||
!feature.strategies?.data?.find((strategy) =>
|
!feature.strategies?.data?.find((strategy) =>
|
||||||
DEFAULT_STRATEGIES.includes(strategy.name),
|
BuiltInStrategies.includes(strategy.name),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate, Link } from 'react-router-dom';
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
import FormTemplate from 'component/common/FormTemplate/FormTemplate';
|
import FormTemplate from 'component/common/FormTemplate/FormTemplate';
|
||||||
@ -11,6 +11,25 @@ import { formatUnknownError } from 'utils/formatUnknownError';
|
|||||||
import { CreateButton } from 'component/common/CreateButton/CreateButton';
|
import { CreateButton } from 'component/common/CreateButton/CreateButton';
|
||||||
import { GO_BACK } from 'constants/navigate';
|
import { GO_BACK } from 'constants/navigate';
|
||||||
import { CustomStrategyInfo } from '../CustomStrategyInfo/CustomStrategyInfo';
|
import { CustomStrategyInfo } from '../CustomStrategyInfo/CustomStrategyInfo';
|
||||||
|
import { Alert } from '@mui/material';
|
||||||
|
|
||||||
|
const CreateStrategyDeprecationWarning = () => (
|
||||||
|
<Alert
|
||||||
|
severity='warning'
|
||||||
|
sx={(theme) => ({
|
||||||
|
marginBottom: theme.spacing(3),
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
Custom strategies are deprecated and may be removed in a future major
|
||||||
|
release. We recommend using the predefined strategies like Gradual
|
||||||
|
rollout with{' '}
|
||||||
|
<Link to='https://docs.getunleash.io/reference/strategy-constraints'>
|
||||||
|
{' '}
|
||||||
|
constraints
|
||||||
|
</Link>{' '}
|
||||||
|
instead of creating a custom strategy.
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
|
|
||||||
export const CreateStrategy = () => {
|
export const CreateStrategy = () => {
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
@ -77,6 +96,7 @@ export const CreateStrategy = () => {
|
|||||||
documentationLinkLabel='Custom strategies documentation'
|
documentationLinkLabel='Custom strategies documentation'
|
||||||
formatApiCode={formatApiCode}
|
formatApiCode={formatApiCode}
|
||||||
>
|
>
|
||||||
|
<CreateStrategyDeprecationWarning />
|
||||||
<CustomStrategyInfo alert />
|
<CustomStrategyInfo alert />
|
||||||
<StrategyForm
|
<StrategyForm
|
||||||
errors={errors}
|
errors={errors}
|
||||||
|
@ -17,11 +17,8 @@ export const CustomStrategyInfo: FC<{ alert?: boolean }> = ({ alert }) => {
|
|||||||
const content = (
|
const content = (
|
||||||
<>
|
<>
|
||||||
<Paragraph>
|
<Paragraph>
|
||||||
We recommend you to use the predefined strategies like Gradual
|
If you decide to create a custom strategy be aware of the
|
||||||
rollout with constraints instead of creating a custom strategy.
|
following:
|
||||||
</Paragraph>
|
|
||||||
<Paragraph>
|
|
||||||
If you decide to create a custom strategy be aware of:
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
They require writing custom code and deployments for
|
They require writing custom code and deployments for
|
||||||
@ -32,8 +29,8 @@ export const CustomStrategyInfo: FC<{ alert?: boolean }> = ({ alert }) => {
|
|||||||
to evaluate differently
|
to evaluate differently
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Requires a lot of configuration in both Unleash admin UI
|
Custom strategies require a lot of configuration in both
|
||||||
and the SDK.
|
Unleash admin UI and the SDK.
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useState, useMemo, useCallback, type FC } from 'react';
|
import { useState, useMemo, useCallback, type FC } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Box, Link, Typography, styled } from '@mui/material';
|
import { Alert, Box, Link, Typography, styled } from '@mui/material';
|
||||||
import Extension from '@mui/icons-material/Extension';
|
import Extension from '@mui/icons-material/Extension';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
@ -110,6 +110,23 @@ const PredefinedStrategyTitle = () => (
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const StrategyDeprecationWarning = () => (
|
||||||
|
<Alert severity='warning' sx={{ mb: 2 }}>
|
||||||
|
Custom strategies are deprecated and may be removed in a future major
|
||||||
|
version. We recommend not using custom strategies going forward and
|
||||||
|
instead using the predefined strategies with{' '}
|
||||||
|
<Link
|
||||||
|
href={'https://docs.getunleash.io/reference/strategy-constraints'}
|
||||||
|
target='_blank'
|
||||||
|
variant='body2'
|
||||||
|
>
|
||||||
|
constraints
|
||||||
|
</Link>
|
||||||
|
. If you have a need for custom strategies that you cannot support with
|
||||||
|
constraints, please reach out to us.
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
|
|
||||||
export const StrategiesList = () => {
|
export const StrategiesList = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [dialogueMetaData, setDialogueMetaData] = useState<IDialogueMetaData>(
|
const [dialogueMetaData, setDialogueMetaData] = useState<IDialogueMetaData>(
|
||||||
@ -434,6 +451,7 @@ export const StrategiesList = () => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Box>
|
<Box>
|
||||||
|
<StrategyDeprecationWarning />
|
||||||
<Table {...customGetTableProps()}>
|
<Table {...customGetTableProps()}>
|
||||||
<SortableTableHeader
|
<SortableTableHeader
|
||||||
headerGroups={customHeaderGroups}
|
headerGroups={customHeaderGroups}
|
||||||
|
@ -36,6 +36,17 @@ export const getFeatureStrategyIcon = (strategyName: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const BuiltInStrategies = [
|
||||||
|
'default',
|
||||||
|
'applicationHostname',
|
||||||
|
'flexibleRollout',
|
||||||
|
'gradualRolloutRandom',
|
||||||
|
'gradualRolloutSessionId',
|
||||||
|
'gradualRolloutUserId',
|
||||||
|
'remoteAddress',
|
||||||
|
'userWithId',
|
||||||
|
];
|
||||||
|
|
||||||
export const GetFeatureStrategyIcon: FC<{ strategyName: string }> = ({
|
export const GetFeatureStrategyIcon: FC<{ strategyName: string }> = ({
|
||||||
strategyName,
|
strategyName,
|
||||||
}) => {
|
}) => {
|
||||||
|
@ -122,11 +122,12 @@ class StrategyController extends Controller {
|
|||||||
permission: CREATE_STRATEGY,
|
permission: CREATE_STRATEGY,
|
||||||
middleware: [
|
middleware: [
|
||||||
openApiService.validPath({
|
openApiService.validPath({
|
||||||
|
deprecated: true,
|
||||||
tags: ['Strategies'],
|
tags: ['Strategies'],
|
||||||
operationId: 'createStrategy',
|
operationId: 'createStrategy',
|
||||||
summary: 'Create a strategy',
|
summary: 'Create a strategy',
|
||||||
description:
|
description:
|
||||||
'Creates a strategy type based on the supplied data.',
|
'Creates a custom strategy type based on the supplied data. Custom strategies are deprecated and should not be used. Prefer using built in strategies with constraints instead.',
|
||||||
requestBody: createRequestSchema('createStrategySchema'),
|
requestBody: createRequestSchema('createStrategySchema'),
|
||||||
responses: {
|
responses: {
|
||||||
201: resourceCreatedResponseSchema('strategySchema'),
|
201: resourceCreatedResponseSchema('strategySchema'),
|
||||||
|
Loading…
Reference in New Issue
Block a user