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:
parent
db37b5a4c8
commit
7e9348f359
25 changed files with 796 additions and 45 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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?
|
||||
|
|
17
app/services/groups/auto_devops_service.rb
Normal file
17
app/services/groups/auto_devops_service.rb
Normal 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
|
15
app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
Normal file
15
app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
Normal 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'
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Enable/disable Auto DevOps at the Group level
|
||||
merge_request: 25533
|
||||
author:
|
||||
type: added
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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"}
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
62
spec/services/groups/auto_devops_service_spec.rb
Normal file
62
spec/services/groups/auto_devops_service_spec.rb
Normal 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
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue