diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-09-02 09:09:10 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-09-02 09:09:10 +0300 |
commit | 951a32fcf3fc8766eae1430a389b77049410c371 (patch) | |
tree | 284b8298b4de14dc2f31b9ef2cdfe3d90ace7296 /spec | |
parent | ceb0c326ae57bac76fe40ca3471b0ee5d152f58e (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/projects/feature_flags_controller_spec.rb | 270 | ||||
-rw-r--r-- | spec/factories/operations/feature_flag_scopes.rb | 10 | ||||
-rw-r--r-- | spec/factories/operations/feature_flags.rb | 8 | ||||
-rw-r--r-- | spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb | 16 | ||||
-rw-r--r-- | spec/finders/feature_flags_finder_spec.rb | 8 | ||||
-rw-r--r-- | spec/fixtures/api/schemas/feature_flag.json | 7 | ||||
-rw-r--r-- | spec/models/operations/feature_flag_scope_spec.rb | 391 | ||||
-rw-r--r-- | spec/models/operations/feature_flag_spec.rb | 118 | ||||
-rw-r--r-- | spec/requests/api/feature_flags_spec.rb | 121 | ||||
-rw-r--r-- | spec/requests/api/unleash_spec.rb | 19 | ||||
-rw-r--r-- | spec/services/feature_flags/create_service_spec.rb | 13 | ||||
-rw-r--r-- | spec/support/database/cross-join-allowlist.yml | 23 |
12 files changed, 22 insertions, 982 deletions
diff --git a/spec/controllers/projects/feature_flags_controller_spec.rb b/spec/controllers/projects/feature_flags_controller_spec.rb index e038b247eff..fd95aa44568 100644 --- a/spec/controllers/projects/feature_flags_controller_spec.rb +++ b/spec/controllers/projects/feature_flags_controller_spec.rb @@ -94,20 +94,6 @@ RSpec.describe Projects::FeatureFlagsController do is_expected.to match_response_schema('feature_flags') end - it 'returns false for active when the feature flag is inactive even if it has an active scope' do - create(:operations_feature_flag_scope, - feature_flag: feature_flag_inactive, - environment_scope: 'production', - active: true) - - subject - - expect(response).to have_gitlab_http_status(:ok) - feature_flag_json = json_response['feature_flags'].second - - expect(feature_flag_json['active']).to eq(false) - end - it 'returns the feature flag iid' do subject @@ -181,7 +167,7 @@ RSpec.describe Projects::FeatureFlagsController do subject { get(:show, params: params, format: :json) } let!(:feature_flag) do - create(:operations_feature_flag, :legacy_flag, project: project) + create(:operations_feature_flag, project: project) end let(:params) do @@ -197,7 +183,7 @@ RSpec.describe Projects::FeatureFlagsController do expect(json_response['name']).to eq(feature_flag.name) expect(json_response['active']).to eq(feature_flag.active) - expect(json_response['version']).to eq('legacy_flag') + expect(json_response['version']).to eq('new_version_flag') end it 'matches json schema' do @@ -245,46 +231,6 @@ RSpec.describe Projects::FeatureFlagsController do end end - context 'when feature flags have additional scopes' do - context 'when there is at least one active scope' do - let!(:feature_flag) do - create(:operations_feature_flag, project: project, active: false) - end - - let!(:feature_flag_scope_production) do - create(:operations_feature_flag_scope, - feature_flag: feature_flag, - environment_scope: 'review/*', - active: true) - end - - it 'returns false for active' do - subject - - expect(json_response['active']).to eq(false) - end - end - - context 'when all scopes are inactive' do - let!(:feature_flag) do - create(:operations_feature_flag, project: project, active: false) - end - - let!(:feature_flag_scope_production) do - create(:operations_feature_flag_scope, - feature_flag: feature_flag, - environment_scope: 'production', - active: false) - end - - it 'recognizes the feature flag as inactive' do - subject - - expect(json_response['active']).to be_falsy - end - end - end - context 'with a version 2 feature flag' do let!(:new_version_feature_flag) do create(:operations_feature_flag, :new_version_flag, project: project) @@ -320,22 +266,6 @@ RSpec.describe Projects::FeatureFlagsController do describe 'GET edit' do subject { get(:edit, params: params) } - context 'with legacy flags' do - let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, project: project) } - - let(:params) do - { - namespace_id: project.namespace, - project_id: project, - iid: feature_flag.iid - } - end - - it 'returns not found' do - is_expected.to have_gitlab_http_status(:not_found) - end - end - context 'with new version flags' do let!(:feature_flag) { create(:operations_feature_flag, project: project) } @@ -378,14 +308,6 @@ RSpec.describe Projects::FeatureFlagsController do expect(json_response['active']).to be_truthy end - it 'creates a default scope' do - subject - - expect(json_response['scopes'].count).to eq(1) - expect(json_response['scopes'].first['environment_scope']).to eq('*') - expect(json_response['scopes'].first['active']).to be_truthy - end - it 'matches json schema' do is_expected.to match_response_schema('feature_flag') end @@ -435,119 +357,6 @@ RSpec.describe Projects::FeatureFlagsController do end end - context 'when creates additional scope' do - let(:params) do - view_params.merge({ - operations_feature_flag: { - name: 'my_feature_flag', - active: true, - scopes_attributes: [{ environment_scope: '*', active: true }, - { environment_scope: 'production', active: false }] - } - }) - end - - it 'creates feature flag scopes successfully' do - expect { subject }.to change { Operations::FeatureFlagScope.count }.by(2) - - expect(response).to have_gitlab_http_status(:ok) - end - - it 'creates feature flag scopes in a correct order' do - subject - - expect(json_response['scopes'].first['environment_scope']).to eq('*') - expect(json_response['scopes'].second['environment_scope']).to eq('production') - end - - context 'when default scope is not placed first' do - let(:params) do - view_params.merge({ - operations_feature_flag: { - name: 'my_feature_flag', - active: true, - scopes_attributes: [{ environment_scope: 'production', active: false }, - { environment_scope: '*', active: true }] - } - }) - end - - it 'returns 400' do - subject - - expect(response).to have_gitlab_http_status(:bad_request) - expect(json_response['message']) - .to include('Default scope has to be the first element') - end - end - end - - context 'when creates additional scope with a percentage rollout' do - it 'creates a strategy for the scope' do - params = view_params.merge({ - operations_feature_flag: { - name: 'my_feature_flag', - active: true, - scopes_attributes: [{ environment_scope: '*', active: true }, - { environment_scope: 'production', active: false, - strategies: [{ name: 'gradualRolloutUserId', - parameters: { groupId: 'default', percentage: '42' } }] }] - } - }) - - post(:create, params: params, format: :json) - - expect(response).to have_gitlab_http_status(:ok) - production_strategies_json = json_response['scopes'].second['strategies'] - expect(production_strategies_json).to eq([{ - 'name' => 'gradualRolloutUserId', - 'parameters' => { "groupId" => "default", "percentage" => "42" } - }]) - end - end - - context 'when creates additional scope with a userWithId strategy' do - it 'creates a strategy for the scope' do - params = view_params.merge({ - operations_feature_flag: { - name: 'my_feature_flag', - active: true, - scopes_attributes: [{ environment_scope: '*', active: true }, - { environment_scope: 'production', active: false, - strategies: [{ name: 'userWithId', - parameters: { userIds: '123,4,6722' } }] }] - } - }) - - post(:create, params: params, format: :json) - - expect(response).to have_gitlab_http_status(:ok) - production_strategies_json = json_response['scopes'].second['strategies'] - expect(production_strategies_json).to eq([{ - 'name' => 'userWithId', - 'parameters' => { "userIds" => "123,4,6722" } - }]) - end - end - - context 'when creates an additional scope without a strategy' do - it 'creates a default strategy' do - params = view_params.merge({ - operations_feature_flag: { - name: 'my_feature_flag', - active: true, - scopes_attributes: [{ environment_scope: '*', active: true }] - } - }) - - post(:create, params: params, format: :json) - - expect(response).to have_gitlab_http_status(:ok) - default_strategies_json = json_response['scopes'].first['strategies'] - expect(default_strategies_json).to eq([{ "name" => "default", "parameters" => {} }]) - end - end - context 'when creating a version 2 feature flag' do let(:params) do { @@ -744,7 +553,7 @@ RSpec.describe Projects::FeatureFlagsController do describe 'DELETE destroy.json' do subject { delete(:destroy, params: params, format: :json) } - let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, project: project) } + let!(:feature_flag) { create(:operations_feature_flag, project: project) } let(:params) do { @@ -762,10 +571,6 @@ RSpec.describe Projects::FeatureFlagsController do expect { subject }.to change { Operations::FeatureFlag.count }.by(-1) end - it 'destroys the default scope' do - expect { subject }.to change { Operations::FeatureFlagScope.count }.by(-1) - end - it 'matches json schema' do is_expected.to match_response_schema('feature_flag') end @@ -792,14 +597,6 @@ RSpec.describe Projects::FeatureFlagsController do end end - context 'when there is an additional scope' do - let!(:scope) { create_scope(feature_flag, 'production', false) } - - it 'destroys the default scope and production scope' do - expect { subject }.to change { Operations::FeatureFlagScope.count }.by(-2) - end - end - context 'with a version 2 flag' do let!(:new_version_flag) { create(:operations_feature_flag, :new_version_flag, project: project) } let(:params) do @@ -828,70 +625,9 @@ RSpec.describe Projects::FeatureFlagsController do put(:update, params: params, format: :json, as: :json) end - context 'with a legacy feature flag' do - subject { put(:update, params: params, format: :json) } - - let!(:feature_flag) do - create(:operations_feature_flag, - :legacy_flag, - name: 'ci_live_trace', - active: true, - project: project) - end - - let(:params) do - { - namespace_id: project.namespace, - project_id: project, - iid: feature_flag.iid, - operations_feature_flag: { - name: 'ci_new_live_trace' - } - } - end - - context 'when user is reporter' do - let(:user) { reporter } - - it 'returns 404' do - is_expected.to have_gitlab_http_status(:not_found) - end - end - - context "when changing default scope's spec" do - let(:params) do - { - namespace_id: project.namespace, - project_id: project, - iid: feature_flag.iid, - operations_feature_flag: { - scopes_attributes: [ - { - id: feature_flag.default_scope.id, - environment_scope: 'review/*' - } - ] - } - } - end - - it 'returns 400' do - is_expected.to have_gitlab_http_status(:bad_request) - end - end - - it 'does not update a legacy feature flag' do - put_request(feature_flag, name: 'ci_new_live_trace') - - expect(response).to have_gitlab_http_status(:bad_request) - expect(json_response['message']).to eq(["Legacy feature flags are read-only"]) - end - end - context 'with a version 2 feature flag' do let!(:new_version_flag) do create(:operations_feature_flag, - :new_version_flag, name: 'new-feature', active: true, project: project) diff --git a/spec/factories/operations/feature_flag_scopes.rb b/spec/factories/operations/feature_flag_scopes.rb deleted file mode 100644 index 4ca9b53f320..00000000000 --- a/spec/factories/operations/feature_flag_scopes.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true - -FactoryBot.define do - factory :operations_feature_flag_scope, class: 'Operations::FeatureFlagScope' do - association :feature_flag, factory: [:operations_feature_flag, :legacy_flag] - active { true } - strategies { [{ name: "default", parameters: {} }] } - sequence(:environment_scope) { |n| "review/patch-#{n}" } - end -end diff --git a/spec/factories/operations/feature_flags.rb b/spec/factories/operations/feature_flags.rb index 32e5ec9fb26..33c13a62445 100644 --- a/spec/factories/operations/feature_flags.rb +++ b/spec/factories/operations/feature_flags.rb @@ -6,13 +6,5 @@ FactoryBot.define do project active { true } version { :new_version_flag } - - trait :legacy_flag do - version { Operations::FeatureFlag.versions['legacy_flag'] } - end - - trait :new_version_flag do - version { Operations::FeatureFlag.versions['new_version_flag'] } - end end end diff --git a/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb b/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb index f6330491886..71c9d89fbde 100644 --- a/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb +++ b/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb @@ -66,20 +66,4 @@ RSpec.describe 'User updates feature flag', :js do end end end - - context 'with a legacy feature flag' do - let!(:feature_flag) do - create_flag(project, 'ci_live_trace', true, - description: 'For live trace feature', - version: :legacy_flag) - end - - let!(:scope) { create_scope(feature_flag, 'review/*', true) } - - it 'shows not found error' do - visit(edit_project_feature_flag_path(project, feature_flag)) - - expect(page).to have_text 'Page Not Found' - end - end end diff --git a/spec/finders/feature_flags_finder_spec.rb b/spec/finders/feature_flags_finder_spec.rb index 4faa6a62a1f..1b3c71b143f 100644 --- a/spec/finders/feature_flags_finder_spec.rb +++ b/spec/finders/feature_flags_finder_spec.rb @@ -72,13 +72,5 @@ RSpec.describe FeatureFlagsFinder do subject end end - - context 'with a legacy flag' do - let!(:feature_flag_3) { create(:operations_feature_flag, :legacy_flag, name: 'flag-c', project: project) } - - it 'returns new flags' do - is_expected.to eq([feature_flag_1, feature_flag_2]) - end - end end end diff --git a/spec/fixtures/api/schemas/feature_flag.json b/spec/fixtures/api/schemas/feature_flag.json index 45b704e4b84..47f86a9f92b 100644 --- a/spec/fixtures/api/schemas/feature_flag.json +++ b/spec/fixtures/api/schemas/feature_flag.json @@ -1,10 +1,7 @@ { "type": "object", - "required" : [ - "id", - "name" - ], - "properties" : { + "required": ["id", "name"], + "properties": { "id": { "type": "integer" }, "iid": { "type": ["integer", "null"] }, "version": { "type": "string" }, diff --git a/spec/models/operations/feature_flag_scope_spec.rb b/spec/models/operations/feature_flag_scope_spec.rb deleted file mode 100644 index dc83789fade..00000000000 --- a/spec/models/operations/feature_flag_scope_spec.rb +++ /dev/null @@ -1,391 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Operations::FeatureFlagScope do - describe 'associations' do - it { is_expected.to belong_to(:feature_flag) } - end - - describe 'validations' do - context 'when duplicate environment scope is going to be created' do - let!(:existing_feature_flag_scope) do - create(:operations_feature_flag_scope) - end - - let(:new_feature_flag_scope) do - build(:operations_feature_flag_scope, - feature_flag: existing_feature_flag_scope.feature_flag, - environment_scope: existing_feature_flag_scope.environment_scope) - end - - it 'validates uniqueness of environment scope' do - new_feature_flag_scope.save - - expect(new_feature_flag_scope.errors[:environment_scope]) - .to include("(#{existing_feature_flag_scope.environment_scope})" \ - " has already been taken") - end - end - - context 'when environment scope of a default scope is updated' do - let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag) } - let!(:scope_default) { feature_flag.default_scope } - - it 'keeps default scope intact' do - scope_default.update(environment_scope: 'review/*') - - expect(scope_default.errors[:environment_scope]) - .to include("cannot be changed from default scope") - end - end - - context 'when a default scope is destroyed' do - let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag) } - let!(:scope_default) { feature_flag.default_scope } - - it 'prevents from destroying the default scope' do - expect { scope_default.destroy! }.to raise_error(ActiveRecord::ReadOnlyRecord) - end - end - - describe 'strategy validations' do - it 'handles null strategies which can occur while adding the column during migration' do - scope = create(:operations_feature_flag_scope, active: true) - allow(scope).to receive(:strategies).and_return(nil) - - scope.active = false - scope.save - - expect(scope.errors[:strategies]).to be_empty - end - - it 'validates multiple strategies' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: "default", parameters: {} }, - { name: "invalid", parameters: {} }]) - - expect(scope.errors[:strategies]).not_to be_empty - end - - where(:invalid_value) do - [{}, 600, "bad", [{ name: 'default', parameters: {} }, 300]] - end - with_them do - it 'must be an array of strategy hashes' do - scope = create(:operations_feature_flag_scope) - - scope.strategies = invalid_value - scope.save - - expect(scope.errors[:strategies]).to eq(['must be an array of strategy hashes']) - end - end - - describe 'name' do - using RSpec::Parameterized::TableSyntax - - where(:name, :params, :expected) do - 'default' | {} | [] - 'gradualRolloutUserId' | { groupId: 'mygroup', percentage: '50' } | [] - 'userWithId' | { userIds: 'sam' } | [] - 5 | nil | ['strategy name is invalid'] - nil | nil | ['strategy name is invalid'] - "nothing" | nil | ['strategy name is invalid'] - "" | nil | ['strategy name is invalid'] - 40.0 | nil | ['strategy name is invalid'] - {} | nil | ['strategy name is invalid'] - [] | nil | ['strategy name is invalid'] - end - with_them do - it 'must be one of "default", "gradualRolloutUserId", or "userWithId"' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: name, parameters: params }]) - - expect(scope.errors[:strategies]).to eq(expected) - end - end - end - - describe 'parameters' do - context 'when the strategy name is gradualRolloutUserId' do - it 'must have parameters' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'gradualRolloutUserId' }]) - - expect(scope.errors[:strategies]).to eq(['parameters are invalid']) - end - - where(:invalid_parameters) do - [nil, {}, { percentage: '40', groupId: 'mygroup', userIds: '4' }, { percentage: '40' }, - { percentage: '40', groupId: 'mygroup', extra: nil }, { groupId: 'mygroup' }] - end - with_them do - it 'must have valid parameters for the strategy' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'gradualRolloutUserId', - parameters: invalid_parameters }]) - - expect(scope.errors[:strategies]).to eq(['parameters are invalid']) - end - end - - it 'allows the parameters in any order' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'gradualRolloutUserId', - parameters: { percentage: '10', groupId: 'mygroup' } }]) - - expect(scope.errors[:strategies]).to be_empty - end - - describe 'percentage' do - where(:invalid_value) do - [50, 40.0, { key: "value" }, "garbage", "00", "01", "101", "-1", "-10", "0100", - "1000", "10.0", "5%", "25%", "100hi", "e100", "30m", " ", "\r\n", "\n", "\t", - "\n10", "20\n", "\n100", "100\n", "\n ", nil] - end - with_them do - it 'must be a string value between 0 and 100 inclusive and without a percentage sign' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'gradualRolloutUserId', - parameters: { groupId: 'mygroup', percentage: invalid_value } }]) - - expect(scope.errors[:strategies]).to eq(['percentage must be a string between 0 and 100 inclusive']) - end - end - - where(:valid_value) do - %w[0 1 10 38 100 93] - end - with_them do - it 'must be a string value between 0 and 100 inclusive and without a percentage sign' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'gradualRolloutUserId', - parameters: { groupId: 'mygroup', percentage: valid_value } }]) - - expect(scope.errors[:strategies]).to eq([]) - end - end - end - - describe 'groupId' do - where(:invalid_value) do - [nil, 4, 50.0, {}, 'spaces bad', 'bad$', '%bad', '<bad', 'bad>', '!bad', - '.bad', 'Bad', 'bad1', "", " ", "b" * 33, "ba_d", "ba\nd"] - end - with_them do - it 'must be a string value of up to 32 lowercase characters' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'gradualRolloutUserId', - parameters: { groupId: invalid_value, percentage: '40' } }]) - - expect(scope.errors[:strategies]).to eq(['groupId parameter is invalid']) - end - end - - where(:valid_value) do - ["somegroup", "anothergroup", "okay", "g", "a" * 32] - end - with_them do - it 'must be a string value of up to 32 lowercase characters' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'gradualRolloutUserId', - parameters: { groupId: valid_value, percentage: '40' } }]) - - expect(scope.errors[:strategies]).to eq([]) - end - end - end - end - - context 'when the strategy name is userWithId' do - it 'must have parameters' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'userWithId' }]) - - expect(scope.errors[:strategies]).to eq(['parameters are invalid']) - end - - where(:invalid_parameters) do - [nil, { userIds: 'sam', percentage: '40' }, { userIds: 'sam', some: 'param' }, { percentage: '40' }, {}] - end - with_them do - it 'must have valid parameters for the strategy' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'userWithId', parameters: invalid_parameters }]) - - expect(scope.errors[:strategies]).to eq(['parameters are invalid']) - end - end - - describe 'userIds' do - where(:valid_value) do - ["", "sam", "1", "a", "uuid-of-some-kind", "sam,fred,tom,jane,joe,mike", - "gitlab@example.com", "123,4", "UPPER,Case,charActeRS", "0", - "$valid$email#2345#$%..{}+=-)?\\/@example.com", "spaces allowed", - "a" * 256, "a,#{'b' * 256},ccc", "many spaces"] - end - with_them do - it 'is valid with a string of comma separated values' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'userWithId', parameters: { userIds: valid_value } }]) - - expect(scope.errors[:strategies]).to be_empty - end - end - - where(:invalid_value) do - [1, 2.5, {}, [], nil, "123\n456", "1,2,3,12\t3", "\n", "\n\r", - "joe\r,sam", "1,2,2", "1,,2", "1,2,,,,", "b" * 257, "1, ,2", "tim, ,7", " ", - " ", " ,1", "1, ", " leading,1", "1,trailing ", "1, both ,2"] - end - with_them do - it 'is invalid' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'userWithId', parameters: { userIds: invalid_value } }]) - - expect(scope.errors[:strategies]).to include( - 'userIds must be a string of unique comma separated values each 256 characters or less' - ) - end - end - end - end - - context 'when the strategy name is default' do - it 'must have parameters' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'default' }]) - - expect(scope.errors[:strategies]).to eq(['parameters are invalid']) - end - - where(:invalid_value) do - [{ groupId: "hi", percentage: "7" }, "", "nothing", 7, nil, [], 2.5] - end - with_them do - it 'must be empty' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'default', - parameters: invalid_value }]) - - expect(scope.errors[:strategies]).to eq(['parameters are invalid']) - end - end - - it 'must be empty' do - feature_flag = create(:operations_feature_flag) - scope = described_class.create(feature_flag: feature_flag, - environment_scope: 'production', active: true, - strategies: [{ name: 'default', - parameters: {} }]) - - expect(scope.errors[:strategies]).to be_empty - end - end - end - end - end - - describe '.enabled' do - subject { described_class.enabled } - - let!(:feature_flag_scope) do - create(:operations_feature_flag_scope, active: active) - end - - context 'when scope is active' do - let(:active) { true } - - it 'returns the scope' do - is_expected.to include(feature_flag_scope) - end - end - - context 'when scope is inactive' do - let(:active) { false } - - it 'returns an empty array' do - is_expected.not_to include(feature_flag_scope) - end - end - end - - describe '.disabled' do - subject { described_class.disabled } - - let!(:feature_flag_scope) do - create(:operations_feature_flag_scope, active: active) - end - - context 'when scope is active' do - let(:active) { true } - - it 'returns an empty array' do - is_expected.not_to include(feature_flag_scope) - end - end - - context 'when scope is inactive' do - let(:active) { false } - - it 'returns the scope' do - is_expected.to include(feature_flag_scope) - end - end - end - - describe '.for_unleash_client' do - it 'returns scopes for the specified project' do - project1 = create(:project) - project2 = create(:project) - expected_feature_flag = create(:operations_feature_flag, project: project1) - create(:operations_feature_flag, project: project2) - - scopes = described_class.for_unleash_client(project1, 'sandbox').to_a - - expect(scopes).to contain_exactly(*expected_feature_flag.scopes) - end - - it 'returns a scope that matches exactly over a match with a wild card' do - project = create(:project) - feature_flag = create(:operations_feature_flag, project: project) - create(:operations_feature_flag_scope, feature_flag: feature_flag, environment_scope: 'production*') - expected_scope = create(:operations_feature_flag_scope, feature_flag: feature_flag, environment_scope: 'production') - - scopes = described_class.for_unleash_client(project, 'production').to_a - - expect(scopes).to contain_exactly(expected_scope) - end - end -end diff --git a/spec/models/operations/feature_flag_spec.rb b/spec/models/operations/feature_flag_spec.rb index cb9da2aea34..d689632e2b4 100644 --- a/spec/models/operations/feature_flag_spec.rb +++ b/spec/models/operations/feature_flag_spec.rb @@ -49,28 +49,7 @@ RSpec.describe Operations::FeatureFlag do it { is_expected.to validate_presence_of(:project) } it { is_expected.to validate_presence_of(:name) } it { is_expected.to validate_uniqueness_of(:name).scoped_to(:project_id) } - it { is_expected.to define_enum_for(:version).with_values(legacy_flag: 1, new_version_flag: 2) } - - context 'a version 1 feature flag' do - it 'is valid if associated with Operations::FeatureFlagScope models' do - project = create(:project) - feature_flag = described_class.create!({ name: 'test', project: project, version: 1, - scopes_attributes: [{ environment_scope: '*', active: false }] }) - - expect(feature_flag).to be_valid - end - - it 'is invalid if associated with Operations::FeatureFlags::Strategy models' do - project = create(:project) - feature_flag = described_class.new({ name: 'test', project: project, version: 1, - strategies_attributes: [{ name: 'default', parameters: {} }] }) - - expect(feature_flag.valid?).to eq(false) - expect(feature_flag.errors.messages).to eq({ - version_associations: ["version 1 feature flags may not have strategies"] - }) - end - end + it { is_expected.to define_enum_for(:version).with_values(new_version_flag: 2) } context 'a version 2 feature flag' do it 'is invalid if associated with Operations::FeatureFlagScope models' do @@ -102,64 +81,9 @@ RSpec.describe Operations::FeatureFlag do end end - describe 'feature flag version' do - it 'defaults to 1 if unspecified' do - project = create(:project) - - feature_flag = described_class.create!(name: 'my_flag', project: project, active: true) - - expect(feature_flag).to be_valid - expect(feature_flag.version_before_type_cast).to eq(1) - end - end - - describe 'Scope creation' do - subject { described_class.new(**params) } - - let(:project) { create(:project) } - - let(:params) do - { name: 'test', project: project, scopes_attributes: scopes_attributes } - end - - let(:scopes_attributes) do - [{ environment_scope: '*', active: false }, - { environment_scope: 'review/*', active: true }] - end - - it { is_expected.to be_valid } - - context 'when the first scope is not wildcard' do - let(:scopes_attributes) do - [{ environment_scope: 'review/*', active: true }, - { environment_scope: '*', active: false }] - end - - it { is_expected.not_to be_valid } - end - end - describe 'the default scope' do let_it_be(:project) { create(:project) } - context 'with a version 1 feature flag' do - it 'creates a default scope' do - feature_flag = described_class.create!({ name: 'test', project: project, scopes_attributes: [], version: 1 }) - - expect(feature_flag.scopes.count).to eq(1) - expect(feature_flag.scopes.first.environment_scope).to eq('*') - end - - it 'allows specifying the default scope in the parameters' do - feature_flag = described_class.create!({ name: 'test', project: project, - scopes_attributes: [{ environment_scope: '*', active: false }, - { environment_scope: 'review/*', active: true }], version: 1 }) - - expect(feature_flag.scopes.count).to eq(2) - expect(feature_flag.scopes.first.environment_scope).to eq('*') - end - end - context 'with a version 2 feature flag' do it 'does not create a default scope' do feature_flag = described_class.create!({ name: 'test', project: project, scopes_attributes: [], version: 2 }) @@ -180,16 +104,6 @@ RSpec.describe Operations::FeatureFlag do end end - context 'when the feature flag is active and all scopes are inactive' do - let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, active: true) } - - it 'returns the flag' do - feature_flag.default_scope.update!(active: false) - - is_expected.to eq([feature_flag]) - end - end - context 'when the feature flag is inactive' do let!(:feature_flag) { create(:operations_feature_flag, active: false) } @@ -197,16 +111,6 @@ RSpec.describe Operations::FeatureFlag do is_expected.to be_empty end end - - context 'when the feature flag is inactive and all scopes are active' do - let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, active: false) } - - it 'does not return the flag' do - feature_flag.default_scope.update!(active: true) - - is_expected.to be_empty - end - end end describe '.disabled' do @@ -220,16 +124,6 @@ RSpec.describe Operations::FeatureFlag do end end - context 'when the feature flag is active and all scopes are inactive' do - let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, active: true) } - - it 'does not return the flag' do - feature_flag.default_scope.update!(active: false) - - is_expected.to be_empty - end - end - context 'when the feature flag is inactive' do let!(:feature_flag) { create(:operations_feature_flag, active: false) } @@ -237,16 +131,6 @@ RSpec.describe Operations::FeatureFlag do is_expected.to eq([feature_flag]) end end - - context 'when the feature flag is inactive and all scopes are active' do - let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, active: false) } - - it 'returns the flag' do - feature_flag.default_scope.update!(active: true) - - is_expected.to eq([feature_flag]) - end - end end describe '.for_unleash_client' do diff --git a/spec/requests/api/feature_flags_spec.rb b/spec/requests/api/feature_flags_spec.rb index 8c8c6803a38..a1aedc1d6b2 100644 --- a/spec/requests/api/feature_flags_spec.rb +++ b/spec/requests/api/feature_flags_spec.rb @@ -116,21 +116,6 @@ RSpec.describe API::FeatureFlags do }]) end end - - context 'with version 1 and 2 feature flags' do - it 'returns both versions of flags ordered by name' do - create(:operations_feature_flag, project: project, name: 'legacy_flag') - feature_flag = create(:operations_feature_flag, :new_version_flag, project: project, name: 'new_version_flag') - strategy = create(:operations_strategy, feature_flag: feature_flag, name: 'default', parameters: {}) - create(:operations_scope, strategy: strategy, environment_scope: 'production') - - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to match_response_schema('public_api/v4/feature_flags') - expect(json_response.map { |f| f['name'] }).to eq(%w[legacy_flag new_version_flag]) - end - end end describe 'GET /projects/:id/feature_flags/:name' do @@ -185,22 +170,13 @@ RSpec.describe API::FeatureFlags do end describe 'POST /projects/:id/feature_flags' do - def scope_default - { - environment_scope: '*', - active: false, - strategies: [{ name: 'default', parameters: {} }].to_json - } - end - subject do post api("/projects/#{project.id}/feature_flags", user), params: params end let(:params) do { - name: 'awesome-feature', - scopes: [scope_default] + name: 'awesome-feature' } end @@ -215,14 +191,14 @@ RSpec.describe API::FeatureFlags do expect(feature_flag.description).to eq(params[:description]) end - it 'defaults to a version 1 (legacy) feature flag' do + it 'defaults to a version 2 (new) feature flag' do subject expect(response).to have_gitlab_http_status(:created) expect(response).to match_response_schema('public_api/v4/feature_flag') feature_flag = project.operations_feature_flags.last - expect(feature_flag.version).to eq('legacy_flag') + expect(feature_flag.version).to eq('new_version_flag') end it_behaves_like 'check user permission' @@ -232,38 +208,7 @@ RSpec.describe API::FeatureFlags do expect(response).to have_gitlab_http_status(:created) expect(response).to match_response_schema('public_api/v4/feature_flag') - expect(json_response['version']).to eq('legacy_flag') - end - - context 'with active set to false in the params for a legacy flag' do - let(:params) do - { - name: 'awesome-feature', - version: 'legacy_flag', - active: 'false', - scopes: [scope_default] - } - end - - it 'creates an inactive feature flag' do - subject - - expect(response).to have_gitlab_http_status(:created) - expect(response).to match_response_schema('public_api/v4/feature_flag') - expect(json_response['active']).to eq(false) - end - end - - context 'when no scopes passed in parameters' do - let(:params) { { name: 'awesome-feature' } } - - it 'creates a new feature flag with active default scope' do - subject - - expect(response).to have_gitlab_http_status(:created) - feature_flag = project.operations_feature_flags.last - expect(feature_flag.default_scope).to be_active - end + expect(json_response['version']).to eq('new_version_flag') end context 'when there is a feature flag with the same name already' do @@ -278,43 +223,6 @@ RSpec.describe API::FeatureFlags do end end - context 'when create a feature flag with two scopes' do - let(:params) do - { - name: 'awesome-feature', - description: 'this is awesome', - scopes: [ - scope_default, - scope_with_user_with_id - ] - } - end - - let(:scope_with_user_with_id) do - { - environment_scope: 'production', - active: true, - strategies: [{ - name: 'userWithId', - parameters: { userIds: 'user:1' } - }].to_json - } - end - - it 'creates a new feature flag with two scopes' do - subject - - expect(response).to have_gitlab_http_status(:created) - - feature_flag = project.operations_feature_flags.last - feature_flag.scopes.ordered.each_with_index do |scope, index| - expect(scope.environment_scope).to eq(params[:scopes][index][:environment_scope]) - expect(scope.active).to eq(params[:scopes][index][:active]) - expect(scope.strategies).to eq(Gitlab::Json.parse(params[:scopes][index][:strategies])) - end - end - end - context 'when creating a version 2 feature flag' do it 'creates a new feature flag' do params = { @@ -455,23 +363,6 @@ RSpec.describe API::FeatureFlags do end describe 'PUT /projects/:id/feature_flags/:name' do - context 'with a legacy feature flag' do - let!(:feature_flag) do - create(:operations_feature_flag, :legacy_flag, project: project, - name: 'feature1', description: 'old description') - end - - it 'returns a 404' do - params = { description: 'new description' } - - put api("/projects/#{project.id}/feature_flags/feature1", user), params: params - - expect(response).to have_gitlab_http_status(:not_found) - expect(json_response).to eq({ 'message' => '404 Not Found' }) - expect(feature_flag.reload.description).to eq('old description') - end - end - context 'with a version 2 feature flag' do let!(:feature_flag) do create(:operations_feature_flag, :new_version_flag, project: project, active: true, @@ -781,7 +672,7 @@ RSpec.describe API::FeatureFlags do params: params end - let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, project: project) } + let!(:feature_flag) { create(:operations_feature_flag, project: project) } let(:params) { {} } it 'destroys the feature flag' do @@ -794,7 +685,7 @@ RSpec.describe API::FeatureFlags do subject expect(response).to have_gitlab_http_status(:ok) - expect(json_response['version']).to eq('legacy_flag') + expect(json_response['version']).to eq('new_version_flag') end context 'with a version 2 feature flag' do diff --git a/spec/requests/api/unleash_spec.rb b/spec/requests/api/unleash_spec.rb index 0718710f15c..6cb801538c6 100644 --- a/spec/requests/api/unleash_spec.rb +++ b/spec/requests/api/unleash_spec.rb @@ -176,25 +176,6 @@ RSpec.describe API::Unleash do it_behaves_like 'authenticated request' - context 'with version 1 (legacy) feature flags' do - let(:feature_flag) { create(:operations_feature_flag, :legacy_flag, project: project, name: 'feature1', active: true, version: 1) } - - it 'does not return a legacy feature flag' do - create(:operations_feature_flag_scope, - feature_flag: feature_flag, - environment_scope: 'sandbox', - active: true, - strategies: [{ name: "gradualRolloutUserId", - parameters: { groupId: "default", percentage: "50" } }]) - headers = { "UNLEASH-INSTANCEID" => client.token, "UNLEASH-APPNAME" => "sandbox" } - - get api(features_url), headers: headers - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response['features']).to be_empty - end - end - context 'with version 2 feature flags' do it 'does not return a flag without any strategies' do create(:operations_feature_flag, project: project, diff --git a/spec/services/feature_flags/create_service_spec.rb b/spec/services/feature_flags/create_service_spec.rb index 4eb2b25fb64..f239f60b385 100644 --- a/spec/services/feature_flags/create_service_spec.rb +++ b/spec/services/feature_flags/create_service_spec.rb @@ -48,8 +48,9 @@ RSpec.describe FeatureFlags::CreateService do { name: 'feature_flag', description: 'description', - scopes_attributes: [{ environment_scope: '*', active: true }, - { environment_scope: 'production', active: false }] + version: 'new_version_flag', + strategies_attributes: [{ name: 'default', scopes_attributes: [{ environment_scope: '*' }], parameters: {} }, + { name: 'default', parameters: {}, scopes_attributes: [{ environment_scope: 'production' }] }] } end @@ -70,10 +71,10 @@ RSpec.describe FeatureFlags::CreateService do it 'creates audit event' do expected_message = 'Created feature flag feature_flag '\ 'with description "description". '\ - 'Created rule * and set it as active '\ - 'with strategies [{"name"=>"default", "parameters"=>{}}]. '\ - 'Created rule production and set it as inactive '\ - 'with strategies [{"name"=>"default", "parameters"=>{}}].' + 'Created strategy "default" with scopes '\ + '"*". '\ + 'Created strategy "default" with scopes '\ + '"production".' expect { subject }.to change { AuditEvent.count }.by(1) expect(AuditEvent.last.details[:custom_message]).to eq(expected_message) diff --git a/spec/support/database/cross-join-allowlist.yml b/spec/support/database/cross-join-allowlist.yml index e1ffb5cff10..5411cbce46f 100644 --- a/spec/support/database/cross-join-allowlist.yml +++ b/spec/support/database/cross-join-allowlist.yml @@ -7,7 +7,6 @@ - "./ee/spec/features/ci_shared_runner_warnings_spec.rb" - "./ee/spec/features/groups/analytics/cycle_analytics/filters_and_data_spec.rb" - "./ee/spec/features/merge_request/sidebar_spec.rb" -- "./ee/spec/features/merge_requests/user_resets_approvers_spec.rb" - "./ee/spec/features/merge_request/user_approves_with_password_spec.rb" - "./ee/spec/features/merge_request/user_creates_merge_request_spec.rb" - "./ee/spec/features/merge_request/user_creates_merge_request_with_blocking_mrs_spec.rb" @@ -23,6 +22,7 @@ - "./ee/spec/features/merge_request/user_sets_approvers_spec.rb" - "./ee/spec/features/merge_request/user_uses_slash_commands_spec.rb" - "./ee/spec/features/merge_request/user_views_blocked_merge_request_spec.rb" +- "./ee/spec/features/merge_requests/user_resets_approvers_spec.rb" - "./ee/spec/features/merge_trains/two_merge_requests_on_train_spec.rb" - "./ee/spec/features/merge_trains/user_adds_merge_request_to_merge_train_spec.rb" - "./ee/spec/features/merge_trains/user_adds_to_merge_train_when_pipeline_succeeds_spec.rb" @@ -37,14 +37,8 @@ - "./ee/spec/finders/group_projects_finder_spec.rb" - "./ee/spec/finders/security/findings_finder_spec.rb" - "./ee/spec/frontend/fixtures/analytics/metrics.rb" -- "./ee/spec/frontend/fixtures/analytics/value_streams_code_stage.rb" -- "./ee/spec/frontend/fixtures/analytics/value_streams_issue_stage.rb" -- "./ee/spec/frontend/fixtures/analytics/value_streams_plan_stage.rb" - "./ee/spec/frontend/fixtures/analytics/value_streams.rb" -- "./ee/spec/frontend/fixtures/analytics/value_streams_review_stage.rb" -- "./ee/spec/frontend/fixtures/analytics/value_streams_staging_stage.rb" - "./ee/spec/frontend/fixtures/merge_requests.rb" -- "./ee/spec/graphql/ee/mutations/ci/runner/update_spec.rb" - "./ee/spec/graphql/ee/resolvers/namespace_projects_resolver_spec.rb" - "./ee/spec/lib/analytics/devops_adoption/snapshot_calculator_spec.rb" - "./ee/spec/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules_spec.rb" @@ -54,7 +48,6 @@ - "./ee/spec/lib/ee/gitlab/background_migration/populate_uuids_for_security_findings_spec.rb" - "./ee/spec/lib/ee/gitlab/background_migration/populate_vulnerability_feedback_pipeline_id_spec.rb" - "./ee/spec/lib/ee/gitlab/usage_data_spec.rb" -- "./ee/spec/lib/gitlab/ci/minutes/build_consumption_spec.rb" - "./ee/spec/lib/gitlab/ci/minutes/runners_availability_spec.rb" - "./ee/spec/lib/gitlab/ci/templates/Jobs/browser_performance_testing_gitlab_ci_yaml_spec.rb" - "./ee/spec/lib/gitlab/ci/templates/Jobs/load_performance_testing_gitlab_ci_yaml_spec.rb" @@ -65,7 +58,6 @@ - "./ee/spec/models/ci/build_spec.rb" - "./ee/spec/models/ci/minutes/project_monthly_usage_spec.rb" - "./ee/spec/models/ci/pipeline_spec.rb" -- "./ee/spec/models/ee/ci/runner_spec.rb" - "./ee/spec/models/ee/vulnerability_spec.rb" - "./ee/spec/models/merge_request_spec.rb" - "./ee/spec/models/project_spec.rb" @@ -74,7 +66,6 @@ - "./ee/spec/presenters/ci/pipeline_presenter_spec.rb" - "./ee/spec/requests/api/ci/jobs_spec.rb" - "./ee/spec/requests/api/ci/minutes_spec.rb" -- "./ee/spec/requests/api/ci/runner_spec.rb" - "./ee/spec/requests/api/graphql/ci/minutes/usage_spec.rb" - "./ee/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb" - "./ee/spec/requests/api/graphql/mutations/vulnerabilities/create_external_issue_link_spec.rb" @@ -216,6 +207,7 @@ - "./spec/features/merge_request/user_views_open_merge_request_spec.rb" - "./spec/features/participants_autocomplete_spec.rb" - "./spec/features/project_group_variables_spec.rb" +- "./spec/features/project_variables_spec.rb" - "./spec/features/projects/badges/list_spec.rb" - "./spec/features/projects/badges/pipeline_badge_spec.rb" - "./spec/features/projects/blobs/edit_spec.rb" @@ -225,9 +217,9 @@ - "./spec/features/projects/infrastructure_registry_spec.rb" - "./spec/features/projects/issuable_templates_spec.rb" - "./spec/features/projects/jobs/permissions_spec.rb" -- "./spec/features/projects/jobs_spec.rb" - "./spec/features/projects/jobs/user_browses_job_spec.rb" - "./spec/features/projects/jobs/user_browses_jobs_spec.rb" +- "./spec/features/projects/jobs_spec.rb" - "./spec/features/projects/package_files_spec.rb" - "./spec/features/projects/pipelines/pipeline_spec.rb" - "./spec/features/projects/pipelines/pipelines_spec.rb" @@ -235,7 +227,6 @@ - "./spec/features/projects/settings/pipelines_settings_spec.rb" - "./spec/features/projects/user_sees_user_popover_spec.rb" - "./spec/features/projects/view_on_env_spec.rb" -- "./spec/features/project_variables_spec.rb" - "./spec/features/runners_spec.rb" - "./spec/features/security/project/internal_access_spec.rb" - "./spec/features/security/project/private_access_spec.rb" @@ -247,7 +238,6 @@ - "./spec/finders/ci/pipelines_for_merge_request_finder_spec.rb" - "./spec/finders/ci/runners_finder_spec.rb" - "./spec/finders/clusters/knative_services_finder_spec.rb" -- "./spec/finders/projects_finder_spec.rb" - "./spec/finders/projects/serverless/functions_finder_spec.rb" - "./spec/frontend/fixtures/analytics.rb" - "./spec/frontend/fixtures/jobs.rb" @@ -259,7 +249,6 @@ - "./spec/graphql/resolvers/ci/group_runners_resolver_spec.rb" - "./spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb" - "./spec/graphql/resolvers/merge_request_pipelines_resolver_spec.rb" -- "./spec/graphql/resolvers/projects_resolver_spec.rb" - "./spec/graphql/types/ci/job_token_scope_type_spec.rb" - "./spec/helpers/packages_helper_spec.rb" - "./spec/lib/api/entities/package_spec.rb" @@ -284,7 +273,6 @@ - "./spec/models/ci/pipeline_spec.rb" - "./spec/models/ci/runner_spec.rb" - "./spec/models/clusters/applications/runner_spec.rb" -- "./spec/models/concerns/chronic_duration_attribute_spec.rb" - "./spec/models/deployment_spec.rb" - "./spec/models/environment_spec.rb" - "./spec/models/environment_status_spec.rb" @@ -298,7 +286,6 @@ - "./spec/requests/api/ci/pipelines_spec.rb" - "./spec/requests/api/ci/runner/jobs_put_spec.rb" - "./spec/requests/api/ci/runner/jobs_request_post_spec.rb" -- "./spec/requests/api/ci/runner/jobs_trace_spec.rb" - "./spec/requests/api/ci/runner/runners_post_spec.rb" - "./spec/requests/api/ci/runners_spec.rb" - "./spec/requests/api/commit_statuses_spec.rb" @@ -325,11 +312,9 @@ - "./spec/requests/api/graphql/project/pipeline_spec.rb" - "./spec/requests/api/merge_requests_spec.rb" - "./spec/requests/api/package_files_spec.rb" -- "./spec/requests/api/projects_spec.rb" - "./spec/requests/projects/cycle_analytics_events_spec.rb" - "./spec/serializers/build_details_entity_spec.rb" - "./spec/serializers/ci/pipeline_entity_spec.rb" -- "./spec/serializers/merge_request_poll_widget_entity_spec.rb" - "./spec/serializers/merge_request_serializer_spec.rb" - "./spec/serializers/pipeline_details_entity_spec.rb" - "./spec/serializers/pipeline_serializer_spec.rb" @@ -353,7 +338,6 @@ - "./spec/services/ci/retry_build_service_spec.rb" - "./spec/services/ci/retry_pipeline_service_spec.rb" - "./spec/services/ci/update_build_queue_service_spec.rb" -- "./spec/services/ci/update_runner_service_spec.rb" - "./spec/services/clusters/applications/prometheus_config_service_spec.rb" - "./spec/services/deployments/older_deployments_drop_service_spec.rb" - "./spec/services/environments/auto_stop_service_spec.rb" @@ -388,7 +372,6 @@ - "./spec/support/shared_examples/features/showing_user_status_shared_examples.rb" - "./spec/support/shared_examples/features/variable_list_shared_examples.rb" - "./spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb" -- "./spec/support/shared_examples/models/cluster_application_status_shared_examples.rb" - "./spec/support/shared_examples/models/concerns/limitable_shared_examples.rb" - "./spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb" - "./spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb" |