提交 76784ebd 编写于 作者: G GitLab Bot

Add latest changes from gitlab-org/gitlab@master

上级 3174adc7
# frozen_string_literal: true
module CheckCodeownerRules
extend ActiveSupport::Concern
def codeowners_check_error(project, branch_name, paths)
::Gitlab::CodeOwners::Validator.new(project, branch_name, paths).execute
end
end
......@@ -9,6 +9,7 @@ class Projects::BlobController < Projects::ApplicationController
include ActionView::Helpers::SanitizeHelper
include RedirectsForMissingPathOnTree
include SourcegraphDecorator
include CheckCodeownerRules
prepend_before_action :authenticate_user!, only: [:edit]
......@@ -28,6 +29,7 @@ class Projects::BlobController < Projects::ApplicationController
before_action :editor_variables, except: [:show, :preview, :diff]
before_action :validate_diff_params, only: :diff
before_action :set_last_commit_sha, only: [:edit, :update]
before_action :validate_codeowner_rules, only: [:create, :update]
before_action only: :show do
push_frontend_feature_flag(:code_navigation, @project)
......@@ -71,6 +73,7 @@ class Projects::BlobController < Projects::ApplicationController
def update
@path = params[:file_path] if params[:file_path].present?
create_commit(Files::UpdateService, success_path: -> { after_edit_path },
failure_view: :edit,
failure_path: project_blob_path(@project, @id))
......@@ -115,6 +118,19 @@ class Projects::BlobController < Projects::ApplicationController
private
def validate_codeowner_rules
return if params[:file_path].blank?
codeowners_error = codeowners_check_error(@project, @branch_name, params[:file_path])
if codeowners_error.present?
flash.now[:alert] = codeowners_error
view = params[:action] == 'update' ? :edit : :new
render view
end
end
def blob
@blob ||= @repository.blob_at(@commit.id, @path)
......
......@@ -249,9 +249,7 @@ module Projects
end
end
# rubocop: disable Cop/InjectEnterpriseEditionModule
Projects::CreateService.prepend_if_ee('EE::Projects::CreateService')
# rubocop: enable Cop/InjectEnterpriseEditionModule
# Measurable should be at the bottom of the ancestor chain, so it will measure execution of EE::Projects::CreateService as well
Projects::CreateService.prepend(Measurable)
......@@ -149,9 +149,7 @@ module Projects
end
end
# rubocop: disable Cop/InjectEnterpriseEditionModule
Projects::ImportService.prepend_if_ee('EE::Projects::ImportService')
# rubocop: enable Cop/InjectEnterpriseEditionModule
# Measurable should be at the bottom of the ancestor chain, so it will measure execution of EE::Projects::ImportService as well
Projects::ImportService.prepend(Measurable)
......@@ -49,7 +49,8 @@ module Spam
# ask the SpamVerdictService what to do with the target.
spam_verdict_service.execute.tap do |result|
case result
when REQUIRE_RECAPTCHA
when CONDITIONAL_ALLOW
# at the moment, this means "ask for reCAPTCHA"
create_spam_log(api)
break if target.allow_possible_spam?
......
......@@ -2,7 +2,7 @@
module Spam
module SpamConstants
REQUIRE_RECAPTCHA = "recaptcha"
CONDITIONAL_ALLOW = "conditional_allow"
DISALLOW = "disallow"
ALLOW = "allow"
BLOCK_USER = "block"
......@@ -14,7 +14,7 @@ module Spam
DISALLOW => {
priority: 2
},
REQUIRE_RECAPTCHA => {
CONDITIONAL_ALLOW => {
priority: 3
},
ALLOW => {
......
......@@ -31,7 +31,7 @@ module Spam
def akismet_verdict
if akismet.spam?
Gitlab::Recaptcha.enabled? ? REQUIRE_RECAPTCHA : DISALLOW
Gitlab::Recaptcha.enabled? ? CONDITIONAL_ALLOW : DISALLOW
else
ALLOW
end
......
此差异已折叠。
......@@ -111,6 +111,14 @@ module WorkerAttributes
1
end
def tags(*values)
worker_attributes[:tags] = values
end
def get_tags
Array(worker_attributes[:tags])
end
protected
# Returns a worker attribute declared on this class or its parent class.
......
---
title: Add tags to experimental queue selector attributes
merge_request: 32651
author:
type: added
---
title: Groups API has top_level_only option to exclude subgroups
merge_request: 32870
author:
type: added
---
title: Skip the individual JIRA issues if failed to import vs failing the whole batch
merge_request: 32673
author:
type: fixed
......@@ -126,6 +126,8 @@ in a more general way using the following components:
### Available attributes
- [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/261) in GitLab 13.1, `tags`.
From the [list of all available
attributes](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml),
`experimental_queue_selector` allows selecting of queues by the
......@@ -144,14 +146,21 @@ following attributes:
- `name` - the queue name. The other attributes are typically more useful as
they are more general, but this is available in case a particular queue needs
to be selected.
- `resource_boundary` - if the worker is bound by `cpu`, `memory`, or
- `resource_boundary` - if the queue is bound by `cpu`, `memory`, or
`unknown`. For example, the `project_export` queue is memory bound as it has
to load data in memory before saving it for export.
- `tags` - short-lived annotations for queues. These are expected to frequently
change from release to release, and may be removed entirely.
`has_external_dependencies` is a boolean attribute: only the exact
string `true` is considered true, and everything else is considered
false.
`tags` is a set, which means that `=` checks for intersecting sets, and
`!=` checks for disjoint sets. For example, `tags=a,b` selects queues
that have tags `a`, `b`, or both. `tags!=a,b` selects queues that have
neither of those tags.
### Available operators
`experimental_queue_selector` supports the following operators, listed
......
......@@ -20,6 +20,7 @@ Parameters:
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
| `owned` | boolean | no | Limit to groups explicitly owned by the current user |
| `min_access_level` | integer | no | Limit to groups where current user has at least this [access level](members.md) |
| `top_level_only` | boolean | no | Limit to top level groups, excluding all subgroups |
```plaintext
GET /groups
......
......@@ -3790,7 +3790,7 @@ Example:
.something_after: &something_after
- echo 'something after'
- echo 'another thing after'
job_name:
before_script:
......
......@@ -61,8 +61,12 @@ This helps maintain a logical connection and consistency between tools (e.g.
### Formality
The level of formality used in software varies by language.
For example, in French we translate `you` as the formal `vous`.
The level of formality used in software varies by language:
| Language | Formality | Example |
| -------- | --------- | ------- |
| French | formal | `vous` for `you` |
| German | informal | `du` for `you` |
You can refer to other translated strings and notes in the glossary to assist
determining a suitable level of formality.
......
......@@ -605,24 +605,22 @@ There are two formats of data in the JSON report that are used side by side:
### Other formats
Reports can also be generated in Markdown, HTML, and XML.
Reports can be published as artifacts using the following configuration:
Reports can also be generated in Markdown, HTML, and XML. These can be published as artifacts using the following configuration:
```yaml
include:
template: DAST.gitlab-ci.yml
dast:
script:
- export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)}
- /analyze -r report.html -w report.md -x report.xml -t $DAST_WEBSITE
- cp /zap/wrk/report.{html,md,xml} "$PWD"
variables:
DAST_HTML_REPORT: report.html
DAST_MARKDOWN_REPORT: report.md
DAST_XML_REPORT: report.xml
artifacts:
paths:
- report.html
- report.md
- report.xml
- $DAST_HTML_REPORT
- $DAST_MARKDOWN_REPORT
- $DAST_XML_REPORT
- gl-dast-report.json
```
......
......@@ -23,13 +23,20 @@ module API
optional :order_by, type: String, values: %w[name path id], default: 'name', desc: 'Order by name, path or id'
optional :sort, type: String, values: %w[asc desc], default: 'asc', desc: 'Sort by asc (ascending) or desc (descending)'
optional :min_access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'Minimum access level of authenticated user'
optional :top_level_only, type: Boolean, desc: 'Only include top level groups'
use :pagination
end
# rubocop: disable CodeReuse/ActiveRecord
def find_groups(params, parent_id = nil)
find_params = params.slice(:all_available, :custom_attributes, :owned, :min_access_level)
find_params[:parent] = find_group!(parent_id) if parent_id
find_params[:parent] = if params[:top_level_only]
[nil]
elsif parent_id
find_group!(parent_id)
end
find_params[:all_available] =
find_params.fetch(:all_available, current_user&.can_read_all_resources?)
......
......@@ -57,17 +57,27 @@ module Gitlab
# For such cases we exit early if issue was already imported.
next if already_imported?(jira_issue.id)
issue_attrs = IssueSerializer.new(project, jira_issue, running_import.user_id, { iid: next_iid }).execute
Gitlab::JiraImport::ImportIssueWorker.perform_async(project.id, jira_issue.id, issue_attrs, job_waiter.key)
job_waiter.jobs_remaining += 1
next_iid += 1
# Mark the issue as imported immediately so we don't end up
# importing it multiple times within same import.
# These ids are cleaned-up when import finishes.
# see Gitlab::JiraImport::Stage::FinishImportWorker
mark_as_imported(jira_issue.id)
begin
issue_attrs = IssueSerializer.new(project, jira_issue, running_import.user_id, { iid: next_iid }).execute
Gitlab::JiraImport::ImportIssueWorker.perform_async(project.id, jira_issue.id, issue_attrs, job_waiter.key)
job_waiter.jobs_remaining += 1
next_iid += 1
# Mark the issue as imported immediately so we don't end up
# importing it multiple times within same import.
# These ids are cleaned-up when import finishes.
# see Gitlab::JiraImport::Stage::FinishImportWorker
mark_as_imported(jira_issue.id)
rescue => ex
# handle exceptionn here and skip the failed to import issue, instead of
# failing to import the entire batch of issues
# track the failed to import issue.
Gitlab::ErrorTracking.track_exception(ex, project_id: project.id)
JiraImport.increment_issue_failures(project.id)
end
end
job_waiter
......
......@@ -14,8 +14,8 @@ module Gitlab
].compact.freeze
DEFAULT_WORKERS = [
DummyWorker.new('default', weight: 1),
DummyWorker.new('mailers', weight: 2)
DummyWorker.new('default', weight: 1, tags: []),
DummyWorker.new('mailers', weight: 2, tags: [])
].map { |worker| Gitlab::SidekiqConfig::Worker.new(worker, ee: false) }.freeze
class << self
......
......@@ -28,6 +28,7 @@ module Gitlab
has_external_dependencies: lambda { |value| value == 'true' },
name: :to_s,
resource_boundary: :to_sym,
tags: :to_sym,
urgency: :to_sym
}.freeze
......@@ -117,7 +118,11 @@ module Gitlab
raise UnknownPredicate.new("Unknown predicate: #{lhs}") unless values_block
lambda { |queue| values.map(&values_block).include?(queue[lhs.to_sym]) }
lambda do |queue|
comparator = Array(queue[lhs.to_sym]).to_set
values.map(&values_block).to_set.intersect?(comparator)
end
end
end
end
......
......@@ -12,7 +12,8 @@ module Gitlab
urgency: :get_urgency,
resource_boundary: :get_worker_resource_boundary,
idempotent: :idempotent?,
weight: :get_weight
weight: :get_weight,
tags: :get_tags
}.freeze
def initialize(queue, attributes = {})
......
......@@ -6,7 +6,7 @@ module Gitlab
include Comparable
attr_reader :klass
delegate :feature_category_not_owned?, :get_feature_category,
delegate :feature_category_not_owned?, :get_feature_category, :get_tags,
:get_urgency, :get_weight, :get_worker_resource_boundary,
:idempotent?, :queue, :queue_namespace,
:worker_has_external_dependencies?,
......@@ -52,7 +52,8 @@ module Gitlab
urgency: get_urgency,
resource_boundary: get_worker_resource_boundary,
weight: get_weight,
idempotent: idempotent?
idempotent: idempotent?,
tags: get_tags
}
end
......
......@@ -2,9 +2,8 @@
module RuboCop
module Cop
# Cop that blacklists the injecting of EE specific modules anywhere but on
# the last line of a file. Injecting a module in the middle of a file will
# cause merge conflicts, while placing it on the last line will not.
# Cop that blacklists the injecting of EE specific modules before any lines which are not already injecting another module.
# It allows multiple module injections as long as they're all at the end.
class InjectEnterpriseEditionModule < RuboCop::Cop::Cop
INVALID_LINE = 'Injecting EE modules must be done on the last line of this file' \
', outside of any class or module definitions'
......@@ -17,10 +16,12 @@ module RuboCop
CHECK_LINE_METHODS =
Set.new(%i[include_if_ee extend_if_ee prepend_if_ee]).freeze
CHECK_LINE_METHODS_REGEXP = Regexp.union(CHECK_LINE_METHODS.map(&:to_s)).freeze
DISALLOW_METHODS = Set.new(%i[include extend prepend]).freeze
COMMENT_OR_EMPTY_LINE = /^\s*(#.*|$)/.freeze
CHECK_LINE_METHODS_REGEXP = Regexp.union((CHECK_LINE_METHODS + DISALLOW_METHODS).map(&:to_s) + [COMMENT_OR_EMPTY_LINE]).freeze
def ee_const?(node)
line = node.location.expression.source_line
......@@ -44,15 +45,11 @@ module RuboCop
line = node.location.line
buffer = node.location.expression.source_buffer
last_line = buffer.last_line
lines = buffer.source.split("\n")
# We allow multiple includes, extends and prepends as long as they're all at the end.
allowed_line = (line...last_line).all? { |i| CHECK_LINE_METHODS_REGEXP.match?(lines[i - 1]) }
# Parser treats the final newline (if present) as a separate line,
# meaning that a simple `line < last_line` would yield true even though
# the expression is the last line _of code_.
last_line -= 1 if buffer.source.end_with?("\n")
last_line_content = buffer.source.split("\n")[-1]
if CHECK_LINE_METHODS_REGEXP.match?(last_line_content)
if allowed_line
ignore_node(node)
elsif line < last_line
add_offense(node, message: INVALID_LINE)
......
......@@ -250,6 +250,56 @@ describe Projects::BlobController do
end
end
shared_examples "file matches a codeowners rule" do
let(:error_msg) { "Example error msg" }
it "renders to the edit page with an error msg" do
default_params[:file_path] = "CHANGELOG"
expect_next_instance_of(Gitlab::CodeOwners::Validator) do |validator|
expect(validator).to receive(:execute).and_return(error_msg)
end
subject
expect(flash[:alert]).to eq(error_msg)
expect(response).to render_template(expected_view)
end
end
describe 'POST create' do
let(:user) { create(:user) }
let(:default_params) do
{
namespace_id: project.namespace,
project_id: project,
id: 'master',
branch_name: 'master',
file_name: 'CHANGELOG',
content: 'Added changes',
commit_message: 'Create CHANGELOG'
}
end
before do
project.add_developer(user)
sign_in(user)
end
it 'redirects to blob' do
post :create, params: default_params
expect(response).to be_ok
end
it_behaves_like "file matches a codeowners rule" do
subject { post :create, params: default_params }
let(:expected_view) { :new }
end
end
describe 'PUT update' do
let(:user) { create(:user) }
let(:default_params) do
......@@ -279,6 +329,12 @@ describe Projects::BlobController do
expect(response).to redirect_to(blob_after_edit_path)
end
it_behaves_like "file matches a codeowners rule" do
subject { put :update, params: default_params }
let(:expected_view) { :edit }
end
context '?from_merge_request_iid' do
let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
let(:mr_params) { default_params.merge(from_merge_request_iid: merge_request.iid) }
......
......@@ -536,7 +536,7 @@ describe Projects::IssuesController do
before do
stub_application_setting(recaptcha_enabled: true)
expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service|
expect(verdict_service).to receive(:execute).and_return(REQUIRE_RECAPTCHA)
expect(verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW)
end
end
......@@ -851,7 +851,7 @@ describe Projects::IssuesController do
context 'when recaptcha is not verified' do
before do
expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service|
expect(verdict_service).to receive(:execute).and_return(REQUIRE_RECAPTCHA)
expect(verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW)
end
end
......@@ -1103,7 +1103,7 @@ describe Projects::IssuesController do
context 'when captcha is not verified' do
before do
expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service|
expect(verdict_service).to receive(:execute).and_return(REQUIRE_RECAPTCHA)
expect(verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW)
end
end
......
......@@ -81,7 +81,7 @@ describe 'New issue', :js do
before do
allow_next_instance_of(Spam::SpamVerdictService) do |verdict_service|
allow(verdict_service).to receive(:execute).and_return(REQUIRE_RECAPTCHA)
allow(verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW)
end
visit new_project_issue_path(project)
......
......@@ -68,7 +68,7 @@ shared_examples_for 'snippet editor' do
context 'when SpamVerdictService requires recaptcha' do
before do
expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service|
expect(verdict_service).to receive(:execute).and_return(REQUIRE_RECAPTCHA)
expect(verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW)
end
end
......
......@@ -74,6 +74,12 @@ describe GroupsFinder do
let!(:internal_subgroup) { create(:group, :internal, parent: parent_group) }
let!(:private_subgroup) { create(:group, :private, parent: parent_group) }
context 'with [nil] parent' do
it 'returns only top-level groups' do
expect(described_class.new(user, parent: [nil]).execute).to contain_exactly(parent_group)
end
end
context 'without a user' do
it 'only returns parent and public subgroups' do
expect(described_class.new(nil).execute).to contain_exactly(parent_group, public_subgroup)
......
......@@ -42,12 +42,19 @@ describe Gitlab::JiraImport::IssuesImporter do
jira_issue = Struct.new(:id)
let_it_be(:jira_issues) { [jira_issue.new(1), jira_issue.new(2)] }
def mock_issue_serializer(count)
def mock_issue_serializer(count, raise_exception_on_even_mocks: false)
serializer = instance_double(Gitlab::JiraImport::IssueSerializer, execute: { key: 'data' })
next_iid = project.issues.maximum(:iid).to_i
count.times do |i|
expect(Gitlab::JiraImport::IssueSerializer).to receive(:new)
.with(project, jira_issues[i], current_user.id, { iid: i + 1 }).and_return(serializer)
if raise_exception_on_even_mocks && i.even?
expect(Gitlab::JiraImport::IssueSerializer).to receive(:new)
.with(project, jira_issues[i], current_user.id, { iid: next_iid + 1 }).and_raise('Some error')
else
next_iid += 1
expect(Gitlab::JiraImport::IssueSerializer).to receive(:new)
.with(project, jira_issues[i], current_user.id, { iid: next_iid }).and_return(serializer)
end
end
end
......@@ -70,21 +77,22 @@ describe Gitlab::JiraImport::IssuesImporter do
end
end
context 'when there is more than one page of results' do
context 'when importing some issue raises an exception' do
before do
stub_const("#{described_class.name}::BATCH_SIZE", 2)
stub_const("#{described_class.name}::BATCH_SIZE", 3)
end
it 'schedules 3 import jobs' do
it 'schedules 2 import jobs' do
expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issues[0], jira_issues[1]])
expect(Gitlab::JiraImport::ImportIssueWorker).to receive(:perform_async).twice.times
expect(Gitlab::Cache::Import::Caching).to receive(:set_add).twice.times.and_call_original
expect(Gitlab::Cache::Import::Caching).to receive(:set_includes?).twice.times.and_call_original
mock_issue_serializer(2)
expect(Gitlab::JiraImport::ImportIssueWorker).to receive(:perform_async).once
expect(Gitlab::Cache::Import::Caching).to receive(:set_add).once.and_call_original
expect(Gitlab::Cache::Import::Caching).to receive(:set_includes?).twice.and_call_original
expect(Gitlab::ErrorTracking).to receive(:track_exception).once
mock_issue_serializer(2, raise_exception_on_even_mocks: true)
job_waiter = subject.execute
expect(job_waiter.jobs_remaining).to eq(2)
expect(job_waiter.jobs_remaining).to eq(1)
expect(Gitlab::JiraImport.get_issues_next_start_at(project.id)).to eq(2)
end
end
......
......@@ -117,28 +117,32 @@ describe Gitlab::SidekiqConfig::CliMethods do
feature_category: :category_a,
has_external_dependencies: false,
urgency: :low,
resource_boundary: :cpu
resource_boundary: :cpu,
tags: [:no_disk_io, :git_access]
},
{
name: 'a:2',
feature_category: :category_a,
has_external_dependencies: false,
urgency: :high,
resource_boundary: :none
resource_boundary: :none,
tags: [:git_access]
},
{
name: 'b',
feature_category: :category_b,
has_external_dependencies: true,
urgency: :high,
resource_boundary: :memory
resource_boundary: :memory,
tags: [:no_disk_io]
},
{
name: 'c',
feature_category: :category_c,
has_external_dependencies: false,
urgency: :throttled,
resource_boundary: :memory
resource_boundary: :memory,
tags: []
}
]
end
......@@ -177,6 +181,18 @@ describe Gitlab::SidekiqConfig::CliMethods do
'resource_boundary=memory|resource_boundary=cpu' | %w(a b c)
'resource_boundary!=memory,cpu' | %w(a:2)
# tags
'tags=no_disk_io' | %w(a b)
'tags=no_disk_io,git_access' | %w(a a:2 b)
'tags=no_disk_io|tags=git_access' | %w(a a:2 b)
'tags=no_disk_io&tags=git_access' | %w(a)
'tags!=no_disk_io' | %w(a:2 c)
'tags!=no_disk_io,git_access' | %w(c)
'tags=unknown_tag' | []
'tags!=no_disk_io' | %w(a:2 c)
'tags!=no_disk_io,git_access' | %w(c)
'tags!=unknown_tag' | %w(a a:2 b c)
# combinations
'feature_category=category_a&urgency=high' | %w(a:2)
'feature_category=category_a&urgency=high|feature_category=category_c' | %w(a:2 c)
......
......@@ -13,7 +13,8 @@ describe Gitlab::SidekiqConfig::Worker do
get_worker_resource_boundary: attributes[:resource_boundary],
get_urgency: attributes[:urgency],
worker_has_external_dependencies?: attributes[:has_external_dependencies],
idempotent?: attributes[:idempotent]
idempotent?: attributes[:idempotent],
get_tags: attributes[:tags]
)
described_class.new(inner_worker, ee: false)
......@@ -91,7 +92,8 @@ describe Gitlab::SidekiqConfig::Worker do
urgency: :low,
resource_boundary: :memory,
weight: 2,
idempotent: true
idempotent: true,
tags: []
}
attributes_b = {
......@@ -100,7 +102,8 @@ describe Gitlab::SidekiqConfig::Worker do
urgency: :high,
resource_boundary: :unknown,
weight: 3,
idempotent: false
idempotent: false,
tags: [:no_disk_io]
}
worker_a = create_worker(queue: 'a', **attributes_a)
......
......@@ -231,6 +231,27 @@ describe API::Groups do
end
end
context "when using top_level_only" do
let(:top_level_group) { create(:group, name: 'top-level-group') }
let(:subgroup) { create(:group, :nested, name: 'subgroup') }
let(:response_groups) { json_response.map { |group| group['name'] } }
before do
top_level_group.add_owner(user1)
subgroup.add_owner(user1)
end
it "doesn't return subgroups" do
get api("/groups", user1), params: { top_level_only: true }
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(response_groups).to include(top_level_group.name)
expect(response_groups).not_to include(subgroup.name)
end
end
context "when using sorting" do
let(:group3) { create(:group, name: "a#{group1.name}", path: "z#{group1.path}") }
let(:group4) { create(:group, name: "same-name", path: "y#{group1.path}") }
......
......@@ -170,6 +170,20 @@ describe RuboCop::Cop::InjectEnterpriseEditionModule do
SOURCE
end
it 'does not flag the use of `prepend_if_ee EE` as long as all injections are at the end of the file' do
expect_no_offenses(<<~SOURCE)
class Foo
end
Foo.include_if_ee('EE::Foo')
Foo.prepend_if_ee('EE::Foo')
Foo.include(Bar)
# comment on prepending Bar
Foo.prepend(Bar)
SOURCE
end
it 'autocorrects offenses by just disabling the Cop' do
source = <<~SOURCE
class Foo
......
......@@ -458,7 +458,7 @@ describe Issues::CreateService do
context 'when SpamVerdictService requires reCAPTCHA' do
before do
expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service|
expect(verdict_service).to receive(:execute).and_return(REQUIRE_RECAPTCHA)
expect(verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW)
end
end
......
......@@ -163,9 +163,9 @@ describe Spam::SpamActionService do
end
end
context 'when spam verdict service requires reCAPTCHA' do
context 'when spam verdict service conditionally allows' do
before do
allow(fake_verdict_service).to receive(:execute).and_return(REQUIRE_RECAPTCHA)
allow(fake_verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW)
end
context 'when allow_possible_spam feature flag is false' do
......
......@@ -123,8 +123,8 @@ describe Spam::SpamVerdictService do
stub_application_setting(recaptcha_enabled: true)
end
it 'returns require reCAPTCHA verdict' do
expect(subject).to eq REQUIRE_RECAPTCHA
it 'returns conditionally allow verdict' do
expect(subject).to eq CONDITIONAL_ALLOW
end
end
......
......@@ -2,7 +2,7 @@
shared_context 'includes Spam constants' do
before do
stub_const('REQUIRE_RECAPTCHA', Spam::SpamConstants::REQUIRE_RECAPTCHA)
stub_const('CONDITIONAL_ALLOW', Spam::SpamConstants::CONDITIONAL_ALLOW)
stub_const('DISALLOW', Spam::SpamConstants::DISALLOW)
stub_const('ALLOW', Spam::SpamConstants::ALLOW)
stub_const('BLOCK_USER', Spam::SpamConstants::BLOCK_USER)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册