From af5fe4ac92733c481c420b2360631a3ba3500e48 Mon Sep 17 00:00:00 2001 From: Aleksei Lipniagov <alipniagov@gitlab.com> Date: Tue, 5 Dec 2023 12:40:33 +0000 Subject: [PATCH] Introduce AI-powered settings UI behind FF Introduce updated UI preparing for CS GA. It is hidden behind FF as it will only debut in 16.8. --- .../application_setting_implementation.rb | 1 + .../application_settings/general.html.haml | 5 +- ...pdated_ai_powered_features_menu_for_sm.yml | 8 +++ .../admin/application_settings_helper.rb | 26 +++++++++ .../helpers/ee/application_settings_helper.rb | 1 + .../_ai_powered.html.haml | 33 +++++++++++ .../admin/application_settings_helper_spec.rb | 14 +++++ .../general.html.haml_spec.rb | 57 +++++++++++++++++++ locale/gitlab.pot | 18 ++++++ .../general.html.haml_spec.rb | 3 +- 10 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 config/feature_flags/development/updated_ai_powered_features_menu_for_sm.yml create mode 100644 ee/app/views/admin/application_settings/_ai_powered.html.haml diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb index 16991937e2f3..bb1368f6dc1e 100644 --- a/app/models/application_setting_implementation.rb +++ b/app/models/application_setting_implementation.rb @@ -110,6 +110,7 @@ def defaults # rubocop:disable Metrics/AbcSize housekeeping_gc_period: 200, housekeeping_incremental_repack_period: 10, import_sources: Settings.gitlab['import_sources'], + instance_level_ai_beta_features_enabled: false, instance_level_code_suggestions_enabled: false, invisible_captcha_enabled: false, issues_create_limit: 300, diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/general.html.haml index d84fbe94f651..0ba883872a17 100644 --- a/app/views/admin/application_settings/general.html.haml +++ b/app/views/admin/application_settings/general.html.haml @@ -120,4 +120,7 @@ = render_if_exists 'admin/application_settings/add_license' = render 'admin/application_settings/jira_connect' = render 'admin/application_settings/slack' -= render_if_exists 'admin/application_settings/ai_access' +- if Feature.enabled?(:updated_ai_powered_features_menu_for_sm) + = render_if_exists 'admin/application_settings/ai_powered' +- else + = render_if_exists 'admin/application_settings/ai_access' diff --git a/config/feature_flags/development/updated_ai_powered_features_menu_for_sm.yml b/config/feature_flags/development/updated_ai_powered_features_menu_for_sm.yml new file mode 100644 index 000000000000..64377eacd5d0 --- /dev/null +++ b/config/feature_flags/development/updated_ai_powered_features_menu_for_sm.yml @@ -0,0 +1,8 @@ +--- +name: updated_ai_powered_features_menu_for_sm +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/138337 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/433255 +milestone: '16.7' +type: development +group: group::cloud connector +default_enabled: false diff --git a/ee/app/helpers/admin/application_settings_helper.rb b/ee/app/helpers/admin/application_settings_helper.rb index 0d9b5101306d..a924d3a302b7 100644 --- a/ee/app/helpers/admin/application_settings_helper.rb +++ b/ee/app/helpers/admin/application_settings_helper.rb @@ -22,6 +22,20 @@ def code_suggestions_agreement s_('CodeSuggestionsSM|By enabling this feature, you agree to the %{terms_link_start}GitLab Testing Agreement%{link_end} and acknowledge that GitLab will send data from the instance, including personal data, to our %{ai_docs_link_start}AI providers%{link_end} to provide this feature.') .html_safe % { terms_link_start: terms_link_start, ai_docs_link_start: ai_docs_link_start, link_end: '</a>'.html_safe } end + + def ai_powered_testing_agreement + terms_link_start = ai_powered_link_start(gitlab_testing_agreement_url) + + s_('AIPoweredSM|By enabling this feature, you agree to the %{terms_link_start}GitLab Testing Agreement%{link_end}.') + .html_safe % { terms_link_start: terms_link_start, link_end: '</a>'.html_safe } + end + + def ai_powered_description + link_start = ai_powered_link_start(ai_powered_docs_url) + + s_('AIPoweredSM|Enable %{link_start}AI-powered features%{link_end} for this instance.') + .html_safe % { link_start: link_start, link_end: '</a>'.html_safe } + end # rubocop:enable Layout/LineLength # rubocop:enable Style/FormatString # rubocop:enable Rails/OutputSafety @@ -42,12 +56,24 @@ def code_suggestions_agreement_url def code_suggestions_ai_docs_url 'https://docs.gitlab.com/ee/user/ai_features.html#third-party-services' end + + def ai_powered_docs_url + 'https://docs.gitlab.com/ee/user/ai_features.html' + end + + def gitlab_testing_agreement_url + 'https://about.gitlab.com/handbook/legal/testing-agreement/' + end # rubocop:enable Gitlab/DocUrl # rubocop:disable Rails/OutputSafety def code_suggestions_link_start(url) "<a href=\"#{url}\" target=\"_blank\" rel=\"noopener noreferrer\">".html_safe end + + def ai_powered_link_start(url) + "<a href=\"#{url}\" target=\"_blank\" rel=\"noopener noreferrer\">".html_safe + end # rubocop:enable Rails/OutputSafety end end diff --git a/ee/app/helpers/ee/application_settings_helper.rb b/ee/app/helpers/ee/application_settings_helper.rb index ef9f97f5d889..b104cfe509e1 100644 --- a/ee/app/helpers/ee/application_settings_helper.rb +++ b/ee/app/helpers/ee/application_settings_helper.rb @@ -44,6 +44,7 @@ def visible_attributes :geo_node_allowed_ips, :geo_status_timeout, :help_text, + :instance_level_ai_beta_features_enabled, :instance_level_code_suggestions_enabled, :lock_memberships_to_ldap, :lock_memberships_to_saml, diff --git a/ee/app/views/admin/application_settings/_ai_powered.html.haml b/ee/app/views/admin/application_settings/_ai_powered.html.haml new file mode 100644 index 000000000000..801a77dd4996 --- /dev/null +++ b/ee/app/views/admin/application_settings/_ai_powered.html.haml @@ -0,0 +1,33 @@ +- return if Gitlab.org_or_com? +- return unless License.feature_available?(:code_suggestions) || License.feature_available?(:ai_chat) + +- expanded = false + +%section.settings.no-animate#js-ai-powered-settings{ class: ('expanded' if expanded) } + .settings-header + %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only + = s_('AIPoweredSM|AI-powered features') + = render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do + = expanded ? _('Collapse') : _('Expand') + %p.gl-text-secondary + = ai_powered_description + + .settings-content + = gitlab_ui_form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-ai-powered-settings'), html: { class: 'fieldset-form', id: 'ai-powered-settings' } do |f| + = form_errors(@application_setting) + + %fieldset + .form-group + %h5.settings-header-controls + = s_('CodeSuggestionsSM|Code Suggestions %{beta}').html_safe % { beta: gl_badge_tag(_('Beta'), variant: :neutral, size: :sm) } + = f.gitlab_ui_checkbox_component :instance_level_code_suggestions_enabled, + s_('CodeSuggestionsSM|Enable Code Suggestions for this instance'), + help_text: ai_powered_testing_agreement + + %h5.settings-header-controls + = s_('AIPoweredSM|AI-powered features') + = f.gitlab_ui_checkbox_component :instance_level_ai_beta_features_enabled, + s_('AIPoweredSM|Enable Experiment and Beta AI-powered features'), + help_text: ai_powered_testing_agreement + + = f.submit _('Save changes'), pajamas_button: true diff --git a/ee/spec/helpers/admin/application_settings_helper_spec.rb b/ee/spec/helpers/admin/application_settings_helper_spec.rb index 0b2698b727e9..f8f41c88524b 100644 --- a/ee/spec/helpers/admin/application_settings_helper_spec.rb +++ b/ee/spec/helpers/admin/application_settings_helper_spec.rb @@ -16,4 +16,18 @@ it { is_expected.to include 'https://about.gitlab.com/handbook/legal/testing-agreement/' } end end + + describe 'AI-Powered features settings for Self-Managed instances' do + describe '#ai_powered_description' do + subject { helper.ai_powered_description } + + it { is_expected.to include 'https://docs.gitlab.com/ee/user/ai_features.html' } + end + + describe '#ai_powered_testing_agreement' do + subject { helper.ai_powered_testing_agreement } + + it { is_expected.to include 'https://about.gitlab.com/handbook/legal/testing-agreement/' } + end + end end diff --git a/ee/spec/views/admin/application_settings/general.html.haml_spec.rb b/ee/spec/views/admin/application_settings/general.html.haml_spec.rb index b71042a5561f..1bc0463e3638 100644 --- a/ee/spec/views/admin/application_settings/general.html.haml_spec.rb +++ b/ee/spec/views/admin/application_settings/general.html.haml_spec.rb @@ -183,4 +183,61 @@ end end end + + describe 'instance-level ai-powered beta features settings', feature_category: :duo_chat do + before do + allow(::Gitlab).to receive(:org_or_com?).and_return(gitlab_org_or_com?) + stub_licensed_features(ai_chat: false) + end + + shared_examples 'does not render the form' do + it 'does not render the form' do + render + expect(rendered).not_to have_field('application_setting_instance_level_ai_beta_features_enabled') + end + end + + context 'when on .com or .org' do + let(:gitlab_org_or_com?) { true } + + it_behaves_like 'does not render the form' + end + + context 'when not on .com and not on .org' do + let(:gitlab_org_or_com?) { false } + + context 'with license', :with_license do + context 'with :ai_chat feature available' do + before do + stub_licensed_features(ai_chat: true) + end + + it 'renders the form' do + render + expect(rendered).to have_field('application_setting_instance_level_ai_beta_features_enabled') + end + + context 'with :updated_ai_powered_features_menu_for_sm FF disabled' do + before do + stub_feature_flags(updated_ai_powered_features_menu_for_sm: false) + end + + it_behaves_like 'does not render the form' + end + end + + context 'with :ai_chat feature not available' do + before do + stub_licensed_features(ai_chat: false) + end + + it_behaves_like 'does not render the form' + end + end + + context 'with no license', :without_license do + it_behaves_like 'does not render the form' + end + end + end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index dd05b368fa1d..6bbd06dd5dc5 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1915,6 +1915,18 @@ msgstr "" msgid "AI-generated summary" msgstr "" +msgid "AIPoweredSM|AI-powered features" +msgstr "" + +msgid "AIPoweredSM|By enabling this feature, you agree to the %{terms_link_start}GitLab Testing Agreement%{link_end}." +msgstr "" + +msgid "AIPoweredSM|Enable %{link_start}AI-powered features%{link_end} for this instance." +msgstr "" + +msgid "AIPoweredSM|Enable Experiment and Beta AI-powered features" +msgstr "" + msgid "AISummary|Generates a summary of all comments" msgstr "" @@ -11931,6 +11943,12 @@ msgstr "" msgid "CodeSuggestionsSM|Code Suggestions" msgstr "" +msgid "CodeSuggestionsSM|Code Suggestions %{beta}" +msgstr "" + +msgid "CodeSuggestionsSM|Enable Code Suggestions for this instance" +msgstr "" + msgid "CodeSuggestionsSM|Enable Code Suggestions for this instance %{beta}" msgstr "" diff --git a/spec/views/admin/application_settings/general.html.haml_spec.rb b/spec/views/admin/application_settings/general.html.haml_spec.rb index 99564003d59f..ad581ee60935 100644 --- a/spec/views/admin/application_settings/general.html.haml_spec.rb +++ b/spec/views/admin/application_settings/general.html.haml_spec.rb @@ -115,7 +115,7 @@ end # for the licensed tests, refer to ee/spec/views/admin/application_settings/general.html.haml_spec.rb - describe 'instance-level code suggestions settings', :without_license, feature_category: :code_suggestions do + describe 'instance-level ai-powered settings', :without_license, feature_category: :code_suggestions do before do allow(::Gitlab).to receive(:org_or_com?).and_return(gitlab_org_or_com?) @@ -125,6 +125,7 @@ shared_examples 'does not render the form' do it 'does not render the form' do expect(rendered).not_to have_field('application_setting_instance_level_code_suggestions_enabled') + expect(rendered).not_to have_field('application_setting_instance_level_ai_beta_features_enabled') end end -- GitLab