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
This commit is contained in:
Mayra Cabrera 2019-03-12 10:15:33 +00:00 committed by Kamil Trzciński
parent db37b5a4c8
commit 7e9348f359
25 changed files with 796 additions and 45 deletions

View file

@ -17,6 +17,16 @@ module Groups
redirect_to group_settings_ci_cd_path
end
def update_auto_devops
if auto_devops_service.execute
flash[:notice] = s_('GroupSettings|Auto DevOps pipeline was updated for the group')
else
flash[:alert] = s_("GroupSettings|There was a problem updating Auto DevOps pipeline: %{error_messages}." % { error_messages: group.errors.full_messages })
end
redirect_to group_settings_ci_cd_path
end
private
def define_ci_variables
@ -29,6 +39,14 @@ module Groups
def authorize_admin_group!
return render_404 unless can?(current_user, :admin_group, group)
end
def auto_devops_params
params.require(:group).permit(:auto_devops_enabled)
end
def auto_devops_service
Groups::AutoDevopsService.new(group, current_user, auto_devops_params)
end
end
end
end

View file

@ -9,4 +9,17 @@ module AutoDevopsHelper
!project.repository.gitlab_ci_yml &&
!project.ci_service
end
def badge_for_auto_devops_scope(auto_devops_receiver)
return unless auto_devops_receiver.auto_devops_enabled?
case auto_devops_receiver.first_auto_devops_config[:scope]
when :project
nil
when :group
s_('CICD|group enabled')
when :instance
s_('CICD|instance enabled')
end
end
end

View file

@ -11,6 +11,7 @@ class Namespace < ApplicationRecord
include IgnorableColumn
include FeatureGate
include FromUnion
include Gitlab::Utils::StrongMemoize
ignore_column :deleted_at
@ -267,6 +268,22 @@ class Namespace < ApplicationRecord
owner.refresh_authorized_projects
end
def auto_devops_enabled?
first_auto_devops_config[:status]
end
def first_auto_devops_config
return { scope: :group, status: auto_devops_enabled } unless auto_devops_enabled.nil?
strong_memoize(:first_auto_devops_config) do
if has_parent?
parent.first_auto_devops_config
else
{ scope: :instance, status: Gitlab::CurrentSettings.auto_devops_enabled? }
end
end
end
private
def path_or_parent_changed?

View file

@ -631,12 +631,21 @@ class Project < ActiveRecord::Base
end
def has_auto_devops_implicitly_enabled?
auto_devops&.enabled.nil? &&
(Gitlab::CurrentSettings.auto_devops_enabled? || Feature.enabled?(:force_autodevops_on_by_default, self))
auto_devops_config = first_auto_devops_config
auto_devops_config[:scope] != :project && auto_devops_config[:status]
end
def has_auto_devops_implicitly_disabled?
auto_devops&.enabled.nil? && !(Gitlab::CurrentSettings.auto_devops_enabled? || Feature.enabled?(:force_autodevops_on_by_default, self))
auto_devops_config = first_auto_devops_config
auto_devops_config[:scope] != :project && !auto_devops_config[:status]
end
def first_auto_devops_config
return namespace.first_auto_devops_config if auto_devops&.enabled.nil?
{ scope: :project, status: auto_devops&.enabled || Feature.enabled?(:force_autodevops_on_by_default, self) }
end
def daily_statistics_enabled?

View file

@ -0,0 +1,17 @@
# frozen_string_literal: true
module Groups
class AutoDevopsService < Groups::BaseService
def execute
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :admin_group, group)
group.update(auto_devops_enabled: auto_devops_enabled)
end
private
def auto_devops_enabled
params[:auto_devops_enabled]
end
end
end

View file

@ -0,0 +1,15 @@
= form_for group, url: update_auto_devops_group_settings_ci_cd_path(group), method: :patch do |f|
= form_errors(group)
%fieldset
.form-group
.card.auto-devops-card
.card-body
.form-check
= f.check_box :auto_devops_enabled, class: 'form-check-input', checked: group.auto_devops_enabled?
= f.label :auto_devops_enabled, class: 'form-check-label' do
%strong= s_('GroupSettings|Default to Auto DevOps pipeline for all projects within this group')
%span.badge.badge-info#auto-devops-badge= badge_for_auto_devops_scope(group)
.form-text.text-muted
= s_('GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found.')
= link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank'
= f.submit _('Save changes'), class: 'btn btn-success prepend-top-15'

View file

@ -19,3 +19,17 @@
= _('Register and see your runners for this group.')
.settings-content
= render 'groups/runners/index'
%section.settings#auto-devops-settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4
= _('Auto DevOps')
%button.btn.btn-default.js-settings-toggle{ type: "button" }
= expanded ? _('Collapse') : _('Expand')
%p
- auto_devops_url = help_page_path('topics/autodevops/index')
- auto_devops_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: auto_devops_url }
= s_('GroupSettings|Auto DevOps will automatically build, test and deploy your application based on a predefined Continuous Integration and Delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end}').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: '</a>'.html_safe }
.settings-content
= render 'groups/settings/ci_cd/auto_devops_form', group: @group

View file

@ -8,15 +8,15 @@
.card.auto-devops-card
.card-body
.form-check
= form.check_box :enabled, class: 'form-check-input js-toggle-extra-settings', checked: @project.auto_devops_enabled?
= form.check_box :enabled, class: 'form-check-input js-toggle-extra-settings', checked: auto_devops_enabled
= form.label :enabled, class: 'form-check-label' do
%strong= s_('CICD|Default to Auto DevOps pipeline')
- if @project.has_auto_devops_implicitly_enabled?
%span.badge.badge-info.js-instance-default-badge= s_('CICD|instance enabled')
- if auto_devops_enabled
%span.badge.badge-info.js-instance-default-badge= badge_for_auto_devops_scope(@project)
.form-text.text-muted
= s_('CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found.')
= link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank'
.card-footer.js-extra-settings{ class: @project.auto_devops_enabled? || 'hidden' }
.card-footer.js-extra-settings{ class: auto_devops_enabled || 'hidden' }
%p.settings-message.text-center
- kubernetes_cluster_link = help_page_path('user/project/clusters/index')
- kubernetes_cluster_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: kubernetes_cluster_link }

View file

@ -26,7 +26,7 @@
= s_('CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration.')
= link_to s_('CICD|Learn more about Auto DevOps'), help_page_path('topics/autodevops/index.md')
.settings-content
= render 'autodevops_form'
= render 'autodevops_form', auto_devops_enabled: @project.auto_devops_enabled?
= render_if_exists 'projects/settings/ci_cd/protected_environments', expanded: expanded

View file

@ -0,0 +1,5 @@
---
title: Enable/disable Auto DevOps at the Group level
merge_request: 25533
author:
type: added

View file

@ -31,6 +31,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
namespace :settings do
resource :ci_cd, only: [:show], controller: 'ci_cd' do
put :reset_registration_token
patch :update_auto_devops
end
end

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddAutoDevOpsEnabledToNamespaces < ActiveRecord::Migration[5.0]
DOWNTIME = false
def change
add_column :namespaces, :auto_devops_enabled, :boolean
end
end

View file

@ -1377,6 +1377,7 @@ ActiveRecord::Schema.define(version: 20190301182457) do
t.integer "cached_markdown_version"
t.string "runners_token"
t.string "runners_token_encrypted"
t.boolean "auto_devops_enabled"
t.index ["created_at"], name: "index_namespaces_on_created_at", using: :btree
t.index ["name", "parent_id"], name: "index_namespaces_on_name_and_parent_id", unique: true, using: :btree
t.index ["name"], name: "index_namespaces_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}

View file

@ -1332,6 +1332,9 @@ msgstr ""
msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|group enabled"
msgstr ""
msgid "CICD|instance enabled"
msgstr ""
@ -3828,18 +3831,33 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
msgid "GroupSettings|Auto DevOps will automatically build, test and deploy your application based on a predefined Continuous Integration and Delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end}"
msgstr ""
msgid "GroupSettings|Badges"
msgstr ""
msgid "GroupSettings|Customize your group badges."
msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
msgstr ""
msgid "GroupSettings|Learn more about badges."
msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
msgid "GroupSettings|There was a problem updating Auto DevOps pipeline: %{error_messages}."
msgstr ""
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -3631,28 +3631,28 @@ 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 }
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
end
context 'when disabled in settings' do
@ -3670,12 +3670,93 @@ describe Project do
it { is_expected.to be_truthy }
end
context 'when force_autodevops_on_by_default is enabled for the project' do
context 'when explicitly disabled' do
before do
Feature.get(:force_autodevops_on_by_default).enable_percentage_of_actors(100)
create(:project_auto_devops, :disabled, project: project)
end
it { is_expected.to be_truthy }
it { is_expected.to be_falsey }
end
end
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: instance_enabled)
project.update!(namespace: parent_group)
end
context 'when enabled on parent' do
let(:parent_group) { 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
end
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
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

View file

@ -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

View file

@ -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