Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-08-10 12:10:08 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-08-10 12:10:08 +0300
commit5adf6557e251c047ed68bac28cfecf9491ee6b41 (patch)
treea7ea2924ef96ccf36a915ddaf686f5f6e1e75b00 /spec
parent0adc81d8e0c7b291fd7fdef33a4ea9c01b4852ce (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/lib/gitlab/ci/config/entry/inherit/variables_spec.rb15
-rw-r--r--spec/lib/gitlab/etag_caching/router/restful_spec.rb8
-rw-r--r--spec/lib/gitlab/git/tag_spec.rb83
-rw-r--r--spec/lib/gitlab/gitaly_client/ref_service_spec.rb11
-rw-r--r--spec/lib/gitlab/usage_data_metrics_spec.rb18
-rw-r--r--spec/lib/gitlab/x509/tag_spec.rb20
-rw-r--r--spec/models/analytics/cycle_analytics/stage_event_hash_spec.rb47
-rw-r--r--spec/policies/project_policy_spec.rb17
-rw-r--r--spec/requests/api/maven_packages_spec.rb92
-rw-r--r--spec/support/helpers/x509_helpers.rb11
-rw-r--r--spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb62
-rw-r--r--spec/support/shared_examples/policies/project_policy_shared_examples.rb15
-rw-r--r--spec/workers/web_hook_worker_spec.rb4
13 files changed, 311 insertions, 92 deletions
diff --git a/spec/lib/gitlab/ci/config/entry/inherit/variables_spec.rb b/spec/lib/gitlab/ci/config/entry/inherit/variables_spec.rb
index b1a8fbcdbe0..bdb4d25c142 100644
--- a/spec/lib/gitlab/ci/config/entry/inherit/variables_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/inherit/variables_spec.rb
@@ -24,19 +24,4 @@ RSpec.describe ::Gitlab::Ci::Config::Entry::Inherit::Variables do
end
end
end
-
- describe '#inherit?' do
- where(:config, :inherit) do
- true | true
- false | false
- %w[A] | true
- %w[B] | false
- end
-
- with_them do
- it do
- expect(subject.inherit?('A')).to eq(inherit)
- end
- end
- end
end
diff --git a/spec/lib/gitlab/etag_caching/router/restful_spec.rb b/spec/lib/gitlab/etag_caching/router/restful_spec.rb
index 877789b320f..1f5cac09b6d 100644
--- a/spec/lib/gitlab/etag_caching/router/restful_spec.rb
+++ b/spec/lib/gitlab/etag_caching/router/restful_spec.rb
@@ -87,12 +87,18 @@ RSpec.describe Gitlab::EtagCaching::Router::Restful do
end
it 'matches the environments path' do
- result = match_route('/my-group/my-project/environments.json')
+ result = match_route('/my-group/my-project/-/environments.json')
expect(result).to be_present
expect(result.name).to eq 'environments'
end
+ it 'does not match the operations environments list path' do
+ result = match_route('/-/operations/environments.json')
+
+ expect(result).not_to be_present
+ end
+
it 'matches pipeline#show endpoint' do
result = match_route('/my-group/my-project/-/pipelines/2.json')
diff --git a/spec/lib/gitlab/git/tag_spec.rb b/spec/lib/gitlab/git/tag_spec.rb
index b6ff76c5e1c..79ae47f8a7b 100644
--- a/spec/lib/gitlab/git/tag_spec.rb
+++ b/spec/lib/gitlab/git/tag_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Gitlab::Git::Tag, :seed_helper do
it { expect(tag.tagger.timezone).to eq("+0200") }
end
- describe 'signed tag' do
+ shared_examples 'signed tag' do
let(:project) { create(:project, :repository) }
let(:tag) { project.repository.find_tag('v1.1.1') }
@@ -54,6 +54,18 @@ RSpec.describe Gitlab::Git::Tag, :seed_helper do
it { expect(tag.tagger.timezone).to eq("+0100") }
end
+ context 'with :get_tag_signatures enabled' do
+ it_behaves_like 'signed tag'
+ end
+
+ context 'with :get_tag_signatures disabled' do
+ before do
+ stub_feature_flags(get_tag_signatures: false)
+ end
+
+ it_behaves_like 'signed tag'
+ end
+
it { expect(repository.tags.size).to eq(SeedRepo::Repo::TAGS.size) }
end
@@ -77,6 +89,75 @@ RSpec.describe Gitlab::Git::Tag, :seed_helper do
end
end
+ describe '.extract_signature_lazily' do
+ let(:project) { create(:project, :repository) }
+
+ subject { described_class.extract_signature_lazily(project.repository, tag_id).itself }
+
+ context 'when the tag is signed' do
+ let(:tag_id) { project.repository.find_tag('v1.1.1').id }
+
+ it 'returns signature and signed text' do
+ signature, signed_text = subject
+
+ expect(signature).to eq(X509Helpers::User1.signed_tag_signature.chomp)
+ expect(signature).to be_a_binary_string
+ expect(signed_text).to eq(X509Helpers::User1.signed_tag_base_data)
+ expect(signed_text).to be_a_binary_string
+ end
+ end
+
+ context 'when the tag has no signature' do
+ let(:tag_id) { project.repository.find_tag('v1.0.0').id }
+
+ it 'returns empty signature and message as signed text' do
+ signature, signed_text = subject
+
+ expect(signature).to be_empty
+ expect(signed_text).to eq(X509Helpers::User1.unsigned_tag_base_data)
+ expect(signed_text).to be_a_binary_string
+ end
+ end
+
+ context 'when the tag cannot be found' do
+ let(:tag_id) { Gitlab::Git::BLANK_SHA }
+
+ it 'raises GRPC::Internal' do
+ expect { subject }.to raise_error(GRPC::Internal)
+ end
+ end
+
+ context 'when the tag ID is invalid' do
+ let(:tag_id) { '4b4918a572fa86f9771e5ba40fbd48e' }
+
+ it 'raises GRPC::Internal' do
+ expect { subject }.to raise_error(GRPC::Internal)
+ end
+ end
+
+ context 'when loading signatures in batch once' do
+ it 'fetches signatures in batch once' do
+ tag_ids = [project.repository.find_tag('v1.1.1').id, project.repository.find_tag('v1.0.0').id]
+ signatures = tag_ids.map do |tag_id|
+ described_class.extract_signature_lazily(repository, tag_id)
+ end
+
+ other_repository = double(:repository)
+ described_class.extract_signature_lazily(other_repository, tag_ids.first)
+
+ expect(described_class).to receive(:batch_signature_extraction)
+ .with(repository, tag_ids)
+ .once
+ .and_return({})
+
+ expect(described_class).not_to receive(:batch_signature_extraction)
+ .with(other_repository, tag_ids.first)
+
+ 2.times { signatures.each(&:itself) }
+ end
+ end
+ end
+
describe 'tag into from Gitaly tag' do
context 'message_size != message.size' do
let(:gitaly_tag) { build(:gitaly_tag, message: ''.b, message_size: message_size) }
diff --git a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
index a4c6e30bba8..e19be965e68 100644
--- a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
@@ -178,6 +178,17 @@ RSpec.describe Gitlab::GitalyClient::RefService do
end
end
+ describe '#get_tag_signatures' do
+ it 'sends a get_tag_signatures message' do
+ expect_any_instance_of(Gitaly::RefService::Stub)
+ .to receive(:get_tag_signatures)
+ .with(gitaly_request_with_params(tag_revisions: ['some_tag_id']), kind_of(Hash))
+ .and_return([])
+
+ client.get_tag_signatures(['some_tag_id'])
+ end
+ end
+
describe '#find_ref_name', :seed_helper do
subject { client.find_ref_name(SeedRepo::Commit::ID, 'refs/heads/master') }
diff --git a/spec/lib/gitlab/usage_data_metrics_spec.rb b/spec/lib/gitlab/usage_data_metrics_spec.rb
index 5bc72845222..7b6b8dacc4c 100644
--- a/spec/lib/gitlab/usage_data_metrics_spec.rb
+++ b/spec/lib/gitlab/usage_data_metrics_spec.rb
@@ -87,6 +87,24 @@ RSpec.describe Gitlab::UsageDataMetrics do
])
end
+ it 'includes terraform monthly key' do
+ expect(subject[:redis_hll_counters][:terraform].keys).to include(:p_terraform_state_api_unique_users_monthly)
+ end
+
+ it 'includes terraform monthly and weekly keys' do
+ expect(subject[:redis_hll_counters][:pipeline_authoring].keys).to contain_exactly(*[
+ :o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly, :o_pipeline_authoring_unique_users_committing_ciconfigfile_weekly,
+ :o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_monthly, :o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_weekly,
+ :pipeline_authoring_total_unique_counts_monthly, :pipeline_authoring_total_unique_counts_weekly
+ ])
+ end
+
+ it 'includes users_expanding_secure_security_report monthly and weekly keys' do
+ expect(subject[:redis_hll_counters][:secure].keys).to contain_exactly(*[
+ :users_expanding_secure_security_report_monthly, :users_expanding_secure_security_report_weekly
+ ])
+ end
+
it 'includes issues_edit monthly and weekly keys' do
expect(subject[:redis_hll_counters][:issues_edit].keys).to include(
:g_project_management_issue_title_changed_monthly, :g_project_management_issue_title_changed_weekly,
diff --git a/spec/lib/gitlab/x509/tag_spec.rb b/spec/lib/gitlab/x509/tag_spec.rb
index b011ea515de..be120aaf16a 100644
--- a/spec/lib/gitlab/x509/tag_spec.rb
+++ b/spec/lib/gitlab/x509/tag_spec.rb
@@ -2,13 +2,13 @@
require 'spec_helper'
RSpec.describe Gitlab::X509::Tag do
- subject(:signature) { described_class.new(tag).signature }
+ subject(:signature) { described_class.new(project.repository, tag).signature }
describe '#signature' do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:project) { create(:project, :repository) }
- describe 'signed tag' do
+ shared_examples 'signed tag' do
let(:tag) { project.repository.find_tag('v1.1.1') }
let(:certificate_attributes) do
{
@@ -33,10 +33,24 @@ RSpec.describe Gitlab::X509::Tag do
it { expect(signature.x509_certificate.x509_issuer).to have_attributes(issuer_attributes) }
end
- context 'unsigned tag' do
+ shared_examples 'unsigned tag' do
let(:tag) { project.repository.find_tag('v1.0.0') }
it { expect(signature).to be_nil }
end
+
+ context 'with :get_tag_signatures enabled' do
+ it_behaves_like 'signed tag'
+ it_behaves_like 'unsigned tag'
+ end
+
+ context 'with :get_tag_signatures disabled' do
+ before do
+ stub_feature_flags(get_tag_signatures: false)
+ end
+
+ it_behaves_like 'signed tag'
+ it_behaves_like 'unsigned tag'
+ end
end
end
diff --git a/spec/models/analytics/cycle_analytics/stage_event_hash_spec.rb b/spec/models/analytics/cycle_analytics/stage_event_hash_spec.rb
new file mode 100644
index 00000000000..ffddaf1e1b2
--- /dev/null
+++ b/spec/models/analytics/cycle_analytics/stage_event_hash_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Analytics::CycleAnalytics::StageEventHash, type: :model do
+ let(:stage_event_hash) { described_class.create!(hash_sha256: hash_sha256) }
+ let(:hash_sha256) { 'does_not_matter' }
+
+ describe 'associations' do
+ it { is_expected.to have_many(:cycle_analytics_project_stages) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:hash_sha256) }
+ end
+
+ describe '.record_id_by_hash_sha256' do
+ it 'returns an existing id' do
+ id = stage_event_hash.id
+ same_id = described_class.record_id_by_hash_sha256(hash_sha256)
+
+ expect(same_id).to eq(id)
+ end
+
+ it 'creates a new record' do
+ expect do
+ described_class.record_id_by_hash_sha256(hash_sha256)
+ end.to change { described_class.count }.from(0).to(1)
+ end
+ end
+
+ describe '.cleanup_if_unused' do
+ it 'removes the record' do
+ described_class.cleanup_if_unused(stage_event_hash.id)
+
+ expect(described_class.find_by_id(stage_event_hash.id)).to be_nil
+ end
+
+ it 'does not remove the record' do
+ id = create(:cycle_analytics_project_stage).stage_event_hash_id
+
+ described_class.cleanup_if_unused(id)
+
+ expect(described_class.find_by_id(id)).not_to be_nil
+ end
+ end
+end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index a6beb12886b..f36b0a62aa3 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -840,6 +840,8 @@ RSpec.describe ProjectPolicy do
it { is_expected.to be_allowed(:read_package) }
it { is_expected.to be_allowed(:read_project) }
it { is_expected.to be_disallowed(:create_package) }
+
+ it_behaves_like 'package access with repository disabled'
end
context 'a deploy token with write_package_registry scope' do
@@ -849,6 +851,8 @@ RSpec.describe ProjectPolicy do
it { is_expected.to be_allowed(:read_package) }
it { is_expected.to be_allowed(:read_project) }
it { is_expected.to be_disallowed(:destroy_package) }
+
+ it_behaves_like 'package access with repository disabled'
end
end
@@ -1021,18 +1025,7 @@ RSpec.describe ProjectPolicy do
it { is_expected.to be_allowed(:read_package) }
- context 'when repository is disabled' do
- before do
- project.project_feature.update!(
- # Disable merge_requests and builds as well, since merge_requests and
- # builds cannot have higher visibility than repository.
- merge_requests_access_level: ProjectFeature::DISABLED,
- builds_access_level: ProjectFeature::DISABLED,
- repository_access_level: ProjectFeature::DISABLED)
- end
-
- it { is_expected.to be_disallowed(:read_package) }
- end
+ it_behaves_like 'package access with repository disabled'
end
context 'with owner' do
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index 2bb6d05f54b..c3fd02dad51 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -217,6 +217,15 @@ RSpec.describe API::MavenPackages do
end
end
+ shared_examples 'successfully returning the file' do
+ it 'returns the file', :aggregate_failures do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
+ end
+
describe 'GET /api/v4/packages/maven/*path/:file_name' do
context 'a public project' do
subject { download_file(file_name: package_file.file_name) }
@@ -224,12 +233,7 @@ RSpec.describe API::MavenPackages do
shared_examples 'getting a file' do
it_behaves_like 'tracking the file download event'
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it_behaves_like 'successfully returning the file'
it 'returns sha1 of the file' do
download_file(file_name: package_file.file_name + '.sha1')
@@ -260,12 +264,7 @@ RSpec.describe API::MavenPackages do
shared_examples 'getting a file' do
it_behaves_like 'tracking the file download event'
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it_behaves_like 'successfully returning the file'
it 'denies download when no private token' do
download_file(file_name: package_file.file_name)
@@ -297,12 +296,7 @@ RSpec.describe API::MavenPackages do
shared_examples 'getting a file' do
it_behaves_like 'tracking the file download event'
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it_behaves_like 'successfully returning the file'
it 'denies download when not enough permissions' do
unless project.root_namespace == user.namespace
@@ -409,12 +403,7 @@ RSpec.describe API::MavenPackages do
shared_examples 'getting a file for a group' do
it_behaves_like 'tracking the file download event'
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it_behaves_like 'successfully returning the file'
it 'returns sha1 of the file' do
download_file(file_name: package_file.file_name + '.sha1')
@@ -445,12 +434,7 @@ RSpec.describe API::MavenPackages do
shared_examples 'getting a file for a group' do
it_behaves_like 'tracking the file download event'
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it_behaves_like 'successfully returning the file'
it 'denies download when no private token' do
download_file(file_name: package_file.file_name)
@@ -482,12 +466,7 @@ RSpec.describe API::MavenPackages do
shared_examples 'getting a file for a group' do
it_behaves_like 'tracking the file download event'
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it_behaves_like 'successfully returning the file'
it 'denies download when not enough permissions' do
group.add_guest(user)
@@ -516,12 +495,7 @@ RSpec.describe API::MavenPackages do
context 'with group deploy token' do
subject { download_file_with_token(file_name: package_file.file_name, request_headers: group_deploy_token_headers) }
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it_behaves_like 'successfully returning the file'
it 'returns the file with only write_package_registry scope' do
deploy_token_for_group.update!(read_package_registry: false)
@@ -553,12 +527,7 @@ RSpec.describe API::MavenPackages do
group.add_reporter(user)
end
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it_behaves_like 'successfully returning the file'
context 'with a non existing maven path' do
subject { download_file_with_token(file_name: package_file.file_name, path: 'foo/bar/1.2.3', request_headers: headers_with_token, group_id: root_group.id) }
@@ -657,12 +626,7 @@ RSpec.describe API::MavenPackages do
it_behaves_like 'tracking the file download event'
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it_behaves_like 'successfully returning the file'
it 'returns sha1 of the file' do
download_file(file_name: package_file.file_name + '.sha1')
@@ -672,6 +636,19 @@ RSpec.describe API::MavenPackages do
expect(response.body).to eq(package_file.file_sha1)
end
+ context 'when the repository is disabled' do
+ before do
+ project.project_feature.update!(
+ # Disable merge_requests and builds as well, since merge_requests and
+ # builds cannot have higher visibility than repository.
+ merge_requests_access_level: ProjectFeature::DISABLED,
+ builds_access_level: ProjectFeature::DISABLED,
+ repository_access_level: ProjectFeature::DISABLED)
+ end
+
+ it_behaves_like 'successfully returning the file'
+ end
+
context 'with a non existing maven path' do
subject { download_file(file_name: package_file.file_name, path: 'foo/bar/1.2.3') }
@@ -688,12 +665,7 @@ RSpec.describe API::MavenPackages do
it_behaves_like 'tracking the file download event'
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it_behaves_like 'successfully returning the file'
it 'denies download when not enough permissions' do
project.add_guest(user)
diff --git a/spec/support/helpers/x509_helpers.rb b/spec/support/helpers/x509_helpers.rb
index ce0fa268ace..1dc8b1d4845 100644
--- a/spec/support/helpers/x509_helpers.rb
+++ b/spec/support/helpers/x509_helpers.rb
@@ -290,6 +290,17 @@ module X509Helpers
SIGNEDDATA
end
+ def unsigned_tag_base_data
+ <<~SIGNEDDATA
+ object 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ type commit
+ tag v1.0.0
+ tagger Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> 1393491299 +0200
+
+ Release
+ SIGNEDDATA
+ end
+
def certificate_crl
'http://ch.siemens.com/pki?ZZZZZZA2.crl'
end
diff --git a/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb b/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb
index cf38a583944..78aa4b0b809 100644
--- a/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb
+++ b/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb
@@ -13,6 +13,7 @@ RSpec.shared_examples 'value stream analytics stage' do
describe 'associations' do
it { is_expected.to belong_to(:end_event_label) }
it { is_expected.to belong_to(:start_event_label) }
+ it { is_expected.to belong_to(:stage_event_hash) }
end
describe 'validation' do
@@ -138,6 +139,67 @@ RSpec.shared_examples 'value stream analytics stage' do
expect(stage_1.events_hash_code).not_to eq(stage_2.events_hash_code)
end
end
+
+ # rubocop: disable Rails/SaveBang
+ describe '#event_hash' do
+ it 'associates the same stage event hash record' do
+ first = create(factory)
+ second = create(factory)
+
+ expect(first.stage_event_hash_id).to eq(second.stage_event_hash_id)
+ end
+
+ it 'does not introduce duplicated stage event hash records' do
+ expect do
+ create(factory)
+ create(factory)
+ end.to change { Analytics::CycleAnalytics::StageEventHash.count }.from(0).to(1)
+ end
+
+ it 'creates different hash record for different event configurations' do
+ expect do
+ create(factory, start_event_identifier: :issue_created, end_event_identifier: :issue_first_mentioned_in_commit)
+ create(factory, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged)
+ end.to change { Analytics::CycleAnalytics::StageEventHash.count }.from(0).to(2)
+ end
+
+ context 'when the stage event hash changes' do
+ let(:stage) { create(factory, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) }
+
+ it 'deletes the old, unused stage event hash record' do
+ old_stage_event_hash = stage.stage_event_hash
+
+ stage.update!(end_event_identifier: :merge_request_first_deployed_to_production)
+
+ expect(stage.stage_event_hash_id).not_to eq(old_stage_event_hash.id)
+
+ old_stage_event_hash_from_db = Analytics::CycleAnalytics::StageEventHash.find_by_id(old_stage_event_hash.id)
+ expect(old_stage_event_hash_from_db).to be_nil
+ end
+
+ it 'does not delete used stage event hash record' do
+ other_stage = create(factory, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged)
+
+ stage.update!(end_event_identifier: :merge_request_first_deployed_to_production)
+
+ expect(stage.stage_event_hash_id).not_to eq(other_stage.stage_event_hash_id)
+
+ old_stage_event_hash_from_db = Analytics::CycleAnalytics::StageEventHash.find_by_id(other_stage.stage_event_hash_id)
+ expect(old_stage_event_hash_from_db).not_to be_nil
+ end
+ end
+
+ context 'when the stage events hash code does not change' do
+ it 'does not trigger extra query on save' do
+ stage = create(factory, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged)
+
+ expect(Analytics::CycleAnalytics::StageEventHash).not_to receive(:record_id_by_hash_sha256)
+
+ stage.update!(name: 'new title')
+ end
+ end
+ end
+ # rubocop: enable Rails/SaveBang
end
RSpec.shared_examples 'value stream analytics label based stage' do
diff --git a/spec/support/shared_examples/policies/project_policy_shared_examples.rb b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
index 013c9b61b99..a4243db6bc9 100644
--- a/spec/support/shared_examples/policies/project_policy_shared_examples.rb
+++ b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
@@ -330,3 +330,18 @@ RSpec.shared_examples 'project policies as admin without admin mode' do
end
end
end
+
+RSpec.shared_examples 'package access with repository disabled' do
+ context 'when repository is disabled' do
+ before do
+ project.project_feature.update!(
+ # Disable merge_requests and builds as well, since merge_requests and
+ # builds cannot have higher visibility than repository.
+ merge_requests_access_level: ProjectFeature::DISABLED,
+ builds_access_level: ProjectFeature::DISABLED,
+ repository_access_level: ProjectFeature::DISABLED)
+ end
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+end
diff --git a/spec/workers/web_hook_worker_spec.rb b/spec/workers/web_hook_worker_spec.rb
index a86964aa417..0f40177eb7d 100644
--- a/spec/workers/web_hook_worker_spec.rb
+++ b/spec/workers/web_hook_worker_spec.rb
@@ -15,6 +15,10 @@ RSpec.describe WebHookWorker do
subject.perform(project_hook.id, data, hook_name)
end
+ it 'does not error when the WebHook record cannot be found' do
+ expect { subject.perform(non_existing_record_id, data, hook_name) }.not_to raise_error
+ end
+
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :delayed