diff options
author | Mayra Cabrera <mcabrera@gitlab.com> | 2019-03-12 13:15:33 +0300 |
---|---|---|
committer | Kamil TrzciĆski <ayufan@ayufan.eu> | 2019-03-12 13:15:33 +0300 |
commit | 7e9348f3594ee158dfd4aaa9e03e5bb5dd36aead (patch) | |
tree | 74e03ba375331ab619a766d5d2a3c12aaa267095 /spec | |
parent | db37b5a4c8d408e1bce0843162c609dcb1781188 (diff) |
Enable/disable Auto DevOps at Group level
- Includes instance methods on Group model to detect when a group has
AutoDevOps explicitly/implicitly enabled/disabled.
- Includes migration to add a new column to namespaces table
- Add UI necessary modifications
- Add service and controller to update auto devops
related instances
- Updates project and groups auto devops badges
Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/52447
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/groups/settings/ci_cd_controller_spec.rb | 73 | ||||
-rw-r--r-- | spec/factories/groups.rb | 8 | ||||
-rw-r--r-- | spec/factories/projects.rb | 4 | ||||
-rw-r--r-- | spec/features/groups/settings/ci_cd_spec.rb | 45 | ||||
-rw-r--r-- | spec/features/projects/settings/pipelines_settings_spec.rb | 31 | ||||
-rw-r--r-- | spec/helpers/auto_devops_helper_spec.rb | 138 | ||||
-rw-r--r-- | spec/models/group_spec.rb | 121 | ||||
-rw-r--r-- | spec/models/namespace_spec.rb | 24 | ||||
-rw-r--r-- | spec/models/project_spec.rb | 167 | ||||
-rw-r--r-- | spec/services/groups/auto_devops_service_spec.rb | 62 | ||||
-rw-r--r-- | spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb | 1 |
11 files changed, 644 insertions, 30 deletions
diff --git a/spec/controllers/groups/settings/ci_cd_controller_spec.rb b/spec/controllers/groups/settings/ci_cd_controller_spec.rb index 40673d10b91..15eb0a442a6 100644 --- a/spec/controllers/groups/settings/ci_cd_controller_spec.rb +++ b/spec/controllers/groups/settings/ci_cd_controller_spec.rb @@ -66,4 +66,77 @@ describe Groups::Settings::CiCdController do end end end + + describe 'PATCH #update_auto_devops' do + let(:auto_devops_param) { '1' } + + subject do + patch :update_auto_devops, params: { + group_id: group, + group: { auto_devops_enabled: auto_devops_param } + } + end + + context 'when user does not have enough permission' do + before do + group.add_maintainer(user) + end + + it { is_expected.to have_gitlab_http_status(404) } + end + + context 'when user has enough privileges' do + before do + group.add_owner(user) + end + + it { is_expected.to redirect_to(group_settings_ci_cd_path) } + + context 'when service execution went wrong' do + before do + allow_any_instance_of(Groups::AutoDevopsService).to receive(:execute).and_return(false) + allow_any_instance_of(Group).to receive_message_chain(:errors, :full_messages) + .and_return(['Error 1']) + + subject + end + + it 'returns a flash alert' do + expect(response).to set_flash[:alert] + .to eq("There was a problem updating Auto DevOps pipeline: [\"Error 1\"].") + end + end + + context 'when service execution was successful' do + it 'returns a flash notice' do + subject + + expect(response).to set_flash[:notice] + .to eq('Auto DevOps pipeline was updated for the group') + end + end + + context 'when changing auto devops value' do + before do + subject + + group.reload + end + + context 'when explicitly enabling auto devops' do + it 'should update group attribute' do + expect(group.auto_devops_enabled).to eq(true) + end + end + + context 'when explicitly disabling auto devops' do + let(:auto_devops_param) { '0' } + + it 'should update group attribute' do + expect(group.auto_devops_enabled).to eq(false) + end + end + end + end + end end diff --git a/spec/factories/groups.rb b/spec/factories/groups.rb index 3b354c0d96b..dcef8571f41 100644 --- a/spec/factories/groups.rb +++ b/spec/factories/groups.rb @@ -36,5 +36,13 @@ FactoryBot.define do trait :nested do parent factory: :group end + + trait :auto_devops_enabled do + auto_devops_enabled true + end + + trait :auto_devops_disabled do + auto_devops_enabled false + end end end diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 30d3b22d868..ab185ab3972 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -271,6 +271,10 @@ FactoryBot.define do trait :auto_devops do association :auto_devops, factory: :project_auto_devops end + + trait :auto_devops_disabled do + association :auto_devops, factory: [:project_auto_devops, :disabled] + end end # Project with empty repository diff --git a/spec/features/groups/settings/ci_cd_spec.rb b/spec/features/groups/settings/ci_cd_spec.rb index d422fd18346..0f793dbab6e 100644 --- a/spec/features/groups/settings/ci_cd_spec.rb +++ b/spec/features/groups/settings/ci_cd_spec.rb @@ -5,8 +5,8 @@ require 'spec_helper' describe 'Group CI/CD settings' do include WaitForRequests - let(:user) {create(:user)} - let(:group) {create(:group)} + let(:user) { create(:user) } + let(:group) { create(:group) } before do group.add_owner(user) @@ -36,4 +36,45 @@ describe 'Group CI/CD settings' do end end end + + describe 'Auto DevOps form' do + before do + stub_application_setting(auto_devops_enabled: true) + end + + context 'as owner first visiting group settings' do + it 'should see instance enabled badge' do + visit group_settings_ci_cd_path(group) + + page.within '#auto-devops-settings' do + expect(page).to have_content('instance enabled') + end + end + end + + context 'when Auto DevOps group has been enabled' do + it 'should see group enabled badge' do + group.update!(auto_devops_enabled: true) + + visit group_settings_ci_cd_path(group) + + page.within '#auto-devops-settings' do + expect(page).to have_content('group enabled') + end + end + end + + context 'when Auto DevOps group has been disabled' do + it 'should not see a badge' do + group.update!(auto_devops_enabled: false) + + visit group_settings_ci_cd_path(group) + + page.within '#auto-devops-settings' do + expect(page).not_to have_content('instance enabled') + expect(page).not_to have_content('group enabled') + end + end + end + end end diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb index 4c85abe9971..bf0c0de89b2 100644 --- a/spec/features/projects/settings/pipelines_settings_spec.rb +++ b/spec/features/projects/settings/pipelines_settings_spec.rb @@ -110,6 +110,37 @@ describe "Projects > Settings > Pipelines settings" do expect(page).not_to have_content('instance enabled') end end + + context 'when auto devops is turned on group level' do + before do + project.update!(namespace: create(:group, :auto_devops_enabled)) + end + + it 'renders group enabled badge' do + visit project_settings_ci_cd_path(project) + + page.within '#autodevops-settings' do + expect(page).to have_content('group enabled') + expect(find_field('project_auto_devops_attributes_enabled')).to be_checked + end + end + end + + context 'when auto devops is turned on group parent level', :nested_groups do + before do + group = create(:group, parent: create(:group, :auto_devops_enabled)) + project.update!(namespace: group) + end + + it 'renders group enabled badge' do + visit project_settings_ci_cd_path(project) + + page.within '#autodevops-settings' do + expect(page).to have_content('group enabled') + expect(find_field('project_auto_devops_attributes_enabled')).to be_checked + end + end + end end end diff --git a/spec/helpers/auto_devops_helper_spec.rb b/spec/helpers/auto_devops_helper_spec.rb index 223e562238d..d2540696b17 100644 --- a/spec/helpers/auto_devops_helper_spec.rb +++ b/spec/helpers/auto_devops_helper_spec.rb @@ -29,11 +29,11 @@ describe AutoDevopsHelper do end context 'when the banner is disabled by feature flag' do - it 'allows the feature flag to disable' do + before do Feature.get(:auto_devops_banner_disabled).enable - - expect(subject).to be(false) end + + it { is_expected.to be_falsy } end context 'when dismissed' do @@ -90,4 +90,136 @@ describe AutoDevopsHelper do it { is_expected.to eq(false) } end end + + describe '#badge_for_auto_devops_scope' do + subject { helper.badge_for_auto_devops_scope(receiver) } + + context 'when receiver is a group' do + context 'when explicitly enabled' do + let(:receiver) { create(:group, :auto_devops_enabled) } + + it { is_expected.to eq('group enabled') } + end + + context 'when explicitly disabled' do + let(:receiver) { create(:group, :auto_devops_disabled) } + + it { is_expected.to be_nil } + end + + context 'when auto devops is implicitly enabled' do + let(:receiver) { create(:group) } + + context 'by instance' do + before do + stub_application_setting(auto_devops_enabled: true) + end + + it { is_expected.to eq('instance enabled') } + end + + context 'with groups', :nested_groups do + before do + receiver.update(parent: parent) + end + + context 'when auto devops is enabled on parent' do + let(:parent) { create(:group, :auto_devops_enabled) } + + it { is_expected.to eq('group enabled') } + end + + context 'when auto devops is enabled on parent group' do + let(:root_parent) { create(:group, :auto_devops_enabled) } + let(:parent) { create(:group, parent: root_parent) } + + it { is_expected.to eq('group enabled') } + end + + context 'when auto devops disabled set on parent group' do + let(:root_parent) { create(:group, :auto_devops_disabled) } + let(:parent) { create(:group, parent: root_parent) } + + it { is_expected.to be_nil } + end + end + end + end + + context 'when receiver is a project' do + context 'when auto devops is enabled at project level' do + let(:receiver) { create(:project, :auto_devops) } + + it { is_expected.to be_nil } + end + + context 'when auto devops is disabled at project level' do + let(:receiver) { create(:project, :auto_devops_disabled) } + + it { is_expected.to be_nil } + end + + context 'when auto devops is implicitly enabled' do + let(:receiver) { create(:project) } + + context 'by instance' do + before do + stub_application_setting(auto_devops_enabled: true) + end + + it { is_expected.to eq('instance enabled') } + end + + context 'with groups', :nested_groups do + let(:receiver) { create(:project, :repository, namespace: group) } + + before do + stub_application_setting(auto_devops_enabled: false) + end + + context 'when auto devops is enabled on group level' do + let(:group) { create(:group, :auto_devops_enabled) } + + it { is_expected.to eq('group enabled') } + end + + context 'when auto devops is enabled on root group' do + let(:root_parent) { create(:group, :auto_devops_enabled) } + let(:group) { create(:group, parent: root_parent) } + + it { is_expected.to eq('group enabled') } + end + end + end + + context 'when auto devops is implicitly disabled' do + let(:receiver) { create(:project) } + + context 'by instance' do + before do + stub_application_setting(auto_devops_enabled: false) + end + + it { is_expected.to be_nil } + end + + context 'with groups', :nested_groups do + let(:receiver) { create(:project, :repository, namespace: group) } + + context 'when auto devops is disabled on group level' do + let(:group) { create(:group, :auto_devops_disabled) } + + it { is_expected.to be_nil } + end + + context 'when root group is enabled and parent disabled' do + let(:root_parent) { create(:group, :auto_devops_enabled) } + let(:group) { create(:group, :auto_devops_disabled, parent: root_parent) } + + it { is_expected.to be_nil } + end + end + end + end + end end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 9dc32a815d8..16624ce47d0 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -810,4 +810,125 @@ describe Group do it { is_expected.to be_truthy } end end + + describe '#first_auto_devops_config' do + using RSpec::Parameterized::TableSyntax + + let(:group) { create(:group) } + + subject { group.first_auto_devops_config } + + where(:instance_value, :group_value, :config) do + # Instance level enabled + true | nil | { status: true, scope: :instance } + true | true | { status: true, scope: :group } + true | false | { status: false, scope: :group } + + # Instance level disabled + false | nil | { status: false, scope: :instance } + false | true | { status: true, scope: :group } + false | false | { status: false, scope: :group } + end + + with_them do + before do + stub_application_setting(auto_devops_enabled: instance_value) + + group.update_attribute(:auto_devops_enabled, group_value) + end + + it { is_expected.to eq(config) } + end + + context 'with parent groups', :nested_groups do + where(:instance_value, :parent_value, :group_value, :config) do + # Instance level enabled + true | nil | nil | { status: true, scope: :instance } + true | nil | true | { status: true, scope: :group } + true | nil | false | { status: false, scope: :group } + + true | true | nil | { status: true, scope: :group } + true | true | true | { status: true, scope: :group } + true | true | false | { status: false, scope: :group } + + true | false | nil | { status: false, scope: :group } + true | false | true | { status: true, scope: :group } + true | false | false | { status: false, scope: :group } + + # Instance level disable + false | nil | nil | { status: false, scope: :instance } + false | nil | true | { status: true, scope: :group } + false | nil | false | { status: false, scope: :group } + + false | true | nil | { status: true, scope: :group } + false | true | true | { status: true, scope: :group } + false | true | false | { status: false, scope: :group } + + false | false | nil | { status: false, scope: :group } + false | false | true | { status: true, scope: :group } + false | false | false | { status: false, scope: :group } + end + + with_them do + before do + stub_application_setting(auto_devops_enabled: instance_value) + parent = create(:group, auto_devops_enabled: parent_value) + + group.update!( + auto_devops_enabled: group_value, + parent: parent + ) + end + + it { is_expected.to eq(config) } + end + end + end + + describe '#auto_devops_enabled?' do + subject { group.auto_devops_enabled? } + + context 'when auto devops is explicitly enabled on group' do + let(:group) { create(:group, :auto_devops_enabled) } + + it { is_expected.to be_truthy } + end + + context 'when auto devops is explicitly disabled on group' do + let(:group) { create(:group, :auto_devops_disabled) } + + it { is_expected.to be_falsy } + end + + context 'when auto devops is implicitly enabled or disabled' do + before do + stub_application_setting(auto_devops_enabled: false) + + group.update!(parent: parent_group) + end + + context 'when auto devops is enabled on root group' do + let(:root_group) { create(:group, :auto_devops_enabled) } + let(:subgroup) { create(:group, parent: root_group) } + let(:parent_group) { create(:group, parent: subgroup) } + + it { is_expected.to be_truthy } + end + + context 'when auto devops is disabled on root group' do + let(:root_group) { create(:group, :auto_devops_disabled) } + let(:subgroup) { create(:group, parent: root_group) } + let(:parent_group) { create(:group, parent: subgroup) } + + it { is_expected.to be_falsy } + end + + context 'when auto devops is disabled on parent group and enabled on root group' do + let(:root_group) { create(:group, :auto_devops_enabled) } + let(:parent_group) { create(:group, :auto_devops_disabled, parent: root_group) } + + it { is_expected.to be_falsy } + end + end + end end diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 475fbe56e4d..aadc298ae0b 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -775,4 +775,28 @@ describe Namespace do end end end + + describe '#auto_devops_enabled' do + context 'with users' do + let(:user) { create(:user) } + + subject { user.namespace.auto_devops_enabled? } + + before do + user.namespace.update!(auto_devops_enabled: auto_devops_enabled) + end + + context 'when auto devops is explicitly enabled' do + let(:auto_devops_enabled) { true } + + it { is_expected.to eq(true) } + end + + context 'when auto devops is explicitly disabled' do + let(:auto_devops_enabled) { false } + + it { is_expected.to eq(false) } + end + end + end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 71bd7972436..5c09faafd83 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -3631,12 +3631,36 @@ describe Project do subject { project.auto_devops_enabled? } + context 'when explicitly enabled' do + before do + create(:project_auto_devops, project: project) + end + + it { is_expected.to be_truthy } + end + + context 'when explicitly disabled' do + before do + create(:project_auto_devops, project: project, enabled: false) + end + + it { is_expected.to be_falsey } + end + context 'when enabled in settings' do before do stub_application_setting(auto_devops_enabled: true) end it { is_expected.to be_truthy } + end + + context 'when disabled in settings' do + before do + stub_application_setting(auto_devops_enabled: false) + end + + it { is_expected.to be_falsey } context 'when explicitly enabled' do before do @@ -3648,34 +3672,91 @@ describe Project do context 'when explicitly disabled' do before do - create(:project_auto_devops, project: project, enabled: false) + create(:project_auto_devops, :disabled, project: project) end it { is_expected.to be_falsey } end end - context 'when disabled in settings' do + context 'when force_autodevops_on_by_default is enabled for the project' do + it { is_expected.to be_truthy } + end + + context 'with group parents' do + let(:instance_enabled) { true } + before do - stub_application_setting(auto_devops_enabled: false) + stub_application_setting(auto_devops_enabled: instance_enabled) + project.update!(namespace: parent_group) end - it { is_expected.to be_falsey } + context 'when enabled on parent' do + let(:parent_group) { create(:group, :auto_devops_enabled) } - context 'when explicitly enabled' do - before do - create(:project_auto_devops, project: project) + context 'when auto devops instance enabled' do + it { is_expected.to be_truthy } end - it { is_expected.to be_truthy } + context 'when auto devops instance disabled' do + let(:instance_disabled) { false } + + it { is_expected.to be_truthy } + end end - context 'when force_autodevops_on_by_default is enabled for the project' do - before do - Feature.get(:force_autodevops_on_by_default).enable_percentage_of_actors(100) + context 'when disabled on parent' do + let(:parent_group) { create(:group, :auto_devops_disabled) } + + context 'when auto devops instance enabled' do + it { is_expected.to be_falsy } end - it { is_expected.to be_truthy } + context 'when auto devops instance disabled' do + let(:instance_disabled) { false } + + it { is_expected.to be_falsy } + end + end + + context 'when enabled on root parent', :nested_groups do + let(:parent_group) { create(:group, parent: create(:group, :auto_devops_enabled)) } + + context 'when auto devops instance enabled' do + it { is_expected.to be_truthy } + end + + context 'when auto devops instance disabled' do + let(:instance_disabled) { false } + + it { is_expected.to be_truthy } + end + + context 'when explicitly disabled on parent' do + let(:parent_group) { create(:group, :auto_devops_disabled, parent: create(:group, :auto_devops_enabled)) } + + it { is_expected.to be_falsy } + end + end + + context 'when disabled on root parent', :nested_groups do + let(:parent_group) { create(:group, parent: create(:group, :auto_devops_disabled)) } + + context 'when auto devops instance enabled' do + it { is_expected.to be_falsy } + end + + context 'when auto devops instance disabled' do + let(:instance_disabled) { false } + + it { is_expected.to be_falsy } + end + + context 'when explicitly disabled on parent' do + let(:parent_group) { create(:group, :auto_devops_disabled, parent: create(:group, :auto_devops_enabled)) } + + it { is_expected.to be_falsy } + end end end end @@ -3722,15 +3803,52 @@ describe Project do end end end + + context 'when enabled on group' do + it 'has auto devops implicitly enabled' do + project.update(namespace: create(:group, :auto_devops_enabled)) + + expect(project).to have_auto_devops_implicitly_enabled + end + end + + context 'when enabled on parent group' do + it 'has auto devops implicitly enabled' do + subgroup = create(:group, parent: create(:group, :auto_devops_enabled)) + project.update(namespace: subgroup) + + expect(project).to have_auto_devops_implicitly_enabled + end + end end describe '#has_auto_devops_implicitly_disabled?' do + set(:project) { create(:project) } + before do allow(Feature).to receive(:enabled?).and_call_original Feature.get(:force_autodevops_on_by_default).enable_percentage_of_actors(0) end - set(:project) { create(:project) } + context 'when explicitly disabled' do + before do + create(:project_auto_devops, project: project, enabled: false) + end + + it 'does not have auto devops implicitly disabled' do + expect(project).not_to have_auto_devops_implicitly_disabled + end + end + + context 'when explicitly enabled' do + before do + create(:project_auto_devops, project: project, enabled: true) + end + + it 'does not have auto devops implicitly disabled' do + expect(project).not_to have_auto_devops_implicitly_disabled + end + end context 'when enabled in settings' do before do @@ -3753,6 +3871,8 @@ describe Project do context 'when force_autodevops_on_by_default is enabled for the project' do before do + create(:project_auto_devops, project: project, enabled: false) + Feature.get(:force_autodevops_on_by_default).enable_percentage_of_actors(100) end @@ -3761,23 +3881,20 @@ describe Project do end end - context 'when explicitly disabled' do - before do - create(:project_auto_devops, project: project, enabled: false) - end + context 'when disabled on group' do + it 'has auto devops implicitly disabled' do + project.update!(namespace: create(:group, :auto_devops_disabled)) - it 'does not have auto devops implicitly disabled' do - expect(project).not_to have_auto_devops_implicitly_disabled + expect(project).to have_auto_devops_implicitly_disabled end end - context 'when explicitly enabled' do - before do - create(:project_auto_devops, project: project, enabled: true) - end + context 'when disabled on parent group' do + it 'has auto devops implicitly disabled' do + subgroup = create(:group, parent: create(:group, :auto_devops_disabled)) + project.update!(namespace: subgroup) - it 'does not have auto devops implicitly disabled' do - expect(project).not_to have_auto_devops_implicitly_disabled + expect(project).to have_auto_devops_implicitly_disabled end end end diff --git a/spec/services/groups/auto_devops_service_spec.rb b/spec/services/groups/auto_devops_service_spec.rb new file mode 100644 index 00000000000..7f8ab517cef --- /dev/null +++ b/spec/services/groups/auto_devops_service_spec.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe Groups::AutoDevopsService, '#execute' do + set(:group) { create(:group) } + set(:user) { create(:user) } + let(:group_params) { { auto_devops_enabled: '0' } } + let(:service) { described_class.new(group, user, group_params) } + + context 'when user does not have enough privileges' do + it 'raises exception' do + group.add_developer(user) + + expect do + service.execute + end.to raise_exception(Gitlab::Access::AccessDeniedError) + end + end + + context 'when user has enough privileges' do + before do + group.add_owner(user) + end + + it 'updates group auto devops enabled accordingly' do + service.execute + + expect(group.auto_devops_enabled).to eq(false) + end + + context 'when group has projects' do + it 'reflects changes on projects' do + project_1 = create(:project, namespace: group) + + service.execute + + expect(project_1).not_to have_auto_devops_implicitly_enabled + end + end + + context 'when group has subgroups' do + it 'reflects changes on subgroups' do + subgroup_1 = create(:group, parent: group) + + service.execute + + expect(subgroup_1.auto_devops_enabled?).to eq(false) + end + + context 'when subgroups have projects', :nested_groups do + it 'reflects changes on projects' do + subgroup_1 = create(:group, parent: group) + project_1 = create(:project, namespace: subgroup_1) + + service.execute + + expect(project_1).not_to have_auto_devops_implicitly_enabled + end + end + end + end +end diff --git a/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb b/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb index 2a2539c80b5..b52fc719a64 100644 --- a/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb +++ b/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb @@ -5,6 +5,7 @@ describe 'projects/settings/ci_cd/_autodevops_form' do before do assign :project, project + allow(view).to receive(:auto_devops_enabled) { true } end it 'shows a warning message about Kubernetes cluster' do |