Commit 07f86bcd authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 1f5bbf3f 61decce7
......@@ -23,6 +23,7 @@ query getFiles(
$nextPageCursor: String
) {
project(fullPath: $projectPath) {
id
__typename
repository {
__typename
......
query pathLastCommit($projectPath: ID!, $path: String, $ref: String!) {
project(fullPath: $projectPath) {
id
__typename
repository {
__typename
......
query getPermissions($projectPath: ID!) {
project(fullPath: $projectPath) {
id
__typename
userPermissions {
__typename
......
......@@ -643,7 +643,7 @@ class Note < ApplicationRecord
user_visible_reference_count > 0 && user_visible_reference_count == total_reference_count
else
refs = all_references(user)
refs.all.any? && refs.stateful_not_visible_counter == 0
refs.all.any? && refs.all_visible?
end
end
......
......@@ -5,7 +5,7 @@ module Projects
def execute(source_project, remove_remaining_elements: true)
return unless super
Project.transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
Project.transaction do
move_deploy_keys_projects
remove_remaining_deploy_keys_projects if remove_remaining_elements
......
......@@ -5,7 +5,7 @@ module Projects
def execute(source_project, remove_remaining_elements: true)
return unless super && source_project.fork_network
Project.transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
Project.transaction do
move_fork_network_members
update_root_project
refresh_forks_count
......
......@@ -5,7 +5,7 @@ module Projects
def execute(source_project, remove_remaining_elements: true)
return unless super
Project.transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
Project.transaction do
move_lfs_objects_projects
remove_remaining_lfs_objects_project if remove_remaining_elements
......
......@@ -5,7 +5,7 @@ module Projects
def execute(source_project, remove_remaining_elements: true)
return unless super
Project.transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
Project.transaction do
move_notification_settings
remove_remaining_notification_settings if remove_remaining_elements
......
......@@ -9,7 +9,7 @@ module Projects
def execute(source_project, remove_remaining_elements: true)
return unless super
Project.transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
Project.transaction do
move_project_authorizations
remove_remaining_authorizations if remove_remaining_elements
......
......@@ -9,7 +9,7 @@ module Projects
def execute(source_project, remove_remaining_elements: true)
return unless super
Project.transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
Project.transaction do
move_group_links
remove_remaining_project_group_links if remove_remaining_elements
......
......@@ -9,7 +9,7 @@ module Projects
def execute(source_project, remove_remaining_elements: true)
return unless super
Project.transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
Project.transaction do
move_project_members
remove_remaining_members if remove_remaining_elements
......
......@@ -9,7 +9,7 @@ module Projects
return unless user_stars.any?
Project.transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
Project.transaction do
user_stars.update_all(project_id: @project.id)
Project.reset_counters @project.id, :users_star_projects
......
......@@ -30,7 +30,7 @@
},
"status": {
"type": ["string"],
"enum": ["data_available", "implemented", "not_used", "deprecated", "removed", "broken"]
"enum": ["active", "data_available", "implemented", "deprecated", "removed", "broken"]
},
"milestone": {
"type": ["string", "null"],
......
......@@ -20,7 +20,7 @@ class ScheduleExtractProjectTopicsIntoSeparateTable < ActiveRecord::Migration[6.
def up
# this index is used in 20210730104800_schedule_extract_project_topics_into_separate_table
add_concurrent_index :taggings, :id, where: INDEX_CONDITION, name: INDEX_NAME
add_concurrent_index :taggings, :id, where: INDEX_CONDITION, name: INDEX_NAME # rubocop:disable Migration/PreventIndexCreation
queue_background_migration_jobs_by_range_at_intervals(
Tagging.where(taggable_type: 'Project'),
......
......@@ -220,7 +220,8 @@ You can use a GitLab CI/CD job token to authenticate with specific API endpoints
Package Registry, you can use [deploy tokens](../user/project/deploy_tokens/index.md).
- [Container Registry](../user/packages/container_registry/index.md)
(the `$CI_REGISTRY_PASSWORD` is `$CI_JOB_TOKEN`).
- [Container Registry API](container_registry.md) (scoped to the job's project, when the `ci_job_token_scope` feature flag is enabled)
- [Container Registry API](container_registry.md)
(scoped to the job's project, when the `ci_job_token_scope` feature flag is enabled).
- [Get job artifacts](job_artifacts.md#get-job-artifacts).
- [Get job token's job](jobs.md#get-job-tokens-job).
- [Pipeline triggers](pipeline_triggers.md), using the `token=` parameter.
......@@ -682,7 +683,7 @@ send the payload body:
```shell
curl --request POST --header "Content-Type: application/json" \
--data '{"name":"<example-name>", "description":"<example-description"}' "https://gitlab/api/v4/projects"
--data '{"name":"<example-name>", "description":"<example-description>"}' "https://gitlab/api/v4/projects"
```
URL encoded query strings have a length limitation. Requests that are too large
......
......@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Validate the CI YAML configuration
Checks if CI/CD YAML configuration is valid. This endpoint validates basic CI/CD
configuration syntax. It doesn't have any namespace specific context.
configuration syntax. It doesn't have any namespace-specific context.
Access to this endpoint does not require authentication when the instance
[allows new sign ups](../user/admin_area/settings/sign_up_restrictions.md#disable-new-sign-ups)
......
......@@ -37,7 +37,7 @@ Example response:
product_group: group::global search
product_category: global_search
value_type: number
status: data_available
status: active
time_frame: 28d
data_source: redis_hll
distribution:
......
......@@ -34,7 +34,7 @@ Each metric is defined in a separate YAML file consisting of a number of fields:
| `product_group` | yes | The [group](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml) that owns the metric. |
| `product_category` | no | The [product category](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml) for the metric. |
| `value_type` | yes | `string`; one of [`string`, `number`, `boolean`, `object`](https://json-schema.org/understanding-json-schema/reference/type.html). |
| `status` | yes | `string`; [status](#metric-statuses) of the metric, may be set to `data_available`, `implemented`, `not_used`, `deprecated`, `removed`, `broken`. |
| `status` | yes | `string`; [status](#metric-statuses) of the metric, may be set to `active`, `deprecated`, `removed`, `broken`. |
| `time_frame` | yes | `string`; may be set to a value like `7d`, `28d`, `all`, `none`. |
| `data_source` | yes | `string`; may be set to a value like `database`, `redis`, `redis_hll`, `prometheus`, `system`. |
| `data_category` | yes | `string`; [categories](#data-category) of the metric, may be set to `operational`, `optional`, `subscription`, `standard`. The default value is `optional`.|
......@@ -53,11 +53,8 @@ Each metric is defined in a separate YAML file consisting of a number of fields:
Metric definitions can have one of the following statuses:
- `data_available`: Metric data is available and used in a Sisense dashboard.
- `implemented`: Metric is implemented but data is not yet available. This is a temporary
status for newly added metrics awaiting inclusion in a new release.
- `active`: Metric is used and reports data.
- `broken`: Metric reports broken data (for example, -1 fallback), or does not report data at all. A metric marked as `broken` must also have the `repair_issue_url` attribute.
- `not_used`: Metric is not used in any dashboard.
- `deprecated`: Metric is deprecated and possibly planned to be removed.
- `removed`: Metric was removed, but it may appear in Service Ping payloads sent from instances running on older versions of GitLab.
......@@ -177,7 +174,7 @@ product_section: growth
product_stage: growth
product_group: group::product intelligence
value_type: string
status: data_available
status: active
milestone: 9.1
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1521
time_frame: none
......
......@@ -60,10 +60,7 @@ API calls made with a project access token are associated with the corresponding
These bot users are included in a project's **Project information > Members** list but cannot be modified. Also, a bot
user cannot be added to any other project.
- The username is set to `project_{project_id}_bot` for the first access token, such as `project_123_bot`.
- The username is set to `project_{project_id}_bot{bot_count}` for further access tokens, such as `project_123_bot1`.
When the project access token is [revoked](#revoking-a-project-access-token) the bot user is deleted
When the project access token is [revoked](#revoking-a-project-access-token), the bot user is deleted
and all records are moved to a system-wide user with the username "Ghost User". For more
information, see [Associated Records](../../profile/account/delete_account.md#associated-records).
......
......@@ -212,9 +212,8 @@ module Banzai
def gather_references(nodes, ids_only: false)
nodes = nodes_user_can_reference(current_user, nodes)
visible = nodes_visible_to_user(current_user, nodes)
not_visible = nodes - visible
{ visible: referenced_by(visible, ids_only: ids_only), not_visible: not_visible }
{ visible: referenced_by(visible, ids_only: ids_only), nodes: nodes, visible_nodes: visible }
end
# Returns a Hash containing the projects for a given list of HTML nodes.
......
......@@ -6,16 +6,11 @@ module Gitlab
REFERABLES = %i(user issue label milestone mentioned_user mentioned_group mentioned_project
merge_request snippet commit commit_range directly_addressed_user epic iteration vulnerability).freeze
attr_accessor :project, :current_user, :author
# This counter is increased by a number of references filtered out by
# banzai reference exctractor. Note that this counter is stateful and
# not idempotent and is increased whenever you call `references`.
attr_reader :stateful_not_visible_counter
def initialize(project, current_user = nil)
@project = project
@current_user = current_user
@references = {}
@stateful_not_visible_counter = 0
super()
end
......@@ -26,14 +21,19 @@ module Gitlab
def references(type, ids_only: false)
refs = super(type, project, current_user, ids_only: ids_only)
@stateful_not_visible_counter += refs[:not_visible].count
update_visible_nodes_set(refs[:nodes], refs[:visible_nodes])
refs[:visible]
end
# this method is stateful, it tracks if all nodes from `references`
# calls are visible or not
def all_visible?
not_visible_nodes.empty?
end
def reset_memoized_values
@references = {}
@stateful_not_visible_counter = 0
super()
end
......@@ -76,5 +76,16 @@ module Gitlab
@pattern = Regexp.union(patterns.compact)
end
private
def update_visible_nodes_set(all, visible)
not_visible_nodes.merge(all)
not_visible_nodes.subtract(visible)
end
def not_visible_nodes
@not_visible_nodes ||= Set.new
end
end
end
# frozen_string_literal: true
namespace :gitlab do
namespace :product_intelligence do
# @example
# bundle exec rake gitlab:product_intelligence:activate_metrics MILESTONE=14.0
desc 'GitLab | Product Intelligence | Update milestone metrics status to data_available'
task activate_metrics: :environment do
milestone = ENV['MILESTONE']
raise "Please supply the MILESTONE env var".color(:red) unless milestone.present?
Gitlab::Usage::MetricDefinition.definitions.values.each do |metric|
next if metric.attributes[:milestone] != milestone || metric.attributes[:status] != 'implemented'
metric.attributes[:status] = 'data_available'
path = metric.path
File.open(path, "w") { |file| file << metric.to_h.deep_stringify_keys.to_yaml }
end
puts "Task completed successfully"
end
end
end
......@@ -8,7 +8,7 @@ module RuboCop
class PreventIndexCreation < RuboCop::Cop::Cop
include MigrationHelpers
FORBIDDEN_TABLES = %i[ci_builds].freeze
FORBIDDEN_TABLES = %i[ci_builds taggings ci_builds_metadata events].freeze
MSG = "Adding new index to #{FORBIDDEN_TABLES.join(", ")} is forbidden, see https://gitlab.com/gitlab-org/gitlab/-/issues/332886"
......
......@@ -247,15 +247,15 @@ RSpec.describe Banzai::ReferenceParser::BaseParser do
end
end
it 'returns referenceable and visible objects, alongside nodes that are referenceable but not visible' do
expect(subject.gather_references(nodes)).to match(
visible: contain_exactly(6, 8, 10),
not_visible: match_array(nodes.select { |n| n.id.even? && n.id <= 5 })
)
it 'returns referenceable and visible objects, alongside all and visible nodes' do
referenceable = nodes.select { |n| n.id.even? }
visible = nodes.select { |n| [6, 8, 10].include?(n.id) }
expect_gathered_references(subject.gather_references(nodes), [6, 8, 10], referenceable, visible)
end
it 'is always empty if the input is empty' do
expect(subject.gather_references([])) .to match(visible: be_empty, not_visible: be_empty)
expect_gathered_references(subject.gather_references([]), [], [], [])
end
end
......
......@@ -19,7 +19,7 @@ RSpec.describe Banzai::ReferenceParser::MentionedGroupParser do
it 'returns empty array' do
link['data-group'] = project.group.id.to_s
expect_gathered_references(subject.gather_references([link]), [], 1)
expect_gathered_references(subject.gather_references([link]), [], [link], [])
end
end
......@@ -30,7 +30,7 @@ RSpec.describe Banzai::ReferenceParser::MentionedGroupParser do
end
it 'returns groups' do
expect_gathered_references(subject.gather_references([link]), [group], 0)
expect_gathered_references(subject.gather_references([link]), [group], [link], [link])
end
end
......@@ -38,7 +38,7 @@ RSpec.describe Banzai::ReferenceParser::MentionedGroupParser do
it 'returns an empty Array' do
link['data-group'] = 'test-non-existing'
expect_gathered_references(subject.gather_references([link]), [], 1)
expect_gathered_references(subject.gather_references([link]), [], [link], [])
end
end
end
......
......@@ -19,7 +19,7 @@ RSpec.describe Banzai::ReferenceParser::MentionedProjectParser do
it 'returns empty Array' do
link['data-project'] = project.id.to_s
expect_gathered_references(subject.gather_references([link]), [], 1)
expect_gathered_references(subject.gather_references([link]), [], [link], [])
end
end
......@@ -30,7 +30,7 @@ RSpec.describe Banzai::ReferenceParser::MentionedProjectParser do
end
it 'returns an Array of referenced projects' do
expect_gathered_references(subject.gather_references([link]), [project], 0)
expect_gathered_references(subject.gather_references([link]), [project], [link], [link])
end
end
......@@ -38,7 +38,7 @@ RSpec.describe Banzai::ReferenceParser::MentionedProjectParser do
it 'returns an empty Array' do
link['data-project'] = 'inexisting-project-id'
expect_gathered_references(subject.gather_references([link]), [], 1)
expect_gathered_references(subject.gather_references([link]), [], [link], [])
end
end
end
......
......@@ -22,7 +22,7 @@ RSpec.describe Banzai::ReferenceParser::MentionedUserParser do
end
it 'returns empty list of users' do
expect_gathered_references(subject.gather_references([link]), [], 0)
expect_gathered_references(subject.gather_references([link]), [], [link], [link])
end
end
end
......@@ -35,7 +35,7 @@ RSpec.describe Banzai::ReferenceParser::MentionedUserParser do
end
it 'returns empty list of users' do
expect_gathered_references(subject.gather_references([link]), [], 0)
expect_gathered_references(subject.gather_references([link]), [], [link], [link])
end
end
end
......@@ -44,7 +44,7 @@ RSpec.describe Banzai::ReferenceParser::MentionedUserParser do
it 'returns an Array of users' do
link['data-user'] = user.id.to_s
expect_gathered_references(subject.gather_references([link]), [user], 0)
expect_gathered_references(subject.gather_references([link]), [user], [link], [link])
end
end
end
......
......@@ -17,7 +17,7 @@ RSpec.describe Banzai::ReferenceParser::ProjectParser do
it 'returns an Array of projects' do
link['data-project'] = project.id.to_s
expect_gathered_references(subject.gather_references([link]), [project], 0)
expect_gathered_references(subject.gather_references([link]), [project], [link], [link])
end
end
......@@ -25,7 +25,7 @@ RSpec.describe Banzai::ReferenceParser::ProjectParser do
it 'returns an empty Array' do
link['data-project'] = ''
expect_gathered_references(subject.gather_references([link]), [], 1)
expect_gathered_references(subject.gather_references([link]), [], [link], [])
end
end
......@@ -35,7 +35,7 @@ RSpec.describe Banzai::ReferenceParser::ProjectParser do
link['data-project'] = private_project.id.to_s
expect_gathered_references(subject.gather_references([link]), [], 1)
expect_gathered_references(subject.gather_references([link]), [], [link], [])
end
it 'returns an Array when authorized' do
......@@ -43,7 +43,7 @@ RSpec.describe Banzai::ReferenceParser::ProjectParser do
link['data-project'] = private_project.id.to_s
expect_gathered_references(subject.gather_references([link]), [private_project], 0)
expect_gathered_references(subject.gather_references([link]), [private_project], [link], [link])
end
end
end
......
......@@ -332,14 +332,59 @@ RSpec.describe Gitlab::ReferenceExtractor do
it 'returns visible references of given type' do
expect(subject.references(:issue)).to eq([issue])
end
end
it 'does not increase stateful_not_visible_counter' do
expect { subject.references(:issue) }.not_to change { subject.stateful_not_visible_counter }
end
it 'does not return any references' do
expect(subject.references(:issue)).to be_empty
end
end
describe '#all_visible?' do
let_it_be(:user) { create(:user) }
let_it_be(:project2) { create(:project) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:issue2) { create(:issue, project: project2) }
let(:text) { "Ref. #{issue.to_reference} and #{issue2.to_reference(project)}" }
subject { described_class.new(project, user) }
before do
subject.analyze(text)
end
it 'increases stateful_not_visible_counter' do
expect { subject.references(:issue) }.to change { subject.stateful_not_visible_counter }.by(1)
it 'returns true if no references were parsed yet' do
expect(subject.all_visible?).to be_truthy
end
context 'when references was already called' do
let(:membership) { [] }
before do
membership.each { |p| p.add_developer(user) }
subject.references(:issue)
end
it 'returns false' do
expect(subject.all_visible?).to be_falsey
end
context 'when user can access only some references' do
let(:membership) { [project] }
it 'returns false' do
expect(subject.all_visible?).to be_falsey
end
end
context 'when user can access all references' do
let(:membership) { [project, project2] }
it 'returns true' do
expect(subject.all_visible?).to be_truthy
end
end
end
end
end
......@@ -9,7 +9,7 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
value_type: 'string',
product_category: 'collection',
product_stage: 'growth',
status: 'data_available',
status: 'active',
default_generation: 'generation_1',
key_path: 'uuid',
product_group: 'group::product analytics',
......@@ -127,9 +127,7 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
where(:status, :skip_validation?) do
'deprecated' | true
'removed' | true
'data_available' | false
'implemented' | false
'not_used' | false
'active' | false
end
with_them do
......@@ -191,7 +189,7 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
value_type: 'string',
product_category: 'collection',
product_stage: 'growth',
status: 'data_available',
status: 'active',
default_generation: 'generation_1',
key_path: 'counter.category.event',
product_group: 'group::product analytics',
......
......@@ -15,7 +15,7 @@ RSpec.describe Gitlab::Usage::Metric do
product_group: "group::plan",
product_category: "issue_tracking",
value_type: "number",
status: "data_available",
status: "active",
time_frame: "all",
data_source: "database",
instrumentation_class: "CountIssuesMetric",
......
......@@ -500,15 +500,15 @@ RSpec.describe Note do
let_it_be(:ext_issue) { create(:issue, project: ext_proj) }
shared_examples "checks references" do
it "returns true" do
it "returns false" do
expect(note.system_note_with_references_visible_for?(ext_issue.author)).to be_falsy
end
it "returns false" do
it "returns true" do
expect(note.system_note_with_references_visible_for?(private_user)).to be_truthy
end
it "returns false if user visible reference count set" do
it "returns true if user visible reference count set" do
note.user_visible_reference_count = 1
note.total_reference_count = 1
......@@ -516,7 +516,15 @@ RSpec.describe Note do
expect(note.system_note_with_references_visible_for?(ext_issue.author)).to be_truthy
end
it "returns true if ref count is 0" do
it "returns false if user visible reference count set but does not match total reference count" do
note.user_visible_reference_count = 1
note.total_reference_count = 2
expect(note).not_to receive(:reference_mentionables)
expect(note.system_note_with_references_visible_for?(ext_issue.author)).to be_falsy
end
it "returns false if ref count is 0" do
note.user_visible_reference_count = 0
expect(note).not_to receive(:reference_mentionables)
......@@ -562,13 +570,35 @@ RSpec.describe Note do
end
it_behaves_like "checks references"
end
it "returns true if user visible reference count set and there is a private reference" do
note.user_visible_reference_count = 1
note.total_reference_count = 2
context "when there is a private issue and user reference" do
let_it_be(:ext_issue2) { create(:issue, project: ext_proj) }
expect(note).not_to receive(:reference_mentionables)
expect(note.system_note_with_references_visible_for?(ext_issue.author)).to be_falsy
let(:note) do
create :note,
noteable: ext_issue2, project: ext_proj,
note: "mentioned in #{private_issue.to_reference(ext_proj)} and pinged user #{private_user.to_reference}",
system: true
end
it_behaves_like "checks references"
end
context "when there is a publicly visible user reference" do
let(:note) do
create :note,
noteable: ext_issue, project: ext_proj,
note: "mentioned in #{ext_proj.owner.to_reference}",
system: true
end
it "returns true for other users" do
expect(note.system_note_with_references_visible_for?(ext_issue.author)).to be_truthy
end
it "returns true for anonymous users" do
expect(note.system_note_with_references_visible_for?(nil)).to be_truthy
end
end
end
......
......@@ -6,28 +6,35 @@ require_relative '../../../../rubocop/cop/migration/prevent_index_creation'
RSpec.describe RuboCop::Cop::Migration::PreventIndexCreation do
subject(:cop) { described_class.new }
let(:forbidden_tables) { %w(ci_builds taggings ci_builds_metadata events) }
let(:forbidden_tables_list) { forbidden_tables.join(', ') }
context 'when in migration' do
before do
allow(cop).to receive(:in_migration?).and_return(true)
end
context 'when adding an index to a forbidden table' do
it 'registers an offense when add_index is used' do
expect_offense(<<~RUBY)
def change
add_index :ci_builds, :protected
^^^^^^^^^ Adding new index to ci_builds is forbidden, see https://gitlab.com/gitlab-org/gitlab/-/issues/332886
end
RUBY
it "registers an offense when add_index is used", :aggregate_failures do
forbidden_tables.each do |table|
expect_offense(<<~RUBY)
def change
add_index :#{table}, :protected
^^^^^^^^^ Adding new index to #{forbidden_tables_list} is forbidden, see https://gitlab.com/gitlab-org/gitlab/-/issues/332886
end
RUBY
end
end
it 'registers an offense when add_concurrent_index is used' do
expect_offense(<<~RUBY)
def change
add_concurrent_index :ci_builds, :protected
^^^^^^^^^^^^^^^^^^^^ Adding new index to ci_builds is forbidden, see https://gitlab.com/gitlab-org/gitlab/-/issues/332886
end
RUBY
it "registers an offense when add_concurrent_index is used", :aggregate_failures do
forbidden_tables.each do |table|
expect_offense(<<~RUBY)
def change
add_concurrent_index :#{table}, :protected
^^^^^^^^^^^^^^^^^^^^ Adding new index to #{forbidden_tables_list} is forbidden, see https://gitlab.com/gitlab-org/gitlab/-/issues/332886
end
RUBY
end
end
end
......
......@@ -5,9 +5,10 @@ module ReferenceParserHelpers
Nokogiri::HTML.fragment('<a></a>').children[0]
end
def expect_gathered_references(result, visible, not_visible_count)
def expect_gathered_references(result, visible, nodes, visible_nodes)
expect(result[:visible]).to eq(visible)
expect(result[:not_visible].count).to eq(not_visible_count)
expect(result[:nodes]).to eq(nodes)
expect(result[:visible_nodes]).to eq(visible_nodes)
end
RSpec.shared_examples 'no project N+1 queries' do
......
# frozen_string_literal: true
require 'rake_helper'
RSpec.describe 'gitlab:product_intelligence:activate_metrics', :silence_stdout do
def fake_metric(key_path, milestone: 'test_milestone', status: 'implemented')
Gitlab::Usage::MetricDefinition.new(key_path, { key_path: key_path, milestone: milestone, status: status })
end
before do
Rake.application.rake_require 'tasks/gitlab/product_intelligence'
stub_warn_user_is_not_gitlab
end
describe 'activate_metrics' do
it 'fails if the MILESTONE env var is not set' do
stub_env('MILESTONE' => nil)
expect { run_rake_task('gitlab:product_intelligence:activate_metrics') }.to raise_error(RuntimeError, 'Please supply the MILESTONE env var')
end
context 'with MILESTONE env var' do
subject do
updated_metrics = []
file = double('file')
allow(file).to receive(:<<) { |contents| updated_metrics << YAML.safe_load(contents) }
allow(File).to receive(:open).and_yield(file)
stub_env('MILESTONE' => 'test_milestone')
run_rake_task('gitlab:product_intelligence:activate_metrics')
updated_metrics
end
let(:metric_definitions) do
{
matching_metric: fake_metric('matching_metric'),
matching_metric2: fake_metric('matching_metric2'),
other_status_metric: fake_metric('other_status_metric', status: 'deprecated'),
other_milestone_metric: fake_metric('other_milestone_metric', milestone: 'other_milestone')
}
end
before do
allow(Gitlab::Usage::MetricDefinition).to receive(:definitions).and_return(metric_definitions)
end
context 'with metric matching status and milestone' do
it 'updates matching_metric yaml file' do
expect(subject).to eq([
{ 'key_path' => 'matching_metric', 'milestone' => 'test_milestone', 'status' => 'data_available' },
{ 'key_path' => 'matching_metric2', 'milestone' => 'test_milestone', 'status' => 'data_available' }
])
end
end
context 'without metrics definitions' do
let(:metric_definitions) { {} }
it 'runs successfully with no updates' do
expect(subject).to eq([])
end
end
context 'without matching metrics' do
let(:metric_definitions) do
{
other_status_metric: fake_metric('other_status_metric', status: 'deprecated'),
other_milestone_metric: fake_metric('other_milestone_metric', milestone: 'other_milestone')
}
end
it 'runs successfully with no updates' do
expect(subject).to eq([])
end
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment