diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-26 12:10:08 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-26 12:10:08 +0000 |
commit | c4af99d56fdef59d1da557d88a334f52e7531eb3 (patch) | |
tree | 10425fe4cbe9ceff8f567c5e1ebb0eea125afdd4 /spec | |
parent | ec3483bd1831dfca0c7baec0f8aad9079d28907d (diff) | |
download | gitlab-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.rb | 158 | ||||
-rw-r--r-- | spec/factories/projects.rb | 15 | ||||
-rw-r--r-- | spec/frontend/security_configuration/components/upgrade_banner_spec.js | 4 | ||||
-rw-r--r-- | spec/graphql/types/base_field_spec.rb | 32 | ||||
-rw-r--r-- | spec/lib/gitlab/github_import/user_finder_spec.rb | 29 | ||||
-rw-r--r-- | spec/lib/gitlab/subscription_portal_spec.rb | 2 | ||||
-rw-r--r-- | spec/models/container_repository_spec.rb | 2 | ||||
-rw-r--r-- | spec/models/namespace_spec.rb | 62 | ||||
-rw-r--r-- | spec/models/project_feature_spec.rb | 34 | ||||
-rw-r--r-- | spec/models/project_spec.rb | 32 | ||||
-rw-r--r-- | spec/models/project_team_spec.rb | 2 | ||||
-rw-r--r-- | spec/services/ci/build_cancel_service_spec.rb | 52 | ||||
-rw-r--r-- | spec/services/ci/build_unschedule_service_spec.rb | 52 | ||||
-rw-r--r-- | spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb | 17 |
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 |