diff options
Diffstat (limited to 'spec')
27 files changed, 383 insertions, 84 deletions
diff --git a/spec/config/object_store_settings_spec.rb b/spec/config/object_store_settings_spec.rb index 56ad0943377..1555124fe03 100644 --- a/spec/config/object_store_settings_spec.rb +++ b/spec/config/object_store_settings_spec.rb @@ -73,6 +73,7 @@ RSpec.describe ObjectStoreSettings do expect(settings.artifacts['object_store']['background_upload']).to be false expect(settings.artifacts['object_store']['proxy_download']).to be false expect(settings.artifacts['object_store']['remote_directory']).to eq('artifacts') + expect(settings.artifacts['object_store']['bucket_prefix']).to eq(nil) expect(settings.artifacts['object_store']['consolidated_settings']).to be true expect(settings.artifacts).to eq(settings['artifacts']) @@ -83,6 +84,7 @@ RSpec.describe ObjectStoreSettings do expect(settings.lfs['object_store']['background_upload']).to be false expect(settings.lfs['object_store']['proxy_download']).to be true expect(settings.lfs['object_store']['remote_directory']).to eq('lfs-objects') + expect(settings.lfs['object_store']['bucket_prefix']).to eq(nil) expect(settings.lfs['object_store']['consolidated_settings']).to be true expect(settings.lfs).to eq(settings['lfs']) @@ -90,6 +92,7 @@ RSpec.describe ObjectStoreSettings do expect(settings.pages['object_store']['enabled']).to be true expect(settings.pages['object_store']['connection']).to eq(connection) expect(settings.pages['object_store']['remote_directory']).to eq('pages') + expect(settings.pages['object_store']['bucket_prefix']).to eq(nil) expect(settings.pages['object_store']['consolidated_settings']).to be true expect(settings.pages).to eq(settings['pages']) @@ -98,6 +101,18 @@ RSpec.describe ObjectStoreSettings do expect(settings.external_diffs).to eq(settings['external_diffs']) end + it 'supports bucket prefixes' do + config['object_store']['objects']['artifacts']['bucket'] = 'gitlab/artifacts' + config['object_store']['objects']['lfs']['bucket'] = 'gitlab/lfs' + + subject + + expect(settings.artifacts['object_store']['remote_directory']).to eq('gitlab') + expect(settings.artifacts['object_store']['bucket_prefix']).to eq('artifacts') + expect(settings.lfs['object_store']['remote_directory']).to eq('gitlab') + expect(settings.lfs['object_store']['bucket_prefix']).to eq('lfs') + end + it 'raises an error when a bucket is missing' do config['object_store']['objects']['lfs'].delete('bucket') @@ -152,6 +167,7 @@ RSpec.describe ObjectStoreSettings do expect(settings.artifacts['enabled']).to be true expect(settings.artifacts['object_store']['remote_directory']).to be_nil + expect(settings.artifacts['object_store']['bucket_prefix']).to be_nil expect(settings.artifacts['object_store']['enabled']).to be_falsey expect(settings.artifacts['object_store']['consolidated_settings']).to be_falsey end @@ -177,6 +193,7 @@ RSpec.describe ObjectStoreSettings do expect(settings.artifacts['object_store']).to be_nil expect(settings.lfs['object_store']['remote_directory']).to eq('some-bucket') + expect(settings.lfs['object_store']['bucket_prefix']).to eq(nil) # Disable background_upload, regardless of the input config expect(settings.lfs['object_store']['direct_upload']).to eq(true) expect(settings.lfs['object_store']['background_upload']).to eq(false) @@ -203,6 +220,7 @@ RSpec.describe ObjectStoreSettings do expect(settings.artifacts['object_store']).to be_nil expect(settings.lfs['object_store']['remote_directory']).to eq('some-bucket') + expect(settings.lfs['object_store']['bucket_prefix']).to eq(nil) # Enable background_upload if the environment variable is available expect(settings.lfs['object_store']['direct_upload']).to eq(false) expect(settings.lfs['object_store']['background_upload']).to eq(true) @@ -220,6 +238,7 @@ RSpec.describe ObjectStoreSettings do expect(settings['direct_upload']).to be true expect(settings['background_upload']).to be false expect(settings['remote_directory']).to be nil + expect(settings['bucket_prefix']).to be nil end it 'respects original values' do @@ -234,6 +253,18 @@ RSpec.describe ObjectStoreSettings do expect(settings['direct_upload']).to be true expect(settings['background_upload']).to be false expect(settings['remote_directory']).to eq 'artifacts' + expect(settings['bucket_prefix']).to be nil + end + + it 'supports bucket prefixes' do + original_settings = Settingslogic.new({ + 'enabled' => true, + 'remote_directory' => 'gitlab/artifacts' + }) + + settings = described_class.legacy_parse(original_settings, 'artifacts') + expect(settings['remote_directory']).to eq 'gitlab' + expect(settings['bucket_prefix']).to eq 'artifacts' end context 'legacy background upload environment variable is enabled' do @@ -253,6 +284,7 @@ RSpec.describe ObjectStoreSettings do expect(settings['direct_upload']).to be false expect(settings['background_upload']).to be true expect(settings['remote_directory']).to eq 'artifacts' + expect(settings['bucket_prefix']).to eq nil end end @@ -273,6 +305,50 @@ RSpec.describe ObjectStoreSettings do expect(settings['direct_upload']).to be true expect(settings['background_upload']).to be false expect(settings['remote_directory']).to eq 'artifacts' + expect(settings['bucket_prefix']).to eq nil + end + end + end + + describe '.split_bucket_prefix' do + using RSpec::Parameterized::TableSyntax + + subject { described_class.split_bucket_prefix(input) } + + context 'valid inputs' do + where(:input, :bucket, :prefix) do + nil | nil | nil + '' | nil | nil + 'bucket' | 'bucket' | nil + 'bucket/prefix' | 'bucket' | 'prefix' + 'bucket/pre/fix' | 'bucket' | 'pre/fix' + end + + with_them do + it { expect(subject).to eq([bucket, prefix]) } + end + end + + context 'invalid inputs' do + where(:input) do + [ + ['bucket/'], + ['bucket/.'], + ['bucket/..'], + ['bucket/prefix/'], + ['bucket/prefix/.'], + ['bucket/prefix/..'], + ['/bucket/prefix'], + ['./bucket/prefix'], + ['../bucket/prefix'], + ['bucket//prefix'], + ['bucket/./prefix'], + ['bucket/../prefix'] + ] + end + + with_them do + it { expect { subject }.to raise_error(/invalid bucket/) } end end end diff --git a/spec/features/projects/commits/multi_view_diff_spec.rb b/spec/features/projects/commits/multi_view_diff_spec.rb index 282112a3767..5af2e367aed 100644 --- a/spec/features/projects/commits/multi_view_diff_spec.rb +++ b/spec/features/projects/commits/multi_view_diff_spec.rb @@ -46,28 +46,28 @@ RSpec.describe 'Multiple view Diffs', :js do end context 'opening a diff with ipynb' do - it 'loads the rendered diff as hidden' do + it 'loads the raw diff as hidden' do diff = page.find('.diff-file, .file-holder', match: :first) - expect(diff).not_to have_selector '[data-diff-toggle-entity="toHide"]' - expect(diff).to have_selector '[data-diff-toggle-entity="toShow"]' + expect(diff).not_to have_selector '[data-diff-toggle-entity="rawViewer"]' + expect(diff).to have_selector '[data-diff-toggle-entity="renderedViewer"]' - expect(classes_for_element(diff, 'toHide', visible: false)).to include('hidden') - expect(classes_for_element(diff, 'toShow')).not_to include('hidden') + expect(classes_for_element(diff, 'rawViewer', visible: false)).to include('hidden') + expect(classes_for_element(diff, 'renderedViewer')).not_to include('hidden') - expect(classes_for_element(diff, 'toShowBtn')).to include('selected') - expect(classes_for_element(diff, 'toHideBtn')).not_to include('selected') + expect(classes_for_element(diff, 'renderedButton')).to include('selected') + expect(classes_for_element(diff, 'rawButton')).not_to include('selected') end - it 'displays the rendered diff and hides after selection changes' do + it 'displays the raw diff and hides after selection changes' do diff = page.find('.diff-file, .file-holder', match: :first) - diff.find('[data-diff-toggle-entity="toShowBtn"]').click + diff.find('[data-diff-toggle-entity="rawButton"]').click - expect(diff).to have_selector '[data-diff-toggle-entity="toShow"]' - expect(diff).not_to have_selector '[data-diff-toggle-entity="toHide"]' + expect(diff).to have_selector '[data-diff-toggle-entity="rawViewer"]' + expect(diff).not_to have_selector '[data-diff-toggle-entity="renderedViewer"]' - expect(classes_for_element(diff, 'toHideBtn')).not_to include('selected') - expect(classes_for_element(diff, 'toShowBtn')).to include('selected') + expect(classes_for_element(diff, 'renderedButton')).not_to include('selected') + expect(classes_for_element(diff, 'rawButton')).to include('selected') end it 'transforms the diff' do diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb index a1e92a79516..9d2d1454d77 100644 --- a/spec/features/projects/new_project_spec.rb +++ b/spec/features/projects/new_project_spec.rb @@ -61,15 +61,15 @@ RSpec.describe 'New project', :js do expect(page).to have_link('GitLab export') end - describe 'github import option' do + shared_examples 'renders importer link' do |params| context 'with user namespace' do before do visit new_project_path click_link 'Import project' end - it 'renders link to github importer' do - expect(page).to have_link(href: new_import_github_path) + it "renders link to #{params[:name]} importer" do + expect(page).to have_link(href: Rails.application.routes.url_helpers.send(params[:route])) end end @@ -82,21 +82,56 @@ RSpec.describe 'New project', :js do click_link 'Import project' end - it 'renders link to github importer including namespace id' do - expect(page).to have_link(href: new_import_github_path(namespace_id: group.id)) + it "renders link to #{params[:name]} importer including namespace id" do + expect(page).to have_link(href: Rails.application.routes.url_helpers.send(params[:route], namespace_id: group.id)) end end end - describe 'manifest import option' do - before do - visit new_project_path + describe 'importer links' do + shared_examples 'link to importers' do + let(:importer_routes) do + { + 'github': :new_import_github_path, + 'bitbucket': :status_import_bitbucket_path, + 'bitbucket server': :status_import_bitbucket_server_path, + 'gitlab.com': :status_import_gitlab_path, + 'fogbugz': :new_import_fogbugz_path, + 'gitea': :new_import_gitea_path, + 'manifest': :new_import_manifest_path, + 'phabricator': :new_import_phabricator_path + } + end + + it 'renders links to several importers', :aggregate_failures do + importer_routes.each_value do |route| + expect(page).to have_link(href: Rails.application.routes.url_helpers.send(route, link_params)) + end + end + end - click_link 'Import project' + context 'with user namespace' do + let(:link_params) { {} } + + before do + visit new_project_path + click_link 'Import project' + end + + include_examples 'link to importers' end - it 'has Manifest file' do - expect(page).to have_link('Manifest file') + context 'with group namespace' do + let(:group) { create(:group, :private) } + let(:link_params) { { namespace_id: group.id } } + + before do + group.add_owner(user) + visit new_project_path(namespace_id: group.id) + click_link 'Import project' + end + + include_examples 'link to importers' end end diff --git a/spec/frontend/__helpers__/web_worker_fake.js b/spec/frontend/__helpers__/web_worker_fake.js index 041a9bd8540..fb37e41a853 100644 --- a/spec/frontend/__helpers__/web_worker_fake.js +++ b/spec/frontend/__helpers__/web_worker_fake.js @@ -14,8 +14,7 @@ const createRelativeRequire = (filename) => { const rel = path.relative(__dirname, path.dirname(filename)); const base = path.resolve(__dirname, rel); - // reason: Dynamic require should be fine here since the code is dynamically evaluated anyways. - // eslint-disable-next-line import/no-dynamic-require, global-require + // eslint-disable-next-line global-require return (pathArg) => require(transformRequirePath(base, pathArg)); }; diff --git a/spec/frontend/jobs/components/job_sidebar_details_container_spec.js b/spec/frontend/jobs/components/job_sidebar_details_container_spec.js index cc9a5e4ee25..4046f0269dd 100644 --- a/spec/frontend/jobs/components/job_sidebar_details_container_spec.js +++ b/spec/frontend/jobs/components/job_sidebar_details_container_spec.js @@ -42,7 +42,7 @@ describe('Job Sidebar Details Container', () => { expect(wrapper.html()).toBe(''); }); - it.each(['duration', 'erased_at', 'finished_at', 'queued', 'runner', 'coverage'])( + it.each(['duration', 'erased_at', 'finished_at', 'queued_at', 'runner', 'coverage'])( 'should not render %s details when missing', async (detail) => { await store.dispatch('receiveJobSuccess', { [detail]: undefined }); @@ -59,7 +59,7 @@ describe('Job Sidebar Details Container', () => { ['duration', 'Elapsed time: 6 seconds'], ['erased_at', 'Erased: 3 weeks ago'], ['finished_at', 'Finished: 3 weeks ago'], - ['queued', 'Queued: 9 seconds'], + ['queued_duration', 'Queued: 9 seconds'], ['runner', 'Runner: #1 (ABCDEFGH) local ci runner'], ['coverage', 'Coverage: 20%'], ])('uses %s to render job-%s', async (detail, value) => { diff --git a/spec/frontend/jobs/mock_data.js b/spec/frontend/jobs/mock_data.js index 57ec1c7ef3f..cc5fd92615a 100644 --- a/spec/frontend/jobs/mock_data.js +++ b/spec/frontend/jobs/mock_data.js @@ -930,7 +930,7 @@ export default { created_at: threeWeeksAgo.toISOString(), updated_at: threeWeeksAgo.toISOString(), finished_at: threeWeeksAgo.toISOString(), - queued: 9.54, + queued_duration: 9.54, status: { icon: 'status_success', text: 'passed', diff --git a/spec/frontend/lib/utils/rails_ujs_spec.js b/spec/frontend/lib/utils/rails_ujs_spec.js index 00c29b72e73..c10301523c9 100644 --- a/spec/frontend/lib/utils/rails_ujs_spec.js +++ b/spec/frontend/lib/utils/rails_ujs_spec.js @@ -8,7 +8,7 @@ beforeAll(async () => { // that jQuery isn't available *before* we import @rails/ujs. delete global.jQuery; - const { initRails } = await import('~/lib/utils/rails_ujs.js'); + const { initRails } = await import('~/lib/utils/rails_ujs'); initRails(); }); diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb index 961e7688202..b5b572e9719 100644 --- a/spec/helpers/commits_helper_spec.rb +++ b/spec/helpers/commits_helper_spec.rb @@ -94,7 +94,7 @@ RSpec.describe CommitsHelper do it 'renders the correct select-rendered button' do expect(node[:title]).to eq('Display rendered diff') expect(node['data-file-hash']).to eq('abc') - expect(node['data-diff-toggle-entity']).to eq('toShowBtn') + expect(node['data-diff-toggle-entity']).to eq('renderedButton') expect(node.xpath("//a/svg")[0]["data-testid"]).to eq('doc-text-icon') end end @@ -105,7 +105,7 @@ RSpec.describe CommitsHelper do it 'renders the correct select-raw button' do expect(node[:title]).to eq('Display raw diff') expect(node['data-file-hash']).to eq('abc') - expect(node['data-diff-toggle-entity']).to eq('toHideBtn') + expect(node['data-diff-toggle-entity']).to eq('rawButton') expect(node.xpath("//a/svg")[0]["data-testid"]).to eq('doc-code-icon') end end diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb index de342444c15..44b24385a6f 100644 --- a/spec/lib/gitlab/git/commit_spec.rb +++ b/spec/lib/gitlab/git/commit_spec.rb @@ -62,7 +62,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do after do # Erase the new commit so other tests get the original repo - rugged_repo.references.update("refs/heads/master", SeedRepo::LastCommit::ID) + repository.write_ref("refs/heads/master", SeedRepo::LastCommit::ID) end end diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 3081a3960e9..f75e3352e96 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -676,7 +676,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do after do # Erase our commits so other tests get the original repo - repository_rugged.references.update("refs/heads/master", SeedRepo::LastCommit::ID) + repository.write_ref("refs/heads/master", SeedRepo::LastCommit::ID) end context "where 'follow' == true" do @@ -2294,7 +2294,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do after do # Erase our commits so other tests get the original repo - repository_rugged.references.update('refs/heads/master', SeedRepo::LastCommit::ID) + repository.write_ref('refs/heads/master', SeedRepo::LastCommit::ID) end it 'does not include the renamed file in the sparse checkout' do @@ -2343,7 +2343,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do def create_remote_branch(remote_name, branch_name, source_branch_name) source_branch = repository.branches.find { |branch| branch.name == source_branch_name } - repository_rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", source_branch.dereferenced_target.sha) + repository.write_ref("refs/remotes/#{remote_name}/#{branch_name}", source_branch.dereferenced_target.sha) end def refs(dir) diff --git a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb index d3397e89f1f..95a995b1d5e 100644 --- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb @@ -441,7 +441,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do end it 'has a new CI build token' do - expect(Ci::Build.where(token: 'abcd')).to be_empty + expect(Ci::Build.find_by_token('abcd')).to be_nil end end @@ -568,20 +568,10 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do context 'when there is an existing build with build token' do before do - create(:ci_build, token: 'abcd') - end - - it_behaves_like 'restores project successfully', - issues: 1, - labels: 2, - label_with_priorities: 'A project label', - milestones: 1, - first_issue_labels: 1 - end - - context 'when there is an existing build with build token' do - before do - create(:ci_build, token: 'abcd') + create(:ci_build).tap do |job| + job.set_token('abcd') + job.save! + end end it_behaves_like 'restores project successfully', diff --git a/spec/mailers/emails/admin_notification_spec.rb b/spec/mailers/emails/admin_notification_spec.rb index a233be86a83..bfd07f1d438 100644 --- a/spec/mailers/emails/admin_notification_spec.rb +++ b/spec/mailers/emails/admin_notification_spec.rb @@ -18,12 +18,14 @@ RSpec.describe Emails::AdminNotification do let(:max_project_downloads) { 5 } let(:time_period) { 600 } + let(:group) { nil } subject do Notify.user_auto_banned_email( admin.id, user.id, max_project_downloads: max_project_downloads, - within_seconds: time_period + within_seconds: time_period, + group: group ) end @@ -45,6 +47,10 @@ RSpec.describe Emails::AdminNotification do is_expected.to have_body_text user.name end + it 'includes the scope of the ban' do + is_expected.to have_body_text "banned from your GitLab instance" + end + it 'includes the reason' do is_expected.to have_body_text "due to them downloading more than 5 project repositories within 10 minutes" end @@ -60,5 +66,13 @@ RSpec.describe Emails::AdminNotification do it 'includes the email reason' do is_expected.to have_body_text "You're receiving this email because of your account on localhost" end + + context 'when scoped to a group' do + let(:group) { create(:group) } + + it 'includes the scope of the ban' do + is_expected.to have_body_text "banned from your group (#{group.name})" + end + end end end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index dea1c5c57e1..d45660d120d 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -2598,7 +2598,7 @@ RSpec.describe Ci::Build do context 'when token is empty' do before do - build.update_columns(token: nil, token_encrypted: nil) + build.update_columns(token_encrypted: nil) end it { is_expected.to be_nil} diff --git a/spec/models/ci/processable_spec.rb b/spec/models/ci/processable_spec.rb index cdd96d45561..743736236c2 100644 --- a/spec/models/ci/processable_spec.rb +++ b/spec/models/ci/processable_spec.rb @@ -57,7 +57,7 @@ RSpec.describe Ci::Processable do let(:clone_accessors) { ::Ci::Build.clone_accessors.without(::Ci::Build.extra_accessors) } let(:reject_accessors) do - %i[id status user token token_encrypted coverage trace runner + %i[id status user token_encrypted coverage trace runner artifacts_expire_at created_at updated_at started_at finished_at queued_at erased_by erased_at auto_canceled_by job_artifacts job_artifacts_archive diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb index 366de809bed..a3fc09b31fb 100644 --- a/spec/models/protected_branch_spec.rb +++ b/spec/models/protected_branch_spec.rb @@ -190,6 +190,14 @@ RSpec.describe ProtectedBranch do expect(described_class).not_to receive(:matching) expect(described_class.protected?(project, protected_branch.name)).to eq(true) end + + it 'sets expires_in for a cache key' do + cache_key = described_class.protected_ref_cache_key(project, protected_branch.name) + + expect(Rails.cache).to receive(:fetch).with(cache_key, expires_in: 1.hour) + + described_class.protected?(project, protected_branch.name) + end end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index b5db4492ab9..05ba79e2b98 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -2773,8 +2773,7 @@ RSpec.describe Repository do end def create_remote_branch(remote_name, branch_name, target) - rugged = rugged_repo(repository) - rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", target.id) + repository.write_ref("refs/remotes/#{remote_name}/#{branch_name}", target.id) end shared_examples '#ancestor?' do diff --git a/spec/requests/api/ci/runner/jobs_request_post_spec.rb b/spec/requests/api/ci/runner/jobs_request_post_spec.rb index 738c0bed6cf..3f3a61949d4 100644 --- a/spec/requests/api/ci/runner/jobs_request_post_spec.rb +++ b/spec/requests/api/ci/runner/jobs_request_post_spec.rb @@ -546,7 +546,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do let!(:job) { create(:ci_build, :pending, :queued, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) } let!(:job2) { create(:ci_build, :pending, :queued, :tag, pipeline: pipeline, name: 'rubocop', stage: 'test', stage_idx: 0) } let!(:test_job) do - create(:ci_build, :pending, :queued, pipeline: pipeline, token: 'test-job-token', name: 'deploy', + create(:ci_build, :pending, :queued, pipeline: pipeline, name: 'deploy', stage: 'deploy', stage_idx: 1, options: { script: ['bash'], dependencies: [job2.name] }) end @@ -570,7 +570,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do let!(:job) { create(:ci_build, :pending, :queued, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) } let!(:job2) { create(:ci_build, :pending, :queued, :tag, pipeline: pipeline, name: 'rubocop', stage: 'test', stage_idx: 0) } let!(:empty_dependencies_job) do - create(:ci_build, :pending, :queued, pipeline: pipeline, token: 'test-job-token', name: 'empty_dependencies_job', + create(:ci_build, :pending, :queued, pipeline: pipeline, name: 'empty_dependencies_job', stage: 'deploy', stage_idx: 1, options: { script: ['bash'], dependencies: [] }) end @@ -897,7 +897,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do describe 'a job with excluded artifacts' do context 'when excluded paths are defined' do let(:job) do - create(:ci_build, :pending, :queued, pipeline: pipeline, token: 'test-job-token', name: 'test', + create(:ci_build, :pending, :queued, pipeline: pipeline, name: 'test', stage: 'deploy', stage_idx: 1, options: { artifacts: { paths: ['abc'], exclude: ['cde'] } }) end diff --git a/spec/requests/api/conan_instance_packages_spec.rb b/spec/requests/api/conan_instance_packages_spec.rb index ff3b332c620..54cad3093d7 100644 --- a/spec/requests/api/conan_instance_packages_spec.rb +++ b/spec/requests/api/conan_instance_packages_spec.rb @@ -17,6 +17,12 @@ RSpec.describe API::ConanInstancePackages do let_it_be(:url) { '/packages/conan/v1/conans/search' } it_behaves_like 'conan search endpoint' + + it_behaves_like 'conan FIPS mode' do + let(:params) { { q: package.conan_recipe } } + + subject { get api(url), params: params } + end end describe 'GET /api/v4/packages/conan/v1/users/authenticate' do diff --git a/spec/requests/api/conan_project_packages_spec.rb b/spec/requests/api/conan_project_packages_spec.rb index c108f2efaaf..e28105eb8eb 100644 --- a/spec/requests/api/conan_project_packages_spec.rb +++ b/spec/requests/api/conan_project_packages_spec.rb @@ -17,6 +17,12 @@ RSpec.describe API::ConanProjectPackages do let(:url) { "/projects/#{project.id}/packages/conan/v1/conans/search" } it_behaves_like 'conan search endpoint' + + it_behaves_like 'conan FIPS mode' do + let(:params) { { q: package.conan_recipe } } + + subject { get api(url), params: params } + end end describe 'GET /api/v4/projects/:id/packages/conan/v1/users/authenticate' do diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb index ff7f8f0f7a9..dd7d32f3565 100644 --- a/spec/requests/api/issues/issues_spec.rb +++ b/spec/requests/api/issues/issues_spec.rb @@ -20,6 +20,7 @@ RSpec.describe API::Issues do let_it_be(:milestone) { create(:milestone, title: '1.0.0', project: project) } let_it_be(:empty_milestone) { create(:milestone, title: '2.0.0', project: project) } + let_it_be(:task) { create(:issue, :task, author: user, project: project) } let_it_be(:closed_issue) do create :closed_issue, diff --git a/spec/services/ci/generate_coverage_reports_service_spec.rb b/spec/services/ci/generate_coverage_reports_service_spec.rb index d12a9268e7e..dea946f3b1c 100644 --- a/spec/services/ci/generate_coverage_reports_service_spec.rb +++ b/spec/services/ci/generate_coverage_reports_service_spec.rb @@ -3,8 +3,9 @@ require 'spec_helper' RSpec.describe Ci::GenerateCoverageReportsService do + let_it_be(:project) { create(:project, :repository) } + let(:service) { described_class.new(project) } - let(:project) { create(:project, :repository) } describe '#execute' do subject { service.execute(base_pipeline, head_pipeline) } @@ -52,4 +53,55 @@ RSpec.describe Ci::GenerateCoverageReportsService do end end end + + describe '#latest?' do + subject { service.latest?(base_pipeline, head_pipeline, data) } + + let!(:base_pipeline) { nil } + let!(:head_pipeline) { create(:ci_pipeline, :with_coverage_reports, project: project) } + let!(:child_pipeline) { create(:ci_pipeline, child_of: head_pipeline) } + let!(:key) { service.send(:key, base_pipeline, head_pipeline) } + + let(:data) { { key: key } } + + context 'when cache key is latest' do + it { is_expected.to be_truthy } + end + + context 'when head pipeline has been updated' do + before do + head_pipeline.update_column(:updated_at, 1.minute.from_now) + end + + it { is_expected.to be_falsy } + end + + context 'when cache key is empty' do + let(:data) { { key: nil } } + + it { is_expected.to be_falsy } + end + + context 'when the pipeline has a child that is updated' do + before do + child_pipeline.update_column(:updated_at, 1.minute.from_now) + end + + it { is_expected.to be_falsy } + + context 'when feature flag ci_child_pipeline_coverage_reports is disabled' do + let!(:key) do + # `let!` is executed before `before` block. If the feature flag + # is stubbed in `before`, the first call to `#key` uses the + # default feature flag value (enabled). + # The feature flag needs to be stubbed before the first call to `#key` + # so that the first and second key are calculated using the same method. + stub_feature_flags(ci_child_pipeline_coverage_reports: false) + service.send(:key, base_pipeline, head_pipeline) + end + + it { is_expected.to be_truthy } + end + end + end end diff --git a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb index 284c129221b..b786d7e5527 100644 --- a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb @@ -265,10 +265,9 @@ RSpec.shared_examples 'common trace features' do end context 'build token' do - let(:token) { 'my_secret_token' } + let(:token) { build.token } before do - build.update!(token: token) trace.append(token, 0) end diff --git a/spec/support/shared_examples/lib/gitlab/search_language_filter_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/search_language_filter_shared_examples.rb new file mode 100644 index 00000000000..a3e4379f4d3 --- /dev/null +++ b/spec/support/shared_examples/lib/gitlab/search_language_filter_shared_examples.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'search results filtered by language' do + let(:scope) { 'blobs' } + let(:filters) { { language: %w[Ruby Markdown] } } + let(:query) { 'def | popen | test' } + + before do + project.repository.index_commits_and_blobs + + ensure_elasticsearch_index! + end + + subject(:blob_results) { results.objects('blobs') } + + it 'filters by language', :sidekiq_inline, :aggregate_failures do + expected_paths = %w[ + files/ruby/popen.rb + files/markdown/ruby-style-guide.md + files/ruby/regex.rb + files/ruby/version_info.rb + CONTRIBUTING.md + ] + + paths = blob_results.map { |blob| blob.binary_path } + expect(blob_results.size).to eq(5) + expect(paths).to match_array(expected_paths) + end + + context 'when the search_blobs_language_aggregation feature flag is disabled' do + before do + stub_feature_flags(search_blobs_language_aggregation: false) + end + + it 'does not filter by language', :sidekiq_inline, :aggregate_failures do + expected_paths = %w[ + CHANGELOG + CONTRIBUTING.md + bar/branch-test.txt + custom-highlighting/test.gitlab-custom + files/ruby/popen.rb + files/ruby/regex.rb + files/ruby/version_info.rb + files/whitespace + encoding/test.txt + files/markdown/ruby-style-guide.md + ] + + paths = blob_results.map { |blob| blob.binary_path } + expect(blob_results.size).to eq(10) + expect(paths).to match_array(expected_paths) + end + end +end diff --git a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb index e6b0772aec1..d7c2b645de9 100644 --- a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb @@ -1,6 +1,10 @@ # frozen_string_literal: true RSpec.shared_examples 'conan ping endpoint' do + it_behaves_like 'conan FIPS mode' do + subject { get api(url) } + end + it 'responds with 200 OK when no token provided' do get api(url) @@ -85,6 +89,8 @@ end RSpec.shared_examples 'conan authenticate endpoint' do subject { get api(url), headers: headers } + it_behaves_like 'conan FIPS mode' + context 'when using invalid token' do let(:auth_token) { 'invalid_token' } @@ -159,6 +165,10 @@ RSpec.shared_examples 'conan authenticate endpoint' do end RSpec.shared_examples 'conan check_credentials endpoint' do + it_behaves_like 'conan FIPS mode' do + subject { get api(url), headers: headers } + end + it 'responds with a 200 OK with PAT' do get api(url), headers: headers @@ -390,6 +400,7 @@ end RSpec.shared_examples 'recipe snapshot endpoint' do subject { get api(url), headers: headers } + it_behaves_like 'conan FIPS mode' it_behaves_like 'rejects invalid recipe' it_behaves_like 'rejects recipe for invalid project' it_behaves_like 'empty recipe for not found package' @@ -415,6 +426,7 @@ end RSpec.shared_examples 'package snapshot endpoint' do subject { get api(url), headers: headers } + it_behaves_like 'conan FIPS mode' it_behaves_like 'rejects invalid recipe' it_behaves_like 'rejects recipe for invalid project' it_behaves_like 'empty recipe for not found package' @@ -436,6 +448,10 @@ RSpec.shared_examples 'package snapshot endpoint' do end RSpec.shared_examples 'recipe download_urls endpoint' do + it_behaves_like 'conan FIPS mode' do + let(:recipe_path) { package.conan_recipe_path } + end + it_behaves_like 'rejects invalid recipe' it_behaves_like 'rejects recipe for invalid project' it_behaves_like 'recipe download_urls' @@ -443,6 +459,10 @@ RSpec.shared_examples 'recipe download_urls endpoint' do end RSpec.shared_examples 'package download_urls endpoint' do + it_behaves_like 'conan FIPS mode' do + let(:recipe_path) { package.conan_recipe_path } + end + it_behaves_like 'rejects invalid recipe' it_behaves_like 'rejects recipe for invalid project' it_behaves_like 'package download_urls' @@ -457,6 +477,7 @@ RSpec.shared_examples 'recipe upload_urls endpoint' do 'conanmanifest.txt': 123 } end + it_behaves_like 'conan FIPS mode' it_behaves_like 'rejects invalid recipe' it_behaves_like 'rejects invalid upload_url params' it_behaves_like 'handling empty values for username and channel' @@ -519,6 +540,7 @@ RSpec.shared_examples 'package upload_urls endpoint' do 'conan_package.tgz': 523 } end + it_behaves_like 'conan FIPS mode' it_behaves_like 'rejects invalid recipe' it_behaves_like 'rejects invalid upload_url params' it_behaves_like 'handling empty values for username and channel' @@ -556,6 +578,7 @@ end RSpec.shared_examples 'delete package endpoint' do let(:recipe_path) { package.conan_recipe_path } + it_behaves_like 'conan FIPS mode' it_behaves_like 'rejects invalid recipe' it_behaves_like 'handling empty values for username and channel' @@ -665,6 +688,7 @@ RSpec.shared_examples 'not found request' do end RSpec.shared_examples 'recipe file download endpoint' do + it_behaves_like 'conan FIPS mode' it_behaves_like 'a public project with packages' it_behaves_like 'an internal project with packages' it_behaves_like 'a private project with packages' @@ -672,6 +696,7 @@ RSpec.shared_examples 'recipe file download endpoint' do end RSpec.shared_examples 'package file download endpoint' do + it_behaves_like 'conan FIPS mode' it_behaves_like 'a public project with packages' it_behaves_like 'an internal project with packages' it_behaves_like 'a private project with packages' @@ -697,6 +722,7 @@ RSpec.shared_examples 'project not found by project id' do end RSpec.shared_examples 'workhorse authorize endpoint' do + it_behaves_like 'conan FIPS mode' it_behaves_like 'rejects invalid recipe' it_behaves_like 'rejects invalid file_name', 'conanfile.py.git%2fgit-upload-pack' it_behaves_like 'workhorse authorization' @@ -718,6 +744,7 @@ RSpec.shared_examples 'workhorse recipe file upload endpoint' do ) end + it_behaves_like 'conan FIPS mode' it_behaves_like 'rejects invalid recipe' it_behaves_like 'rejects invalid file_name', 'conanfile.py.git%2fgit-upload-pack' it_behaves_like 'uploads a package file' @@ -979,3 +1006,9 @@ RSpec.shared_examples 'workhorse authorization' do end end end + +RSpec.shared_examples 'conan FIPS mode' do + context 'when FIPS mode is enabled', :fips_mode do + it_behaves_like 'returning response status', :not_found + end +end diff --git a/spec/support/shared_examples/workers/concerns/git_garbage_collect_methods_shared_examples.rb b/spec/support/shared_examples/workers/concerns/git_garbage_collect_methods_shared_examples.rb index 77c4a3431e2..de257fb4fde 100644 --- a/spec/support/shared_examples/workers/concerns/git_garbage_collect_methods_shared_examples.rb +++ b/spec/support/shared_examples/workers/concerns/git_garbage_collect_methods_shared_examples.rb @@ -259,7 +259,7 @@ RSpec.shared_examples 'can collect git garbage' do |update_statistics: true| tree: old_commit.tree, parents: [old_commit] ) - rugged.references.create("refs/heads/#{SecureRandom.hex(6)}", new_commit_sha) + repository.write_ref("refs/heads/#{SecureRandom.hex(6)}", new_commit_sha) end def packs(resource) diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb index 13f70e3f85b..1bcc43b81a8 100644 --- a/spec/uploaders/object_storage_spec.rb +++ b/spec/uploaders/object_storage_spec.rb @@ -48,6 +48,28 @@ RSpec.describe ObjectStorage do expect(uploader.store_dir).to start_with("uploads/-/system/user/") end end + + describe '#store_path' do + subject { uploader.store_path('filename') } + + it 'uses store_dir' do + expect(subject).to eq("uploads/-/system/user/#{object.id}/filename") + end + + context 'when a bucket prefix is configured' do + before do + allow(uploader_class).to receive(:object_store_options) do + double( + bucket_prefix: 'my/prefix' + ) + end + end + + it 'uses store_dir and ignores prefix' do + expect(subject).to eq("uploads/-/system/user/#{object.id}/filename") + end + end + end end context 'object_store is Store::REMOTE' do @@ -60,6 +82,28 @@ RSpec.describe ObjectStorage do expect(uploader.store_dir).to start_with("user/") end end + + describe '#store_path' do + subject { uploader.store_path('filename') } + + it 'uses store_dir' do + expect(subject).to eq("user/#{object.id}/filename") + end + + context 'when a bucket prefix is configured' do + before do + allow(uploader_class).to receive(:object_store_options) do + double( + bucket_prefix: 'my/prefix' + ) + end + end + + it 'uses the prefix and store_dir' do + expect(subject).to eq("my/prefix/user/#{object.id}/filename") + end + end + end end end diff --git a/spec/workers/gitlab_service_ping_worker_spec.rb b/spec/workers/gitlab_service_ping_worker_spec.rb index 057639dcf1d..c88708dc50a 100644 --- a/spec/workers/gitlab_service_ping_worker_spec.rb +++ b/spec/workers/gitlab_service_ping_worker_spec.rb @@ -21,29 +21,12 @@ RSpec.describe GitlabServicePingWorker, :clean_gitlab_redis_shared_state do subject.perform end - context 'with prerecord_service_ping_data feature enabled' do - it 'delegates to ServicePing::SubmitService' do - stub_feature_flags(prerecord_service_ping_data: true) - - expect_next_instance_of(ServicePing::SubmitService, payload: payload) do |service| - expect(service).to receive(:execute) - end - - subject.perform + it 'delegates to ServicePing::SubmitService' do + expect_next_instance_of(ServicePing::SubmitService, payload: payload) do |service| + expect(service).to receive(:execute) end - end - context 'with prerecord_service_ping_data feature disabled' do - it 'does not prerecord ServicePing, and calls SubmitService', :aggregate_failures do - stub_feature_flags(prerecord_service_ping_data: false) - - expect(ServicePing::BuildPayload).not_to receive(:new) - expect(ServicePing::BuildPayload).not_to receive(:new) - expect_next_instance_of(ServicePing::SubmitService, payload: nil) do |service| - expect(service).to receive(:execute) - end - expect { subject.perform }.not_to change { RawUsageData.count } - end + subject.perform end context 'payload computation' do |