Commit c739007a authored by Jan Provaznik's avatar Jan Provaznik

Merge branch 'issue_222856_be_license_checks' into 'master'

RUN AS-IF-FOSS Remove service desk license checks

See merge request gitlab-org/gitlab!35444
parents 4f07b50e 36e92db8
......@@ -750,6 +750,10 @@ module ProjectsHelper
::Feature.enabled?(:resource_access_token, project)
end
def render_service_desk_menu?
false
end
end
ProjectsHelper.prepend_if_ee('EE::ProjectsHelper')
......@@ -9,7 +9,6 @@ module EE
prepended do
include DescriptionDiffActions
before_action :check_service_desk_available!, only: [:service_desk]
before_action :whitelist_query_limiting_ee, only: [:update]
before_action do
......
......@@ -253,6 +253,11 @@ module EE
project&.compliance_framework_setting&.present?
end
override :render_service_desk_menu?
def render_service_desk_menu?
true
end
private
def get_project_security_nav_tabs(project, current_user)
......
......@@ -337,7 +337,7 @@ module EE
override :service_desk_enabled
def service_desk_enabled
::EE::Gitlab::ServiceDesk.enabled?(project: self) && self[:service_desk_enabled]
::EE::Gitlab::ServiceDesk.enabled?(project: self)
end
alias_method :service_desk_enabled?, :service_desk_enabled
......
......@@ -37,7 +37,6 @@ class License < ApplicationRecord
repository_size_limit
seat_link
send_emails_from_admin_area
service_desk
scoped_issue_board
usage_quotas
visual_review_app
......@@ -165,7 +164,6 @@ class License < ApplicationRecord
related_issues
repository_mirrors
scoped_issue_board
service_desk
].freeze
FEATURES_BY_PLAN = {
......@@ -187,8 +185,7 @@ class License < ApplicationRecord
'GitLab_Auditor_User' => :auditor_user,
'GitLab_DeployBoard' => :deploy_board,
'GitLab_FileLocks' => :file_locks,
'GitLab_Geo' => :geo,
'GitLab_ServiceDesk' => :service_desk
'GitLab_Geo' => :geo
}.freeze
# Global features that cannot be restricted to only a subset of projects or namespaces.
......
......@@ -97,7 +97,7 @@ module EE
end
def send_service_desk_notification(note)
return unless EE::Gitlab::ServiceDesk.enabled?
return unless EE::Gitlab::ServiceDesk.supported?
return unless note.noteable_type == 'Issue'
issue = note.noteable
......
- if EE::Gitlab::ServiceDesk.enabled?(project: @project) || (show_promotions? && show_callout?('promote_service_desk_dismissed'))
- expanded = expanded_by_default?
%section.settings.js-service-desk-setting-wrapper.no-animate#js-service-desk{ class: ('expanded' if expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Service Desk')
%button.btn.js-settings-toggle
= expanded ? _('Collapse') : _('Expand')
- link_start = "<a href='#{help_page_path('user/project/service_desk')}' target='_blank' rel='noopener noreferrer'>".html_safe
%p= _('Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
.settings-content
- if EE::Gitlab::ServiceDesk.enabled?(project: @project)
.js-service-desk-setting-root{ data: { endpoint: project_service_desk_path(@project),
enabled: "#{@project.service_desk_enabled}",
incoming_email: (@project.service_desk_address if @project.service_desk_enabled),
selected_template: "#{@project.service_desk_setting&.issue_template_key}",
outgoing_name: "#{@project.service_desk_setting&.outgoing_name}",
project_key: "#{@project.service_desk_setting&.project_key}",
templates: issuable_templates_names(Issue.new) } }
- elsif show_promotions? && show_callout?('promote_service_desk_dismissed')
= render 'shared/promotions/promote_servicedesk'
- expanded = expanded_by_default?
%section.settings.js-service-desk-setting-wrapper.no-animate#js-service-desk{ class: ('expanded' if expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Service Desk')
%button.btn.js-settings-toggle
= expanded ? _('Collapse') : _('Expand')
- link_start = "<a href='#{help_page_path('user/project/service_desk')}' target='_blank' rel='noopener noreferrer'>".html_safe
%p= _('Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
.settings-content
- if EE::Gitlab::ServiceDesk.supported?
.js-service-desk-setting-root{ data: { endpoint: project_service_desk_path(@project),
enabled: "#{@project.service_desk_enabled}",
incoming_email: (@project.service_desk_address if @project.service_desk_enabled),
selected_template: "#{@project.service_desk_setting&.issue_template_key}",
outgoing_name: "#{@project.service_desk_setting&.outgoing_name}",
project_key: "#{@project.service_desk_setting&.project_key}",
templates: issuable_templates_names(Issue.new) } }
- elsif show_callout?('promote_service_desk_dismissed')
= render 'shared/promotions/promote_servicedesk'
- return unless EE::Gitlab::ServiceDesk.available?(project: @project)
-# TODO - Remove this check when service desk gets moved into core tier
-# More information on: https://gitlab.com/gitlab-org/gitlab/-/issues/215364
- return unless render_service_desk_menu?
= nav_link(controller: :issues, action: :service_desk ) do
= link_to service_desk_project_issues_path(@project), title: 'Service Desk' do
......
......@@ -6,12 +6,7 @@
= custom_icon('icon_service_desk')
.user-callout-copy
%h4
- if Gitlab::CurrentSettings.should_check_namespace_plan?
Upgrade your plan to activate Service Desk.
- else
Improve customer support with GitLab Service Desk.
Improve customer support with GitLab Service Desk.
%p
GitLab Service Desk is a simple way to allow people to create issues in your GitLab instance without needing their own user account. It provides a unique email address for end users to create issues in a project, and replies can be sent either through the GitLab interface or by email. End users will only see the thread through email.
= link_to 'Read more', help_page_path('user/project/service_desk.html'), target: '_blank'
= render 'shared/promotions/promotion_link_project'
......@@ -25,8 +25,8 @@ module EE
expose :external_authorization_classification_label,
if: ->(_, _) { License.feature_available?(:external_authorization_service_api_management) }
expose :packages_enabled, if: ->(project, _) { project.feature_available?(:packages) }
expose :service_desk_enabled, if: ->(project, _) { project.feature_available?(:service_desk) }
expose :service_desk_address, if: ->(project, _) { project.feature_available?(:service_desk) }
expose :service_desk_enabled
expose :service_desk_address
expose :marked_for_deletion_at, if: ->(project, _) { project.feature_available?(:adjourned_deletion_for_projects_and_groups) }
expose :marked_for_deletion_on, if: ->(project, _) { project.feature_available?(:adjourned_deletion_for_projects_and_groups) } do |project, _|
project.marked_for_deletion_at
......
......@@ -6,17 +6,13 @@ module EE
# Check whether a project or GitLab instance can support the Service Desk
# feature. Use `project.service_desk_enabled?` to check whether it is
# enabled for a particular project.
def self.enabled?(project: nil)
supported? && available?(project: project)
def self.enabled?(project:)
supported? && project[:service_desk_enabled]
end
def self.supported?
::Gitlab::IncomingEmail.enabled? && ::Gitlab::IncomingEmail.supports_wildcard?
end
def self.available?(project: nil)
(project || ::License).feature_available?(:service_desk)
end
end
end
end
......@@ -98,8 +98,6 @@ module EE
# rubocop: disable CodeReuse/ActiveRecord
def service_desk_counts
return {} unless ::License.feature_available?(:service_desk)
projects_with_service_desk = ::Project.where(service_desk_enabled: true)
{
......
......@@ -29,7 +29,7 @@ module Gitlab
end
def can_handle?
::EE::Gitlab::ServiceDesk.enabled? && (project_id || can_handle_legacy_format? || service_desk_key)
::EE::Gitlab::ServiceDesk.supported? && (project_id || can_handle_legacy_format? || service_desk_key)
end
def execute
......
......@@ -116,56 +116,38 @@ RSpec.describe Projects::IssuesController do
end
describe 'GET service_desk' do
let(:support_bot) { User.support_bot }
let(:other_user) { create(:user) }
let!(:service_desk_issue_1) { create(:issue, project: project, author: support_bot) }
let!(:service_desk_issue_2) { create(:issue, project: project, author: support_bot, assignees: [other_user]) }
let!(:other_user_issue) { create(:issue, project: project, author: other_user) }
def get_service_desk(extra_params = {})
get :service_desk, params: extra_params.merge(namespace_id: project.namespace, project_id: project)
end
context 'when Service Desk is available on the project' do
let(:support_bot) { User.support_bot }
let(:other_user) { create(:user) }
let!(:service_desk_issue_1) { create(:issue, project: project, author: support_bot) }
let!(:service_desk_issue_2) { create(:issue, project: project, author: support_bot, assignees: [other_user]) }
let!(:other_user_issue) { create(:issue, project: project, author: other_user) }
before do
stub_licensed_features(service_desk: true)
end
it 'adds an author filter for the support bot user' do
get_service_desk
it 'adds an author filter for the support bot user' do
get_service_desk
expect(assigns(:issues)).to contain_exactly(service_desk_issue_1, service_desk_issue_2)
end
it 'does not allow any other author to be set' do
get_service_desk(author_username: other_user.username)
expect(assigns(:issues)).to contain_exactly(service_desk_issue_1, service_desk_issue_2)
end
expect(assigns(:issues)).to contain_exactly(service_desk_issue_1, service_desk_issue_2)
end
it 'supports other filters' do
get_service_desk(assignee_username: other_user.username)
it 'does not allow any other author to be set' do
get_service_desk(author_username: other_user.username)
expect(assigns(:issues)).to contain_exactly(service_desk_issue_2)
end
expect(assigns(:issues)).to contain_exactly(service_desk_issue_1, service_desk_issue_2)
end
it 'allows an assignee to be specified by id' do
get_service_desk(assignee_id: other_user.id)
it 'supports other filters' do
get_service_desk(assignee_username: other_user.username)
expect(assigns(:users)).to contain_exactly(other_user, support_bot)
end
expect(assigns(:issues)).to contain_exactly(service_desk_issue_2)
end
context 'when Service Desk is not available on the project' do
before do
stub_licensed_features(service_desk: false)
end
it 'allows an assignee to be specified by id' do
get_service_desk(assignee_id: other_user.id)
it 'returns a 404' do
get_service_desk
expect(response).to have_gitlab_http_status(:not_found)
end
expect(assigns(:users)).to contain_exactly(other_user, support_bot)
end
end
......
......@@ -207,7 +207,6 @@ RSpec.describe ProjectsController do
it 'updates Service Desk attributes' do
allow(Gitlab::IncomingEmail).to receive(:enabled?) { true }
allow(Gitlab::IncomingEmail).to receive(:supports_wildcard?) { true }
stub_licensed_features(service_desk: true)
params = {
service_desk_enabled: true
}
......
......@@ -12,7 +12,6 @@ RSpec.describe 'Service Desk Setting', :js do
sign_in(user)
allow_any_instance_of(Project).to receive(:present).with(current_user: user).and_return(presenter)
allow(::EE::Gitlab::ServiceDesk).to receive(:enabled?).with(project: presenter).and_return(true)
allow(::Gitlab::IncomingEmail).to receive(:enabled?) { true }
allow(::Gitlab::IncomingEmail).to receive(:supports_wildcard?) { true }
......
......@@ -17,96 +17,48 @@ RSpec.describe 'Promotions', :js do
promotion_issue_weight_session_dismiss: false
end
describe 'if you have a license' do
describe 'for service desk', :js do
before do
project.add_maintainer(user)
end
it 'shows no promotion at all' do
sign_in(user)
visit edit_project_path(project)
expect(page).not_to have_selector('#promote_service_desk')
end
end
describe 'for project features in general on premise' do
context 'no license installed' do
context 'when service desk is not supported' do
before do
allow(License).to receive(:current).and_return(nil)
stub_application_setting(check_namespace_plan: false)
project.add_maintainer(user)
allow(::EE::Gitlab::ServiceDesk).to receive(:supported?).and_return(false)
end
it 'has the contact admin line' do
sign_in(user)
it 'appears in project edit page' do
visit edit_project_path(project)
expect(find('#promote_service_desk')).to have_content 'Contact your Administrator to upgrade your license.'
expect(find('#promote_service_desk')).to have_content 'Improve customer support with GitLab Service Desk.'
end
it 'has the start trial button' do
sign_in(admin)
it 'does not show when cookie is set' do
visit edit_project_path(project)
expect(find('#promote_service_desk')).to have_content 'Start GitLab Ultimate trial'
end
end
end
describe 'for project features in general', :js do
context 'for .com' do
before do
project.add_maintainer(user)
otherproject.add_maintainer(user)
stub_application_setting(check_namespace_plan: true)
allow(Gitlab).to receive(:com?) { true }
within('#promote_service_desk') do
find('.close').click
end
sign_in(user)
end
wait_for_requests
it "has the 'Upgrade your plan' button" do
visit edit_project_path(project)
expect(find('#promote_service_desk')).to have_content 'Upgrade your plan'
end
it 'has the contact owner line' do
visit edit_project_path(otherproject)
expect(find('#promote_service_desk')).to have_content 'Contact owner'
expect(page).not_to have_selector('#promote_service_desk')
end
end
end
describe 'for service desk', :js do
before do
allow(License).to receive(:current).and_return(nil)
stub_application_setting(check_namespace_plan: false)
project.add_maintainer(user)
sign_in(user)
end
it 'appears in project edit page' do
visit edit_project_path(project)
expect(find('#promote_service_desk')).to have_content 'Improve customer support with GitLab Service Desk.'
end
it 'does not show when cookie is set' do
visit edit_project_path(project)
within('#promote_service_desk') do
find('.close').click
context 'when service desk is supported' do
before do
allow(::EE::Gitlab::ServiceDesk).to receive(:supported?).and_return(true)
end
wait_for_requests
visit edit_project_path(project)
it 'does not show promotion' do
visit edit_project_path(project)
expect(page).not_to have_selector('#promote_service_desk')
expect(page).not_to have_selector('#promote_service_desk')
end
end
end
......
......@@ -77,7 +77,9 @@ RSpec.describe EE::IssuesHelper do
let!(:new_issue) { create(:issue, author: User.support_bot, project: project2) }
before do
allow(::EE::Gitlab::ServiceDesk).to receive(:enabled?).and_return(true)
allow(Gitlab::IncomingEmail).to receive(:enabled?) { true }
allow(Gitlab::IncomingEmail).to receive(:supports_wildcard?) { true }
old_issue.update(moved_to: new_issue)
end
......
......@@ -4,27 +4,28 @@ require 'spec_helper'
RSpec.describe EE::Gitlab::ServiceDesk do
before do
stub_licensed_features(service_desk: true)
allow(::Gitlab::IncomingEmail).to receive(:enabled?).and_return(true)
allow(::Gitlab::IncomingEmail).to receive(:supports_wildcard?).and_return(true)
allow(Gitlab::IncomingEmail).to receive(:enabled?).and_return(true)
allow(Gitlab::IncomingEmail).to receive(:supports_wildcard?).and_return(true)
end
describe 'enabled?' do
subject { described_class.enabled? }
let_it_be(:project) { create(:project) }
subject { described_class.enabled?(project: project) }
it { is_expected.to be_truthy }
context 'when service desk is not available' do
context 'when service desk is not supported' do
before do
allow(described_class).to receive(:available?).and_return(false)
allow(described_class).to receive(:supported?).and_return(false)
end
it { is_expected.to be_falsy }
end
context 'when service desk is not supported' do
context 'when service desk is disabled for project' do
before do
allow(described_class).to receive(:supported?).and_return(false)
project.update!(service_desk_enabled: false)
end
it { is_expected.to be_falsy }
......@@ -38,7 +39,7 @@ RSpec.describe EE::Gitlab::ServiceDesk do
context 'when incoming emails are disabled' do
before do
allow(::Gitlab::IncomingEmail).to receive(:enabled?).and_return(false)
allow(Gitlab::IncomingEmail).to receive(:enabled?).and_return(false)
end
it { is_expected.to be_falsy }
......@@ -46,21 +47,7 @@ RSpec.describe EE::Gitlab::ServiceDesk do
context 'when email key is not supported' do
before do
allow(::Gitlab::IncomingEmail).to receive(:supports_wildcard?).and_return(false)
end
it { is_expected.to be_falsy }
end
end
describe 'available?' do
subject { described_class.available? }
it { is_expected.to be_truthy }
context 'when license does not support service desk' do
before do
stub_licensed_features(service_desk: false)
allow(Gitlab::IncomingEmail).to receive(:supports_wildcard?).and_return(false)
end
it { is_expected.to be_falsy }
......
......@@ -216,34 +216,15 @@ RSpec.describe Gitlab::UsageData do
describe '.service_desk_counts' do
subject { described_class.service_desk_counts }
context 'when Service Desk is disabled' do
it 'returns an empty hash' do
stub_licensed_features(service_desk: false)
let(:project) { create(:project, :service_desk_enabled) }
expect(subject).to eq({})
end
end
it 'gathers Service Desk data' do
create_list(:issue, 2, confidential: true, author: User.support_bot, project: project)
context 'when there is no license' do
it 'returns an empty hash' do
allow(License).to receive(:current).and_return(nil)
allow(::EE::Gitlab::ServiceDesk).to receive(:enabled?).with(anything).and_return(true)
expect(subject).to eq({})
end
end
context 'when Service Desk is enabled' do
let(:project) { create(:project, :service_desk_enabled) }
it 'gathers Service Desk data' do
create_list(:issue, 2, confidential: true, author: User.support_bot, project: project)
stub_licensed_features(service_desk: true)
allow(::EE::Gitlab::ServiceDesk).to receive(:enabled?).with(anything).and_return(true)
expect(subject).to eq(service_desk_enabled_projects: 1,
service_desk_issues: 2)
end
expect(subject).to eq(service_desk_enabled_projects: 1,
service_desk_issues: 2)
end
end
......
......@@ -20,8 +20,7 @@ RSpec.describe Gitlab::Email::Handler::EE::ServiceDeskHandler do
let_it_be(:project) { create(:project, :repository, :public, namespace: namespace, path: 'test', service_desk_enabled: true) }
before do
allow(::EE::Gitlab::ServiceDesk).to receive(:enabled?).and_return(true)
allow(::EE::Gitlab::ServiceDesk).to receive(:enabled?).with(project: project).and_return(true)
allow(::EE::Gitlab::ServiceDesk).to receive(:supported?).and_return(true)
end
shared_examples 'a new issue request' do
......@@ -247,7 +246,7 @@ RSpec.describe Gitlab::Email::Handler::EE::ServiceDeskHandler do
end
end
context 'when license does not support service desk' do
context 'when service desk is not enabled for project' do
before do
allow(::EE::Gitlab::ServiceDesk).to receive(:enabled?).and_return(false)
end
......
......@@ -18,19 +18,9 @@ RSpec.describe Gitlab::Email::Handler do
end
context 'a Service Desk email' do
it 'uses the Service Desk handler when Service Desk is enabled' do
allow(License).to receive(:feature_available?).and_call_original
allow(License).to receive(:feature_available?).with(:service_desk).and_return(true)
it 'uses the Service Desk handler' do
expect(ee_handler_for('emails/service_desk.eml', 'some/project')).to be_instance_of(Gitlab::Email::Handler::EE::ServiceDeskHandler)
end
it 'uses no handler when Service Desk is disabled' do
allow(License).to receive(:feature_available?).and_call_original
allow(License).to receive(:feature_available?).with(:service_desk).and_return(false)
expect(ee_handler_for('emails/service_desk.eml', 'some/project')).to be_nil
end
end
context 'a new issue email' do
......
......@@ -1159,26 +1159,6 @@ RSpec.describe Project do
expect(project.service_desk_enabled?).to be_truthy
expect(project.service_desk_enabled).to be_truthy
end
context 'namespace plans active' do
before do
stub_application_setting(check_namespace_plan: true)
end
it 'is disabled' do
expect(project.service_desk_enabled?).to be_falsy
expect(project.service_desk_enabled).to be_falsy
end
context 'Service Desk available in namespace plan' do
let!(:gitlab_subscription) { create(:gitlab_subscription, :silver, namespace: namespace) }
it 'is enabled' do
expect(project.service_desk_enabled?).to be_truthy
expect(project.service_desk_enabled).to be_truthy
end
end
end
end
describe '#service_desk_address' do
......@@ -1544,7 +1524,7 @@ RSpec.describe Project do
allow(global_license).to receive(:features).and_return([
:subepics, # Gold only
:epics, # Silver and up
:service_desk, # Silver and up
:push_rules, # Silver and up
:audit_events, # Bronze and up
:geo # Global feature, should not be checked at namespace level
])
......@@ -1561,7 +1541,7 @@ RSpec.describe Project do
let(:plan_license) { :bronze }
it 'filters for bronze features' do
is_expected.to contain_exactly(:audit_events, :geo, :service_desk)
is_expected.to contain_exactly(:audit_events, :geo, :push_rules)
end
end
......@@ -1569,7 +1549,7 @@ RSpec.describe Project do
let(:plan_license) { :silver }
it 'filters for silver features' do
is_expected.to contain_exactly(:service_desk, :audit_events, :geo, :epics)
is_expected.to contain_exactly(:push_rules, :audit_events, :geo, :epics)
end
end
......@@ -1577,7 +1557,7 @@ RSpec.describe Project do
let(:plan_license) { :gold }
it 'filters for gold features' do
is_expected.to contain_exactly(:epics, :service_desk, :audit_events, :geo, :subepics)
is_expected.to contain_exactly(:epics, :push_rules, :audit_events, :geo, :subepics)
end
end
......@@ -1594,7 +1574,7 @@ RSpec.describe Project do
let(:project) { create(:project, :public, group: group) }
it 'includes all features in global license' do
is_expected.to contain_exactly(:epics, :service_desk, :audit_events, :geo, :subepics)
is_expected.to contain_exactly(:epics, :push_rules, :audit_events, :geo, :subepics)
end
end
end
......@@ -1602,7 +1582,7 @@ RSpec.describe Project do
context 'when namespace should not be checked' do
it 'includes all features in global license' do
is_expected.to contain_exactly(:epics, :service_desk, :audit_events, :geo, :subepics)
is_expected.to contain_exactly(:epics, :push_rules, :audit_events, :geo, :subepics)
end
end
......
......@@ -187,22 +187,11 @@ RSpec.describe API::Projects do
describe 'service desk attributes' do
it 'are exposed when the feature is available' do
stub_licensed_features(service_desk: true)
get api("/projects/#{project.id}", user)
expect(json_response).to have_key 'service_desk_enabled'
expect(json_response).to have_key 'service_desk_address'
end
it 'are not exposed when the feature is not available' do
stub_licensed_features(service_desk: false)
get api("/projects/#{project.id}", user)
expect(json_response).not_to have_key 'service_desk_enabled'
expect(json_response).not_to have_key 'service_desk_address'
end
end
context 'project soft-deletion' do
......@@ -741,7 +730,6 @@ RSpec.describe API::Projects do
subject { put(api("/projects/#{project.id}", user), params: { service_desk_enabled: true }) }
before do
stub_licensed_features(service_desk: true)
project.update!(service_desk_enabled: false)
allow(::Gitlab::IncomingEmail).to receive(:enabled?).and_return(true)
......
......@@ -15,7 +15,6 @@ RSpec.describe EE::NotificationService, :mailer do
allow(Notify).to receive(:service_desk_new_note_email)
.with(Integer, Integer).and_return(mailer)
allow(::EE::Gitlab::ServiceDesk).to receive(:enabled?).and_return(true)
allow(::Gitlab::IncomingEmail).to receive(:enabled?) { true }
allow(::Gitlab::IncomingEmail).to receive(:supports_wildcard?) { true }
end
......@@ -71,14 +70,6 @@ RSpec.describe EE::NotificationService, :mailer do
it_should_not_email!
end
context 'when the license doesn\'t allow service desk' do
before do
allow(::EE::Gitlab::ServiceDesk).to receive(:enabled?).and_return(false)
end
it_should_not_email!
end
context 'when the support bot has unsubscribed' do
before do
issue.unsubscribe(User.support_bot, project)
......
......@@ -12,7 +12,16 @@ RSpec.describe 'Project navbar' do
let_it_be(:project) { create(:project, :repository) }
before do
stub_licensed_features(service_desk: false)
# TODO - This can be moved into 'project navbar structure' shared
# context when service desk feature gets moved to core.
# More information in: https://gitlab.com/gitlab-org/gitlab/-/issues/215364
if Gitlab.ee?
insert_after_sub_nav_item(
_('Labels'),
within: _('Issues'),
new_sub_nav_item_name: _('Service Desk')
)
end
project.add_maintainer(user)
sign_in(user)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment