Skip to content

Commit

Permalink
chore: remove usage of feature naming pattern flag (#5364)
Browse files Browse the repository at this point in the history
In preparation for this feature going GA
  • Loading branch information
thomasheartman committed Nov 20, 2023
1 parent fd099e2 commit 90d6c7c
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 135 deletions.
6 changes: 1 addition & 5 deletions frontend/src/component/feature/FeatureForm/FeatureForm.tsx
Expand Up @@ -23,7 +23,6 @@ import React from 'react';
import { useAuthPermissions } from 'hooks/api/getters/useAuth/useAuthPermissions';
import { FeatureNamingType } from 'interfaces/project';
import { FeatureNamingPatternInfo } from '../FeatureNamingPatternInfo/FeatureNamingPatternInfo';
import { useUiFlag } from 'hooks/useUiFlag';

interface IFeatureToggleForm {
type: string;
Expand Down Expand Up @@ -122,15 +121,12 @@ const FeatureForm: React.FC<IFeatureToggleForm> = ({
const navigate = useNavigate();
const { permissions } = useAuthPermissions();
const editable = mode !== 'Edit';
const featureNamingPatternEnabled = useUiFlag('featureNamingPattern');

const renderToggleDescription = () => {
return featureTypes.find((toggle) => toggle.id === type)?.description;
};

const displayFeatureNamingInfo = Boolean(
featureNamingPatternEnabled && featureNaming?.pattern,
);
const displayFeatureNamingInfo = Boolean(featureNaming?.pattern);

React.useEffect(() => {
if (featureNaming?.pattern && validateToggleName && name) {
Expand Down
Expand Up @@ -136,7 +136,6 @@ const ProjectEnterpriseSettingsForm: React.FC<IProjectEnterpriseSettingsForm> =
clearErrors,
}) => {
const privateProjects = useUiFlag('privateProjects');
const shouldShowFlagNaming = useUiFlag('featureNamingPattern');

const { setPreviousPattern, trackPattern } =
useFeatureNamePatternTracking();
Expand Down Expand Up @@ -253,115 +252,104 @@ const ProjectEnterpriseSettingsForm: React.FC<IProjectEnterpriseSettingsForm> =
options={projectModeOptions}
/>
</>
<ConditionallyRender
condition={Boolean(shouldShowFlagNaming)}
show={
<StyledFieldset>
<Box
sx={{
display: 'flex',
alignItems: 'center',
marginBottom: 1,
gap: 1,
}}
>
<legend>Feature flag naming pattern?</legend>
<FeatureFlagNamingTooltip />
</Box>
<StyledSubtitle>
<StyledPatternNamingExplanation id='pattern-naming-description'>
<p>
Define a{' '}
<a
href={`https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Cheatsheet`}
target='_blank'
rel='noreferrer'
>
JavaScript RegEx
</a>{' '}
used to enforce feature flag names
within this project. The regex will be
surrounded by a leading <code>^</code>{' '}
and a trailing <code>$</code>.
</p>
<p>
Leave it empty if you don’t want to add
a naming pattern.
</p>
</StyledPatternNamingExplanation>
</StyledSubtitle>
<StyledFlagNamingContainer>
<StyledInput
label={'Naming Pattern'}
name='feature flag naming pattern'
aria-describedby='pattern-naming-description'
placeholder='[A-Za-z]+.[A-Za-z]+.[A-Za-z0-9-]+'
InputProps={{
startAdornment: (
<InputAdornment position='start'>
^
</InputAdornment>
),
endAdornment: (
<InputAdornment position='end'>
$
</InputAdornment>
),
}}
type={'text'}
value={featureNamingPattern || ''}
error={Boolean(errors.featureNamingPattern)}
errorText={errors.featureNamingPattern}
onChange={(e) =>
onSetFeatureNamingPattern(
e.target.value,
)
}
/>
<StyledSubtitle>
<p id='pattern-additional-description'>
The example and description will be
shown to users when they create a new
feature flag in this project.
</p>
</StyledSubtitle>
<StyledFieldset>
<Box
sx={{
display: 'flex',
alignItems: 'center',
marginBottom: 1,
gap: 1,
}}
>
<legend>Feature flag naming pattern?</legend>
<FeatureFlagNamingTooltip />
</Box>
<StyledSubtitle>
<StyledPatternNamingExplanation id='pattern-naming-description'>
<p>
Define a{' '}
<a
href={`https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Cheatsheet`}
target='_blank'
rel='noreferrer'
>
JavaScript RegEx
</a>{' '}
used to enforce feature flag names within this
project. The regex will be surrounded by a
leading <code>^</code> and a trailing{' '}
<code>$</code>.
</p>
<p>
Leave it empty if you don’t want to add a naming
pattern.
</p>
</StyledPatternNamingExplanation>
</StyledSubtitle>
<StyledFlagNamingContainer>
<StyledInput
label={'Naming Pattern'}
name='feature flag naming pattern'
aria-describedby='pattern-naming-description'
placeholder='[A-Za-z]+.[A-Za-z]+.[A-Za-z0-9-]+'
InputProps={{
startAdornment: (
<InputAdornment position='start'>
^
</InputAdornment>
),
endAdornment: (
<InputAdornment position='end'>
$
</InputAdornment>
),
}}
type={'text'}
value={featureNamingPattern || ''}
error={Boolean(errors.featureNamingPattern)}
errorText={errors.featureNamingPattern}
onChange={(e) =>
onSetFeatureNamingPattern(e.target.value)
}
/>
<StyledSubtitle>
<p id='pattern-additional-description'>
The example and description will be shown to
users when they create a new feature flag in
this project.
</p>
</StyledSubtitle>

<StyledInput
label={'Naming Example'}
name='feature flag naming example'
type={'text'}
aria-describedby='pattern-additional-description'
value={featureNamingExample || ''}
placeholder='dx.feature1.1-135'
error={Boolean(errors.namingExample)}
errorText={errors.namingExample}
onChange={(e) =>
onSetFeatureNamingExample(
e.target.value,
)
}
/>
<StyledTextField
label={'Naming pattern description'}
name='feature flag naming description'
type={'text'}
aria-describedby='pattern-additional-description'
placeholder={`<project>.<featureName>.<ticket>
<StyledInput
label={'Naming Example'}
name='feature flag naming example'
type={'text'}
aria-describedby='pattern-additional-description'
value={featureNamingExample || ''}
placeholder='dx.feature1.1-135'
error={Boolean(errors.namingExample)}
errorText={errors.namingExample}
onChange={(e) =>
onSetFeatureNamingExample(e.target.value)
}
/>
<StyledTextField
label={'Naming pattern description'}
name='feature flag naming description'
type={'text'}
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.`}
multiline
minRows={5}
value={featureNamingDescription || ''}
onChange={(e) =>
onSetFeatureNamingDescription(
e.target.value,
)
}
/>
</StyledFlagNamingContainer>
</StyledFieldset>
}
/>
multiline
minRows={5}
value={featureNamingDescription || ''}
onChange={(e) =>
onSetFeatureNamingDescription(e.target.value)
}
/>
</StyledFlagNamingContainer>
</StyledFieldset>
<StyledButtonContainer>{children}</StyledButtonContainer>
</StyledForm>
);
Expand Down
1 change: 0 additions & 1 deletion frontend/src/interfaces/uiConfig.ts
Expand Up @@ -61,7 +61,6 @@ export type UiFlags = {
customRootRolesKillSwitch?: boolean;
strategyVariant?: boolean;
lastSeenByEnvironment?: boolean;
featureNamingPattern?: boolean;
doraMetrics?: boolean;
variantTypeNumber?: boolean;
privateProjects?: boolean;
Expand Down
1 change: 0 additions & 1 deletion src/lib/__snapshots__/create-config.test.ts.snap
Expand Up @@ -84,7 +84,6 @@ exports[`should create default config 1`] = `
"doraMetrics": false,
"embedProxy": true,
"embedProxyFrontend": true,
"featureNamingPattern": false,
"featureSearchAPI": false,
"featureSearchFrontend": false,
"featuresExportImport": true,
Expand Down
Expand Up @@ -159,7 +159,6 @@ beforeAll(async () => {
experimental: {
flags: {
featuresExportImport: true,
featureNamingPattern: true,
dependentFeatures: true,
},
},
Expand Down
23 changes: 11 additions & 12 deletions src/lib/features/feature-toggle/feature-toggle-service.ts
Expand Up @@ -1168,22 +1168,21 @@ class FeatureToggleService {
projectId: string,
featureNames: string[],
): Promise<FeatureNameCheckResultWithFeaturePattern> {
if (this.flagResolver.isEnabled('featureNamingPattern')) {
const project = await this.projectStore.get(projectId);
const patternData = project.featureNaming;
const namingPattern = patternData?.pattern;
const project = await this.projectStore.get(projectId);
const patternData = project.featureNaming;
const namingPattern = patternData?.pattern;

if (namingPattern) {
const result = checkFeatureFlagNamesAgainstPattern(
featureNames,
namingPattern,
);
if (namingPattern) {
const result = checkFeatureFlagNamesAgainstPattern(
featureNames,
namingPattern,
);

if (result.state === 'invalid') {
return { ...result, featureNaming: patternData };
}
if (result.state === 'invalid') {
return { ...result, featureNaming: patternData };
}
}

return { state: 'valid' };
}

Expand Down
Expand Up @@ -39,7 +39,7 @@ const irrelevantDate = new Date();
beforeAll(async () => {
const config = createTestConfig({
experimental: {
flags: { featureNamingPattern: true, playgroundImprovements: true },
flags: { playgroundImprovements: true },
},
});
db = await dbInit(
Expand Down
5 changes: 0 additions & 5 deletions src/lib/types/experimental.ts
Expand Up @@ -23,7 +23,6 @@ export type IFlagKey =
| 'filterInvalidClientMetrics'
| 'lastSeenByEnvironment'
| 'customRootRolesKillSwitch'
| 'featureNamingPattern'
| 'doraMetrics'
| 'variantTypeNumber'
| 'privateProjects'
Expand Down Expand Up @@ -116,10 +115,6 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_CUSTOM_ROOT_ROLES_KILL_SWITCH,
false,
),
featureNamingPattern: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_FEATURE_NAMING_PATTERN,
false,
),
doraMetrics: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_DORA_METRICS,
false,
Expand Down
1 change: 0 additions & 1 deletion src/server-dev.ts
Expand Up @@ -38,7 +38,6 @@ process.nextTick(async () => {
anonymiseEventLog: false,
responseTimeWithAppNameKillSwitch: false,
lastSeenByEnvironment: true,
featureNamingPattern: true,
doraMetrics: true,
variantTypeNumber: true,
privateProjects: true,
Expand Down
1 change: 0 additions & 1 deletion src/test/e2e/api/client/feature.e2e.test.ts
Expand Up @@ -21,7 +21,6 @@ beforeAll(async () => {
experimental: {
flags: {
strictSchemaValidation: true,
featureNamingPattern: true,
dependentFeatures: true,
},
},
Expand Down

0 comments on commit 90d6c7c

Please sign in to comment.