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>2022-11-09 18:07:50 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-11-09 18:07:50 +0300
commite38a99eb0725697297386dd0bb1045b1fd55493a (patch)
treee6298122cbb5418f59c140f4f9e303abdc0739b5 /spec
parent7c41737ae53e3a237f356480ae04ec3ba182447b (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/frontend/boards/components/board_filtered_search_spec.js9
-rw-r--r--spec/frontend/boards/mock_data.js21
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js8
-rw-r--r--spec/helpers/users_helper_spec.rb2
-rw-r--r--spec/lib/feature/gitaly_spec.rb229
-rw-r--r--spec/lib/gitlab/application_context_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/config/external/file/base_spec.rb22
-rw-r--r--spec/lib/gitlab/git/object_pool_spec.rb66
-rw-r--r--spec/lib/gitlab/gitaly_client/with_feature_flag_actors_spec.rb210
-rw-r--r--spec/lib/gitlab/gitaly_client_spec.rb90
-rw-r--r--spec/lib/gitlab/slash_commands/application_help_spec.rb22
-rw-r--r--spec/lib/gitlab/slash_commands/command_spec.rb20
-rw-r--r--spec/lib/gitlab/slash_commands/incident_management/incident_new_spec.rb60
-rw-r--r--spec/lib/gitlab/slash_commands/presenters/incident_management/incident_new_spec.rb15
-rw-r--r--spec/migrations/sync_new_amount_used_for_ci_namespace_monthly_usages_spec.rb42
-rw-r--r--spec/migrations/sync_new_amount_used_for_ci_project_monthly_usages_spec.rb42
-rw-r--r--spec/models/clusters/applications/cert_manager_spec.rb5
-rw-r--r--spec/models/clusters/applications/crossplane_spec.rb5
-rw-r--r--spec/models/clusters/applications/helm_spec.rb4
-rw-r--r--spec/models/clusters/applications/ingress_spec.rb5
-rw-r--r--spec/models/clusters/applications/jupyter_spec.rb4
-rw-r--r--spec/models/clusters/applications/knative_spec.rb4
-rw-r--r--spec/models/clusters/applications/prometheus_spec.rb7
-rw-r--r--spec/models/clusters/applications/runner_spec.rb4
-rw-r--r--spec/models/clusters/cluster_spec.rb4
-rw-r--r--spec/models/clusters/integrations/prometheus_spec.rb10
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb6
-rw-r--r--spec/models/clusters/providers/aws_spec.rb2
-rw-r--r--spec/models/clusters/providers/gcp_spec.rb3
-rw-r--r--spec/support/shared_examples/lib/cache_helpers_shared_examples.rb1
-rw-r--r--spec/support/shared_examples/lib/gitlab/gitaly_client_shared_examples.rb46
-rw-r--r--spec/workers/repository_check/single_repository_worker_spec.rb10
32 files changed, 910 insertions, 76 deletions
diff --git a/spec/frontend/boards/components/board_filtered_search_spec.js b/spec/frontend/boards/components/board_filtered_search_spec.js
index 1a07b9f0b78..f1113ee3073 100644
--- a/spec/frontend/boards/components/board_filtered_search_spec.js
+++ b/spec/frontend/boards/components/board_filtered_search_spec.js
@@ -3,7 +3,10 @@ import Vue from 'vue';
import Vuex from 'vuex';
import BoardFilteredSearch from '~/boards/components/board_filtered_search.vue';
import * as urlUtility from '~/lib/utils/url_utility';
-import { __ } from '~/locale';
+import {
+ TOKEN_TITLE_AUTHOR,
+ TOKEN_TITLE_LABEL,
+} from '~/vue_shared/components/filtered_search_bar/constants';
import FilteredSearchBarRoot from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
@@ -17,7 +20,7 @@ describe('BoardFilteredSearch', () => {
const tokens = [
{
icon: 'labels',
- title: __('Label'),
+ title: TOKEN_TITLE_LABEL,
type: 'label',
operators: [
{ value: '=', description: 'is' },
@@ -30,7 +33,7 @@ describe('BoardFilteredSearch', () => {
},
{
icon: 'pencil',
- title: __('Author'),
+ title: TOKEN_TITLE_AUTHOR,
type: 'author',
operators: [
{ value: '=', description: 'is' },
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index 17dcf5868a2..c99ae118db7 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -1,7 +1,14 @@
import { GlFilteredSearchToken } from '@gitlab/ui';
import { keyBy } from 'lodash';
import { ListType } from '~/boards/constants';
-import { __ } from '~/locale';
+import {
+ TOKEN_TITLE_ASSIGNEE,
+ TOKEN_TITLE_AUTHOR,
+ TOKEN_TITLE_LABEL,
+ TOKEN_TITLE_MILESTONE,
+ TOKEN_TITLE_RELEASE,
+ TOKEN_TITLE_TYPE,
+} from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
@@ -742,7 +749,7 @@ export const mockConfidentialToken = {
export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedIn) => [
{
icon: 'user',
- title: __('Assignee'),
+ title: TOKEN_TITLE_ASSIGNEE,
type: 'assignee',
operators: [
{ value: '=', description: 'is' },
@@ -755,7 +762,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedI
},
{
icon: 'pencil',
- title: __('Author'),
+ title: TOKEN_TITLE_AUTHOR,
type: 'author',
operators: [
{ value: '=', description: 'is' },
@@ -769,7 +776,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedI
},
{
icon: 'labels',
- title: __('Label'),
+ title: TOKEN_TITLE_LABEL,
type: 'label',
operators: [
{ value: '=', description: 'is' },
@@ -783,7 +790,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedI
...(isSignedIn ? [mockEmojiToken, mockConfidentialToken] : []),
{
icon: 'clock',
- title: __('Milestone'),
+ title: TOKEN_TITLE_MILESTONE,
symbol: '%',
type: 'milestone',
shouldSkipSort: true,
@@ -793,7 +800,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedI
},
{
icon: 'issues',
- title: __('Type'),
+ title: TOKEN_TITLE_TYPE,
type: 'type',
token: GlFilteredSearchToken,
unique: true,
@@ -804,7 +811,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedI
},
{
type: 'release',
- title: __('Release'),
+ title: TOKEN_TITLE_RELEASE,
icon: 'rocket',
token: ReleaseToken,
fetchReleases: expect.any(Function),
diff --git a/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js b/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js
index d85574262fe..8eeba4d6274 100644
--- a/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import MergeChecksFailed from '~/vue_merge_request_widget/components/states/merge_checks_failed.vue';
+import { DETAILED_MERGE_STATUS } from '~/vue_merge_request_widget/constants';
let wrapper;
@@ -15,9 +16,10 @@ describe('Merge request widget merge checks failed state component', () => {
});
it.each`
- mrState | displayText
- ${{ approvals: true, isApproved: false }} | ${'approvalNeeded'}
- ${{ detailedMergeStatus: 'BLOCKED_STATUS' }} | ${'blockingMergeRequests'}
+ mrState | displayText
+ ${{ approvals: true, isApproved: false }} | ${'approvalNeeded'}
+ ${{ detailedMergeStatus: DETAILED_MERGE_STATUS.BLOCKED_STATUS }} | ${'blockingMergeRequests'}
+ ${{ detailedMergeStatus: DETAILED_MERGE_STATUS.EXTERNAL_STATUS_CHECKS }} | ${'externalStatusChecksFailed'}
`('display $displayText text for $mrState', ({ mrState, displayText }) => {
factory({ mr: mrState });
diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb
index 6971ec83ce2..c2c78be6a0f 100644
--- a/spec/helpers/users_helper_spec.rb
+++ b/spec/helpers/users_helper_spec.rb
@@ -391,7 +391,7 @@ RSpec.describe UsersHelper do
expect_next_instance_of(Admin::UserSerializer) do |instance|
expect(instance).to receive(:represent).with([user], { current_user: user }).and_return(entity)
end
- expect(entity).to receive(:as_json).and_return({ "username" => "admin" })
+ expect(entity).to receive(:to_json).and_return("{\"username\":\"admin\"}")
expect(data[:users]).to eq "{\"username\":\"admin\"}"
end
diff --git a/spec/lib/feature/gitaly_spec.rb b/spec/lib/feature/gitaly_spec.rb
index ed80e31e3cd..33696290483 100644
--- a/spec/lib/feature/gitaly_spec.rb
+++ b/spec/lib/feature/gitaly_spec.rb
@@ -6,73 +6,207 @@ RSpec.describe Feature::Gitaly do
let_it_be(:project) { create(:project) }
let_it_be(:project_2) { create(:project) }
+ let_it_be(:repository) { project.repository.raw }
+ let_it_be(:repository_2) { project_2.repository.raw }
+
before do
skip_feature_flags_yaml_validation
+ allow(Feature::Definition).to receive(:get).with(any_args).and_return(
+ Feature::Definition.new('flag.yml', name: :flag, type: :development)
+ )
end
- describe ".enabled?" do
+ describe ".enabled_for_any?" do
context 'when the flag is set globally' do
- let(:feature_flag) { 'global_flag' }
-
context 'when the gate is closed' do
before do
stub_feature_flags(gitaly_global_flag: false)
end
it 'returns false' do
- expect(described_class.enabled?(feature_flag)).to be(false)
+ expect(described_class.enabled_for_any?(:gitaly_global_flag)).to be(false)
end
end
context 'when the flag defaults to on' do
it 'returns true' do
- expect(described_class.enabled?(feature_flag)).to be(true)
+ expect(described_class.enabled_for_any?(:gitaly_global_flag)).to be(true)
end
end
end
context 'when the flag is enabled for a particular project' do
- let(:feature_flag) { 'project_flag' }
-
before do
stub_feature_flags(gitaly_project_flag: project)
end
it 'returns true for that project' do
- expect(described_class.enabled?(feature_flag, project)).to be(true)
+ expect(described_class.enabled_for_any?(:gitaly_project_flag, project)).to be(true)
end
it 'returns false for any other project' do
- expect(described_class.enabled?(feature_flag, project_2)).to be(false)
+ expect(described_class.enabled_for_any?(:gitaly_project_flag, project_2)).to be(false)
end
it 'returns false when no project is passed' do
- expect(described_class.enabled?(feature_flag)).to be(false)
+ expect(described_class.enabled_for_any?(:gitaly_project_flag)).to be(false)
+ end
+ end
+
+ context 'when the flag is enabled for a particular repository' do
+ before do
+ stub_feature_flags(gitaly_repository_flag: repository)
+ end
+
+ it 'returns true for that repository' do
+ expect(described_class.enabled_for_any?(:gitaly_repository_flag, repository)).to be(true)
+ end
+
+ it 'returns false for any other repository' do
+ expect(described_class.enabled_for_any?(:gitaly_repository_flag, repository_2)).to be(false)
+ end
+
+ it 'returns false when no repository is passed' do
+ expect(described_class.enabled_for_any?(:gitaly_repository_flag)).to be(false)
+ end
+ end
+
+ context 'when the flag is checked with multiple input actors' do
+ before do
+ stub_feature_flags(gitaly_flag: repository)
+ end
+
+ it 'returns true if any of the flag is enabled for any of the input actors' do
+ expect(described_class.enabled_for_any?(:gitaly_flag, project, repository)).to be(true)
+ end
+
+ it 'returns false if any of the flag is not enabled for any of the input actors' do
+ expect(
+ described_class.enabled_for_any?(:gitaly_flag, project, project_2, repository_2)
+ ).to be(false)
end
end
end
describe ".server_feature_flags" do
+ let(:group) { create(:group) }
+ let(:user) { create(:user) }
+
before do
- stub_feature_flags(gitaly_global_flag: true, gitaly_project_flag: project, non_gitaly_flag: false)
+ stub_feature_flags(
+ gitaly_global_flag: true,
+ gitaly_project_flag: project,
+ gitaly_repository_flag: repository,
+ gitaly_user_flag: user,
+ gitaly_group_flag: group,
+ non_gitaly_flag: false
+ )
end
subject { described_class.server_feature_flags }
it 'returns a hash of flags starting with the prefix, with dashes instead of underscores' do
expect(subject).to eq('gitaly-feature-global-flag' => 'true',
- 'gitaly-feature-project-flag' => 'false')
+ 'gitaly-feature-project-flag' => 'false',
+ 'gitaly-feature-repository-flag' => 'false',
+ 'gitaly-feature-user-flag' => 'false',
+ 'gitaly-feature-group-flag' => 'false')
end
context 'when a project is passed' do
it 'returns the value for the flag on the given project' do
- expect(described_class.server_feature_flags(project))
+ expect(described_class.server_feature_flags(project: project))
+ .to eq('gitaly-feature-global-flag' => 'true',
+ 'gitaly-feature-project-flag' => 'true',
+ 'gitaly-feature-repository-flag' => 'false',
+ 'gitaly-feature-user-flag' => 'false',
+ 'gitaly-feature-group-flag' => 'false')
+
+ expect(described_class.server_feature_flags(project: project_2))
+ .to eq('gitaly-feature-global-flag' => 'true',
+ 'gitaly-feature-project-flag' => 'false',
+ 'gitaly-feature-repository-flag' => 'false',
+ 'gitaly-feature-user-flag' => 'false',
+ 'gitaly-feature-group-flag' => 'false')
+ end
+ end
+
+ context 'when a repository is passed' do
+ it 'returns the value for the flag on the given repository' do
+ expect(described_class.server_feature_flags(repository: repository))
+ .to eq('gitaly-feature-global-flag' => 'true',
+ 'gitaly-feature-project-flag' => 'false',
+ 'gitaly-feature-repository-flag' => 'true',
+ 'gitaly-feature-user-flag' => 'false',
+ 'gitaly-feature-group-flag' => 'false')
+
+ expect(described_class.server_feature_flags(repository: repository_2))
+ .to eq('gitaly-feature-global-flag' => 'true',
+ 'gitaly-feature-project-flag' => 'false',
+ 'gitaly-feature-repository-flag' => 'false',
+ 'gitaly-feature-user-flag' => 'false',
+ 'gitaly-feature-group-flag' => 'false')
+ end
+ end
+
+ context 'when a user is passed' do
+ it 'returns the value for the flag on the given user' do
+ expect(described_class.server_feature_flags(user: user))
+ .to eq('gitaly-feature-global-flag' => 'true',
+ 'gitaly-feature-project-flag' => 'false',
+ 'gitaly-feature-repository-flag' => 'false',
+ 'gitaly-feature-user-flag' => 'true',
+ 'gitaly-feature-group-flag' => 'false')
+
+ expect(described_class.server_feature_flags(user: create(:user)))
+ .to eq('gitaly-feature-global-flag' => 'true',
+ 'gitaly-feature-project-flag' => 'false',
+ 'gitaly-feature-repository-flag' => 'false',
+ 'gitaly-feature-user-flag' => 'false',
+ 'gitaly-feature-group-flag' => 'false')
+ end
+ end
+
+ context 'when a group is passed' do
+ it 'returns the value for the flag on the given group' do
+ expect(described_class.server_feature_flags(group: group))
.to eq('gitaly-feature-global-flag' => 'true',
- 'gitaly-feature-project-flag' => 'true')
+ 'gitaly-feature-project-flag' => 'false',
+ 'gitaly-feature-repository-flag' => 'false',
+ 'gitaly-feature-user-flag' => 'false',
+ 'gitaly-feature-group-flag' => 'true')
- expect(described_class.server_feature_flags(project_2))
+ expect(described_class.server_feature_flags(group: create(:group)))
.to eq('gitaly-feature-global-flag' => 'true',
- 'gitaly-feature-project-flag' => 'false')
+ 'gitaly-feature-project-flag' => 'false',
+ 'gitaly-feature-repository-flag' => 'false',
+ 'gitaly-feature-user-flag' => 'false',
+ 'gitaly-feature-group-flag' => 'false')
+ end
+ end
+
+ context 'when multiple actors are passed' do
+ it 'returns the corresponding enablement status for actors' do
+ expect(described_class.server_feature_flags(project: project_2, repository: repository))
+ .to eq('gitaly-feature-global-flag' => 'true',
+ 'gitaly-feature-project-flag' => 'false',
+ 'gitaly-feature-repository-flag' => 'true',
+ 'gitaly-feature-user-flag' => 'false',
+ 'gitaly-feature-group-flag' => 'false')
+
+ expect(described_class.server_feature_flags(project: project, repository: repository_2))
+ .to eq('gitaly-feature-global-flag' => 'true',
+ 'gitaly-feature-project-flag' => 'true',
+ 'gitaly-feature-repository-flag' => 'false',
+ 'gitaly-feature-user-flag' => 'false',
+ 'gitaly-feature-group-flag' => 'false')
+
+ expect(described_class.server_feature_flags(user: user, project: project, repository: repository, group: group))
+ .to eq('gitaly-feature-global-flag' => 'true',
+ 'gitaly-feature-project-flag' => 'true',
+ 'gitaly-feature-repository-flag' => 'true',
+ 'gitaly-feature-user-flag' => 'true',
+ 'gitaly-feature-group-flag' => 'true')
end
end
@@ -88,4 +222,67 @@ RSpec.describe Feature::Gitaly do
end
end
end
+
+ describe ".user_actor" do
+ let(:user) { create(:user) }
+
+ context 'when user is passed in' do
+ it 'returns a actor wrapper from user' do
+ expect(described_class.user_actor(user).flipper_id).to eql(user.flipper_id)
+ end
+ end
+
+ context 'when called without user and user_id is available in application context' do
+ it 'returns a actor wrapper from user_id' do
+ ::Gitlab::ApplicationContext.with_context(user: user) do
+ expect(described_class.user_actor.flipper_id).to eql(user.flipper_id)
+ end
+ end
+ end
+
+ context 'when called without user and user_id is absent from application context' do
+ it 'returns nil' do
+ expect(described_class.user_actor).to be(nil)
+ end
+ end
+
+ context 'when something else is passed' do
+ it 'returns nil' do
+ expect(described_class.user_actor(1234)).to be(nil)
+ end
+ end
+ end
+
+ describe ".project_actor" do
+ let_it_be(:project) { create(:project) }
+
+ context 'when project is passed in' do
+ it 'returns a actor wrapper from project' do
+ expect(described_class.project_actor(project).flipper_id).to eql(project.flipper_id)
+ end
+ end
+
+ context 'when something else is passed in' do
+ it 'returns nil' do
+ expect(described_class.project_actor(1234)).to be(nil)
+ end
+ end
+ end
+
+ describe ".group_actor" do
+ let_it_be(:group) { create(:group ) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ context 'when project is passed in' do
+ it "returns a actor wrapper from project's group" do
+ expect(described_class.group_actor(project).flipper_id).to eql(group.flipper_id)
+ end
+ end
+
+ context 'when something else is passed in' do
+ it 'returns nil' do
+ expect(described_class.group_actor(1234)).to be(nil)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/application_context_spec.rb b/spec/lib/gitlab/application_context_spec.rb
index 8b2a228b935..58d462aa27f 100644
--- a/spec/lib/gitlab/application_context_spec.rb
+++ b/spec/lib/gitlab/application_context_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe Gitlab::ApplicationContext do
describe '.push' do
it 'passes the expected context on to labkit' do
fake_proc = duck_type(:call)
- expected_context = { user: fake_proc, client_id: fake_proc }
+ expected_context = { user: fake_proc, user_id: fake_proc, client_id: fake_proc }
expect(Labkit::Context).to receive(:push).with(expected_context)
@@ -108,14 +108,16 @@ RSpec.describe Gitlab::ApplicationContext do
context = described_class.new(user: -> { user }, project: -> { project }, namespace: -> { subgroup })
expect(result(context))
- .to include(user: user.username, project: project.full_path, root_namespace: namespace.full_path)
+ .to include(user: user.username, user_id: user.id, project: project.full_path,
+ root_namespace: namespace.full_path)
end
it 'correctly loads the expected values when passed directly' do
context = described_class.new(user: user, project: project, namespace: subgroup)
expect(result(context))
- .to include(user: user.username, project: project.full_path, root_namespace: namespace.full_path)
+ .to include(user: user.username, user_id: user.id, project: project.full_path,
+ root_namespace: namespace.full_path)
end
it 'falls back to a projects namespace when a project is passed but no namespace' do
diff --git a/spec/lib/gitlab/ci/config/external/file/base_spec.rb b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
index 1306d61d99c..8475c3a8b19 100644
--- a/spec/lib/gitlab/ci/config/external/file/base_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
@@ -14,6 +14,10 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base do
super
end
+
+ def validate_context!
+ # no-op
+ end
end
end
@@ -95,6 +99,24 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base do
expect(file.error_message).to eq('Included file `some/file/xxxxxxxxxxxxxxxx.yml` does not have valid YAML syntax!')
end
end
+
+ context 'when the class has no validate_context!' do
+ let(:test_class) do
+ Class.new(described_class) do
+ def initialize(params, context)
+ @location = params
+
+ super
+ end
+ end
+ end
+
+ let(:location) { 'some/file/config.yaml' }
+
+ it 'raises an error' do
+ expect { valid? }.to raise_error(NotImplementedError)
+ end
+ end
end
describe '#to_hash' do
diff --git a/spec/lib/gitlab/git/object_pool_spec.rb b/spec/lib/gitlab/git/object_pool_spec.rb
index 3b1eb0319f8..b158c7227d4 100644
--- a/spec/lib/gitlab/git/object_pool_spec.rb
+++ b/spec/lib/gitlab/git/object_pool_spec.rb
@@ -78,44 +78,40 @@ RSpec.describe Gitlab::Git::ObjectPool do
end
describe '#fetch' do
- let(:commit_count) { source_repository.commit_count }
+ context 'when the object pool repository exists' do
+ let!(:pool_repository) { create(:pool_repository, :ready) }
- context "when the object's pool repository exists" do
- it 'does not raise an error' do
- expect { subject.fetch }.not_to raise_error
+ context 'without changes' do
+ it 'does not raise an error' do
+ expect { subject.fetch }.not_to raise_error
+ end
end
- end
-
- context "when the object's pool repository does not exist" do
- before do
- subject.delete
- end
-
- it "re-creates the object pool's repository" do
- subject.fetch
-
- expect(subject.repository.exists?).to be true
- end
-
- it 'does not raise an error' do
- expect { subject.fetch }.not_to raise_error
- end
-
- it 'fetches objects from the source repository' do
- new_commit_id = source_repository.create_file(
- pool_repository.source_project.owner,
- 'a.file',
- 'This is a file',
- branch_name: source_repository.root_ref,
- message: 'Add a file'
- )
-
- expect(subject.repository.exists?).to be false
-
- subject.fetch
- expect(subject.repository.commit_count('refs/remotes/origin/heads/master')).to eq(commit_count)
- expect(subject.repository.commit(new_commit_id).id).to eq(new_commit_id)
+ context 'with new commit in source repository' do
+ let(:branch_name) { Gitlab::Git::Ref.extract_branch_name(source_repository.root_ref) }
+ let(:source_ref_name) { "refs/heads/#{branch_name}" }
+ let(:pool_ref_name) { "refs/remotes/origin/heads/#{branch_name}" }
+
+ let(:new_commit_id) do
+ source_repository.create_file(
+ pool_repository.source_project.owner,
+ 'a.file',
+ 'This is a file',
+ branch_name: branch_name,
+ message: 'Add a file'
+ )
+ end
+
+ it 'fetches objects from the source repository' do
+ # Sanity-check that the commit does not yet exist in the pool repository.
+ expect(subject.repository.commit(new_commit_id)).to be_nil
+
+ subject.fetch
+
+ expect(subject.repository.commit(pool_ref_name).id).to eq(new_commit_id)
+ expect(subject.repository.commit_count(pool_ref_name))
+ .to eq(source_repository.raw_repository.commit_count(source_ref_name))
+ end
end
end
end
diff --git a/spec/lib/gitlab/gitaly_client/with_feature_flag_actors_spec.rb b/spec/lib/gitlab/gitaly_client/with_feature_flag_actors_spec.rb
new file mode 100644
index 00000000000..dd54ac0c6ac
--- /dev/null
+++ b/spec/lib/gitlab/gitaly_client/with_feature_flag_actors_spec.rb
@@ -0,0 +1,210 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GitalyClient::WithFeatureFlagActors do
+ let(:user) { create(:user) }
+ let(:service) do
+ Class.new do
+ include Gitlab::GitalyClient::WithFeatureFlagActors
+ end.new
+ end
+
+ describe '#user_actor' do
+ context 'when user is not available in ApplicationContext' do
+ it 'returns nil' do
+ expect(service.user_actor).to be(nil)
+ end
+ end
+
+ context 'when user is available in ApplicationContext' do
+ around do |example|
+ ::Gitlab::ApplicationContext.with_context(user: user) { example.run }
+ end
+
+ it 'returns corresponding user record' do
+ expect(service.user_actor.flipper_id).to eql(user.flipper_id)
+ end
+ end
+
+ context 'when user does not exist' do
+ around do |example|
+ ::Gitlab::ApplicationContext.with_context(user: SecureRandom.uuid) { example.run }
+ end
+
+ it 'returns corresponding user record' do
+ expect(service.user_actor).to be(nil)
+ end
+ end
+ end
+
+ describe '#repository, #project_actor, #group_actor' do
+ context 'when normal project repository' do
+ let_it_be(:project) { create(:project, group: create(:group)) }
+ let(:expected_project) { project }
+ let(:expected_group) { Feature::Gitaly::ActorWrapper.new(::Group, project.group.id) }
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { project.repository }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { project.repository.raw }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { raw_repo_without_container(project.repository) }
+ end
+ end
+
+ context 'when project wiki repository' do
+ let_it_be(:project) { create(:project, :wiki_repo, group: create(:group)) }
+ let(:expected_project) { nil }
+ let(:expected_group) { nil }
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { project.wiki.repository }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { project.wiki.repository.raw }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { raw_repo_without_container(project.wiki.repository) }
+ end
+ end
+
+ context 'when repository of project in user namespace' do
+ let_it_be(:project) { create(:project, namespace: create(:user).namespace) }
+ let(:expected_project) { project }
+ let(:expected_group) { Feature::Gitaly::ActorWrapper.new(::Group, project.namespace_id) }
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { project.repository }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { project.repository.raw }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { raw_repo_without_container(project.repository) }
+ end
+ end
+
+ context 'when personal snippet' do
+ let(:snippet) { create(:personal_snippet) }
+ let(:expected_project) { nil }
+ let(:expected_group) { nil }
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { snippet.repository }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { snippet.repository.raw }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { raw_repo_without_container(snippet.repository) }
+ end
+ end
+
+ context 'when project snippet' do
+ let_it_be(:project) { create(:project, group: create(:group)) }
+ let(:snippet) { create(:project_snippet, project: project) }
+ let(:expected_project) { nil }
+ let(:expected_group) { nil }
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { snippet.repository }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { snippet.repository.raw }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { raw_repo_without_container(snippet.repository) }
+ end
+ end
+
+ context 'when project design' do
+ let_it_be(:project) { create(:project, group: create(:group)) }
+ let(:issue) { create(:issue, project: project) }
+ let(:design) { create(:design, issue: issue) }
+
+ let(:expected_project) { project }
+ let(:expected_group) { project.group }
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { design.repository }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { design.repository.raw }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { raw_repo_without_container(design.repository) }
+ end
+ end
+ end
+
+ describe '#gitaly_client_call' do
+ let(:call_arg_1) { double }
+ let(:call_arg_2) { double }
+ let(:call_arg_3) { double }
+ let(:call_result) { double }
+
+ before do
+ allow(Gitlab::GitalyClient).to receive(:call).and_return(call_result)
+ end
+
+ context 'when actors_aware_gitaly_calls flag is enabled' do
+ let(:repository_actor) { instance_double(::Repository) }
+ let(:user_actor) { instance_double(::User) }
+ let(:project_actor) { instance_double(Project) }
+ let(:group_actor) { instance_double(Group) }
+
+ before do
+ stub_feature_flags(actors_aware_gitaly_calls: true)
+
+ allow(service).to receive(:user_actor).and_return(user_actor)
+ allow(service).to receive(:repository_actor).and_return(repository_actor)
+ allow(service).to receive(:project_actor).and_return(project_actor)
+ allow(service).to receive(:group_actor).and_return(group_actor)
+ allow(Gitlab::GitalyClient).to receive(:with_feature_flag_actors).and_call_original
+ end
+
+ it 'triggers client call with feature flag actors' do
+ result = service.gitaly_client_call(call_arg_1, call_arg_2, karg: call_arg_3)
+
+ expect(Gitlab::GitalyClient).to have_received(:call).with(call_arg_1, call_arg_2, karg: call_arg_3)
+ expect(Gitlab::GitalyClient).to have_received(:with_feature_flag_actors).with(
+ repository: repository_actor,
+ user: user_actor,
+ project: project_actor,
+ group: group_actor
+ )
+ expect(result).to be(call_result)
+ end
+ end
+
+ context 'when actors_aware_gitaly_calls not enabled' do
+ before do
+ stub_feature_flags(actors_aware_gitaly_calls: false)
+ end
+
+ it 'triggers client call without feature flag actors' do
+ expect(Gitlab::GitalyClient).not_to receive(:with_feature_flag_actors)
+
+ result = service.gitaly_client_call(call_arg_1, call_arg_2, karg: call_arg_3)
+
+ expect(Gitlab::GitalyClient).to have_received(:call).with(call_arg_1, call_arg_2, karg: call_arg_3)
+ expect(result).to be(call_result)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/gitaly_client_spec.rb b/spec/lib/gitlab/gitaly_client_spec.rb
index a3840ca843f..a3b2fb2d9d0 100644
--- a/spec/lib/gitlab/gitaly_client_spec.rb
+++ b/spec/lib/gitlab/gitaly_client_spec.rb
@@ -259,6 +259,58 @@ RSpec.describe Gitlab::GitalyClient do
end
end
+ shared_examples 'gitaly feature flags in metadata' do
+ before do
+ allow(Feature::Gitaly).to receive(:server_feature_flags).and_return(
+ 'gitaly-feature-a' => 'true',
+ 'gitaly-feature-b' => 'false'
+ )
+ end
+
+ it 'evaluates Gitaly server feature flags' do
+ metadata = described_class.request_kwargs('default', timeout: 1)[:metadata]
+
+ expect(Feature::Gitaly).to have_received(:server_feature_flags).with(no_args)
+ expect(metadata['gitaly-feature-a']).to be('true')
+ expect(metadata['gitaly-feature-b']).to be('false')
+ end
+
+ context 'when there are actors' do
+ let(:repository_actor) { double(:actor) }
+ let(:project_actor) { double(:actor) }
+ let(:user_actor) { double(:actor) }
+ let(:group_actor) { double(:actor) }
+
+ it 'evaluates Gitaly server feature flags with actors' do
+ metadata = described_class.with_feature_flag_actors(
+ repository: repository_actor,
+ project: project_actor,
+ user: user_actor,
+ group: group_actor
+ ) do
+ described_class.request_kwargs('default', timeout: 1)[:metadata]
+ end
+
+ expect(Feature::Gitaly).to have_received(:server_feature_flags).with(
+ repository: repository_actor,
+ project: project_actor,
+ user: user_actor,
+ group: group_actor
+ )
+ expect(metadata['gitaly-feature-a']).to be('true')
+ expect(metadata['gitaly-feature-b']).to be('false')
+ end
+ end
+ end
+
+ context 'server_feature_flags when RequestStore is activated', :request_store do
+ it_behaves_like 'gitaly feature flags in metadata'
+ end
+
+ context 'server_feature_flags when RequestStore is not activated' do
+ it_behaves_like 'gitaly feature flags in metadata'
+ end
+
context 'gitlab_git_env' do
let(:policy) { 'gitaly-route-repository-accessor-policy' }
@@ -585,4 +637,42 @@ RSpec.describe Gitlab::GitalyClient do
end
end
end
+
+ describe '.with_feature_flag_actor', :request_store do
+ shared_examples 'with_feature_flag_actor' do
+ let(:repository_actor) { double(:actor) }
+ let(:project_actor) { double(:actor) }
+ let(:user_actor) { double(:actor) }
+ let(:group_actor) { double(:actor) }
+
+ it 'allows access to feature flag actors inside the block' do
+ expect(described_class.feature_flag_actors).to eql({})
+
+ described_class.with_feature_flag_actors(
+ repository: repository_actor,
+ project: project_actor,
+ user: user_actor,
+ group: group_actor
+ ) do
+ expect(
+ described_class.feature_flag_actors
+ ).to eql(
+ repository: repository_actor,
+ project: project_actor,
+ user: user_actor,
+ group: group_actor)
+ end
+
+ expect(described_class.feature_flag_actors).to eql({})
+ end
+ end
+
+ context 'when RequestStore is activated', :request_store do
+ it_behaves_like 'with_feature_flag_actor'
+ end
+
+ context 'when RequestStore is not activated' do
+ it_behaves_like 'with_feature_flag_actor'
+ end
+ end
end
diff --git a/spec/lib/gitlab/slash_commands/application_help_spec.rb b/spec/lib/gitlab/slash_commands/application_help_spec.rb
index b82121bf3a8..b182c0e5cc6 100644
--- a/spec/lib/gitlab/slash_commands/application_help_spec.rb
+++ b/spec/lib/gitlab/slash_commands/application_help_spec.rb
@@ -4,11 +4,13 @@ require 'spec_helper'
RSpec.describe Gitlab::SlashCommands::ApplicationHelp do
let(:params) { { command: '/gitlab', text: 'help' } }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:chat_user) { create(:chat_name, user: user) }
let(:project) { build(:project) }
describe '#execute' do
subject do
- described_class.new(project, params).execute
+ described_class.new(project, chat_user, params).execute
end
it 'displays the help section' do
@@ -16,5 +18,23 @@ RSpec.describe Gitlab::SlashCommands::ApplicationHelp do
expect(subject[:text]).to include('Available commands')
expect(subject[:text]).to include('/gitlab [project name or alias] issue show')
end
+
+ context 'with incident declare command' do
+ context 'when feature flag is enabled' do
+ it 'displays the declare command' do
+ expect(subject[:text]).to include('/gitlab incident declare')
+ end
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(incident_declare_slash_command: false)
+ end
+
+ it 'does not displays the declare command' do
+ expect(subject[:text]).not_to include('/gitlab incident declare')
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/slash_commands/command_spec.rb b/spec/lib/gitlab/slash_commands/command_spec.rb
index 069577b3846..f4664bcfef9 100644
--- a/spec/lib/gitlab/slash_commands/command_spec.rb
+++ b/spec/lib/gitlab/slash_commands/command_spec.rb
@@ -122,5 +122,25 @@ RSpec.describe Gitlab::SlashCommands::Command do
it { is_expected.to eq(Gitlab::SlashCommands::IssueComment) }
end
+
+ context 'when incident declare is triggered' do
+ context 'IncidentNew is triggered' do
+ let(:params) { { text: 'incident declare' } }
+
+ it { is_expected.to eq(Gitlab::SlashCommands::IncidentManagement::IncidentNew) }
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(incident_declare_slash_command: false)
+ end
+
+ context 'IncidentNew is triggered' do
+ let(:params) { { text: 'incident declare' } }
+
+ it { is_expected.not_to eq(Gitlab::SlashCommands::IncidentManagement::IncidentNew) }
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/slash_commands/incident_management/incident_new_spec.rb b/spec/lib/gitlab/slash_commands/incident_management/incident_new_spec.rb
new file mode 100644
index 00000000000..ee54f29aec7
--- /dev/null
+++ b/spec/lib/gitlab/slash_commands/incident_management/incident_new_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::SlashCommands::IncidentManagement::IncidentNew do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:chat_name) { create(:chat_name, user: user) }
+ let_it_be(:regex_match) { described_class.match('declare') }
+
+ subject do
+ described_class.new(project, chat_name)
+ end
+
+ describe '#execute' do
+ context 'when invoked' do
+ it 'sends ephemeral response' do
+ response = subject.execute(regex_match)
+
+ expect(response[:response_type]).to be(:ephemeral)
+ expect(response[:text]).to eq('It works!')
+ end
+ end
+ end
+
+ describe '#allowed?' do
+ context 'when user has permissions' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'returns true' do
+ expect(described_class).to be_allowed(project, user)
+ end
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ project.add_developer(user)
+ stub_feature_flags(incident_declare_slash_command: false)
+ end
+
+ it 'returns false in allowed?' do
+ expect(described_class).not_to be_allowed(project, user)
+ end
+ end
+ end
+
+ describe '#collection' do
+ context 'when collection method id called' do
+ it 'calls IssuesFinder' do
+ expect_next_instance_of(IssuesFinder) do |finder|
+ expect(finder).to receive(:execute)
+ end
+
+ subject.collection
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/slash_commands/presenters/incident_management/incident_new_spec.rb b/spec/lib/gitlab/slash_commands/presenters/incident_management/incident_new_spec.rb
new file mode 100644
index 00000000000..cbc584b931f
--- /dev/null
+++ b/spec/lib/gitlab/slash_commands/presenters/incident_management/incident_new_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::SlashCommands::Presenters::IncidentManagement::IncidentNew do
+ subject { described_class.new }
+
+ it 'returns the ephemeral message' do
+ message = subject.present('It works!')
+
+ expect(message).to be_a(Hash)
+ expect(message[:text]).to eq('It works!')
+ expect(message[:response_type]).to be(:ephemeral)
+ end
+end
diff --git a/spec/migrations/sync_new_amount_used_for_ci_namespace_monthly_usages_spec.rb b/spec/migrations/sync_new_amount_used_for_ci_namespace_monthly_usages_spec.rb
new file mode 100644
index 00000000000..9a17f375f82
--- /dev/null
+++ b/spec/migrations/sync_new_amount_used_for_ci_namespace_monthly_usages_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe SyncNewAmountUsedForCiNamespaceMonthlyUsages, migration: :gitlab_ci do
+ let(:namespace_usages) { table(:ci_namespace_monthly_usages) }
+
+ before do
+ # Disabling the trigger temporarily to allow records being created with out-of-sync
+ # `new_amount_used` and `amount_used`. This will simulate existing records before
+ # we add the trigger.
+ ActiveRecord::Base.connection
+ .execute("ALTER TABLE ci_namespace_monthly_usages DISABLE TRIGGER sync_namespaces_amount_used_columns")
+
+ this_month = Time.now.utc.beginning_of_month
+ last_month = 1.month.ago.utc.beginning_of_month
+ last_year = 1.year.ago.utc.beginning_of_month
+
+ namespace_usages.create!(namespace_id: 1, date: last_year)
+ namespace_usages.create!(namespace_id: 1, date: this_month, amount_used: 10, new_amount_used: 0)
+ namespace_usages.create!(namespace_id: 1, date: last_month, amount_used: 20, new_amount_used: 0)
+
+ namespace_usages.create!(namespace_id: 2, date: last_year)
+ namespace_usages.create!(namespace_id: 2, date: this_month, amount_used: 30, new_amount_used: 0)
+ namespace_usages.create!(namespace_id: 2, date: last_month, amount_used: 40, new_amount_used: 0)
+
+ ActiveRecord::Base.connection
+ .execute("ALTER TABLE ci_namespace_monthly_usages ENABLE TRIGGER sync_namespaces_amount_used_columns")
+ end
+
+ it 'updates `new_amount_used` with values from `amount_used`' do
+ expect(namespace_usages.where(new_amount_used: 0).count).to eq(6)
+
+ migrate!
+
+ expect(namespace_usages.where(new_amount_used: 0).count).to eq(2)
+ expect(namespace_usages.order(:id).pluck(:new_amount_used))
+ .to contain_exactly(0, 0, 10, 20, 30, 40)
+ end
+end
diff --git a/spec/migrations/sync_new_amount_used_for_ci_project_monthly_usages_spec.rb b/spec/migrations/sync_new_amount_used_for_ci_project_monthly_usages_spec.rb
new file mode 100644
index 00000000000..8d45f1107ea
--- /dev/null
+++ b/spec/migrations/sync_new_amount_used_for_ci_project_monthly_usages_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe SyncNewAmountUsedForCiProjectMonthlyUsages, migration: :gitlab_ci do
+ let(:project_usages) { table(:ci_project_monthly_usages) }
+
+ before do
+ # Disabling the trigger temporarily to allow records being created with out-of-sync
+ # `new_amount_used` and `amount_used`. This will simulate existing records before
+ # we add the trigger.
+ ActiveRecord::Base.connection
+ .execute("ALTER TABLE ci_project_monthly_usages DISABLE TRIGGER sync_projects_amount_used_columns")
+
+ this_month = Time.now.utc.beginning_of_month
+ last_month = 1.month.ago.utc.beginning_of_month
+ last_year = 1.year.ago.utc.beginning_of_month
+
+ project_usages.create!(project_id: 1, date: last_year)
+ project_usages.create!(project_id: 1, date: this_month, amount_used: 10, new_amount_used: 0)
+ project_usages.create!(project_id: 1, date: last_month, amount_used: 20, new_amount_used: 0)
+
+ project_usages.create!(project_id: 2, date: last_year)
+ project_usages.create!(project_id: 2, date: this_month, amount_used: 30, new_amount_used: 0)
+ project_usages.create!(project_id: 2, date: last_month, amount_used: 40, new_amount_used: 0)
+
+ ActiveRecord::Base.connection
+ .execute("ALTER TABLE ci_project_monthly_usages ENABLE TRIGGER sync_projects_amount_used_columns")
+ end
+
+ it 'updates `new_amount_used` with values from `amount_used`' do
+ expect(project_usages.where(new_amount_used: 0).count).to eq(6)
+
+ migrate!
+
+ expect(project_usages.where(new_amount_used: 0).count).to eq(2)
+ expect(project_usages.order(:id).pluck(:new_amount_used))
+ .to contain_exactly(0, 0, 10, 20, 30, 40)
+ end
+end
diff --git a/spec/models/clusters/applications/cert_manager_spec.rb b/spec/models/clusters/applications/cert_manager_spec.rb
index 05ab8c4108e..427a99efadd 100644
--- a/spec/models/clusters/applications/cert_manager_spec.rb
+++ b/spec/models/clusters/applications/cert_manager_spec.rb
@@ -10,6 +10,11 @@ RSpec.describe Clusters::Applications::CertManager do
include_examples 'cluster application version specs', :clusters_applications_cert_manager
include_examples 'cluster application initial status specs'
+ describe 'default values' do
+ it { expect(cert_manager.version).to eq(described_class::VERSION) }
+ it { expect(cert_manager.email).to eq("admin@example.com") }
+ end
+
describe '#can_uninstall?' do
subject { cert_manager.can_uninstall? }
diff --git a/spec/models/clusters/applications/crossplane_spec.rb b/spec/models/clusters/applications/crossplane_spec.rb
index 7082576028b..d1abaa52c7f 100644
--- a/spec/models/clusters/applications/crossplane_spec.rb
+++ b/spec/models/clusters/applications/crossplane_spec.rb
@@ -14,6 +14,11 @@ RSpec.describe Clusters::Applications::Crossplane do
it { is_expected.to validate_presence_of(:stack) }
end
+ describe 'default values' do
+ it { expect(subject.version).to eq(described_class::VERSION) }
+ it { expect(subject.stack).to be_empty }
+ end
+
describe '#can_uninstall?' do
subject { crossplane.can_uninstall? }
diff --git a/spec/models/clusters/applications/helm_spec.rb b/spec/models/clusters/applications/helm_spec.rb
index 5212e321a55..1b8be92475a 100644
--- a/spec/models/clusters/applications/helm_spec.rb
+++ b/spec/models/clusters/applications/helm_spec.rb
@@ -5,6 +5,10 @@ require 'spec_helper'
RSpec.describe Clusters::Applications::Helm do
include_examples 'cluster application core specs', :clusters_applications_helm
+ describe 'default values' do
+ it { expect(subject.version).to eq(Gitlab::Kubernetes::Helm::V2::BaseCommand::HELM_VERSION) }
+ end
+
describe '.available' do
subject { described_class.available }
diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb
index e16d97c42d9..e5caa11452e 100644
--- a/spec/models/clusters/applications/ingress_spec.rb
+++ b/spec/models/clusters/applications/ingress_spec.rb
@@ -18,6 +18,11 @@ RSpec.describe Clusters::Applications::Ingress do
allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_async)
end
+ describe 'default values' do
+ it { expect(subject.ingress_type).to eq("nginx") }
+ it { expect(subject.version).to eq(described_class::VERSION) }
+ end
+
describe '#can_uninstall?' do
subject { ingress.can_uninstall? }
diff --git a/spec/models/clusters/applications/jupyter_spec.rb b/spec/models/clusters/applications/jupyter_spec.rb
index e7de2d24334..9336d2352f8 100644
--- a/spec/models/clusters/applications/jupyter_spec.rb
+++ b/spec/models/clusters/applications/jupyter_spec.rb
@@ -10,6 +10,10 @@ RSpec.describe Clusters::Applications::Jupyter do
it { is_expected.to belong_to(:oauth_application) }
+ describe 'default values' do
+ it { expect(subject.version).to eq(described_class::VERSION) }
+ end
+
describe '#can_uninstall?' do
let(:ingress) { create(:clusters_applications_ingress, :installed, external_hostname: 'localhost.localdomain') }
let(:jupyter) { create(:clusters_applications_jupyter, cluster: ingress.cluster) }
diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb
index d0e470bfa42..3914450339a 100644
--- a/spec/models/clusters/applications/knative_spec.rb
+++ b/spec/models/clusters/applications/knative_spec.rb
@@ -21,6 +21,10 @@ RSpec.describe Clusters::Applications::Knative do
it { is_expected.to have_one(:serverless_domain_cluster).class_name('::Serverless::DomainCluster').with_foreign_key('clusters_applications_knative_id').inverse_of(:knative) }
end
+ describe 'default values' do
+ it { expect(subject.version).to eq(described_class::VERSION) }
+ end
+
describe 'when cloud run is enabled' do
let(:cluster) { create(:cluster, :provided_by_gcp, :cloud_run_enabled) }
let(:knative_cloud_run) { create(:clusters_applications_knative, cluster: cluster) }
diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb
index b60c5ec114d..15c3162270e 100644
--- a/spec/models/clusters/applications/prometheus_spec.rb
+++ b/spec/models/clusters/applications/prometheus_spec.rb
@@ -12,6 +12,13 @@ RSpec.describe Clusters::Applications::Prometheus do
include_examples 'cluster application helm specs', :clusters_applications_prometheus
include_examples 'cluster application initial status specs'
+ describe 'default values' do
+ subject(:prometheus) { build(:clusters_applications_prometheus) }
+
+ it { expect(prometheus.alert_manager_token).to be_an_instance_of(String) }
+ it { expect(prometheus.version).to eq(described_class::VERSION) }
+ end
+
describe 'after_destroy' do
let(:cluster) { create(:cluster, :with_installed_helm) }
let(:application) { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb
index 8f02161843b..04b5ae9641d 100644
--- a/spec/models/clusters/applications/runner_spec.rb
+++ b/spec/models/clusters/applications/runner_spec.rb
@@ -13,6 +13,10 @@ RSpec.describe Clusters::Applications::Runner do
it { is_expected.to belong_to(:runner) }
+ describe 'default values' do
+ it { expect(subject.version).to eq(described_class::VERSION) }
+ end
+
describe '#can_uninstall?' do
let(:gitlab_runner) { create(:clusters_applications_runner, runner: ci_runner) }
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index 73cd7bb9075..be64d72e031 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -49,6 +49,10 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
it { is_expected.to respond_to :project }
it { is_expected.to be_namespace_per_environment }
+ describe 'default values' do
+ it { expect(subject.helm_major_version).to eq(3) }
+ end
+
it_behaves_like 'it has loose foreign keys' do
let(:factory_name) { :cluster }
end
diff --git a/spec/models/clusters/integrations/prometheus_spec.rb b/spec/models/clusters/integrations/prometheus_spec.rb
index 90e99aefdce..d6d1105cdb1 100644
--- a/spec/models/clusters/integrations/prometheus_spec.rb
+++ b/spec/models/clusters/integrations/prometheus_spec.rb
@@ -15,6 +15,16 @@ RSpec.describe Clusters::Integrations::Prometheus do
it { is_expected.not_to allow_value(nil).for(:enabled) }
end
+ describe 'default values' do
+ subject(:integration) { build(:clusters_integrations_prometheus) }
+
+ before do
+ allow(SecureRandom).to receive(:hex).and_return('randomtoken')
+ end
+
+ it { expect(integration.alert_manager_token).to eq('randomtoken') }
+ end
+
describe 'after_destroy' do
subject(:integration) { create(:clusters_integrations_prometheus, cluster: cluster, enabled: true) }
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index 35ed6f4e2c6..99dbb654b7f 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -21,6 +21,12 @@ RSpec.describe Clusters::Platforms::Kubernetes do
it_behaves_like 'having unique enum values'
+ describe 'default values' do
+ let(:kubernetes) { create(:cluster_platform_kubernetes) }
+
+ it { expect(kubernetes.authorization_type).to eq("rbac") }
+ end
+
describe 'before_validation' do
let(:kubernetes) { create(:cluster_platform_kubernetes, :configured, namespace: namespace) }
diff --git a/spec/models/clusters/providers/aws_spec.rb b/spec/models/clusters/providers/aws_spec.rb
index 3b4a48cc5be..2afed663edf 100644
--- a/spec/models/clusters/providers/aws_spec.rb
+++ b/spec/models/clusters/providers/aws_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Clusters::Providers::Aws do
include_examples 'provider status', :cluster_provider_aws
- describe 'default_value_for' do
+ describe 'default values' do
let(:provider) { build(:cluster_provider_aws) }
it "sets default values" do
diff --git a/spec/models/clusters/providers/gcp_spec.rb b/spec/models/clusters/providers/gcp_spec.rb
index ad9ada04875..a1f00069937 100644
--- a/spec/models/clusters/providers/gcp_spec.rb
+++ b/spec/models/clusters/providers/gcp_spec.rb
@@ -8,13 +8,14 @@ RSpec.describe Clusters::Providers::Gcp do
include_examples 'provider status', :cluster_provider_gcp
- describe 'default_value_for' do
+ describe 'default values' do
let(:gcp) { build(:cluster_provider_gcp) }
it "has default value" do
expect(gcp.zone).to eq('us-central1-a')
expect(gcp.num_nodes).to eq(3)
expect(gcp.machine_type).to eq('n1-standard-2')
+ expect(gcp.cloud_run).to eq(false)
end
end
diff --git a/spec/support/shared_examples/lib/cache_helpers_shared_examples.rb b/spec/support/shared_examples/lib/cache_helpers_shared_examples.rb
index 2e00abe2f8e..6cdd7954b5f 100644
--- a/spec/support/shared_examples/lib/cache_helpers_shared_examples.rb
+++ b/spec/support/shared_examples/lib/cache_helpers_shared_examples.rb
@@ -129,6 +129,7 @@ RSpec.shared_examples_for 'collection cache helper' do
before do
allow(::Gitlab::Metrics::WebTransaction).to receive(:current).and_return(transaction)
allow(transaction).to receive(:increment)
+ allow(Gitlab::ApplicationContext).to receive(:current_context_attribute).with(any_args).and_call_original
allow(Gitlab::ApplicationContext).to receive(:current_context_attribute).with(:caller_id).and_return(caller_id)
end
diff --git a/spec/support/shared_examples/lib/gitlab/gitaly_client_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/gitaly_client_shared_examples.rb
new file mode 100644
index 00000000000..f26b9a4a7bd
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/gitaly_client_shared_examples.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+def raw_repo_without_container(repository)
+ Gitlab::Git::Repository.new(repository.shard,
+ "#{repository.disk_path}.git",
+ repository.repo_type.identifier_for_container(repository.container),
+ repository.container.full_path)
+end
+
+RSpec.shared_examples 'Gitaly feature flag actors are inferred from repository' do
+ it 'captures correct actors' do
+ service.repository_actor = repository
+
+ expect(service.repository_actor.flipper_id).to eql(repository.flipper_id)
+
+ if expected_project.nil?
+ expect(service.project_actor).to be(nil)
+ else
+ expect(service.project_actor.flipper_id).to eql(expected_project.flipper_id)
+ end
+
+ if expected_group.nil?
+ expect(service.group_actor).to be(nil)
+ else
+ expect(service.group_actor.flipper_id).to eql(expected_group.flipper_id)
+ end
+ end
+
+ it 'does not issues SQL queries after the first invocation' do
+ service.repository_actor = repository
+
+ service.repository_actor
+ service.project_actor
+ service.group_actor
+
+ recorder = ActiveRecord::QueryRecorder.new do
+ 3.times do
+ service.repository_actor
+ service.project_actor
+ service.group_actor
+ end
+ end
+
+ expect(recorder.count).to be(0)
+ end
+end
diff --git a/spec/workers/repository_check/single_repository_worker_spec.rb b/spec/workers/repository_check/single_repository_worker_spec.rb
index a0cf3b1e978..b8db262598b 100644
--- a/spec/workers/repository_check/single_repository_worker_spec.rb
+++ b/spec/workers/repository_check/single_repository_worker_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe RepositoryCheck::SingleRepositoryWorker do
repository = instance_double(::Gitlab::Git::Repository)
allow(::Gitlab::Git::Repository).to receive(:new)
- .with(project.repository_storage, "#{project.disk_path}.git", anything, anything)
+ .with(project.repository_storage, "#{project.disk_path}.git", anything, anything, container: project)
.and_return(repository)
worker.perform(project.id)
@@ -31,7 +31,7 @@ RSpec.describe RepositoryCheck::SingleRepositoryWorker do
repository = project.repository.raw
expect(repository).to receive(:fsck).and_raise(::Gitlab::Git::Repository::GitError)
expect(::Gitlab::Git::Repository).to receive(:new)
- .with(project.repository_storage, "#{project.disk_path}.git", anything, anything)
+ .with(project.repository_storage, "#{project.disk_path}.git", anything, anything, container: project)
.and_return(repository)
worker.perform(project.id)
@@ -46,7 +46,7 @@ RSpec.describe RepositoryCheck::SingleRepositoryWorker do
repository = project.repository.raw
expect(repository).to receive(:fsck).and_call_original
expect(::Gitlab::Git::Repository).to receive(:new)
- .with(project.repository_storage, "#{project.disk_path}.git", anything, anything)
+ .with(project.repository_storage, "#{project.disk_path}.git", anything, anything, container: project)
.and_return(repository)
expect do
@@ -68,7 +68,7 @@ RSpec.describe RepositoryCheck::SingleRepositoryWorker do
repository = project.wiki.repository.raw
expect(repository).to receive(:fsck).and_raise(::Gitlab::Git::Repository::GitError)
expect(::Gitlab::Git::Repository).to receive(:new)
- .with(project.repository_storage, "#{project.disk_path}.wiki.git", anything, anything)
+ .with(project.repository_storage, "#{project.disk_path}.wiki.git", anything, anything, container: project.wiki)
.and_return(repository)
worker.perform(project.id)
@@ -81,7 +81,7 @@ RSpec.describe RepositoryCheck::SingleRepositoryWorker do
# Make sure the test would fail if the wiki repo was checked
repository = instance_double(::Gitlab::Git::Repository)
allow(::Gitlab::Git::Repository).to receive(:new)
- .with(project.repository_storage, "#{project.disk_path}.wiki.git", anything, anything)
+ .with(project.repository_storage, "#{project.disk_path}.wiki.git", anything, anything, container: project)
.and_return(repository)
subject.perform(project.id)