1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-09 00:18:00 +01:00

chore: remove usage of feature naming pattern flag (#5364)

In preparation for this feature going GA
This commit is contained in:
Thomas Heartman 2023-11-20 12:42:24 +01:00 committed by GitHub
parent fd099e242e
commit 90d6c7c0ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 108 additions and 135 deletions

View File

@ -23,7 +23,6 @@ import React from 'react';
import { useAuthPermissions } from 'hooks/api/getters/useAuth/useAuthPermissions'; import { useAuthPermissions } from 'hooks/api/getters/useAuth/useAuthPermissions';
import { FeatureNamingType } from 'interfaces/project'; import { FeatureNamingType } from 'interfaces/project';
import { FeatureNamingPatternInfo } from '../FeatureNamingPatternInfo/FeatureNamingPatternInfo'; import { FeatureNamingPatternInfo } from '../FeatureNamingPatternInfo/FeatureNamingPatternInfo';
import { useUiFlag } from 'hooks/useUiFlag';
interface IFeatureToggleForm { interface IFeatureToggleForm {
type: string; type: string;
@ -122,15 +121,12 @@ const FeatureForm: React.FC<IFeatureToggleForm> = ({
const navigate = useNavigate(); const navigate = useNavigate();
const { permissions } = useAuthPermissions(); const { permissions } = useAuthPermissions();
const editable = mode !== 'Edit'; const editable = mode !== 'Edit';
const featureNamingPatternEnabled = useUiFlag('featureNamingPattern');
const renderToggleDescription = () => { const renderToggleDescription = () => {
return featureTypes.find((toggle) => toggle.id === type)?.description; return featureTypes.find((toggle) => toggle.id === type)?.description;
}; };
const displayFeatureNamingInfo = Boolean( const displayFeatureNamingInfo = Boolean(featureNaming?.pattern);
featureNamingPatternEnabled && featureNaming?.pattern,
);
React.useEffect(() => { React.useEffect(() => {
if (featureNaming?.pattern && validateToggleName && name) { if (featureNaming?.pattern && validateToggleName && name) {

View File

@ -136,7 +136,6 @@ const ProjectEnterpriseSettingsForm: React.FC<IProjectEnterpriseSettingsForm> =
clearErrors, clearErrors,
}) => { }) => {
const privateProjects = useUiFlag('privateProjects'); const privateProjects = useUiFlag('privateProjects');
const shouldShowFlagNaming = useUiFlag('featureNamingPattern');
const { setPreviousPattern, trackPattern } = const { setPreviousPattern, trackPattern } =
useFeatureNamePatternTracking(); useFeatureNamePatternTracking();
@ -253,115 +252,104 @@ const ProjectEnterpriseSettingsForm: React.FC<IProjectEnterpriseSettingsForm> =
options={projectModeOptions} options={projectModeOptions}
/> />
</> </>
<ConditionallyRender <StyledFieldset>
condition={Boolean(shouldShowFlagNaming)} <Box
show={ sx={{
<StyledFieldset> display: 'flex',
<Box alignItems: 'center',
sx={{ marginBottom: 1,
display: 'flex', gap: 1,
alignItems: 'center', }}
marginBottom: 1, >
gap: 1, <legend>Feature flag naming pattern?</legend>
}} <FeatureFlagNamingTooltip />
> </Box>
<legend>Feature flag naming pattern?</legend> <StyledSubtitle>
<FeatureFlagNamingTooltip /> <StyledPatternNamingExplanation id='pattern-naming-description'>
</Box> <p>
<StyledSubtitle> Define a{' '}
<StyledPatternNamingExplanation id='pattern-naming-description'> <a
<p> href={`https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Cheatsheet`}
Define a{' '} target='_blank'
<a rel='noreferrer'
href={`https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Cheatsheet`} >
target='_blank' JavaScript RegEx
rel='noreferrer' </a>{' '}
> used to enforce feature flag names within this
JavaScript RegEx project. The regex will be surrounded by a
</a>{' '} leading <code>^</code> and a trailing{' '}
used to enforce feature flag names <code>$</code>.
within this project. The regex will be </p>
surrounded by a leading <code>^</code>{' '} <p>
and a trailing <code>$</code>. Leave it empty if you dont want to add a naming
</p> pattern.
<p> </p>
Leave it empty if you dont want to add </StyledPatternNamingExplanation>
a naming pattern. </StyledSubtitle>
</p> <StyledFlagNamingContainer>
</StyledPatternNamingExplanation> <StyledInput
</StyledSubtitle> label={'Naming Pattern'}
<StyledFlagNamingContainer> name='feature flag naming pattern'
<StyledInput aria-describedby='pattern-naming-description'
label={'Naming Pattern'} placeholder='[A-Za-z]+.[A-Za-z]+.[A-Za-z0-9-]+'
name='feature flag naming pattern' InputProps={{
aria-describedby='pattern-naming-description' startAdornment: (
placeholder='[A-Za-z]+.[A-Za-z]+.[A-Za-z0-9-]+' <InputAdornment position='start'>
InputProps={{ ^
startAdornment: ( </InputAdornment>
<InputAdornment position='start'> ),
^ endAdornment: (
</InputAdornment> <InputAdornment position='end'>
), $
endAdornment: ( </InputAdornment>
<InputAdornment position='end'> ),
$ }}
</InputAdornment> type={'text'}
), value={featureNamingPattern || ''}
}} error={Boolean(errors.featureNamingPattern)}
type={'text'} errorText={errors.featureNamingPattern}
value={featureNamingPattern || ''} onChange={(e) =>
error={Boolean(errors.featureNamingPattern)} onSetFeatureNamingPattern(e.target.value)
errorText={errors.featureNamingPattern} }
onChange={(e) => />
onSetFeatureNamingPattern( <StyledSubtitle>
e.target.value, <p id='pattern-additional-description'>
) The example and description will be shown to
} users when they create a new feature flag in
/> this project.
<StyledSubtitle> </p>
<p id='pattern-additional-description'> </StyledSubtitle>
The example and description will be
shown to users when they create a new
feature flag in this project.
</p>
</StyledSubtitle>
<StyledInput <StyledInput
label={'Naming Example'} label={'Naming Example'}
name='feature flag naming example' name='feature flag naming example'
type={'text'} type={'text'}
aria-describedby='pattern-additional-description' aria-describedby='pattern-additional-description'
value={featureNamingExample || ''} value={featureNamingExample || ''}
placeholder='dx.feature1.1-135' placeholder='dx.feature1.1-135'
error={Boolean(errors.namingExample)} error={Boolean(errors.namingExample)}
errorText={errors.namingExample} errorText={errors.namingExample}
onChange={(e) => onChange={(e) =>
onSetFeatureNamingExample( onSetFeatureNamingExample(e.target.value)
e.target.value, }
) />
} <StyledTextField
/> label={'Naming pattern description'}
<StyledTextField name='feature flag naming description'
label={'Naming pattern description'} type={'text'}
name='feature flag naming description' aria-describedby='pattern-additional-description'
type={'text'} placeholder={`<project>.<featureName>.<ticket>
aria-describedby='pattern-additional-description'
placeholder={`<project>.<featureName>.<ticket>
The flag name should contain the project name, the feature name, and the ticket number, each separated by a dot.`} The flag name should contain the project name, the feature name, and the ticket number, each separated by a dot.`}
multiline multiline
minRows={5} minRows={5}
value={featureNamingDescription || ''} value={featureNamingDescription || ''}
onChange={(e) => onChange={(e) =>
onSetFeatureNamingDescription( onSetFeatureNamingDescription(e.target.value)
e.target.value, }
) />
} </StyledFlagNamingContainer>
/> </StyledFieldset>
</StyledFlagNamingContainer>
</StyledFieldset>
}
/>
<StyledButtonContainer>{children}</StyledButtonContainer> <StyledButtonContainer>{children}</StyledButtonContainer>
</StyledForm> </StyledForm>
); );

View File

@ -61,7 +61,6 @@ export type UiFlags = {
customRootRolesKillSwitch?: boolean; customRootRolesKillSwitch?: boolean;
strategyVariant?: boolean; strategyVariant?: boolean;
lastSeenByEnvironment?: boolean; lastSeenByEnvironment?: boolean;
featureNamingPattern?: boolean;
doraMetrics?: boolean; doraMetrics?: boolean;
variantTypeNumber?: boolean; variantTypeNumber?: boolean;
privateProjects?: boolean; privateProjects?: boolean;

View File

@ -84,7 +84,6 @@ exports[`should create default config 1`] = `
"doraMetrics": false, "doraMetrics": false,
"embedProxy": true, "embedProxy": true,
"embedProxyFrontend": true, "embedProxyFrontend": true,
"featureNamingPattern": false,
"featureSearchAPI": false, "featureSearchAPI": false,
"featureSearchFrontend": false, "featureSearchFrontend": false,
"featuresExportImport": true, "featuresExportImport": true,

View File

@ -159,7 +159,6 @@ beforeAll(async () => {
experimental: { experimental: {
flags: { flags: {
featuresExportImport: true, featuresExportImport: true,
featureNamingPattern: true,
dependentFeatures: true, dependentFeatures: true,
}, },
}, },

View File

@ -1168,22 +1168,21 @@ class FeatureToggleService {
projectId: string, projectId: string,
featureNames: string[], featureNames: string[],
): Promise<FeatureNameCheckResultWithFeaturePattern> { ): Promise<FeatureNameCheckResultWithFeaturePattern> {
if (this.flagResolver.isEnabled('featureNamingPattern')) { const project = await this.projectStore.get(projectId);
const project = await this.projectStore.get(projectId); const patternData = project.featureNaming;
const patternData = project.featureNaming; const namingPattern = patternData?.pattern;
const namingPattern = patternData?.pattern;
if (namingPattern) { if (namingPattern) {
const result = checkFeatureFlagNamesAgainstPattern( const result = checkFeatureFlagNamesAgainstPattern(
featureNames, featureNames,
namingPattern, namingPattern,
); );
if (result.state === 'invalid') { if (result.state === 'invalid') {
return { ...result, featureNaming: patternData }; return { ...result, featureNaming: patternData };
}
} }
} }
return { state: 'valid' }; return { state: 'valid' };
} }

View File

@ -39,7 +39,7 @@ const irrelevantDate = new Date();
beforeAll(async () => { beforeAll(async () => {
const config = createTestConfig({ const config = createTestConfig({
experimental: { experimental: {
flags: { featureNamingPattern: true, playgroundImprovements: true }, flags: { playgroundImprovements: true },
}, },
}); });
db = await dbInit( db = await dbInit(

View File

@ -23,7 +23,6 @@ export type IFlagKey =
| 'filterInvalidClientMetrics' | 'filterInvalidClientMetrics'
| 'lastSeenByEnvironment' | 'lastSeenByEnvironment'
| 'customRootRolesKillSwitch' | 'customRootRolesKillSwitch'
| 'featureNamingPattern'
| 'doraMetrics' | 'doraMetrics'
| 'variantTypeNumber' | 'variantTypeNumber'
| 'privateProjects' | 'privateProjects'
@ -116,10 +115,6 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_CUSTOM_ROOT_ROLES_KILL_SWITCH, process.env.UNLEASH_EXPERIMENTAL_CUSTOM_ROOT_ROLES_KILL_SWITCH,
false, false,
), ),
featureNamingPattern: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_FEATURE_NAMING_PATTERN,
false,
),
doraMetrics: parseEnvVarBoolean( doraMetrics: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_DORA_METRICS, process.env.UNLEASH_EXPERIMENTAL_DORA_METRICS,
false, false,

View File

@ -38,7 +38,6 @@ process.nextTick(async () => {
anonymiseEventLog: false, anonymiseEventLog: false,
responseTimeWithAppNameKillSwitch: false, responseTimeWithAppNameKillSwitch: false,
lastSeenByEnvironment: true, lastSeenByEnvironment: true,
featureNamingPattern: true,
doraMetrics: true, doraMetrics: true,
variantTypeNumber: true, variantTypeNumber: true,
privateProjects: true, privateProjects: true,

View File

@ -21,7 +21,6 @@ beforeAll(async () => {
experimental: { experimental: {
flags: { flags: {
strictSchemaValidation: true, strictSchemaValidation: true,
featureNamingPattern: true,
dependentFeatures: true, dependentFeatures: true,
}, },
}, },