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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-09-14 12:11:32 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-09-14 12:11:32 +0300
commit7b69070a7468c4a9b6fe0ed7fbf1b3f2b58434e0 (patch)
tree58e4ce0c7dbbe3442a707e53701ede51139f1c24
parent5628b1ec1507638b47fda279b2a70b526a36613f (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue8
-rw-r--r--app/controllers/concerns/issuable_collections.rb8
-rw-r--r--app/controllers/concerns/issuable_collections_action.rb4
-rw-r--r--app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb9
-rw-r--r--doc/api/admin_sidekiq_queues.md19
-rw-r--r--doc/api/graphql/reference/index.md1
-rw-r--r--doc/development/code_review.md53
-rw-r--r--doc/development/go_guide/index.md2
-rw-r--r--doc/development/query_recorder.md8
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md13
-rw-r--r--doc/user/application_security/terminology/index.md12
-rw-r--r--lib/api/admin/sidekiq.rb4
-rw-r--r--lib/gitlab/database/load_balancing/configuration.rb18
-rw-r--r--lib/gitlab/sidekiq_queue.rb15
-rw-r--r--locale/gitlab.pot3
-rwxr-xr-xscripts/static-analysis12
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb8
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb9
-rw-r--r--spec/frontend/sidebar/sidebar_labels_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js18
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js12
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js4
-rw-r--r--spec/lib/gitlab/database/load_balancing/configuration_spec.rb42
-rw-r--r--spec/lib/gitlab/sidekiq_queue_spec.rb30
-rw-r--r--spec/requests/api/admin/sidekiq_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb2
-rw-r--r--spec/support/shared_examples/controllers/issuable_anonymous_search_disabled_examples.rb55
30 files changed, 308 insertions, 79 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 14d9b7ca9f3..f5ee64f96ab 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-1418db66513d291e36fb5877b032e109763ec733
+07a81867515f925c6108033d2bb05aebfcf14bd0
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue
index 46ccb9470e5..35ac9ef8565 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue
@@ -1,5 +1,6 @@
<script>
import { GlLabel } from '@gitlab/ui';
+import { sortBy } from 'lodash';
import { mapState } from 'vuex';
import { isScopedLabel } from '~/lib/utils/common_utils';
@@ -23,6 +24,9 @@ export default {
'labelsFilterBasePath',
'labelsFilterParam',
]),
+ sortedSelectedLabels() {
+ return sortBy(this.selectedLabels, (label) => (isScopedLabel(label) ? 0 : 1));
+ },
},
methods: {
labelFilterUrl(label) {
@@ -47,7 +51,7 @@ export default {
<span v-if="!selectedLabels.length" class="text-secondary">
<slot></slot>
</span>
- <template v-for="label in selectedLabels" v-else>
+ <template v-for="label in sortedSelectedLabels" v-else>
<gl-label
:key="label.id"
data-qa-selector="selected_label_content"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
index 3575f3865ff..71d3d87cce5 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
@@ -1,5 +1,6 @@
<script>
import { GlLabel } from '@gitlab/ui';
+import { sortBy } from 'lodash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { isScopedLabel } from '~/lib/utils/common_utils';
@@ -31,6 +32,11 @@ export default {
required: true,
},
},
+ computed: {
+ sortedSelectedLabels() {
+ return sortBy(this.selectedLabels, (label) => (isScopedLabel(label) ? 0 : 1));
+ },
+ },
methods: {
labelFilterUrl(label) {
return `${this.labelsFilterBasePath}?${this.labelsFilterParam}[]=${encodeURIComponent(
@@ -60,7 +66,7 @@ export default {
</span>
<template v-else>
<gl-label
- v-for="label in selectedLabels"
+ v-for="label in sortedSelectedLabels"
:key="label.id"
data-qa-selector="selected_label_content"
:data-qa-label-name="label.title"
diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb
index d2d2e656af8..fe793a1116f 100644
--- a/app/controllers/concerns/issuable_collections.rb
+++ b/app/controllers/concerns/issuable_collections.rb
@@ -13,8 +13,16 @@ module IssuableCollections
private
+ def show_alert_if_search_is_disabled
+ return if current_user || params[:search].blank? || !html_request? || Feature.disabled?(:disable_anonymous_search, type: :ops)
+
+ flash[:notice] = _('You must sign in to search for specific terms.')
+ end
+
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def set_issuables_index
+ show_alert_if_search_is_disabled
+
@issuables = issuables_collection
unless pagination_disabled?
diff --git a/app/controllers/concerns/issuable_collections_action.rb b/app/controllers/concerns/issuable_collections_action.rb
index ca2979a5a29..b68db0e3f9f 100644
--- a/app/controllers/concerns/issuable_collections_action.rb
+++ b/app/controllers/concerns/issuable_collections_action.rb
@@ -7,6 +7,8 @@ module IssuableCollectionsAction
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def issues
+ show_alert_if_search_is_disabled
+
@issues = issuables_collection
.non_archived
.page(params[:page])
@@ -20,6 +22,8 @@ module IssuableCollectionsAction
end
def merge_requests
+ show_alert_if_search_is_disabled
+
@merge_requests = issuables_collection.page(params[:page])
@issuable_meta_data = Gitlab::IssuableMetadata.new(current_user, @merge_requests).data
diff --git a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
index d943816089f..c4f91d0c15c 100644
--- a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
+++ b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
@@ -8,13 +8,18 @@ module Mutations
ADMIN_MESSAGE = 'You must be an admin to use this mutation'
- Gitlab::ApplicationContext::KNOWN_KEYS.each do |key|
+ ::Gitlab::ApplicationContext::KNOWN_KEYS.each do |key|
argument key,
GraphQL::Types::String,
required: false,
- description: "Delete jobs matching #{key} in the context metadata"
+ description: "Delete jobs matching #{key} in the context metadata."
end
+ argument ::Gitlab::SidekiqQueue::WORKER_KEY,
+ GraphQL::Types::String,
+ required: false,
+ description: 'Delete jobs with the given worker class.'
+
argument :queue_name,
GraphQL::Types::String,
required: true,
diff --git a/doc/api/admin_sidekiq_queues.md b/doc/api/admin_sidekiq_queues.md
index d0e310ab548..569dfd4c413 100644
--- a/doc/api/admin_sidekiq_queues.md
+++ b/doc/api/admin_sidekiq_queues.md
@@ -27,15 +27,16 @@ This API endpoint is only available to administrators.
DELETE /admin/sidekiq/queues/:queue_name
```
-| Attribute | Type | Required | Description |
-| --------- | -------------- | -------- | ----------- |
-| `queue_name` | string | yes | The name of the queue to delete jobs from |
-| `user` | string | no | The username of the user who scheduled the jobs |
-| `project` | string | no | The full path of the project where the jobs were scheduled from |
-| `root_namespace` | string | no | The root namespace of the project |
-| `subscription_plan` | string | no | The subscription plan of the root namespace (GitLab.com only) |
-| `caller_id` | string | no | The endpoint or background job that schedule the job (for example: `ProjectsController#create`, `/api/:version/projects/:id`, `PostReceive`) |
-| `feature_category` | string | no | The feature category of the background job (for example: `issue_tracking` or `code_review`) |
+| Attribute | Type | Required | Description |
+|---------------------|--------|----------|----------------------------------------------------------------------------------------------------------------------------------------------|
+| `queue_name` | string | yes | The name of the queue to delete jobs from |
+| `user` | string | no | The username of the user who scheduled the jobs |
+| `project` | string | no | The full path of the project where the jobs were scheduled from |
+| `root_namespace` | string | no | The root namespace of the project |
+| `subscription_plan` | string | no | The subscription plan of the root namespace (GitLab.com only) |
+| `caller_id` | string | no | The endpoint or background job that schedule the job (for example: `ProjectsController#create`, `/api/:version/projects/:id`, `PostReceive`) |
+| `feature_category` | string | no | The feature category of the background job (for example: `issue_tracking` or `code_review`) |
+| `worker_class` | string | no | The class of the background job worker (for example: `PostReceive` or `MergeWorker`) |
At least one attribute, other than `queue_name`, is required.
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 83d3e67e5fc..7fc8e6638ed 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -563,6 +563,7 @@ Input type: `AdminSidekiqQueuesDeleteJobsInput`
| <a id="mutationadminsidekiqqueuesdeletejobsrootnamespace"></a>`rootNamespace` | [`String`](#string) | Delete jobs matching root_namespace in the context metadata. |
| <a id="mutationadminsidekiqqueuesdeletejobssubscriptionplan"></a>`subscriptionPlan` | [`String`](#string) | Delete jobs matching subscription_plan in the context metadata. |
| <a id="mutationadminsidekiqqueuesdeletejobsuser"></a>`user` | [`String`](#string) | Delete jobs matching user in the context metadata. |
+| <a id="mutationadminsidekiqqueuesdeletejobsworkerclass"></a>`workerClass` | [`String`](#string) | Delete jobs with the given worker class. |
#### Fields
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index cc19c981d8c..12cc63ef56d 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -137,9 +137,54 @@ with [domain expertise](#domain-experts).
the content.
- (*4*): End-to-end changes include all files within the `qa` directory.
-#### Security requirements
+#### Acceptance checklist
-View the updated documentation regarding [internal application security reviews](https://about.gitlab.com/handbook/engineering/security/#internal-application-security-reviews) for **when** and **how** to request a security review.
+This checklist encourages the authors, reviewers, and maintainers of merge requests (MRs) to confirm changes were analyzed for high-impact risks to quality, performance, reliability, security, and maintainability.
+
+Using checklists improves quality in software engineering. This checklist is a straightforward tool to support and bolster the skills of contributors to the GitLab codebase.
+
+##### Quality
+
+See the [test engineering process](https://about.gitlab.com/handbook/engineering/quality/test-engineering/) for further quality guidelines.
+
+1. I have self-reviewed this MR per [code review guidelines](code_review.md).
+1. For the code that this change impacts, I believe that the automated tests ([Testing Guide](testing_guide/index.md)) validate functionality that is highly important to users (including consideration of [all test levels](testing_guide/testing_levels.md)).
+1. If the existing automated tests do not cover the above functionality, I have added the necessary additional tests or added an issue to describe the automation testing gap and linked it to this MR.
+1. I have considered the technical aspects of this change's impact on GitLab.com hosted customers and self-managed customers.
+1. I have considered the impact of this change on the frontend, backend, and database portions of the system where appropriate and applied the `~frontend`, `~backend`, and `~database` labels accordingly.
+1. I have tested this MR in [all supported browsers](../install/requirements.md#supported-web-browsers), or determined that this testing is not needed.
+1. I have confirmed that this change is [backwards compatible across updates](multi_version_compatibility.md), or I have decided that this does not apply.
+1. I have properly separated EE content from FOSS, or this MR is FOSS only.
+ - [Where should EE code go?](ee_features.md#separation-of-ee-code)
+1. If I am introducing a new expectation for existing data, I have confirmed that existing data meets this expectation or I have made this expectation optional rather than required.
+
+##### Performance, reliability, and availability
+
+1. I am confident that this MR does not harm performance, or I have asked a reviewer to help assess the performance impact. ([Merge request performance guidelines](merge_request_performance_guidelines.md))
+1. I have added [information for database reviewers in the MR description](database_review.md#required), or I have decided that it is unnecessary.
+ - [Does this MR have database-related changes?](database_review.md)
+1. I have considered the availability and reliability risks of this change.
+1. I have considered the scalability risk based on future predicted growth.
+1. I have considered the performance, reliability, and availability impacts of this change on large customers who may have significantly more data than the average customer.
+
+##### Documentation
+
+1. I have included changelog trailers, or I have decided that they are not needed.
+ - [Does this MR need a changelog?](changelog.md#what-warrants-a-changelog-entry)
+1. I have added/updated documentation or decided that documentation changes are unnecessary for this MR.
+ - [Is documentation required?](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#when-documentation-is-required)
+
+##### Security
+
+1. I have confirmed that if this MR contains changes to processing or storing of credentials or tokens, authorization, and authentication methods, or other items described in [the security review guidelines](https://about.gitlab.com/handbook/engineering/security/#when-to-request-a-security-review), I have added the `~security` label and I have `@`-mentioned `@gitlab-com/gl-security/appsec`.
+1. I have reviewed the documentation regarding [internal application security reviews](https://about.gitlab.com/handbook/engineering/security/#internal-application-security-reviews) for **when** and **how** to request a security review and requested a security review if this is warranted for this change.
+
+##### Deployment
+
+1. I have considered using a feature flag for this change because the change may be high risk.
+1. If I am using a feature flag, I plan to test the change in staging before I test it in production, and I have considered rolling it out to a subset of production customers before rolling it out to all customers.
+ - [When to use a feature flag](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#when-to-use-feature-flags)
+1. I have informed the Infrastructure department of a default setting or new setting change per [definition of done](contributing/merge_request_workflow.md#definition-of-done), or decided that this is unnecessary.
### The responsibility of the merge request author
@@ -529,7 +574,7 @@ author.
GitLab is used in a lot of places. Many users use
our [Omnibus packages](https://about.gitlab.com/install/), but some use
-the [Docker images](https://docs.gitlab.com/omnibus/docker/), some are
+the [Docker images](../install/docker.md), some are
[installed from source](../install/installation.md),
and there are other installation methods available. GitLab.com itself is a large
Enterprise Edition instance. This has some implications:
@@ -569,7 +614,7 @@ Enterprise Edition instance. This has some implications:
If you're adding a new setting in `gitlab.yml`:
1. Try to avoid that, and add to `ApplicationSetting` instead.
1. Ensure that it is also
- [added to Omnibus](https://docs.gitlab.com/omnibus/settings/gitlab.yml.html#adding-a-new-setting-to-gitlab-yml).
+ [added to Omnibus](https://docs.gitlab.com/omnibus/settings/gitlab.yml#adding-a-new-setting-to-gitlabyml).
1. **File system access** is not possible in a [cloud-native architecture](architecture.md#adapting-existing-and-introducing-new-components).
Ensure that we support object storage for any file storage we need to perform. For more
information, see the [uploads documentation](uploads.md).
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index 5da981a7a17..0ee73da48db 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -65,7 +65,7 @@ Remember to run
[SAST](../../user/application_security/sast/index.md) and [Dependency Scanning](../../user/application_security/dependency_scanning/index.md)
**(ULTIMATE)** on your project (or at least the
[`gosec` analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/gosec)),
-and to follow our [Security requirements](../code_review.md#security-requirements).
+and to follow our [Security requirements](../code_review.md#security).
Web servers can take advantages of middlewares like [Secure](https://github.com/unrolled/secure).
diff --git a/doc/development/query_recorder.md b/doc/development/query_recorder.md
index 8759bd09538..424c089f88e 100644
--- a/doc/development/query_recorder.md
+++ b/doc/development/query_recorder.md
@@ -18,9 +18,9 @@ This style of test works by counting the number of SQL queries executed by Activ
```ruby
it "avoids N+1 database queries" do
- control_count = ActiveRecord::QueryRecorder.new { visit_some_page }.count
+ control = ActiveRecord::QueryRecorder.new { visit_some_page }
create_list(:issue, 5)
- expect { visit_some_page }.not_to exceed_query_limit(control_count)
+ expect { visit_some_page }.not_to exceed_query_limit(control)
end
```
@@ -37,9 +37,9 @@ You should pass the `skip_cached` variable to `QueryRecorder` and use the `excee
```ruby
it "avoids N+1 database queries", :use_sql_query_cache do
- control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { visit_some_page }.count
+ control = ActiveRecord::QueryRecorder.new(skip_cached: false) { visit_some_page }
create_list(:issue, 5)
- expect { visit_some_page }.not_to exceed_all_query_limit(control_count)
+ expect { visit_some_page }.not_to exceed_all_query_limit(control)
end
```
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index 2048cc48000..0d5eb2b6d50 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -82,7 +82,7 @@ The `my_fuzz_target` job (the separate job for your fuzz target) does the follow
- Runs on a fuzz stage that usually comes after a test stage.
The `gitlab-cov-fuzz` is a command-line tool that runs the instrumented application. It parses and
-analyzes the exception information that the fuzzer outputs. It also downloads the [corpus](#glossary)
+analyzes the exception information that the fuzzer outputs. It also downloads the [corpus](../terminology/index.md#corpus)
and crash events from previous pipelines automatically. This helps your fuzz targets build on the
progress of previous fuzzing jobs. The parsed crash events and data are written to
`gl-coverage-fuzzing-report.json`.
@@ -127,7 +127,7 @@ any option available in the underlying fuzzing engine.
| `COVFUZZ_SEED_CORPUS` | Path to a seed corpus directory. The default is empty. |
| `COVFUZZ_URL_PREFIX` | Path to the `gitlab-cov-fuzz` repository cloned for use with an offline environment. You should only change this when using an offline environment. The default value is `https://gitlab.com/gitlab-org/security-products/analyzers/gitlab-cov-fuzz/-/raw`. |
-The files in the seed corpus (`COVFUZZ_SEED_CORPUS`), if provided, aren't updated unless you commit new
+The files in the [seed corpus](../terminology/index.md#seed-corpus) (`COVFUZZ_SEED_CORPUS`), if provided, aren't updated unless you commit new
files to your Git repository. There's usually no need to frequently update the seed corpus. As part
of the GitLab artifacts system, GitLab saves in a corpus directory the new test cases that every run
generates. In any subsequent runs, GitLab also reuses the generated corpus together with the seed
@@ -262,12 +262,3 @@ vulnerability:
- Scanner: The scanner that detected the vulnerability (for example, Coverage Fuzzing).
- Scanner Provider: The engine that did the scan. For Coverage Fuzzing, this can be any of the
engines listed in [Supported fuzzing engines and languages](#supported-fuzzing-engines-and-languages).
-
-### Glossary
-
-- Seed corpus: The set of test cases given as initial input to the fuzz target. This usually speeds
- up the fuzz target substantially. This can be either manually created test cases or auto-generated
- with the fuzz target itself from previous runs.
-- Corpus: The set of meaningful test cases that are generated while the fuzzer is running. Each
- meaningful test case produces new coverage in the tested program. It's advised to re-use the
- corpus and pass it to subsequent runs.
diff --git a/doc/user/application_security/terminology/index.md b/doc/user/application_security/terminology/index.md
index c96497e9233..8277c30b81f 100644
--- a/doc/user/application_security/terminology/index.md
+++ b/doc/user/application_security/terminology/index.md
@@ -38,6 +38,12 @@ The different places in an application that are vulnerable to attack. Secure pro
search the attack surface during scans. Each product defines the attack surface differently. For
example, SAST uses files and line numbers, and DAST uses URLs.
+### Corpus
+
+The set of meaningful test cases that are generated while the fuzzer is running. Each meaningful
+test case produces new coverage in the tested program. It's advised to re-use the corpus and pass it
+to subsequent runs.
+
### CVE
Common Vulnerabilities and Exposures (CVE®) is a list of common identifiers for publicly known
@@ -142,6 +148,12 @@ A standard report format that Secure products comply with when creating JSON rep
Provides an overview of all the vulnerabilities for a project, group, or GitLab instance.
Vulnerabilities are only created from findings discovered on the project's default branch.
+### Seed corpus
+
+The set of test cases given as initial input to the fuzz target. This usually speeds up the fuzz
+target substantially. This can be either manually created test cases or auto-generated with the fuzz
+target itself from previous runs.
+
### Vendor
The party maintaining an analyzer. As such, a vendor is responsible for integrating a scanner into
diff --git a/lib/api/admin/sidekiq.rb b/lib/api/admin/sidekiq.rb
index d91d4a0d4d5..05eb7f8222b 100644
--- a/lib/api/admin/sidekiq.rb
+++ b/lib/api/admin/sidekiq.rb
@@ -12,11 +12,11 @@ module API
namespace 'queues' do
desc 'Drop jobs matching the given metadata from the Sidekiq queue'
params do
- Gitlab::ApplicationContext::KNOWN_KEYS.each do |key|
+ Gitlab::SidekiqQueue::ALLOWED_KEYS.each do |key|
optional key, type: String, allow_blank: false
end
- at_least_one_of(*Gitlab::ApplicationContext::KNOWN_KEYS)
+ at_least_one_of(*Gitlab::SidekiqQueue::ALLOWED_KEYS)
end
delete ':queue_name' do
result =
diff --git a/lib/gitlab/database/load_balancing/configuration.rb b/lib/gitlab/database/load_balancing/configuration.rb
index c874825c98a..238f55fd98e 100644
--- a/lib/gitlab/database/load_balancing/configuration.rb
+++ b/lib/gitlab/database/load_balancing/configuration.rb
@@ -7,7 +7,7 @@ module Gitlab
class Configuration
attr_accessor :hosts, :max_replication_difference,
:max_replication_lag_time, :replica_check_interval,
- :service_discovery, :pool_size, :model
+ :service_discovery, :model
# Creates a configuration object for the given ActiveRecord model.
def self.for_model(model)
@@ -15,10 +15,6 @@ module Gitlab
lb_cfg = cfg[:load_balancing] || {}
config = new(model)
- if (size = cfg[:pool])
- config.pool_size = size
- end
-
if (diff = lb_cfg[:max_replication_difference])
config.max_replication_difference = diff
end
@@ -54,7 +50,6 @@ module Gitlab
@replica_check_interval = 60.0
@model = model
@hosts = hosts
- @pool_size = Database.default_pool_size
@service_discovery = {
nameserver: 'localhost',
port: 8600,
@@ -66,6 +61,17 @@ module Gitlab
}
end
+ def pool_size
+ # The pool size may change when booting up GitLab, as GitLab enforces
+ # a certain number of threads. If a Configuration is memoized, this
+ # can lead to incorrect pool sizes.
+ #
+ # To support this scenario, we always attempt to read the pool size
+ # from the model's configuration.
+ @model.connection_db_config.configuration_hash[:pool] ||
+ Database.default_pool_size
+ end
+
def load_balancing_enabled?
hosts.any? || service_discovery_enabled?
end
diff --git a/lib/gitlab/sidekiq_queue.rb b/lib/gitlab/sidekiq_queue.rb
index eb3a8e3d497..67a9d8120d8 100644
--- a/lib/gitlab/sidekiq_queue.rb
+++ b/lib/gitlab/sidekiq_queue.rb
@@ -7,6 +7,9 @@ module Gitlab
NoMetadataError = Class.new(StandardError)
InvalidQueueError = Class.new(StandardError)
+ WORKER_KEY = 'worker_class'
+ ALLOWED_KEYS = Gitlab::ApplicationContext::KNOWN_KEYS + [WORKER_KEY]
+
attr_reader :queue_name
def initialize(queue_name)
@@ -21,8 +24,8 @@ module Gitlab
job_search_metadata =
search_metadata
.stringify_keys
- .slice(*Gitlab::ApplicationContext::KNOWN_KEYS)
- .transform_keys { |key| "meta.#{key}" }
+ .slice(*ALLOWED_KEYS)
+ .transform_keys(&method(:transform_key))
.compact
raise NoMetadataError if job_search_metadata.empty?
@@ -49,6 +52,14 @@ module Gitlab
private
+ def transform_key(key)
+ if Gitlab::ApplicationContext::KNOWN_KEYS.include?(key)
+ "meta.#{key}"
+ elsif key == WORKER_KEY
+ 'class'
+ end
+ end
+
def queue
strong_memoize(:queue) do
# Sidekiq::Queue.new always returns a queue, even if it doesn't
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 9d30f0de0e5..376c2bc1ef8 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -38695,6 +38695,9 @@ msgstr ""
msgid "You must provide your current password in order to change it."
msgstr ""
+msgid "You must sign in to search for specific terms."
+msgstr ""
+
msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
diff --git a/scripts/static-analysis b/scripts/static-analysis
index 6ad7c0b19c3..de5a1b407f9 100755
--- a/scripts/static-analysis
+++ b/scripts/static-analysis
@@ -27,6 +27,16 @@ class StaticAnalysis
end
end
+ def self.project_path
+ project_root = File.expand_path('..', __dir__)
+
+ if Gitlab.jh?
+ "#{project_root}/jh"
+ else
+ project_root
+ end
+ end
+
# `gettext:updated_check` and `gitlab:sidekiq:sidekiq_queues_yml:check` will fail on FOSS installations
# (e.g. gitlab-org/gitlab-foss) since they test against a single
# file that is generated by an EE installation, which can
@@ -42,7 +52,7 @@ class StaticAnalysis
Task.new(%w[bundle exec rubocop --parallel], 60),
Task.new(%w[yarn run lint:prettier], 160),
Task.new(%w[bin/rake gettext:lint], 85),
- Task.new(%w[bundle exec license_finder], 20),
+ Task.new(%W[bundle exec license_finder --decisions-file config/dependency_decisions.yml --project-path #{project_path}], 20),
Task.new(%w[bin/rake lint:static_verification], 35),
Task.new(%w[bin/rake config_lint], 10),
Task.new(%w[bin/rake gitlab:sidekiq:all_queues_yml:check], 15),
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index b3b9941062d..980264bef5c 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -109,6 +109,14 @@ RSpec.describe Projects::IssuesController do
end
end
+ it_behaves_like 'issuable list with anonymous search disabled' do
+ let(:params) { { namespace_id: project.namespace, project_id: project } }
+
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ end
+ end
+
it_behaves_like 'paginated collection' do
let!(:issue_list) { create_list(:issue, 2, project: project) }
let(:collection) { project.issues }
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 7b5a58fe2e5..0da8a30611c 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -349,6 +349,15 @@ RSpec.describe Projects::MergeRequestsController do
end
end
end
+
+ it_behaves_like 'issuable list with anonymous search disabled' do
+ let(:params) { { namespace_id: project.namespace, project_id: project } }
+
+ before do
+ sign_out(user)
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ end
+ end
end
describe 'PUT update' do
diff --git a/spec/frontend/sidebar/sidebar_labels_spec.js b/spec/frontend/sidebar/sidebar_labels_spec.js
index ab08a1e65e2..7455f684380 100644
--- a/spec/frontend/sidebar/sidebar_labels_spec.js
+++ b/spec/frontend/sidebar/sidebar_labels_spec.js
@@ -156,7 +156,7 @@ describe('sidebar labels', () => {
variables: {
input: {
iid: defaultProps.iid,
- labelIds: [toLabelGid(27), toLabelGid(28), toLabelGid(29), toLabelGid(40)],
+ labelIds: [toLabelGid(29), toLabelGid(28), toLabelGid(27), toLabelGid(40)],
operationMode: MutationOperationMode.Replace,
projectPath: defaultProps.projectPath,
},
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
index a1942e59571..e39e8794fdd 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
@@ -124,7 +124,7 @@ describe('DropdownContentsLabelsView', () => {
});
it('returns false when provided `label` param is not one of the selected labels', () => {
- expect(wrapper.vm.isLabelSelected(mockLabels[2])).toBe(false);
+ expect(wrapper.vm.isLabelSelected(mockLabels[1])).toBe(false);
});
});
@@ -203,7 +203,7 @@ describe('DropdownContentsLabelsView', () => {
it('calls action `updateSelectedLabels` with currently highlighted label when Enter key is pressed', () => {
jest.spyOn(wrapper.vm, 'updateSelectedLabels').mockImplementation();
wrapper.setData({
- currentHighlightItem: 1,
+ currentHighlightItem: 2,
});
wrapper.vm.handleKeyDown({
@@ -213,7 +213,7 @@ describe('DropdownContentsLabelsView', () => {
expect(wrapper.vm.updateSelectedLabels).toHaveBeenCalledWith([
{
- ...mockLabels[1],
+ ...mockLabels[2],
set: true,
},
]);
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js
index c90e63313b2..960ea77cb6e 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js
@@ -6,7 +6,7 @@ import DropdownValue from '~/vue_shared/components/sidebar/labels_select_vue/dro
import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store';
-import { mockConfig, mockRegularLabel, mockScopedLabel } from './mock_data';
+import { mockConfig, mockLabels, mockRegularLabel, mockScopedLabel } from './mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -14,6 +14,9 @@ localVue.use(Vuex);
describe('DropdownValue', () => {
let wrapper;
+ const findAllLabels = () => wrapper.findAllComponents(GlLabel);
+ const findLabel = (index) => findAllLabels().at(index).props('title');
+
const createComponent = (initialState = {}, slots = {}) => {
const store = new Vuex.Store(labelsSelectModule());
@@ -28,7 +31,6 @@ describe('DropdownValue', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
describe('methods', () => {
@@ -82,7 +84,17 @@ describe('DropdownValue', () => {
it('renders labels when `selectedLabels` is not empty', () => {
createComponent();
- expect(wrapper.findAll(GlLabel).length).toBe(2);
+ expect(findAllLabels()).toHaveLength(2);
+ });
+
+ it('orders scoped labels first', () => {
+ createComponent({ selectedLabels: mockLabels });
+
+ expect(findAllLabels()).toHaveLength(mockLabels.length);
+ expect(findLabel(0)).toBe('Foo::Bar');
+ expect(findLabel(1)).toBe('Boog');
+ expect(findLabel(2)).toBe('Bug');
+ expect(findLabel(3)).toBe('Foo Label');
});
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
index 730afcbecab..1faa3b0af1d 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
@@ -15,22 +15,22 @@ export const mockScopedLabel = {
};
export const mockLabels = [
- mockRegularLabel,
- mockScopedLabel,
{
- id: 28,
- title: 'Bug',
+ id: 29,
+ title: 'Boog',
description: 'Label for bugs',
color: '#FF0000',
textColor: '#FFFFFF',
},
{
- id: 29,
- title: 'Boog',
+ id: 28,
+ title: 'Bug',
description: 'Label for bugs',
color: '#FF0000',
textColor: '#FFFFFF',
},
+ mockRegularLabel,
+ mockScopedLabel,
];
export const mockCollapsedLabels = [
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js
index 6dcd0e4e8ac..e7e78cd7a33 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js
@@ -9,8 +9,8 @@ describe('DropdownValue', () => {
let wrapper;
const findAllLabels = () => wrapper.findAllComponents(GlLabel);
- const findRegularLabel = () => findAllLabels().at(0);
- const findScopedLabel = () => findAllLabels().at(1);
+ const findRegularLabel = () => findAllLabels().at(1);
+ const findScopedLabel = () => findAllLabels().at(0);
const findWrapper = () => wrapper.find('[data-testid="value-wrapper"]');
const findEmptyPlaceholder = () => wrapper.find('[data-testid="empty-placeholder"]');
diff --git a/spec/lib/gitlab/database/load_balancing/configuration_spec.rb b/spec/lib/gitlab/database/load_balancing/configuration_spec.rb
index 4102c96d509..6621e6276a5 100644
--- a/spec/lib/gitlab/database/load_balancing/configuration_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/configuration_spec.rb
@@ -3,14 +3,14 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::LoadBalancing::Configuration do
- describe '.for_model' do
- let(:model) do
- config = ActiveRecord::DatabaseConfigurations::HashConfig
- .new('main', 'test', configuration_hash)
+ let(:model) do
+ config = ActiveRecord::DatabaseConfigurations::HashConfig
+ .new('main', 'test', configuration_hash)
- double(:model, connection_db_config: config)
- end
+ double(:model, connection_db_config: config)
+ end
+ describe '.for_model' do
context 'when load balancing is not configured' do
let(:configuration_hash) { {} }
@@ -142,4 +142,34 @@ RSpec.describe Gitlab::Database::LoadBalancing::Configuration do
expect(config.service_discovery_enabled?).to eq(false)
end
end
+
+ describe '#pool_size' do
+ context 'when a custom pool size is used' do
+ let(:configuration_hash) { { pool: 4 } }
+
+ it 'always reads the value from the model configuration' do
+ config = described_class.new(model)
+
+ expect(config.pool_size).to eq(4)
+
+ # We can't modify `configuration_hash` as it's only used to populate the
+ # internal hash used by ActiveRecord; instead of it being used as-is.
+ allow(model.connection_db_config)
+ .to receive(:configuration_hash)
+ .and_return({ pool: 42 })
+
+ expect(config.pool_size).to eq(42)
+ end
+ end
+
+ context 'when the pool size is nil' do
+ let(:configuration_hash) { {} }
+
+ it 'returns the default pool size' do
+ config = described_class.new(model)
+
+ expect(config.pool_size).to eq(Gitlab::Database.default_pool_size)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/sidekiq_queue_spec.rb b/spec/lib/gitlab/sidekiq_queue_spec.rb
index 2ab32657f0e..5e91282612e 100644
--- a/spec/lib/gitlab/sidekiq_queue_spec.rb
+++ b/spec/lib/gitlab/sidekiq_queue_spec.rb
@@ -4,15 +4,15 @@ require 'spec_helper'
RSpec.describe Gitlab::SidekiqQueue, :clean_gitlab_redis_queues do
around do |example|
- Sidekiq::Queue.new('authorized_projects').clear
+ Sidekiq::Queue.new('default').clear
Sidekiq::Testing.disable!(&example)
- Sidekiq::Queue.new('authorized_projects').clear
+ Sidekiq::Queue.new('default').clear
end
- def add_job(user, args)
+ def add_job(args, user:, klass: 'AuthorizedProjectsWorker')
Sidekiq::Client.push(
- 'class' => 'AuthorizedProjectsWorker',
- 'queue' => 'authorized_projects',
+ 'class' => klass,
+ 'queue' => 'default',
'args' => args,
'meta.user' => user.username
)
@@ -20,13 +20,13 @@ RSpec.describe Gitlab::SidekiqQueue, :clean_gitlab_redis_queues do
describe '#drop_jobs!' do
shared_examples 'queue processing' do
- let(:sidekiq_queue) { described_class.new('authorized_projects') }
+ let(:sidekiq_queue) { described_class.new('default') }
let_it_be(:sidekiq_queue_user) { create(:user) }
before do
- add_job(create(:user), [1])
- add_job(sidekiq_queue_user, [2])
- add_job(sidekiq_queue_user, [3])
+ add_job([1], user: create(:user))
+ add_job([2], user: sidekiq_queue_user, klass: 'MergeWorker')
+ add_job([3], user: sidekiq_queue_user)
end
context 'when the queue is not processed in time' do
@@ -68,11 +68,19 @@ RSpec.describe Gitlab::SidekiqQueue, :clean_gitlab_redis_queues do
end
end
+ context 'when there are jobs matching the class name' do
+ include_examples 'queue processing' do
+ let(:search_metadata) { { user: sidekiq_queue_user.username, worker_class: 'AuthorizedProjectsWorker' } }
+ let(:timeout_deleted) { 1 }
+ let(:no_timeout_deleted) { 1 }
+ end
+ end
+
context 'when there are no valid metadata keys passed' do
it 'raises NoMetadataError' do
- add_job(create(:user), [1])
+ add_job([1], user: create(:user))
- expect { described_class.new('authorized_projects').drop_jobs!({ username: 'sidekiq_queue_user' }, timeout: 1) }
+ expect { described_class.new('default').drop_jobs!({ username: 'sidekiq_queue_user' }, timeout: 1) }
.to raise_error(described_class::NoMetadataError)
end
end
diff --git a/spec/requests/api/admin/sidekiq_spec.rb b/spec/requests/api/admin/sidekiq_spec.rb
index 3c488816bed..1e626c90e7e 100644
--- a/spec/requests/api/admin/sidekiq_spec.rb
+++ b/spec/requests/api/admin/sidekiq_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe API::Admin::Sidekiq, :clean_gitlab_redis_queues do
add_job(admin, [2])
add_job(create(:user), [3])
- delete api("/admin/sidekiq/queues/authorized_projects?user=#{admin.username}", admin)
+ delete api("/admin/sidekiq/queues/authorized_projects?user=#{admin.username}&worker_class=AuthorizedProjectsWorker", admin)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to eq('completed' => true,
diff --git a/spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb b/spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb
index 1692cfbcf84..f992e46879f 100644
--- a/spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb
+++ b/spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Deleting Sidekiq jobs', :clean_gitlab_redis_queues do
let(:queue) { 'authorized_projects' }
- let(:variables) { { user: admin.username, queue_name: queue } }
+ let(:variables) { { user: admin.username, worker_class: 'AuthorizedProjectsWorker', queue_name: queue } }
let(:mutation) { graphql_mutation(:admin_sidekiq_queues_delete_jobs, variables) }
def mutation_response
diff --git a/spec/support/shared_examples/controllers/issuable_anonymous_search_disabled_examples.rb b/spec/support/shared_examples/controllers/issuable_anonymous_search_disabled_examples.rb
new file mode 100644
index 00000000000..ea2d348a700
--- /dev/null
+++ b/spec/support/shared_examples/controllers/issuable_anonymous_search_disabled_examples.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'issuable list with anonymous search disabled' do |action|
+ let(:controller_action) { :index }
+ let(:params_with_search) { params.merge(search: 'some search term') }
+
+ context 'when disable_anonymous_search is enabled' do
+ before do
+ stub_feature_flags(disable_anonymous_search: true)
+ end
+
+ it 'shows a flash message' do
+ get controller_action, params: params_with_search
+
+ expect(flash[:notice]).to eq('You must sign in to search for specific terms.')
+ end
+
+ context 'when search param is not given' do
+ it 'does not show a flash message' do
+ get controller_action, params: params
+
+ expect(flash[:notice]).to be_nil
+ end
+ end
+
+ context 'when user is signed-in' do
+ it 'does not show a flash message' do
+ sign_in(create(:user))
+ get controller_action, params: params_with_search
+
+ expect(flash[:notice]).to be_nil
+ end
+ end
+
+ context 'when format is not HTML' do
+ it 'does not show a flash message' do
+ get controller_action, params: params_with_search.merge(format: :atom)
+
+ expect(flash[:notice]).to be_nil
+ end
+ end
+ end
+
+ context 'when disable_anonymous_search is disabled' do
+ before do
+ stub_feature_flags(disable_anonymous_search: false)
+ end
+
+ it 'does not show a flash message' do
+ get controller_action, params: params_with_search
+
+ expect(flash[:notice]).to be_nil
+ end
+ end
+end