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:
-rw-r--r--app/finders/merge_request_target_project_finder.rb2
-rw-r--r--app/graphql/types/achievements/achievement_type.rb2
-rw-r--r--app/graphql/types/achievements/user_achievement_type.rb2
-rw-r--r--app/graphql/types/alert_management/alert_type.rb4
-rw-r--r--app/graphql/types/alert_management/http_integration_type.rb2
-rw-r--r--app/graphql/types/alert_management/prometheus_integration_type.rb2
-rw-r--r--app/graphql/types/ci/group_variable_type.rb2
-rw-r--r--app/graphql/types/ci/instance_variable_type.rb2
-rw-r--r--app/graphql/types/ci/manual_variable_type.rb2
-rw-r--r--app/graphql/types/ci/pipeline_schedule_variable_type.rb2
-rw-r--r--app/graphql/types/ci/project_variable_type.rb2
-rw-r--r--app/graphql/types/commit_type.rb2
-rw-r--r--app/graphql/types/design_management/design_type.rb8
-rw-r--r--app/graphql/types/issue_type.rb6
-rw-r--r--app/graphql/types/merge_request_type.rb6
-rw-r--r--app/graphql/types/notes/discussion_type.rb2
-rw-r--r--app/graphql/types/notes/note_type.rb2
-rw-r--r--app/graphql/types/projects/services/base_service_type.rb2
-rw-r--r--app/graphql/types/projects/services/jira_service_type.rb2
-rw-r--r--app/graphql/types/snippet_type.rb2
-rw-r--r--app/graphql/types/work_item_type.rb2
-rw-r--r--app/models/project.rb1
-rw-r--r--config/feature_flags/development/hide_unaccessible_saml_branches.yml (renamed from config/feature_flags/development/complete_p_ci_builds_partitioning.yml)8
-rw-r--r--config/feature_flags/development/search_index_integrity.yml2
-rw-r--r--danger/model_validations/Dangerfile3
-rw-r--r--danger/plugins/model_validations.rb10
-rw-r--r--doc/ci/yaml/signing_examples.md2
-rw-r--r--doc/development/fe_guide/migrating_from_vuex.md5
-rw-r--r--doc/user/application_security/dependency_list/img/dependency_list_v16_3.pngbin0 -> 214557 bytes
-rw-r--r--doc/user/application_security/dependency_list/index.md24
-rw-r--r--doc/user/application_security/dependency_scanning/index.md8
-rw-r--r--doc/user/application_security/secret_detection/index.md2
-rw-r--r--doc/user/project/repository/mirror/img/mirror_error_v16_3.pngbin0 -> 7610 bytes
-rw-r--r--doc/user/project/repository/mirror/troubleshooting.md7
-rw-r--r--lib/banzai/filter/issuable_reference_expansion_filter.rb9
-rw-r--r--lib/gitlab/database/ci_builds_partitioning.rb224
-rw-r--r--lib/gitlab/database/reindexing.rb1
-rw-r--r--qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb9
-rw-r--r--qa/qa/support/helpers/plan.rb3
-rw-r--r--spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb42
-rw-r--r--spec/tooling/danger/model_validations_spec.rb106
-rw-r--r--tooling/danger/model_validations.rb42
42 files changed, 292 insertions, 274 deletions
diff --git a/app/finders/merge_request_target_project_finder.rb b/app/finders/merge_request_target_project_finder.rb
index ea1aa6d2e9e..d4a910bf226 100644
--- a/app/finders/merge_request_target_project_finder.rb
+++ b/app/finders/merge_request_target_project_finder.rb
@@ -39,3 +39,5 @@ class MergeRequestTargetProjectFinder
end
# rubocop: enable CodeReuse/ActiveRecord
end
+
+MergeRequestTargetProjectFinder.prepend_mod_with("MergeRequestTargetProjectFinder")
diff --git a/app/graphql/types/achievements/achievement_type.rb b/app/graphql/types/achievements/achievement_type.rb
index a39a58ef6f1..d733bf39a51 100644
--- a/app/graphql/types/achievements/achievement_type.rb
+++ b/app/graphql/types/achievements/achievement_type.rb
@@ -5,7 +5,7 @@ module Types
class AchievementType < BaseObject
graphql_name 'Achievement'
- connection_type_class(Types::CountableConnectionType)
+ connection_type_class Types::CountableConnectionType
authorize :read_achievement
diff --git a/app/graphql/types/achievements/user_achievement_type.rb b/app/graphql/types/achievements/user_achievement_type.rb
index 1d52ce4ef2b..7cdcb66576c 100644
--- a/app/graphql/types/achievements/user_achievement_type.rb
+++ b/app/graphql/types/achievements/user_achievement_type.rb
@@ -5,7 +5,7 @@ module Types
class UserAchievementType < BaseObject
graphql_name 'UserAchievement'
- connection_type_class(Types::CountableConnectionType)
+ connection_type_class Types::CountableConnectionType
authorize :read_user_achievement
diff --git a/app/graphql/types/alert_management/alert_type.rb b/app/graphql/types/alert_management/alert_type.rb
index c17406b3e56..eb134b74cac 100644
--- a/app/graphql/types/alert_management/alert_type.rb
+++ b/app/graphql/types/alert_management/alert_type.rb
@@ -8,8 +8,8 @@ module Types
present_using ::AlertManagement::AlertPresenter
- implements(Types::Notes::NoteableInterface)
- implements(Types::TodoableInterface)
+ implements Types::Notes::NoteableInterface
+ implements Types::TodoableInterface
authorize :read_alert_management_alert
diff --git a/app/graphql/types/alert_management/http_integration_type.rb b/app/graphql/types/alert_management/http_integration_type.rb
index bba9cb1bbfc..7c026be86a3 100644
--- a/app/graphql/types/alert_management/http_integration_type.rb
+++ b/app/graphql/types/alert_management/http_integration_type.rb
@@ -6,7 +6,7 @@ module Types
graphql_name 'AlertManagementHttpIntegration'
description 'An endpoint and credentials used to accept alerts for a project'
- implements(Types::AlertManagement::IntegrationType)
+ implements Types::AlertManagement::IntegrationType
authorize :admin_operations
diff --git a/app/graphql/types/alert_management/prometheus_integration_type.rb b/app/graphql/types/alert_management/prometheus_integration_type.rb
index 9a2ef78eca7..0f61eeaa177 100644
--- a/app/graphql/types/alert_management/prometheus_integration_type.rb
+++ b/app/graphql/types/alert_management/prometheus_integration_type.rb
@@ -8,7 +8,7 @@ module Types
include ::Gitlab::Routing
- implements(Types::AlertManagement::IntegrationType)
+ implements Types::AlertManagement::IntegrationType
authorize :admin_project
diff --git a/app/graphql/types/ci/group_variable_type.rb b/app/graphql/types/ci/group_variable_type.rb
index acb003b5977..7be9b3df0b8 100644
--- a/app/graphql/types/ci/group_variable_type.rb
+++ b/app/graphql/types/ci/group_variable_type.rb
@@ -8,7 +8,7 @@ module Types
description 'CI/CD variables for a group.'
connection_type_class Types::Ci::GroupVariableConnectionType
- implements(VariableInterface)
+ implements VariableInterface
field :environment_scope, GraphQL::Types::String,
null: true,
diff --git a/app/graphql/types/ci/instance_variable_type.rb b/app/graphql/types/ci/instance_variable_type.rb
index 7ffc52deb73..e3230556769 100644
--- a/app/graphql/types/ci/instance_variable_type.rb
+++ b/app/graphql/types/ci/instance_variable_type.rb
@@ -7,7 +7,7 @@ module Types
graphql_name 'CiInstanceVariable'
description 'CI/CD variables for a GitLab instance.'
- implements(VariableInterface)
+ implements VariableInterface
field :id, GraphQL::Types::ID,
null: false,
diff --git a/app/graphql/types/ci/manual_variable_type.rb b/app/graphql/types/ci/manual_variable_type.rb
index ed92a6645b4..dcdaa3a6b19 100644
--- a/app/graphql/types/ci/manual_variable_type.rb
+++ b/app/graphql/types/ci/manual_variable_type.rb
@@ -7,7 +7,7 @@ module Types
graphql_name 'CiManualVariable'
description 'CI/CD variables given to a manual job.'
- implements(VariableInterface)
+ implements VariableInterface
field :environment_scope, GraphQL::Types::String,
null: true,
diff --git a/app/graphql/types/ci/pipeline_schedule_variable_type.rb b/app/graphql/types/ci/pipeline_schedule_variable_type.rb
index 1cb407bc2e4..f9c18d6f7df 100644
--- a/app/graphql/types/ci/pipeline_schedule_variable_type.rb
+++ b/app/graphql/types/ci/pipeline_schedule_variable_type.rb
@@ -7,7 +7,7 @@ module Types
authorize :read_pipeline_schedule_variables
- implements(VariableInterface)
+ implements VariableInterface
end
end
end
diff --git a/app/graphql/types/ci/project_variable_type.rb b/app/graphql/types/ci/project_variable_type.rb
index 8c1eb481774..cd069be3320 100644
--- a/app/graphql/types/ci/project_variable_type.rb
+++ b/app/graphql/types/ci/project_variable_type.rb
@@ -8,7 +8,7 @@ module Types
description 'CI/CD variables for a project.'
connection_type_class Types::Ci::ProjectVariableConnectionType
- implements(VariableInterface)
+ implements VariableInterface
field :environment_scope, GraphQL::Types::String,
null: true,
diff --git a/app/graphql/types/commit_type.rb b/app/graphql/types/commit_type.rb
index 2a2c8af5468..ad484b09d4d 100644
--- a/app/graphql/types/commit_type.rb
+++ b/app/graphql/types/commit_type.rb
@@ -8,7 +8,7 @@ module Types
present_using CommitPresenter
- implements(Types::TodoableInterface)
+ implements Types::TodoableInterface
field :id, type: GraphQL::Types::ID, null: false,
description: 'ID (global ID) of the commit.'
diff --git a/app/graphql/types/design_management/design_type.rb b/app/graphql/types/design_management/design_type.rb
index be5edd17643..d253ca8bfea 100644
--- a/app/graphql/types/design_management/design_type.rb
+++ b/app/graphql/types/design_management/design_type.rb
@@ -10,10 +10,10 @@ module Types
alias_method :design, :object
- implements(Types::Notes::NoteableInterface)
- implements(Types::DesignManagement::DesignFields)
- implements(Types::CurrentUserTodos)
- implements(Types::TodoableInterface)
+ implements Types::Notes::NoteableInterface
+ implements Types::DesignManagement::DesignFields
+ implements Types::CurrentUserTodos
+ implements Types::TodoableInterface
field :description,
GraphQL::Types::String,
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index 8577d2b8dc5..7b533a2b46e 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -6,9 +6,9 @@ module Types
connection_type_class Types::IssueConnectionType
- implements(Types::Notes::NoteableInterface)
- implements(Types::CurrentUserTodos)
- implements(Types::TodoableInterface)
+ implements Types::Notes::NoteableInterface
+ implements Types::CurrentUserTodos
+ implements Types::TodoableInterface
authorize :read_issue
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index 30878c17c6b..701fc793436 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -6,9 +6,9 @@ module Types
connection_type_class Types::MergeRequestConnectionType
- implements(Types::Notes::NoteableInterface)
- implements(Types::CurrentUserTodos)
- implements(Types::TodoableInterface)
+ implements Types::Notes::NoteableInterface
+ implements Types::CurrentUserTodos
+ implements Types::TodoableInterface
authorize :read_merge_request
diff --git a/app/graphql/types/notes/discussion_type.rb b/app/graphql/types/notes/discussion_type.rb
index 5e40c8008a9..7afb1f392d3 100644
--- a/app/graphql/types/notes/discussion_type.rb
+++ b/app/graphql/types/notes/discussion_type.rb
@@ -9,7 +9,7 @@ module Types
authorize :read_note
- implements(Types::ResolvableInterface)
+ implements Types::ResolvableInterface
field :created_at, Types::TimeType, null: false,
description: "Timestamp of the discussion's creation."
diff --git a/app/graphql/types/notes/note_type.rb b/app/graphql/types/notes/note_type.rb
index 754c9b3f356..e7e032c67c6 100644
--- a/app/graphql/types/notes/note_type.rb
+++ b/app/graphql/types/notes/note_type.rb
@@ -9,7 +9,7 @@ module Types
expose_permissions Types::PermissionTypes::Note
- implements(Types::ResolvableInterface)
+ implements Types::ResolvableInterface
field :max_access_level_of_author, GraphQL::Types::String,
null: true,
diff --git a/app/graphql/types/projects/services/base_service_type.rb b/app/graphql/types/projects/services/base_service_type.rb
index 9a48aafa5a8..c77dc5c8539 100644
--- a/app/graphql/types/projects/services/base_service_type.rb
+++ b/app/graphql/types/projects/services/base_service_type.rb
@@ -7,7 +7,7 @@ module Types
class BaseServiceType < BaseObject
graphql_name 'BaseService'
- implements(Types::Projects::ServiceType)
+ implements Types::Projects::ServiceType
authorize :admin_project
end
diff --git a/app/graphql/types/projects/services/jira_service_type.rb b/app/graphql/types/projects/services/jira_service_type.rb
index ac274d7f890..a774d381e2b 100644
--- a/app/graphql/types/projects/services/jira_service_type.rb
+++ b/app/graphql/types/projects/services/jira_service_type.rb
@@ -7,7 +7,7 @@ module Types
class JiraServiceType < BaseObject
graphql_name 'JiraService'
- implements(Types::Projects::ServiceType)
+ implements Types::Projects::ServiceType
authorize :admin_project
diff --git a/app/graphql/types/snippet_type.rb b/app/graphql/types/snippet_type.rb
index 5ee0500b1e0..6e6d0edbe15 100644
--- a/app/graphql/types/snippet_type.rb
+++ b/app/graphql/types/snippet_type.rb
@@ -5,7 +5,7 @@ module Types
graphql_name 'Snippet'
description 'Represents a snippet entry'
- implements(Types::Notes::NoteableInterface)
+ implements Types::Notes::NoteableInterface
present_using SnippetPresenter
diff --git a/app/graphql/types/work_item_type.rb b/app/graphql/types/work_item_type.rb
index 1e58781dbb9..05798ba3d2f 100644
--- a/app/graphql/types/work_item_type.rb
+++ b/app/graphql/types/work_item_type.rb
@@ -4,7 +4,7 @@ module Types
class WorkItemType < BaseObject
graphql_name 'WorkItem'
- implements(Types::TodoableInterface)
+ implements Types::TodoableInterface
authorize :read_work_item
diff --git a/app/models/project.rb b/app/models/project.rb
index d3642e7d7d0..8c5bb34d3f2 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -586,6 +586,7 @@ class Project < ApplicationRecord
scope :pending_delete, -> { where(pending_delete: true) }
scope :without_deleted, -> { where(pending_delete: false) }
scope :not_hidden, -> { where(hidden: false) }
+ scope :not_in_groups, ->(groups) { where.not(group: groups) }
scope :not_aimed_for_deletion, -> { where(marked_for_deletion_at: nil).without_deleted }
scope :with_storage_feature, ->(feature) do
diff --git a/config/feature_flags/development/complete_p_ci_builds_partitioning.yml b/config/feature_flags/development/hide_unaccessible_saml_branches.yml
index bd6ed2644af..27761e0e087 100644
--- a/config/feature_flags/development/complete_p_ci_builds_partitioning.yml
+++ b/config/feature_flags/development/hide_unaccessible_saml_branches.yml
@@ -1,8 +1,8 @@
---
-name: complete_p_ci_builds_partitioning
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/126701
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/414396
+name: hide_unaccessible_saml_branches
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122972
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/419594
milestone: '16.2'
type: development
-group: group::pipeline execution
+group: group::code review
default_enabled: false
diff --git a/config/feature_flags/development/search_index_integrity.yml b/config/feature_flags/development/search_index_integrity.yml
index 84e1e4b65c8..87a9536fede 100644
--- a/config/feature_flags/development/search_index_integrity.yml
+++ b/config/feature_flags/development/search_index_integrity.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/392981
milestone: '15.10'
type: development
group: group::global search
-default_enabled: false
+default_enabled: true
diff --git a/danger/model_validations/Dangerfile b/danger/model_validations/Dangerfile
new file mode 100644
index 00000000000..5daea3cdaa2
--- /dev/null
+++ b/danger/model_validations/Dangerfile
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+model_validations.add_comment_for_added_validations
diff --git a/danger/plugins/model_validations.rb b/danger/plugins/model_validations.rb
new file mode 100644
index 00000000000..ceb8db32da2
--- /dev/null
+++ b/danger/plugins/model_validations.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require_relative '../../tooling/danger/model_validations'
+
+module Danger
+ class ModelValidations < ::Danger::Plugin
+ # Put the helper code somewhere it can be tested
+ include Tooling::Danger::ModelValidations
+ end
+end
diff --git a/doc/ci/yaml/signing_examples.md b/doc/ci/yaml/signing_examples.md
index c18e6de6614..a4f8d6bc2f9 100644
--- a/doc/ci/yaml/signing_examples.md
+++ b/doc/ci/yaml/signing_examples.md
@@ -22,7 +22,7 @@ For details on the mapping between GitLab OIDC claims and Fulcio certificate ext
- You must be using GitLab.com.
- Your project's CI/CD configuration must be located in the project.
-## Cosign
+## Sign or verify container images and build artifacts by using Cosign
You can use Cosign to sign and verify container images and build artifacts.
diff --git a/doc/development/fe_guide/migrating_from_vuex.md b/doc/development/fe_guide/migrating_from_vuex.md
index ff79343b79d..8dca744e192 100644
--- a/doc/development/fe_guide/migrating_from_vuex.md
+++ b/doc/development/fe_guide/migrating_from_vuex.md
@@ -60,15 +60,12 @@ export default ({ blobPath = '', summaryEndpoint = '', suiteEndpoint = '' }) =>
The easiest type of values to migrate are static values, either:
-- Client-side constants
-- Rails-injected dataset
-
- Client-side constants: If the static value is a client-side constant, it may have been implemented
in the store for easy access by other state properties or methods. However, it is generally
a better practice to add such values to a `constants.js` file and import it when needed.
- Rails-injected dataset: These are values that we may need to provide to our Vue apps.
They are static, so adding them to the VueX store is not necessary and it could instead
- be done easily through the `provide/inject` Vue API, which would be equivalent but without the VueX overhead.
+ be done easily through the `provide/inject` Vue API, which would be equivalent but without the VueX overhead. This should **only** be injected inside the top-most JS file that mounts our component.
If we take a look at our example above, we can already see that two properties contain `Endpoint` in their name, which probably means that these come from our Rails dataset. To confirm this, we would search the codebase for these properties and see where they are defined, which is the case in our example. Additionally, `blobPath` is also a static property, and a little less obvious here is that `pageInfo` is actually a constant! It is never modified and is only used as a default value that we use inside our getter:
diff --git a/doc/user/application_security/dependency_list/img/dependency_list_v16_3.png b/doc/user/application_security/dependency_list/img/dependency_list_v16_3.png
new file mode 100644
index 00000000000..93bf0dfc756
--- /dev/null
+++ b/doc/user/application_security/dependency_list/img/dependency_list_v16_3.png
Binary files differ
diff --git a/doc/user/application_security/dependency_list/index.md b/doc/user/application_security/dependency_list/index.md
index d41c0eff860..8a4c15b082e 100644
--- a/doc/user/application_security/dependency_list/index.md
+++ b/doc/user/application_security/dependency_list/index.md
@@ -19,7 +19,7 @@ details about those dependencies, including their known vulnerabilities. It is a
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, see [Project Dependency](https://www.youtube.com/watch?v=ckqkn9Tnbw4).
-To see the dependency list, go to your project and select **Secure > Dependency list**.
+To see the dependency list, go to your project or group and select **Secure > Dependency list**.
This information is sometimes referred to as a Software Bill of Materials, SBOM, or BOM.
@@ -74,21 +74,37 @@ Dependency paths are supported for the following package managers:
- [Yarn 1.x](https://classic.yarnpkg.com/lang/en/)
- [sbt](https://www.scala-sbt.org)
-## Licenses
+### Licenses
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10536) in GitLab 12.3.
If the [License Compliance](../../compliance/license_compliance/index.md) CI job is configured,
[discovered licenses](../../compliance/license_compliance/index.md#supported-languages-and-package-managers) are displayed on this page.
+## View a group's dependencies
+
+![Dependency list](img/dependency_list_v16_3.png)
+
+GitLab displays dependencies with the following information:
+
+| Field | Description |
+|-----------|-------------|
+| Component | The dependency's name and version. |
+| Packager | The packager used to install the dependency. |
+| Location | For operating system dependencies, this lists the image that was scanned. For application dependencies, this shows a link to the packager-specific lock file in your project that declared the dependency. It also shows the [dependency path](#dependency-paths) to a top-level dependency, if any, and if supported. If there are multiple locations, the total number of locations is displayed. |
+| Projects | Links to the project related to the dependency. If there are multiple projects, the total number of projects is displayed. |
+
+Displayed dependencies are initially sorted by packager. They
+can also be sorted by name.
+
## Downloading the dependency list
-You can download your project's full list of dependencies and their details in
+You can download the full list of dependencies and their details in
`JSON` format.
### In the UI
-You can download your project's list of dependencies and their details in JSON format by selecting the **Export** button. The dependency list only shows the results of the last successful pipeline to run on the default branch.
+You can download your group's or project's list of dependencies and their details in JSON format by selecting the **Export** button. The dependency list only shows the results of the last successful pipeline to run on the default branch.
### Using the API
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index e7b7790cf9e..4e1fdb1b920 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -314,9 +314,13 @@ are analyzed. There is no limit to the depth of nested or transitive dependencie
Dependency Scanning supports the following official analyzers:
+- `gemnasium`
+- `gemnasium-maven`
+- `gemnasium-python`
+
+Each of these supported Gemnasium-based Dependency Scanning analyzers exist in the following project:
+
- [`gemnasium`](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium)
-- [`gemnasium-maven`](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven)
-- [`gemnasium-python`](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python)
The analyzers are published as Docker images, which Dependency Scanning uses
to launch dedicated containers for each analysis. You can also integrate a custom
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index ea2a66c7cc7..d949a5dabef 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -496,7 +496,7 @@ path = "/gitleaks.toml"
]
```
-## Specify a remote configuration file
+### Specify a remote configuration file
Projects can be configured with a [CI/CD variable](../../../ci/variables/index.md) in order
to specify a ruleset configuration outside of the current repository.
diff --git a/doc/user/project/repository/mirror/img/mirror_error_v16_3.png b/doc/user/project/repository/mirror/img/mirror_error_v16_3.png
new file mode 100644
index 00000000000..7d3c03534ef
--- /dev/null
+++ b/doc/user/project/repository/mirror/img/mirror_error_v16_3.png
Binary files differ
diff --git a/doc/user/project/repository/mirror/troubleshooting.md b/doc/user/project/repository/mirror/troubleshooting.md
index 6474d0c08ed..2bbc69ff9f7 100644
--- a/doc/user/project/repository/mirror/troubleshooting.md
+++ b/doc/user/project/repository/mirror/troubleshooting.md
@@ -6,7 +6,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Troubleshooting repository mirroring **(FREE)**
-Should an error occur during a push, GitLab displays an **Error** highlight for that repository. Details on the error can then be seen by hovering over the highlight text.
+When mirroring fails, project maintainers can see a link similar to **{warning-solid}** **Pull mirroring failed 1 hour ago.**
+on the project details page. Select this link to go directly to the mirroring settings,
+where GitLab displays an **Error** badge for the mirrored repository. You can hover your mouse cursor
+over the badge to display the text of the error:
+
+![Error message shown on hover](img/mirror_error_v16_3.png)
## Received RST_STREAM with error code 2 with GitHub
diff --git a/lib/banzai/filter/issuable_reference_expansion_filter.rb b/lib/banzai/filter/issuable_reference_expansion_filter.rb
index ec7778a3630..1c3e25b3b27 100644
--- a/lib/banzai/filter/issuable_reference_expansion_filter.rb
+++ b/lib/banzai/filter/issuable_reference_expansion_filter.rb
@@ -45,7 +45,7 @@ module Banzai
# Example: Issue Title (#123 - closed)
def expand_reference_with_title_and_state(node, issuable)
- node.content = "#{issuable.title.truncate(50)} (#{node.content}"
+ node.content = "#{expand_emoji(issuable.title).truncate(50)} (#{node.content}"
node.content += " - #{issuable_state_text(issuable)}" if VISIBLE_STATES.include?(issuable.state)
node.content += ')'
end
@@ -124,6 +124,13 @@ module Banzai
def group
context[:group]
end
+
+ def expand_emoji(string)
+ string.gsub(/(?<!\w):(\w+):(?!\w)/) do |match|
+ emoji_codepoint = TanukiEmoji.find_by_alpha_code(::Regexp.last_match(1))&.codepoints
+ !emoji_codepoint.nil? ? emoji_codepoint : match
+ end
+ end
end
end
end
diff --git a/lib/gitlab/database/ci_builds_partitioning.rb b/lib/gitlab/database/ci_builds_partitioning.rb
deleted file mode 100644
index 9f8b19f2d23..00000000000
--- a/lib/gitlab/database/ci_builds_partitioning.rb
+++ /dev/null
@@ -1,224 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Database
- class CiBuildsPartitioning
- include AsyncDdlExclusiveLeaseGuard
-
- ATTEMPTS = 5
- LOCK_TIMEOUT = 10.seconds
- LEASE_TIMEOUT = 30.minutes
-
- FK_NAME = :fk_e20479742e_p
- TEMP_FK_NAME = :temp_fk_e20479742e_p
- NEXT_PARTITION_ID = 101
- BUILDS_PARTITION_NAME = 'gitlab_partitions_dynamic.ci_builds_101'
- ANNOTATION_PARTITION_NAME = 'gitlab_partitions_dynamic.ci_job_annotations_101'
- RUNNER_MACHINE_PARTITION_NAME = 'gitlab_partitions_dynamic.ci_runner_machine_builds_101'
-
- def initialize(logger: Gitlab::AppLogger)
- @connection = ::Ci::ApplicationRecord.connection
- @timing_configuration = Array.new(ATTEMPTS) { [LOCK_TIMEOUT, 3.minutes] }
- @logger = logger
- end
-
- def execute
- return unless can_execute?
-
- try_obtain_lease do
- swap_foreign_keys
- create_new_ci_builds_partition
- create_new_job_annotations_partition
- create_new_runner_machine_partition
- end
-
- rescue StandardError => e
- log_info("Failed to execute: #{e.message}")
- end
-
- private
-
- attr_reader :connection, :timing_configuration, :logger
-
- delegate :quote_table_name, :quote_column_name, to: :connection
-
- def swap_foreign_keys
- if new_foreign_key_exists?
- log_info('Foreign key already renamed, nothing to do')
-
- return
- end
-
- with_lock_retries do
- connection.execute drop_old_foreign_key_sql
-
- rename_constraint :p_ci_builds_metadata, TEMP_FK_NAME, FK_NAME
-
- each_partition do |partition|
- rename_constraint partition.identifier, TEMP_FK_NAME, FK_NAME
- end
- end
-
- log_info('Foreign key successfully renamed')
- end
-
- def create_new_ci_builds_partition
- if connection.table_exists?(BUILDS_PARTITION_NAME)
- log_info('p_ci_builds partition exists, nothing to do')
- return
- end
-
- with_lock_retries do
- connection.execute new_ci_builds_partition_sql
- end
-
- log_info('Partition for p_ci_builds successfully created')
- end
-
- def create_new_job_annotations_partition
- if connection.table_exists?(ANNOTATION_PARTITION_NAME)
- log_info('p_ci_job_annotations partition exists, nothing to do')
- return
- end
-
- with_lock_retries do
- connection.execute new_job_annotations_partition_sql
- end
-
- log_info('Partition for p_ci_job_annotations successfully created')
- end
-
- def create_new_runner_machine_partition
- if connection.table_exists?(RUNNER_MACHINE_PARTITION_NAME)
- log_info('p_ci_runner_machine_builds partition exists, nothing to do')
- return
- end
-
- with_lock_retries do
- connection.execute new_runner_machine_partition_sql
- end
-
- log_info('Partition for p_ci_runner_machine_builds successfully created')
- end
-
- def can_execute?
- return false if process_disabled?
- return false unless Gitlab.com?
-
- if vacuum_running?
- log_info('Autovacuum detected')
-
- return false
- end
-
- true
- end
-
- def process_disabled?
- ::Feature.disabled?(:complete_p_ci_builds_partitioning)
- end
-
- def new_foreign_key_exists?
- Gitlab::Database::SharedModel.using_connection(connection) do
- Gitlab::Database::PostgresForeignKey
- .by_constrained_table_name_or_identifier(:p_ci_builds_metadata)
- .by_referenced_table_name(:p_ci_builds)
- .by_name(FK_NAME)
- .exists?
- end
- end
-
- def vacuum_running?
- Gitlab::Database::SharedModel.using_connection(connection) do
- Gitlab::Database::PostgresAutovacuumActivity
- .wraparound_prevention
- .for_tables(%i[ci_builds ci_builds_metadata])
- .any?
- end
- end
-
- def drop_old_foreign_key_sql
- <<~SQL.squish
- SET LOCAL statement_timeout TO '11s';
-
- LOCK TABLE ci_builds, p_ci_builds_metadata IN ACCESS EXCLUSIVE MODE;
-
- ALTER TABLE p_ci_builds_metadata DROP CONSTRAINT #{FK_NAME};
- SQL
- end
-
- def rename_constraint(table_name, old_name, new_name)
- connection.execute <<~SQL
- ALTER TABLE #{quote_table_name(table_name)}
- RENAME CONSTRAINT #{quote_column_name(old_name)} TO #{quote_column_name(new_name)}
- SQL
- end
-
- def new_ci_builds_partition_sql
- <<~SQL
- SET LOCAL statement_timeout TO '11s';
-
- LOCK ci_pipelines, ci_stages IN SHARE ROW EXCLUSIVE MODE;
- LOCK TABLE ONLY p_ci_builds IN ACCESS EXCLUSIVE MODE;
-
- CREATE TABLE IF NOT EXISTS #{BUILDS_PARTITION_NAME}
- PARTITION OF p_ci_builds
- FOR VALUES IN (#{NEXT_PARTITION_ID});
- SQL
- end
-
- def new_job_annotations_partition_sql
- <<~SQL
- SET LOCAL statement_timeout TO '11s';
-
- LOCK TABLE p_ci_builds IN SHARE ROW EXCLUSIVE MODE;
- LOCK TABLE ONLY p_ci_job_annotations IN ACCESS EXCLUSIVE MODE;
-
- CREATE TABLE IF NOT EXISTS #{ANNOTATION_PARTITION_NAME}
- PARTITION OF p_ci_job_annotations
- FOR VALUES IN (#{NEXT_PARTITION_ID});
- SQL
- end
-
- def new_runner_machine_partition_sql
- <<~SQL
- SET LOCAL statement_timeout TO '11s';
-
- LOCK TABLE p_ci_builds IN SHARE ROW EXCLUSIVE MODE;
- LOCK TABLE ONLY p_ci_runner_machine_builds IN ACCESS EXCLUSIVE MODE;
-
- CREATE TABLE IF NOT EXISTS #{RUNNER_MACHINE_PARTITION_NAME}
- PARTITION OF p_ci_runner_machine_builds
- FOR VALUES IN (#{NEXT_PARTITION_ID});
- SQL
- end
-
- def with_lock_retries(&block)
- Gitlab::Database::WithLockRetries.new(
- timing_configuration: timing_configuration,
- connection: connection,
- logger: logger,
- klass: self.class
- ).run(raise_on_exhaustion: true, &block)
- end
-
- def each_partition(&block)
- Gitlab::Database::SharedModel.using_connection(connection) do
- Gitlab::Database::PostgresPartitionedTable.each_partition(:p_ci_builds_metadata, &block)
- end
- end
-
- def log_info(message)
- logger.info(message: message, class: self.class.to_s)
- end
-
- def connection_db_config
- ::Ci::ApplicationRecord.connection_db_config
- end
-
- def lease_timeout
- LEASE_TIMEOUT
- end
- end
- end
-end
diff --git a/lib/gitlab/database/reindexing.rb b/lib/gitlab/database/reindexing.rb
index 9c860ebc6aa..4a1b0be848e 100644
--- a/lib/gitlab/database/reindexing.rb
+++ b/lib/gitlab/database/reindexing.rb
@@ -59,7 +59,6 @@ module Gitlab
# most bloated indexes for reindexing.
def self.perform_with_heuristic(candidate_indexes = Gitlab::Database::PostgresIndex.reindexing_support, maximum_records: DEFAULT_INDEXES_PER_INVOCATION)
IndexSelection.new(candidate_indexes).take(maximum_records).each do |index|
- Gitlab::Database::CiBuildsPartitioning.new.execute
Coordinator.new(index).perform
end
end
diff --git a/qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb b/qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb
index 9fed6787ade..0817d2f4870 100644
--- a/qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb
+++ b/qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb
@@ -74,7 +74,14 @@ module QA
end
end
- it 'merges when pipeline succeeds', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347842' do
+ it(
+ 'merges when pipeline succeeds',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347842',
+ quarantine: {
+ type: :flaky,
+ issue: "https://gitlab.com/gitlab-org/gitlab/-/issues/346425"
+ }
+ ) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
diff --git a/qa/qa/support/helpers/plan.rb b/qa/qa/support/helpers/plan.rb
index 14273bd0821..c3867b4a1b8 100644
--- a/qa/qa/support/helpers/plan.rb
+++ b/qa/qa/support/helpers/plan.rb
@@ -57,10 +57,11 @@ module QA
}.freeze
CODE_SUGGESTIONS = {
+ # Annual plan, rate and price
plan_id: '8a8aa0ac8874ddc4018878da1f736782',
rate_charge_id: '8a8aa0ac8874ddc4018878da1f9a6784',
name: 'code suggestions',
- price: 9
+ price: 108
}.freeze
LICENSE_TYPE = {
diff --git a/spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb b/spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb
index e14b1362687..06bb0edc92c 100644
--- a/spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb
+++ b/spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb
@@ -173,6 +173,48 @@ RSpec.describe Banzai::Filter::IssuableReferenceExpansionFilter, feature_categor
expect(doc.css('a').last.text).to eq("#{issuable.title} (#{issuable.to_reference} - closed)")
end
+ context 'for references with fenced emoji' do
+ def issuable_link(issuable)
+ create_link(
+ issuable.to_reference,
+ "#{issuable_type}": issuable.id,
+ reference_type: issuable_type,
+ reference_format: '+'
+ )
+ end
+
+ it 'expands emoji for references with +' do
+ issuable = create_item(issuable_type, :opened, title: 'Some issue :eagle:')
+ doc = filter(issuable_link(issuable), context)
+
+ expect(/\p{Emoji_Presentation}/ =~ doc.css('a').last.text).not_to be_nil
+ expect(doc.css('a').last.text.scan(/\p{Emoji_Presentation}/)).to eq(["🦅"])
+ end
+
+ it 'expands when emoji is embedded at the beginning of a string' do
+ issuable = create_item(issuable_type, :opened, title: ':eagle: Some issue')
+ doc = filter(issuable_link(issuable), context)
+
+ expect(/\p{Emoji_Presentation}/ =~ doc.css('a').last.text).not_to be_nil
+ expect(doc.css('a').last.text.scan(/\p{Emoji_Presentation}/)).to eq(["🦅"])
+ end
+
+ it 'expands when emoji appears multiple times' do
+ issuable = create_item(issuable_type, :opened, title: ':eagle: Some issue :dog:')
+ doc = filter(issuable_link(issuable), context)
+
+ expect(/\p{Emoji_Presentation}/ =~ doc.css('a').last.text).not_to be_nil
+ expect(doc.css('a').last.text.scan(/\p{Emoji_Presentation}/)).to eq(["🦅", "🐶"])
+ end
+
+ it 'does not expand when emoji is embedded mid-string' do
+ issuable = create_item(issuable_type, :opened, title: 'Some:eagle:issue')
+ doc = filter(issuable_link(issuable), context)
+
+ expect(/\p{Emoji_Presentation}/ =~ doc.css('a').last.text).to be_nil
+ end
+ end
+
it 'shows title for references with +s' do
issuable = create_item(issuable_type, :opened, title: 'Some issue')
link = create_link(issuable.to_reference, "#{issuable_type}": issuable.id, reference_type: issuable_type,
diff --git a/spec/tooling/danger/model_validations_spec.rb b/spec/tooling/danger/model_validations_spec.rb
new file mode 100644
index 00000000000..bfd63f71656
--- /dev/null
+++ b/spec/tooling/danger/model_validations_spec.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+require 'gitlab-dangerfiles'
+require 'danger'
+require 'danger/plugins/internal/helper'
+require 'gitlab/dangerfiles/spec_helper'
+
+require_relative '../../../tooling/danger/model_validations'
+require_relative '../../../tooling/danger/project_helper'
+
+RSpec.describe Tooling::Danger::ModelValidations, feature_category: :tooling do
+ include_context "with dangerfile"
+
+ let(:fake_danger) { DangerSpecHelper.fake_danger.include(described_class) }
+ let(:fake_project_helper) { instance_double(Tooling::Danger::ProjectHelper) }
+
+ subject(:model_validations) { fake_danger.new(helper: fake_helper) }
+
+ before do
+ allow(model_validations).to receive(:project_helper).and_return(fake_project_helper)
+ end
+
+ describe '#add_comment_for_added_validations' do
+ let(:file_lines) { file_diff.map { |line| line.delete_prefix('+').delete_prefix('-') } }
+ let(:filename) { 'app/models/user.rb' }
+
+ before do
+ allow(model_validations.project_helper).to receive(:file_lines).and_return(file_lines)
+ allow(model_validations.helper).to receive(:all_changed_files).and_return([filename])
+ allow(model_validations.helper).to receive(:changed_lines).with(filename).and_return(file_diff)
+ end
+
+ context 'when model has a newly added validation' do
+ let(:file_diff) do
+ [
+ "+ scope :admins, -> { where(admin: true) }",
+ "+ validates :name, presence: true, length: { maximum: 255 }",
+ "+ validates_with UserValidator",
+ "+ validate :check_password_weakness",
+ "+ validates_each :restricted_visibility_levels do |record, attr, value|",
+ "+ validates_associated :members",
+ "+ with_options if: :is_admin? do |admin|",
+ "+ admin.validates :password, length: { minimum: 10 }",
+ "+ admin.validates :email, presence: true",
+ "+ end",
+ "+ with_options if: :is_admin? { |admin| admin.validates :email, presence: true }",
+ "- validates :first_name, length: { maximum: 127 }"
+ ]
+ end
+
+ it 'adds suggestions at the correct line' do
+ suggested_line = "\n#{described_class::SUGGEST_MR_COMMENT.chomp}"
+
+ matching_line_numbers = [*2..6, 8, 9, 11]
+ matching_line_numbers.each do |line_number|
+ expect(model_validations).to receive(:markdown).with(suggested_line, file: filename, line: line_number)
+ end
+
+ model_validations.add_comment_for_added_validations
+ end
+ end
+
+ context 'when model does not have a newly added validation' do
+ let(:file_diff) do
+ [
+ "+ scope :admins, -> { where(admin: true) }",
+ "- validates :first_name, length: { maximum: 127 }"
+ ]
+ end
+
+ it 'does not add suggestion' do
+ expect(model_validations).not_to receive(:markdown)
+
+ model_validations.add_comment_for_added_validations
+ end
+ end
+ end
+
+ describe '#changed_model_files' do
+ let(:expected_files) do
+ %w[
+ app/models/user.rb
+ app/models/users/user_follow_user.rb
+ ee/app/models/ee/user.rb
+ ee/app/models/sca/license_policy.rb
+ ]
+ end
+
+ before do
+ all_new_files = %w[
+ app/models/user.rb
+ app/models/users/user_follow_user.rb
+ ee/app/models/ee/user.rb
+ ee/app/models/sca/license_policy.rb
+ config/metrics/count_7d/new_metric.yml
+ app/assets/index.js
+ ]
+
+ allow(model_validations.helper).to receive(:all_changed_files).and_return(all_new_files)
+ end
+
+ it 'returns added and modified files' do
+ expect(model_validations.changed_model_files).to match_array(expected_files)
+ end
+ end
+end
diff --git a/tooling/danger/model_validations.rb b/tooling/danger/model_validations.rb
new file mode 100644
index 00000000000..4d7018753ff
--- /dev/null
+++ b/tooling/danger/model_validations.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require_relative 'suggestor'
+
+module Tooling
+ module Danger
+ module ModelValidations
+ include ::Tooling::Danger::Suggestor
+
+ MODEL_FILES_REGEX = 'app/models'
+ EE_PREFIX = 'ee/'
+ VALIDATION_METHODS = %w[validates validate validates_each validates_with validates_associated].freeze
+ VALIDATIONS_REGEX = /^\+\s*(.*\.)?(#{VALIDATION_METHODS.join('|')})[( ]/
+
+ CODE_QUALITY_URL = "https://docs.gitlab.com/ee/development/code_review.html#quality"
+ SUGGEST_MR_COMMENT = <<~SUGGEST_COMMENT.freeze
+ Did you consider new validations can break existing records?
+ Please follow the [code quality guidelines about new model validations](#{CODE_QUALITY_URL}) when adding a new
+ model validation.
+
+ If you're adding the validations to a model with no records you can ignore this warning.
+ SUGGEST_COMMENT
+
+ def add_comment_for_added_validations
+ changed_model_files.each do |filename|
+ add_suggestion(
+ filename: filename,
+ regex: VALIDATIONS_REGEX,
+ comment_text: SUGGEST_MR_COMMENT
+ )
+ end
+ end
+
+ def changed_model_files
+ changed_files = helper.all_changed_files
+ ee_folder_prefix = "(#{EE_PREFIX})?"
+
+ changed_files.grep(%r{\A#{ee_folder_prefix}#{MODEL_FILES_REGEX}})
+ end
+ end
+ end
+end