summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-07-26 12:10:08 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-26 12:10:08 +0000
commitc4af99d56fdef59d1da557d88a334f52e7531eb3 (patch)
tree10425fe4cbe9ceff8f567c5e1ebb0eea125afdd4 /spec
parentec3483bd1831dfca0c7baec0f8aad9079d28907d (diff)
downloadgitlab-ce-c4af99d56fdef59d1da557d88a334f52e7531eb3.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb158
-rw-r--r--spec/factories/projects.rb15
-rw-r--r--spec/frontend/security_configuration/components/upgrade_banner_spec.js4
-rw-r--r--spec/graphql/types/base_field_spec.rb32
-rw-r--r--spec/lib/gitlab/github_import/user_finder_spec.rb29
-rw-r--r--spec/lib/gitlab/subscription_portal_spec.rb2
-rw-r--r--spec/models/container_repository_spec.rb2
-rw-r--r--spec/models/namespace_spec.rb62
-rw-r--r--spec/models/project_feature_spec.rb34
-rw-r--r--spec/models/project_spec.rb32
-rw-r--r--spec/models/project_team_spec.rb2
-rw-r--r--spec/services/ci/build_cancel_service_spec.rb52
-rw-r--r--spec/services/ci/build_unschedule_service_spec.rb52
-rw-r--r--spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb17
14 files changed, 396 insertions, 97 deletions
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index a7a36d3a074..e9e7c3c3bb3 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -868,64 +868,85 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
describe 'POST cancel' do
- before do
- project.add_developer(user)
- sign_in(user)
- end
+ context 'when user is authorized to cancel the build' do
+ before do
+ project.add_developer(user)
+ sign_in(user)
+ end
- context 'when continue url is present' do
- let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) }
+ context 'when continue url is present' do
+ let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) }
- context 'when continue to is a safe url' do
- let(:url) { '/test' }
+ context 'when continue to is a safe url' do
+ let(:url) { '/test' }
- before do
- post_cancel(continue: { to: url })
- end
+ before do
+ post_cancel(continue: { to: url })
+ end
- it 'redirects to the continue url' do
- expect(response).to have_gitlab_http_status(:found)
- expect(response).to redirect_to(url)
+ it 'redirects to the continue url' do
+ expect(response).to have_gitlab_http_status(:found)
+ expect(response).to redirect_to(url)
+ end
+
+ it 'transits to canceled' do
+ expect(job.reload).to be_canceled
+ end
end
- it 'transits to canceled' do
- expect(job.reload).to be_canceled
+ context 'when continue to is not a safe url' do
+ let(:url) { 'http://example.com' }
+
+ it 'raises an error' do
+ expect { cancel_with_redirect(url) }.to raise_error
+ end
end
end
- context 'when continue to is not a safe url' do
- let(:url) { 'http://example.com' }
+ context 'when continue url is not present' do
+ before do
+ post_cancel
+ end
+
+ context 'when job is cancelable' do
+ let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) }
+
+ it 'redirects to the builds page' do
+ expect(response).to have_gitlab_http_status(:found)
+ expect(response).to redirect_to(builds_namespace_project_pipeline_path(id: pipeline.id))
+ end
+
+ it 'transits to canceled' do
+ expect(job.reload).to be_canceled
+ end
+ end
+
+ context 'when job is not cancelable' do
+ let(:job) { create(:ci_build, :canceled, pipeline: pipeline) }
- it 'raises an error' do
- expect { cancel_with_redirect(url) }.to raise_error
+ it 'returns unprocessable_entity' do
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
end
end
end
- context 'when continue url is not present' do
+ context 'when user is not authorized to cancel the build' do
+ let!(:job) { create(:ci_build, :cancelable, pipeline: pipeline) }
+
before do
+ project.add_reporter(user)
+ sign_in(user)
+
post_cancel
end
- context 'when job is cancelable' do
- let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) }
-
- it 'redirects to the builds page' do
- expect(response).to have_gitlab_http_status(:found)
- expect(response).to redirect_to(builds_namespace_project_pipeline_path(id: pipeline.id))
- end
-
- it 'transits to canceled' do
- expect(job.reload).to be_canceled
- end
+ it 'responds with not_found' do
+ expect(response).to have_gitlab_http_status(:not_found)
end
- context 'when job is not cancelable' do
- let(:job) { create(:ci_build, :canceled, pipeline: pipeline) }
-
- it 'returns unprocessable_entity' do
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- end
+ it 'does not transit to canceled' do
+ expect(job.reload).not_to be_canceled
end
end
@@ -938,43 +959,60 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
describe 'POST unschedule' do
before do
- project.add_developer(user)
+ create(:protected_branch, :developers_can_merge, name: 'master', project: project)
+ end
- create(:protected_branch, :developers_can_merge,
- name: 'master', project: project)
+ context 'when user is authorized to unschedule the build' do
+ before do
+ project.add_developer(user)
+ sign_in(user)
- sign_in(user)
+ post_unschedule
+ end
- post_unschedule
- end
+ context 'when job is scheduled' do
+ let(:job) { create(:ci_build, :scheduled, pipeline: pipeline) }
- context 'when job is scheduled' do
- let(:job) { create(:ci_build, :scheduled, pipeline: pipeline) }
+ it 'redirects to the unscheduled job page' do
+ expect(response).to have_gitlab_http_status(:found)
+ expect(response).to redirect_to(namespace_project_job_path(id: job.id))
+ end
- it 'redirects to the unscheduled job page' do
- expect(response).to have_gitlab_http_status(:found)
- expect(response).to redirect_to(namespace_project_job_path(id: job.id))
+ it 'transits to manual' do
+ expect(job.reload).to be_manual
+ end
end
- it 'transits to manual' do
- expect(job.reload).to be_manual
+ context 'when job is not scheduled' do
+ let(:job) { create(:ci_build, pipeline: pipeline) }
+
+ it 'renders unprocessable_entity' do
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
end
end
- context 'when job is not scheduled' do
- let(:job) { create(:ci_build, pipeline: pipeline) }
+ context 'when user is not authorized to unschedule the build' do
+ let(:job) { create(:ci_build, :scheduled, pipeline: pipeline) }
- it 'renders unprocessable_entity' do
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ before do
+ project.add_reporter(user)
+ sign_in(user)
+
+ post_unschedule
+ end
+
+ it 'responds with not_found' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'does not transit to scheduled' do
+ expect(job.reload).not_to be_manual
end
end
def post_unschedule
- post :unschedule, params: {
- namespace_id: project.namespace,
- project_id: project,
- id: job.id
- }
+ post :unschedule, params: { namespace_id: project.namespace, project_id: project, id: job.id }
end
end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 84686c58a8e..d18369b8023 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -34,6 +34,7 @@ FactoryBot.define do
end
metrics_dashboard_access_level { ProjectFeature::PRIVATE }
operations_access_level { ProjectFeature::ENABLED }
+ container_registry_access_level { ProjectFeature::ENABLED }
# we can't assign the delegated `#ci_cd_settings` attributes directly, as the
# `#ci_cd_settings` relation needs to be created first
@@ -70,6 +71,17 @@ FactoryBot.define do
}
project.build_project_feature(hash)
+
+ # This is not included in the `hash` above because the default_value_for in
+ # the ProjectFeature model overrides the value set by `build_project_feature` when
+ # evaluator.container_registry_access_level == ProjectFeature::DISABLED.
+ #
+ # This is because the default_value_for gem uses the <column>_changed? method
+ # to determine if the default value should be applied. For new records,
+ # <column>_changed? returns false if the value of the column is the same as
+ # the database default.
+ # See https://github.com/FooBarWidget/default_value_for/blob/release-3.4.0/lib/default_value_for.rb#L158.
+ project.project_feature.container_registry_access_level = evaluator.container_registry_access_level
end
after(:create) do |project, evaluator|
@@ -344,6 +356,9 @@ FactoryBot.define do
trait(:analytics_enabled) { analytics_access_level { ProjectFeature::ENABLED } }
trait(:analytics_disabled) { analytics_access_level { ProjectFeature::DISABLED } }
trait(:analytics_private) { analytics_access_level { ProjectFeature::PRIVATE } }
+ trait(:container_registry_enabled) { container_registry_access_level { ProjectFeature::ENABLED } }
+ trait(:container_registry_disabled) { container_registry_access_level { ProjectFeature::DISABLED } }
+ trait(:container_registry_private) { container_registry_access_level { ProjectFeature::PRIVATE } }
trait :auto_devops do
association :auto_devops, factory: :project_auto_devops
diff --git a/spec/frontend/security_configuration/components/upgrade_banner_spec.js b/spec/frontend/security_configuration/components/upgrade_banner_spec.js
index cf7945343af..a35fded72fb 100644
--- a/spec/frontend/security_configuration/components/upgrade_banner_spec.js
+++ b/spec/frontend/security_configuration/components/upgrade_banner_spec.js
@@ -43,11 +43,11 @@ describe('UpgradeBanner component', () => {
it('renders the list of benefits', () => {
const wrapperText = wrapper.text();
- expect(wrapperText).toContain('GitLab Ultimate checks your application');
+ expect(wrapperText).toContain('Immediately begin risk analysis and remediation');
expect(wrapperText).toContain('statistics in the merge request');
expect(wrapperText).toContain('statistics across projects');
expect(wrapperText).toContain('Runtime security metrics');
- expect(wrapperText).toContain('risk analysis and remediation');
+ expect(wrapperText).toContain('More scan types, including Container Scanning,');
});
it(`re-emits GlBanner's close event`, () => {
diff --git a/spec/graphql/types/base_field_spec.rb b/spec/graphql/types/base_field_spec.rb
index c34fbf42dd8..82efd618e38 100644
--- a/spec/graphql/types/base_field_spec.rb
+++ b/spec/graphql/types/base_field_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Types::BaseField do
end
it 'defaults to 1' do
- field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true)
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true)
expect(field.to_graphql.complexity).to eq 1
end
@@ -25,7 +25,7 @@ RSpec.describe Types::BaseField do
describe '#base_complexity' do
context 'with no gitaly calls' do
it 'defaults to 1' do
- field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true)
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true)
expect(field.base_complexity).to eq 1
end
@@ -33,7 +33,7 @@ RSpec.describe Types::BaseField do
context 'with a gitaly call' do
it 'adds 1 to the default value' do
- field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true, calls_gitaly: true)
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, calls_gitaly: true)
expect(field.base_complexity).to eq 2
end
@@ -41,14 +41,14 @@ RSpec.describe Types::BaseField do
end
it 'has specified value' do
- field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true, complexity: 12)
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, complexity: 12)
expect(field.to_graphql.complexity).to eq 12
end
context 'when field has a resolver' do
context 'when a valid complexity is already set' do
- let(:field) { described_class.new(name: 'test', type: GraphQL::STRING_TYPE.connection_type, resolver_class: resolver, complexity: 2, max_page_size: 100, null: true) }
+ let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String.connection_type, resolver_class: resolver, complexity: 2, max_page_size: 100, null: true) }
it 'uses this complexity' do
expect(field.to_graphql.complexity).to eq 2
@@ -56,7 +56,7 @@ RSpec.describe Types::BaseField do
end
context 'and is a connection' do
- let(:field) { described_class.new(name: 'test', type: GraphQL::STRING_TYPE.connection_type, resolver_class: resolver, max_page_size: 100, null: true) }
+ let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String.connection_type, resolver_class: resolver, max_page_size: 100, null: true) }
it 'sets complexity depending on arguments for resolvers' do
expect(field.to_graphql.complexity.call({}, {}, 2)).to eq 4
@@ -71,7 +71,7 @@ RSpec.describe Types::BaseField do
context 'and is not a connection' do
it 'sets complexity as normal' do
- field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, resolver_class: resolver, max_page_size: 100, null: true)
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, resolver_class: resolver, max_page_size: 100, null: true)
expect(field.to_graphql.complexity.call({}, {}, 2)).to eq 2
expect(field.to_graphql.complexity.call({}, { first: 50 }, 2)).to eq 2
@@ -82,8 +82,8 @@ RSpec.describe Types::BaseField do
context 'calls_gitaly' do
context 'for fields with a resolver' do
it 'adds 1 if true' do
- with_gitaly_field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, resolver_class: resolver, null: true, calls_gitaly: true)
- without_gitaly_field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, resolver_class: resolver, null: true)
+ with_gitaly_field = described_class.new(name: 'test', type: GraphQL::Types::String, resolver_class: resolver, null: true, calls_gitaly: true)
+ without_gitaly_field = described_class.new(name: 'test', type: GraphQL::Types::String, resolver_class: resolver, null: true)
base_result = without_gitaly_field.to_graphql.complexity.call({}, {}, 2)
expect(with_gitaly_field.to_graphql.complexity.call({}, {}, 2)).to eq base_result + 1
@@ -92,28 +92,28 @@ RSpec.describe Types::BaseField do
context 'for fields without a resolver' do
it 'adds 1 if true' do
- field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true, calls_gitaly: true)
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, calls_gitaly: true)
expect(field.to_graphql.complexity).to eq 2
end
end
it 'defaults to false' do
- field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true)
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true)
expect(field.base_complexity).to eq Types::BaseField::DEFAULT_COMPLEXITY
end
context 'with declared constant complexity value' do
it 'has complexity set to that constant' do
- field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true, complexity: 12)
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, complexity: 12)
expect(field.to_graphql.complexity).to eq 12
end
it 'does not raise an error even with Gitaly calls' do
allow(Gitlab::GitalyClient).to receive(:get_request_count).and_return([0, 1])
- field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true, complexity: 12)
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, complexity: 12)
expect(field.to_graphql.complexity).to eq 12
end
@@ -123,7 +123,7 @@ RSpec.describe Types::BaseField do
describe '#visible?' do
context 'and has a feature_flag' do
let(:flag) { :test_feature }
- let(:field) { described_class.new(name: 'test', type: GraphQL::STRING_TYPE, feature_flag: flag, null: false) }
+ let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String, feature_flag: flag, null: false) }
let(:context) { {} }
before do
@@ -156,7 +156,7 @@ RSpec.describe Types::BaseField do
describe '#description' do
context 'feature flag given' do
- let(:field) { described_class.new(name: 'test', type: GraphQL::STRING_TYPE, feature_flag: flag, null: false, description: 'Test description.') }
+ let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String, feature_flag: flag, null: false, description: 'Test description.') }
let(:flag) { :test_flag }
it 'prepends the description' do
@@ -211,7 +211,7 @@ RSpec.describe Types::BaseField do
include_examples 'Gitlab-style deprecations' do
def subject(args = {})
- base_args = { name: 'test', type: GraphQL::STRING_TYPE, null: true }
+ base_args = { name: 'test', type: GraphQL::Types::String, null: true }
described_class.new(**base_args.merge(args))
end
diff --git a/spec/lib/gitlab/github_import/user_finder_spec.rb b/spec/lib/gitlab/github_import/user_finder_spec.rb
index 20e67a784e1..f81fa3b1e2e 100644
--- a/spec/lib/gitlab/github_import/user_finder_spec.rb
+++ b/spec/lib/gitlab/github_import/user_finder_spec.rb
@@ -3,7 +3,14 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do
- let(:project) { create(:project) }
+ let(:project) do
+ create(
+ :project,
+ import_type: 'github',
+ import_url: 'https://api.github.com/user/repo'
+ )
+ end
+
let(:client) { double(:client) }
let(:finder) { described_class.new(project, client) }
@@ -263,6 +270,26 @@ RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do
finder.id_for_github_id(id)
end
+
+ context 'when importing from github enterprise' do
+ let(:project) do
+ create(
+ :project,
+ import_type: 'github',
+ import_url: 'https://othergithub.net/user/repo'
+ )
+ end
+
+ it 'does not look up the user by external id' do
+ expect(finder).not_to receive(:query_id_for_github_id)
+
+ expect(Gitlab::Cache::Import::Caching)
+ .to receive(:write)
+ .with(described_class::ID_CACHE_KEY % id, nil)
+
+ finder.id_for_github_id(id)
+ end
+ end
end
describe '#id_for_github_email' do
diff --git a/spec/lib/gitlab/subscription_portal_spec.rb b/spec/lib/gitlab/subscription_portal_spec.rb
index ed551521b1d..628eb380396 100644
--- a/spec/lib/gitlab/subscription_portal_spec.rb
+++ b/spec/lib/gitlab/subscription_portal_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe ::Gitlab::SubscriptionPortal, skip: Gitlab.jh? do
+RSpec.describe ::Gitlab::SubscriptionPortal do
using RSpec::Parameterized::TableSyntax
where(:method_name, :test, :development, :result) do
diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb
index a53db07cc59..846dfb30928 100644
--- a/spec/models/container_repository_spec.rb
+++ b/spec/models/container_repository_spec.rb
@@ -323,7 +323,7 @@ RSpec.describe ContainerRepository do
context 'with a subgroup' do
let_it_be(:test_group) { create(:group) }
let_it_be(:another_project) { create(:project, path: 'test', group: test_group) }
- let_it_be(:project3) { create(:project, path: 'test3', group: test_group, container_registry_enabled: false) }
+ let_it_be(:project3) { create(:project, :container_registry_disabled, path: 'test3', group: test_group) }
let_it_be(:another_repository) do
create(:container_repository, name: 'my_image', project: another_project)
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index ea1ce067e4d..57882b6f1b3 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -1152,6 +1152,68 @@ RSpec.describe Namespace do
end
end
+ context 'refreshing project access on updating share_with_group_lock' do
+ let(:group) { create(:group, share_with_group_lock: false) }
+ let(:project) { create(:project, :private, group: group) }
+
+ let_it_be(:shared_with_group_one) { create(:group) }
+ let_it_be(:shared_with_group_two) { create(:group) }
+ let_it_be(:group_one_user) { create(:user) }
+ let_it_be(:group_two_user) { create(:user) }
+
+ subject(:execute_update) { group.update!(share_with_group_lock: true) }
+
+ before do
+ shared_with_group_one.add_developer(group_one_user)
+ shared_with_group_two.add_developer(group_two_user)
+ create(:project_group_link, group: shared_with_group_one, project: project)
+ create(:project_group_link, group: shared_with_group_two, project: project)
+ end
+
+ it 'calls AuthorizedProjectUpdate::ProjectRecalculateWorker to update project authorizations' do
+ expect(AuthorizedProjectUpdate::ProjectRecalculateWorker)
+ .to receive(:perform_async).with(project.id).once
+
+ execute_update
+ end
+
+ it 'updates authorizations leading to users from shared groups losing access', :sidekiq_inline do
+ expect { execute_update }
+ .to change { group_one_user.authorized_projects.include?(project) }.from(true).to(false)
+ .and change { group_two_user.authorized_projects.include?(project) }.from(true).to(false)
+ end
+
+ it 'calls AuthorizedProjectUpdate::UserRefreshFromReplicaWorker with a delay to update project authorizations' do
+ expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to(
+ receive(:bulk_perform_in)
+ .with(1.hour,
+ [[group_one_user.id]],
+ batch_delay: 30.seconds, batch_size: 100)
+ )
+
+ expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to(
+ receive(:bulk_perform_in)
+ .with(1.hour,
+ [[group_two_user.id]],
+ batch_delay: 30.seconds, batch_size: 100)
+ )
+
+ execute_update
+ end
+
+ context 'when the feature flag `specialized_worker_for_group_lock_update_auth_recalculation` is disabled' do
+ before do
+ stub_feature_flags(specialized_worker_for_group_lock_update_auth_recalculation: false)
+ end
+
+ it 'refreshes the permissions of the members of the old and new namespace' do
+ expect { execute_update }
+ .to change { group_one_user.authorized_projects.include?(project) }.from(true).to(false)
+ .and change { group_two_user.authorized_projects.include?(project) }.from(true).to(false)
+ end
+ end
+ end
+
describe '#share_with_group_lock with subgroups' do
context 'when creating a subgroup' do
let(:subgroup) { create(:group, parent: root_group )}
diff --git a/spec/models/project_feature_spec.rb b/spec/models/project_feature_spec.rb
index 3fd7e57a5db..0ef5a2046ba 100644
--- a/spec/models/project_feature_spec.rb
+++ b/spec/models/project_feature_spec.rb
@@ -189,27 +189,33 @@ RSpec.describe ProjectFeature do
end
describe 'container_registry_access_level' do
- context 'when the project is created with container_registry_enabled false' do
- it 'creates project with DISABLED container_registry_access_level' do
- project = create(:project, container_registry_enabled: false)
+ context 'with default value' do
+ let(:project) { Project.new }
- expect(project.project_feature.container_registry_access_level).to eq(described_class::DISABLED)
+ context 'when the default is false' do
+ it 'creates project_feature with `disabled` container_registry_access_level' do
+ stub_config_setting(default_projects_features: { container_registry: false })
+
+ expect(project.project_feature.container_registry_access_level).to eq(described_class::DISABLED)
+ end
end
- end
- context 'when the project is created with container_registry_enabled true' do
- it 'creates project with ENABLED container_registry_access_level' do
- project = create(:project, container_registry_enabled: true)
+ context 'when the default is true' do
+ before do
+ stub_config_setting(default_projects_features: { container_registry: true })
+ end
- expect(project.project_feature.container_registry_access_level).to eq(described_class::ENABLED)
+ it 'creates project_feature with `enabled` container_registry_access_level' do
+ expect(project.project_feature.container_registry_access_level).to eq(described_class::ENABLED)
+ end
end
- end
- context 'when the project is created with container_registry_enabled nil' do
- it 'creates project with DISABLED container_registry_access_level' do
- project = create(:project, container_registry_enabled: nil)
+ context 'when the default is nil' do
+ it 'creates project_feature with `disabled` container_registry_access_level' do
+ stub_config_setting(default_projects_features: { container_registry: nil })
- expect(project.project_feature.container_registry_access_level).to eq(described_class::DISABLED)
+ expect(project.project_feature.container_registry_access_level).to eq(described_class::DISABLED)
+ end
end
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index ec99e094a03..6aade778724 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -2407,7 +2407,7 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#set_container_registry_access_level' do
+ describe '#container_registry_enabled=' do
let_it_be_with_reload(:project) { create(:project) }
it 'updates project_feature', :aggregate_failures do
@@ -2872,6 +2872,36 @@ RSpec.describe Project, factory_default: :keep do
it { expect(project.import?).to be true }
end
+ describe '#github_import?' do
+ let_it_be(:project) { build(:project, import_type: 'github') }
+
+ it { expect(project.github_import?).to be true }
+ end
+
+ describe '#github_enterprise_import?' do
+ let_it_be(:github_com_project) do
+ build(
+ :project,
+ import_type: 'github',
+ import_url: 'https://api.github.com/user/repo'
+ )
+ end
+
+ let_it_be(:github_enterprise_project) do
+ build(
+ :project,
+ import_type: 'github',
+ import_url: 'https://othergithub.net/user/repo'
+ )
+ end
+
+ it { expect(github_com_project.github_import?).to be true }
+ it { expect(github_com_project.github_enterprise_import?).to be false }
+
+ it { expect(github_enterprise_project.github_import?).to be true }
+ it { expect(github_enterprise_project.github_enterprise_import?).to be true }
+ end
+
describe '#remove_import_data' do
let(:import_data) { ProjectImportData.new(data: { 'test' => 'some data' }) }
diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb
index ce75e68de32..8cc70a30794 100644
--- a/spec/models/project_team_spec.rb
+++ b/spec/models/project_team_spec.rb
@@ -307,7 +307,7 @@ RSpec.describe ProjectTeam do
it { expect(project.team.max_member_access(nonmember.id)).to eq(Gitlab::Access::NO_ACCESS) }
it { expect(project.team.max_member_access(requester.id)).to eq(Gitlab::Access::NO_ACCESS) }
- context 'but share_with_group_lock is true' do
+ context 'but share_with_group_lock is true', :sidekiq_inline do
before do
project.namespace.update!(share_with_group_lock: true)
end
diff --git a/spec/services/ci/build_cancel_service_spec.rb b/spec/services/ci/build_cancel_service_spec.rb
new file mode 100644
index 00000000000..fe036dc1368
--- /dev/null
+++ b/spec/services/ci/build_cancel_service_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::BuildCancelService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+
+ describe '#execute' do
+ subject(:execute) { described_class.new(build, user).execute }
+
+ context 'when user is authorized to cancel the build' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'when build is cancelable' do
+ let!(:build) { create(:ci_build, :cancelable, pipeline: pipeline) }
+
+ it 'transits build to canceled', :aggregate_failures do
+ response = execute
+
+ expect(response).to be_success
+ expect(response.payload.reload).to be_canceled
+ end
+ end
+
+ context 'when build is not cancelable' do
+ let!(:build) { create(:ci_build, :canceled, pipeline: pipeline) }
+
+ it 'responds with unprocessable entity', :aggregate_failures do
+ response = execute
+
+ expect(response).to be_error
+ expect(response.http_status).to eq(:unprocessable_entity)
+ end
+ end
+ end
+
+ context 'when user is not authorized to cancel the build' do
+ let!(:build) { create(:ci_build, :cancelable, pipeline: pipeline) }
+
+ it 'responds with forbidden', :aggregate_failures do
+ response = execute
+
+ expect(response).to be_error
+ expect(response.http_status).to eq(:forbidden)
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/build_unschedule_service_spec.rb b/spec/services/ci/build_unschedule_service_spec.rb
new file mode 100644
index 00000000000..d784d9a2754
--- /dev/null
+++ b/spec/services/ci/build_unschedule_service_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::BuildUnscheduleService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+
+ describe '#execute' do
+ subject(:execute) { described_class.new(build, user).execute }
+
+ context 'when user is authorized to unschedule the build' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'when build is scheduled' do
+ let!(:build) { create(:ci_build, :scheduled, pipeline: pipeline) }
+
+ it 'transits build to manual' do
+ response = execute
+
+ expect(response).to be_success
+ expect(response.payload.reload).to be_manual
+ end
+ end
+
+ context 'when build is not scheduled' do
+ let!(:build) { create(:ci_build, pipeline: pipeline) }
+
+ it 'responds with unprocessable entity', :aggregate_failures do
+ response = execute
+
+ expect(response).to be_error
+ expect(response.http_status).to eq(:unprocessable_entity)
+ end
+ end
+ end
+
+ context 'when user is not authorized to unschedule the build' do
+ let!(:build) { create(:ci_build, :scheduled, pipeline: pipeline) }
+
+ it 'responds with forbidden', :aggregate_failures do
+ response = execute
+
+ expect(response).to be_error
+ expect(response.http_status).to eq(:forbidden)
+ end
+ end
+ end
+end
diff --git a/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb b/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
index 506124216af..fdba67638c1 100644
--- a/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
+++ b/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
@@ -25,6 +25,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
expect(ContainerExpirationPolicies::CleanupService)
.to receive(:new).with(repository).and_return(double(execute: service_response))
expect_log_extra_metadata(service_response: service_response)
+ expect_log_info(project_id: project.id, container_repository_id: repository.id)
subject
end
@@ -35,6 +36,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
expect(ContainerExpirationPolicies::CleanupService)
.to receive(:new).with(repository).and_return(double(execute: service_response))
expect_log_extra_metadata(service_response: service_response, cleanup_status: :unfinished)
+ expect_log_info(project_id: project.id, container_repository_id: repository.id)
subject
end
@@ -45,6 +47,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
expect(ContainerExpirationPolicies::CleanupService)
.to receive(:new).with(repository).and_return(double(execute: service_response))
expect_log_extra_metadata(service_response: service_response, cleanup_status: :unfinished, truncated: true)
+ expect_log_info(project_id: project.id, container_repository_id: repository.id)
subject
end
@@ -65,6 +68,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
expect(ContainerExpirationPolicies::CleanupService)
.to receive(:new).with(repository).and_return(double(execute: service_response))
expect_log_extra_metadata(service_response: service_response, cleanup_status: :unfinished, truncated: truncated)
+ expect_log_info(project_id: project.id, container_repository_id: repository.id)
subject
end
@@ -78,6 +82,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
expect(ContainerExpirationPolicies::CleanupService)
.to receive(:new).with(repository).and_return(double(execute: service_response))
expect_log_extra_metadata(service_response: service_response, cleanup_status: :error)
+ expect_log_info(project_id: project.id, container_repository_id: repository.id)
subject
end
@@ -361,6 +366,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
expect(ContainerExpirationPolicies::CleanupService)
.to receive(:new).with(repository).and_return(double(execute: service_response))
expect_log_extra_metadata(service_response: service_response)
+ expect_log_info(project_id: project.id, container_repository_id: repository.id)
subject
end
@@ -396,6 +402,11 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_error_message, service_response.message)
end
end
+
+ def expect_log_info(structure)
+ expect(worker.logger)
+ .to receive(:info).with(worker.structured_payload(structure))
+ end
end
describe '#remaining_work_count' do
@@ -446,6 +457,12 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
end
it { is_expected.to eq(0) }
+
+ it 'does not log a selected container' do
+ expect(worker).not_to receive(:log_info)
+
+ subject
+ end
end
end