diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue index 0807756bc897ad39121828c7509dc7c73a3360a3..0e02863bb9f6bf4ffdd6ee88b5ba9ef216f71e5f 100644 --- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue +++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue @@ -33,6 +33,10 @@ export default { environmentsHelpText: s__( 'ProjectSettings|Every project can make deployments to environments either via CI/CD or API calls. Non-project members have read-only access.', ), + featureFlagsLabel: s__('ProjectSettings|Feature flags'), + featureFlagsHelpText: s__( + 'ProjectSettings|Roll out new features without redeploying with feature flags.', + ), packagesHelpText: s__( 'ProjectSettings|Every project can have its own space to store its packages. Note: The Package Registry is always visible when a project is public.', ), @@ -131,6 +135,16 @@ export default { required: false, default: '', }, + environmentsHelpPath: { + type: String, + required: false, + default: '', + }, + featureFlagsHelpPath: { + type: String, + required: false, + default: '', + }, lfsHelpPath: { type: String, required: false, @@ -214,6 +228,7 @@ export default { securityAndComplianceAccessLevel: featureAccessLevel.PROJECT_MEMBERS, operationsAccessLevel: featureAccessLevel.EVERYONE, environmentsAccessLevel: featureAccessLevel.EVERYONE, + featureFlagsAccessLevel: featureAccessLevel.PROJECT_MEMBERS, containerRegistryAccessLevel: featureAccessLevel.EVERYONE, warnAboutPotentiallyUnwantedCharacters: true, lfsEnabled: true, @@ -290,6 +305,7 @@ export default { environmentsEnabled() { return this.environmentsAccessLevel > featureAccessLevel.NOT_ENABLED; }, + repositoryEnabled() { return this.repositoryAccessLevel > featureAccessLevel.NOT_ENABLED; }, @@ -389,6 +405,10 @@ export default { featureAccessLevel.PROJECT_MEMBERS, this.environmentsAccessLevel, ); + this.featureFlagsAccessLevel = Math.min( + featureAccessLevel.PROJECT_MEMBERS, + this.featureFlagsAccessLevel, + ); this.containerRegistryAccessLevel = Math.min( featureAccessLevel.PROJECT_MEMBERS, this.containerRegistryAccessLevel, @@ -879,6 +899,7 @@ export default { ref="environments-settings" :label="$options.i18n.environmentsLabel" :help-text="$options.i18n.environmentsHelpText" + :help-path="environmentsHelpPath" > + + + diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index dfc270adf8b644dc802d768e947db4e66d36df8c..a65dd6703f28a4886b239dadcc92bd21e5348dbd 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -389,7 +389,9 @@ def project_permissions_panel_data(project) pagesAccessControlForced: ::Gitlab::Pages.access_control_is_forced?, pagesHelpPath: help_page_path('user/project/pages/introduction', anchor: 'gitlab-pages-access-control'), issuesHelpPath: help_page_path('user/project/issues/index'), - membersPagePath: project_project_members_path(project) + membersPagePath: project_project_members_path(project), + environmentsHelpPath: help_page_path('ci/environments/index'), + featureFlagsHelpPath: help_page_path('operations/feature_flags') } end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 2b606d2683b627834131fb6454ee27cd4fc1ff60..48934a0b3d034151b8fdeb2dbdb113136f309d6a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -30859,6 +30859,9 @@ msgstr "" msgid "ProjectSettings|Fast-forward merges only." msgstr "" +msgid "ProjectSettings|Feature flags" +msgstr "" + msgid "ProjectSettings|Flexible tool to collaboratively develop ideas and plan work in this project." msgstr "" @@ -31000,6 +31003,9 @@ msgstr "" msgid "ProjectSettings|Requirements management system." msgstr "" +msgid "ProjectSettings|Roll out new features without redeploying with feature flags." +msgstr "" + msgid "ProjectSettings|Search for topic" msgstr "" diff --git a/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js b/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js index f908508c4b5d3d9b8b278f5eee5e48ecedbf9e6c..b65f2c8020d861e080fdcd195a5b850f2c442747 100644 --- a/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js +++ b/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js @@ -128,6 +128,7 @@ describe('Settings Panel', () => { findOperationsSettings().findComponent(ProjectFeatureSetting); const findConfirmDangerButton = () => wrapper.findComponent(ConfirmDanger); const findEnvironmentsSettings = () => wrapper.findComponent({ ref: 'environments-settings' }); + const findFeatureFlagsSettings = () => wrapper.findComponent({ ref: 'feature-flags-settings' }); afterEach(() => { wrapper.destroy(); @@ -806,4 +807,22 @@ describe('Settings Panel', () => { }); }); }); + describe('Feature Flags', () => { + describe('with feature flag', () => { + it('should show the feature flags toggle', () => { + wrapper = mountComponent({ + glFeatures: { splitOperationsVisibilityPermissions: true }, + }); + + expect(findFeatureFlagsSettings().exists()).toBe(true); + }); + }); + describe('without feature flag', () => { + it('should not show the feature flags toggle', () => { + wrapper = mountComponent({}); + + expect(findFeatureFlagsSettings().exists()).toBe(false); + }); + }); + }); });