Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
65b6ccd12e
commit
b333706699
|
@ -9,7 +9,7 @@ docs/CODEOWNERS @clefelhocz1 @timzallmann @cdu1 @whaber @dsatcher @sgoldstein @j
|
|||
.gitlab/CODEOWNERS @clefelhocz1 @timzallmann @cdu1 @whaber @dsatcher @sgoldstein @jeromezng @stanhu
|
||||
|
||||
## Allows release tooling to update the Gitaly Version
|
||||
GITALY_SERVER_VERSION @project_278964_bot6
|
||||
GITALY_SERVER_VERSION @project_278964_bot6 @gitlab-org/maintainers/rails-backend @gitlab-org/delivery
|
||||
|
||||
## Excludes documentation markdown file changes from required approval
|
||||
/doc/*.md
|
||||
|
|
|
@ -44,7 +44,7 @@ docs-lint markdown:
|
|||
- .default-retry
|
||||
- .docs:rules:docs-lint
|
||||
# When updating the image version here, update it in /scripts/lint-doc.sh too.
|
||||
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-docs/lint-markdown:alpine-3.16-vale-2.17.0-markdownlint-0.31.1
|
||||
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-docs/lint-markdown:alpine-3.16-vale-2.20.1-markdownlint-0.32.2
|
||||
stage: lint
|
||||
needs: []
|
||||
script:
|
||||
|
|
|
@ -23,7 +23,8 @@ first-line-h1: false
|
|||
code-block-style:
|
||||
style: "fenced"
|
||||
emphasis-style: false
|
||||
strong-style: false
|
||||
link-fragments: false
|
||||
reference-links-images: false
|
||||
proper-names:
|
||||
names: [
|
||||
"Akismet",
|
||||
|
|
|
@ -3,10 +3,4 @@
|
|||
Layout/HashAlignment:
|
||||
Exclude:
|
||||
- 'ee/spec/lib/ee/gitlab/usage_data_spec.rb'
|
||||
- 'spec/controllers/projects/merge_requests_controller_spec.rb'
|
||||
- 'spec/routing/project_routing_spec.rb'
|
||||
- 'spec/serializers/ci/lint/job_entity_spec.rb'
|
||||
- 'spec/serializers/container_repository_entity_spec.rb'
|
||||
- 'spec/serializers/deployment_entity_spec.rb'
|
||||
- 'spec/serializers/environment_serializer_spec.rb'
|
||||
- 'spec/serializers/merge_request_metrics_helper_spec.rb'
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -483,7 +483,7 @@ gem 'ssh_data', '~> 1.3'
|
|||
gem 'spamcheck', '~> 1.0.0'
|
||||
|
||||
# Gitaly GRPC protocol definitions
|
||||
gem 'gitaly', '~> 15.3.0-rc4'
|
||||
gem 'gitaly', '~> 15.4.0-rc2'
|
||||
|
||||
# KAS GRPC protocol definitions
|
||||
gem 'kas-grpc', '~> 0.0.2'
|
||||
|
|
|
@ -531,7 +531,7 @@ GEM
|
|||
rails (>= 3.2.0)
|
||||
git (1.11.0)
|
||||
rchardet (~> 1.8)
|
||||
gitaly (15.3.0.pre.rc4)
|
||||
gitaly (15.4.0.pre.rc2)
|
||||
grpc (~> 1.0)
|
||||
github-markup (1.7.0)
|
||||
gitlab (4.16.1)
|
||||
|
@ -1586,7 +1586,7 @@ DEPENDENCIES
|
|||
gettext (~> 3.3)
|
||||
gettext_i18n_rails (~> 1.8.0)
|
||||
gettext_i18n_rails_js (~> 1.3)
|
||||
gitaly (~> 15.3.0.pre.rc4)
|
||||
gitaly (~> 15.4.0.pre.rc2)
|
||||
github-markup (~> 1.7.0)
|
||||
gitlab-chronic (~> 0.10.5)
|
||||
gitlab-dangerfiles (~> 3.5.1)
|
||||
|
|
|
@ -20,6 +20,8 @@ export const createAppOptions = (selector, apolloProvider) => {
|
|||
const {
|
||||
canGenerateCodequalityReports,
|
||||
codequalityReportDownloadPath,
|
||||
codequalityBlobPath,
|
||||
codequalityProjectPath,
|
||||
downloadablePathForReportType,
|
||||
exposeSecurityDashboard,
|
||||
exposeLicenseScanningData,
|
||||
|
@ -40,9 +42,12 @@ export const createAppOptions = (selector, apolloProvider) => {
|
|||
hasTestReport,
|
||||
emptyStateImagePath,
|
||||
artifactsExpiredImagePath,
|
||||
isFullCodequalityReportAvailable,
|
||||
testsCount,
|
||||
} = dataset;
|
||||
|
||||
// TODO remove projectPath variable once https://gitlab.com/gitlab-org/gitlab/-/issues/371641 is resolved
|
||||
const projectPath = fullPath;
|
||||
const defaultTabValue = getPipelineDefaultTab(window.location.href);
|
||||
|
||||
return {
|
||||
|
@ -63,6 +68,10 @@ export const createAppOptions = (selector, apolloProvider) => {
|
|||
provide: {
|
||||
canGenerateCodequalityReports: parseBoolean(canGenerateCodequalityReports),
|
||||
codequalityReportDownloadPath,
|
||||
codequalityBlobPath,
|
||||
codequalityProjectPath,
|
||||
isFullCodequalityReportAvailable: parseBoolean(isFullCodequalityReportAvailable),
|
||||
projectPath,
|
||||
defaultTabValue,
|
||||
downloadablePathForReportType,
|
||||
exposeSecurityDashboard: parseBoolean(exposeSecurityDashboard),
|
||||
|
|
|
@ -333,7 +333,7 @@
|
|||
font-size: 13px;
|
||||
line-height: 1.6em;
|
||||
overflow-x: auto;
|
||||
border-radius: 2px;
|
||||
border-radius: $border-radius-default;
|
||||
|
||||
// Multi-line code blocks should scroll horizontally
|
||||
code {
|
||||
|
|
|
@ -21,9 +21,30 @@ module Types
|
|||
field :path, GraphQL::Types::String, null: false,
|
||||
description: 'Path to the environment.'
|
||||
|
||||
field :slug, GraphQL::Types::String,
|
||||
description: 'Slug of the environment.'
|
||||
|
||||
field :external_url, GraphQL::Types::String, null: true,
|
||||
description: 'External URL of the environment.'
|
||||
|
||||
field :created_at, Types::TimeType,
|
||||
description: 'When the environment was created.'
|
||||
|
||||
field :updated_at, Types::TimeType,
|
||||
description: 'When the environment was updated.'
|
||||
|
||||
field :auto_stop_at, Types::TimeType,
|
||||
description: 'When the environment is going to be stopped automatically.'
|
||||
|
||||
field :auto_delete_at, Types::TimeType,
|
||||
description: 'When the environment is going to be deleted automatically.'
|
||||
|
||||
field :tier, Types::DeploymentTierEnum,
|
||||
description: 'Deployment tier of the environment.'
|
||||
|
||||
field :environment_type, GraphQL::Types::String,
|
||||
description: 'Folder name of the environment.'
|
||||
|
||||
field :metrics_dashboard, Types::Metrics::DashboardType, null: true,
|
||||
description: 'Metrics dashboard schema for the environment.',
|
||||
resolver: Resolvers::Metrics::DashboardResolver
|
||||
|
@ -41,5 +62,9 @@ module Types
|
|||
description: 'Deployments of the environment.',
|
||||
resolver: Resolvers::DeploymentsResolver,
|
||||
complexity: 150
|
||||
|
||||
def tier
|
||||
object.tier.to_sym
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,7 +6,6 @@ module Projects
|
|||
|
||||
def js_pipeline_tabs_data(project, pipeline, _user)
|
||||
{
|
||||
can_generate_codequality_reports: pipeline.can_generate_codequality_reports?.to_json,
|
||||
failed_jobs_count: pipeline.failed_builds.count,
|
||||
failed_jobs_summary: prepare_failed_jobs_summary_data(pipeline.failed_builds),
|
||||
full_path: project.full_path,
|
||||
|
|
|
@ -440,7 +440,6 @@ module ProjectsHelper
|
|||
def show_inactive_project_deletion_banner?(project)
|
||||
return false unless project.present? && project.saved?
|
||||
return false unless delete_inactive_projects?
|
||||
return false unless Feature.enabled?(:inactive_projects_deletion, project.root_namespace)
|
||||
|
||||
project.inactive?
|
||||
end
|
||||
|
|
|
@ -17,4 +17,4 @@ module Preloaders
|
|||
end
|
||||
end
|
||||
|
||||
Preloaders::GroupPolicyPreloader.prepend_mod_with('Preloaders::GroupPolicyPreloader')
|
||||
Preloaders::GroupPolicyPreloader.prepend_mod
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Preloaders
|
||||
class ProjectPolicyPreloader
|
||||
def initialize(projects, current_user)
|
||||
@projects = projects
|
||||
@current_user = current_user
|
||||
end
|
||||
|
||||
def execute
|
||||
return if projects.is_a?(ActiveRecord::NullRelation)
|
||||
|
||||
ActiveRecord::Associations::Preloader.new.preload(projects, { group: :route, namespace: :owner })
|
||||
::Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :projects, :current_user
|
||||
end
|
||||
end
|
||||
|
||||
Preloaders::ProjectPolicyPreloader.prepend_mod
|
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Preloaders
|
||||
class ProjectRootAncestorPreloader
|
||||
def initialize(projects, namespace_sti_name = :namespace, root_ancestor_preloads = [])
|
||||
@projects = projects
|
||||
@namespace_sti_name = namespace_sti_name
|
||||
@root_ancestor_preloads = root_ancestor_preloads
|
||||
end
|
||||
|
||||
def execute
|
||||
return if @projects.is_a?(ActiveRecord::NullRelation)
|
||||
return unless ::Feature.enabled?(:use_traversal_ids)
|
||||
|
||||
root_query = Namespace.joins("INNER JOIN (#{join_sql}) as root_query ON root_query.root_id = namespaces.id")
|
||||
.select('namespaces.*, root_query.id as source_id')
|
||||
|
||||
root_query = root_query.preload(*@root_ancestor_preloads) if @root_ancestor_preloads.any?
|
||||
|
||||
root_ancestors_by_id = root_query.group_by(&:source_id)
|
||||
|
||||
ActiveRecord::Associations::Preloader.new.preload(@projects, :namespace)
|
||||
@projects.each do |project|
|
||||
project.namespace.root_ancestor = root_ancestors_by_id[project.id]&.first
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def join_sql
|
||||
@projects
|
||||
.joins(@namespace_sti_name)
|
||||
.select('projects.id, namespaces.traversal_ids[1] as root_id')
|
||||
.to_sql
|
||||
end
|
||||
end
|
||||
end
|
|
@ -51,4 +51,4 @@ module Preloaders
|
|||
end
|
||||
end
|
||||
|
||||
# Preloaders::UsersMaxAccessLevelInProjectsPreloader.prepend_mod
|
||||
Preloaders::UsersMaxAccessLevelInProjectsPreloader.prepend_mod
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
%p
|
||||
All discussions on merge request #{merge_request_reference_link(@merge_request)}
|
||||
were resolved by #{sanitize_name(@resolved_by.name)}
|
||||
= s_('Notify|All discussions on merge request %{mr_link} were resolved by %{name}') %{mr_link: sanitize(merge_request_reference_link(@merge_request)), name: sanitize_name(@resolved_by.name)}
|
||||
|
|
|
@ -39,8 +39,6 @@ module Projects
|
|||
raise TimeoutError
|
||||
end
|
||||
|
||||
next unless Feature.enabled?(:inactive_projects_deletion, project.root_namespace)
|
||||
|
||||
with_context(project: project, user: admin_user) do
|
||||
deletion_warning_email_sent_on = notified_inactive_projects["project:#{project.id}"]
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: inactive_projects_deletion
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/357968
|
||||
milestone: '15.0'
|
||||
type: development
|
||||
group: group::compliance
|
||||
default_enabled: false
|
|
@ -105,7 +105,10 @@ gitlab:
|
|||
|
||||
## Geo proxying with Separate URLs
|
||||
|
||||
Since GitLab 15.1, Geo secondary proxying is enabled by default for separate URLs also.
|
||||
> Geo secondary proxying for separate URLs is [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/346112) in GitLab 15.1.
|
||||
|
||||
NOTE:
|
||||
The feature flag described in this section is planned to be deprecated and removed in a future release. Support for read-only Geo secondary sites is proposed in [issue 366810](https://gitlab.com/gitlab-org/gitlab/-/issues/366810), you can upvote and share your use cases in that issue.
|
||||
|
||||
There are minor known issues linked in the
|
||||
["Geo secondary proxying with separate URLs" epic](https://gitlab.com/groups/gitlab-org/-/epics/6865).
|
||||
|
|
|
@ -6,18 +6,16 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# Inactive project deletion **(FREE SELF)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0 [with a flag](../administration/feature_flags.md) named `inactive_projects_deletion`. Disabled by default.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to
|
||||
[enable the feature flag](../administration/feature_flags.md) named `inactive_projects_deletion`.
|
||||
On GitLab.com, this feature is not available. This feature is not ready for production use.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0 [with a flag](../administration/feature_flags.md) named `inactive_projects_deletion`. Disabled by default.
|
||||
> - [Feature flag `inactive_projects_deletion`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96803) removed in GitLab 15.4.
|
||||
|
||||
Administrators of large GitLab instances can find that over time, projects become inactive and are no longer used.
|
||||
These projects take up unnecessary disk space. With inactive project deletion, you can identify these projects, warn
|
||||
the maintainers ahead of time, and then delete the projects if they remain inactive. When an inactive project is
|
||||
deleted, the action generates an audit event that it was performed by the first active administrator.
|
||||
|
||||
For the default setting on GitLab.com, see the [GitLab.com settings page](../user/gitlab_com/index.md#inactive-project-deletion).
|
||||
|
||||
## Configure inactive project deletion
|
||||
|
||||
You can configure inactive projects deletion or turn it off using either:
|
||||
|
|
|
@ -11536,12 +11536,19 @@ Describes where code is deployed for a project.
|
|||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="environmentautodeleteat"></a>`autoDeleteAt` | [`Time`](#time) | When the environment is going to be deleted automatically. |
|
||||
| <a id="environmentautostopat"></a>`autoStopAt` | [`Time`](#time) | When the environment is going to be stopped automatically. |
|
||||
| <a id="environmentcreatedat"></a>`createdAt` | [`Time`](#time) | When the environment was created. |
|
||||
| <a id="environmentenvironmenttype"></a>`environmentType` | [`String`](#string) | Folder name of the environment. |
|
||||
| <a id="environmentexternalurl"></a>`externalUrl` | [`String`](#string) | External URL of the environment. |
|
||||
| <a id="environmentid"></a>`id` | [`ID!`](#id) | ID of the environment. |
|
||||
| <a id="environmentlatestopenedmostseverealert"></a>`latestOpenedMostSevereAlert` | [`AlertManagementAlert`](#alertmanagementalert) | Most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned. |
|
||||
| <a id="environmentname"></a>`name` | [`String!`](#string) | Human-readable name of the environment. |
|
||||
| <a id="environmentpath"></a>`path` | [`String!`](#string) | Path to the environment. |
|
||||
| <a id="environmentslug"></a>`slug` | [`String`](#string) | Slug of the environment. |
|
||||
| <a id="environmentstate"></a>`state` | [`String!`](#string) | State of the environment, for example: available/stopped. |
|
||||
| <a id="environmenttier"></a>`tier` | [`DeploymentTier`](#deploymenttier) | Deployment tier of the environment. |
|
||||
| <a id="environmentupdatedat"></a>`updatedAt` | [`Time`](#time) | When the environment was updated. |
|
||||
|
||||
#### Fields with arguments
|
||||
|
||||
|
|
|
@ -286,7 +286,7 @@ listed in the descriptions of the relevant settings.
|
|||
| `default_snippet_visibility` | string | no | What visibility level new snippets receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. |
|
||||
| `delayed_project_deletion` **(PREMIUM SELF)** | boolean | no | Enable delayed project deletion by default in new groups. Default is `false`. [From GitLab 15.1](https://gitlab.com/gitlab-org/gitlab/-/issues/352960), can only be enabled when `delayed_group_deletion` is true. |
|
||||
| `delayed_group_deletion` **(PREMIUM SELF)** | boolean | no | Enable delayed group deletion. Default is `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/352959) in GitLab 15.0. [From GitLab 15.1](https://gitlab.com/gitlab-org/gitlab/-/issues/352960), disables and locks the group-level setting for delayed protect deletion when set to `false`. |
|
||||
| `delete_inactive_projects` | boolean | no | Enable inactive project deletion feature. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84519) in GitLab 14.10. [Became operational](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0 (with feature flag `inactive_projects_deletion`, disabled by default). |
|
||||
| `delete_inactive_projects` | boolean | no | Enable inactive project deletion feature. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84519) in GitLab 14.10. [Became operational without feature flag](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96803) in GitLab 15.4. |
|
||||
| `deletion_adjourned_period` **(PREMIUM SELF)** | integer | no | The number of days to wait before deleting a project or group that is marked for deletion. Value must be between `1` and `90`. Defaults to `7`. [From GitLab 15.1](https://gitlab.com/gitlab-org/gitlab/-/issues/352960), a hook on `deletion_adjourned_period` sets the period to `1` on every update, and sets both `delayed_project_deletion` and `delayed_group_deletion` to `false` if the period is `0`. |
|
||||
| `diff_max_patch_bytes` | integer | no | Maximum [diff patch size](../user/admin_area/diff_limits.md), in bytes. |
|
||||
| `diff_max_files` | integer | no | Maximum [files in a diff](../user/admin_area/diff_limits.md). |
|
||||
|
|
|
@ -79,7 +79,7 @@ cannot be cleaned by `autovacuum`. This highlight the need for small tables.
|
|||
We will measure how much bloat we accumulate when [re]indexing huge tables. Base on this analysis,
|
||||
we will be able to set up SLO (dead tuples / bloat), associated with [re]indexing.
|
||||
|
||||
We’ve seen numerous S1 and S2 database-related production environment
|
||||
We've seen numerous S1 and S2 database-related production environment
|
||||
incidents, over the last couple of months, for example:
|
||||
|
||||
- S1: 2022-03-17 [Increase in writes in `ci_builds` table](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/6625)
|
||||
|
@ -135,7 +135,7 @@ remaining database tables when it becomes necessary.
|
|||
It is also important to avoid large data migrations. We store almost 6
|
||||
terabytes of data in the biggest CI/CD tables, in many different columns and
|
||||
indexes. Migrating this amount of data might be challenging and could cause
|
||||
instability in the production environment. Due to this concern, we’ve developed
|
||||
instability in the production environment. Due to this concern, we've developed
|
||||
a way to attach an existing database table as a partition zero without downtime
|
||||
and excessive database locking, what has been demonstrated in one of the
|
||||
[first proofs of concept](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80186).
|
||||
|
@ -150,7 +150,7 @@ Our plan is to use logical partition IDs. We want to start with the
|
|||
`ci_pipelines` table and create a `partition_id` column with a `DEFAULT` value
|
||||
of `100` or `1000`. Using a `DEFAULT` value avoids the challenge of backfilling
|
||||
this value for every row. Adding a `CHECK` constraint prior to attaching the
|
||||
first partition tells PostgreSQL that we’ve already ensured consistency and
|
||||
first partition tells PostgreSQL that we've already ensured consistency and
|
||||
there is no need to check it while holding an exclusive table lock when
|
||||
attaching this table as a partition to the routing table (partitioned schema
|
||||
definition). We will increment this value every time we create a new partition
|
||||
|
@ -256,12 +256,12 @@ smart enough to move rows between partitions on its own.
|
|||
|
||||
### Naming conventions
|
||||
|
||||
A partitioned table is called a __routing__ table and it will use the `p_`
|
||||
A partitioned table is called a **routing** table and it will use the `p_`
|
||||
prefix which should help us with building automated tooling for query analysis.
|
||||
|
||||
A table partition will be simply called __partition__ and it can use the a
|
||||
A table partition will be simply called **partition** and it can use the a
|
||||
physical partition ID as suffix, leaded by a `p` letter, for example
|
||||
`ci_builds_p101`. Existing CI tables will become __zero partitions__ of the
|
||||
`ci_builds_p101`. Existing CI tables will become **zero partitions** of the
|
||||
new routing tables. Depending on the chosen
|
||||
[partitioning strategy](#how-do-we-want-to-partition-cicd-data) for a given
|
||||
table, it is possible to have many logical partitions per one physical partition.
|
||||
|
@ -274,8 +274,8 @@ metadata table, called `ci_partitions`. In that table we would store metadata
|
|||
about all the logical partitions, with many pipelines per partition. We may
|
||||
need to store a range of pipeline ids per logical partition. Using it we will
|
||||
be able to find the `partition_id` number for a given pipeline ID and we will
|
||||
also find information about which logical partitions are “active” or
|
||||
“archived”, which will help us to implement a time-decay pattern using database
|
||||
also find information about which logical partitions are "active" or
|
||||
"archived", which will help us to implement a time-decay pattern using database
|
||||
declarative partitioning.
|
||||
|
||||
`ci_partitions` table will store information about a partition identifier,
|
||||
|
@ -621,7 +621,7 @@ strategy. The strategy, described in this document, is subject to iteration as
|
|||
well. Whenever we find a better way to reduce the risk and improve our plan, we
|
||||
should update this document as well.
|
||||
|
||||
We’ve managed to find a way to avoid large-scale data migrations, and we are
|
||||
We've managed to find a way to avoid large-scale data migrations, and we are
|
||||
building an iterative strategy for partitioning CI/CD data. We documented our
|
||||
strategy here to share knowledge and solicit feedback from other team members.
|
||||
|
||||
|
|
|
@ -176,7 +176,7 @@ Using phpenv also allows to easily configure the PHP environment with:
|
|||
phpenv config-add my_config.ini
|
||||
```
|
||||
|
||||
*__Important note:__ It seems `phpenv/phpenv`
|
||||
**Important note:** It seems `phpenv/phpenv`
|
||||
[is abandoned](https://github.com/phpenv/phpenv/issues/57). There is a fork
|
||||
at [`madumlao/phpenv`](https://github.com/madumlao/phpenv) that tries to bring
|
||||
the project back to life. [`CHH/phpenv`](https://github.com/CHH/phpenv) also
|
||||
|
|
|
@ -82,8 +82,7 @@ To enable merge trains for your project:
|
|||
1. [Configure your CI/CD configuration file](merge_request_pipelines.md#prerequisites)
|
||||
so that the pipeline or individual jobs run for merge requests.
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Merge requests**.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge method** section, verify that **Merge commit** is selected.
|
||||
1. In the **Merge options** section, select **Enable merged results pipelines** (if not already selected) and **Enable merge trains**.
|
||||
1. Select **Save changes**.
|
||||
|
|
|
@ -42,9 +42,8 @@ To enable merged results pipelines in a project, you must have at least the
|
|||
Maintainer role:
|
||||
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Merge requests**.
|
||||
1. Select **Enable merged results pipelines**.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge options** section, select **Enable merged results pipelines**.
|
||||
1. Select **Save changes**.
|
||||
|
||||
WARNING:
|
||||
|
|
|
@ -3882,16 +3882,13 @@ test:
|
|||
|
||||
### `trigger`
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) in GitLab Premium 11.8.
|
||||
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8.
|
||||
|
||||
Use `trigger` to declare that a job is a "trigger job" which starts a
|
||||
[downstream pipeline](../pipelines/downstream_pipelines.md) that is either:
|
||||
|
||||
- [A multi-project pipeline](../pipelines/downstream_pipelines.md#multi-project-pipelines).
|
||||
- [A child pipeline](../pipelines/downstream_pipelines.md#parent-child-pipelines).
|
||||
|
||||
Trigger jobs can use only a limited set of the GitLab CI/CD configuration keywords.
|
||||
Trigger jobs can use only a limited set of GitLab CI/CD configuration keywords.
|
||||
The keywords available for use in trigger jobs are:
|
||||
|
||||
- [`trigger`](#trigger).
|
||||
|
@ -3907,29 +3904,16 @@ The keywords available for use in trigger jobs are:
|
|||
|
||||
**Possible inputs**:
|
||||
|
||||
- For multi-project pipelines, path to the downstream project. CI/CD variables
|
||||
[are supported](../variables/where_variables_can_be_used.md#gitlab-ciyml-file)
|
||||
- For multi-project pipelines, the path to the downstream project. CI/CD variables [are supported](../variables/where_variables_can_be_used.md#gitlab-ciyml-file)
|
||||
in GitLab 15.3 and later, but not [job-level persisted variables](../variables/where_variables_can_be_used.md#persisted-variables).
|
||||
- For child pipelines, path to the child pipeline CI/CD configuration file.
|
||||
Alternatively, use [`trigger:project](#triggerproject).
|
||||
- For child pipelines, use [`trigger:include`](#triggerinclude).
|
||||
|
||||
**Example of `trigger` for multi-project pipeline**:
|
||||
**Example of `trigger`**:
|
||||
|
||||
```yaml
|
||||
rspec:
|
||||
stage: test
|
||||
script: bundle exec rspec
|
||||
|
||||
staging:
|
||||
stage: deploy
|
||||
trigger: my/deployment
|
||||
```
|
||||
|
||||
**Example of `trigger` for child pipelines**:
|
||||
|
||||
```yaml
|
||||
trigger_job:
|
||||
trigger:
|
||||
include: path/to/child-pipeline.yml
|
||||
trigger-multi-project-pipeline:
|
||||
trigger: my-group/my-project
|
||||
```
|
||||
|
||||
**Additional details**:
|
||||
|
@ -3938,8 +3922,6 @@ trigger_job:
|
|||
- In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/201938), you
|
||||
can use [`when:manual`](#when) in the same job as `trigger`. In GitLab 13.4 and
|
||||
earlier, using them together causes the error `jobs:#{job-name} when should be on_success, on_failure or always`.
|
||||
- In [GitLab 13.2 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/197140/), you can
|
||||
view which job triggered a downstream pipeline in the [pipeline graph](../pipelines/index.md#visualize-pipelines).
|
||||
- [Manual pipeline variables](../variables/index.md#override-a-defined-cicd-variable)
|
||||
and [scheduled pipeline variables](../pipelines/schedules.md#add-a-pipeline-schedule)
|
||||
are not passed to downstream pipelines by default. Use [trigger:forward](#triggerforward)
|
||||
|
@ -3950,11 +3932,74 @@ trigger_job:
|
|||
**Related topics**:
|
||||
|
||||
- [Multi-project pipeline configuration examples](../pipelines/downstream_pipelines.md#trigger-a-multi-project-pipeline-from-a-job-in-your-gitlab-ciyml-file).
|
||||
- [Child pipeline configuration examples](../pipelines/downstream_pipelines.md#trigger-a-parent-child-pipeline).
|
||||
- To run a pipeline for a specific branch, tag, or commit, you can use a [trigger token](../triggers/index.md)
|
||||
to authenticate with the [pipeline triggers API](../../api/pipeline_triggers.md).
|
||||
The trigger token is different than the `trigger` keyword.
|
||||
|
||||
#### `trigger:include`
|
||||
|
||||
Use `trigger:include` to declare that a job is a "trigger job" which starts a
|
||||
[child pipeline](../pipelines/downstream_pipelines.md#parent-child-pipelines).
|
||||
|
||||
Use `trigger:include:artifact` to trigger a [dynamic child pipeline](../pipelines/downstream_pipelines.md#dynamic-child-pipelines).
|
||||
|
||||
**Keyword type**: Job keyword. You can use it only as part of a job.
|
||||
|
||||
**Possible inputs**:
|
||||
|
||||
- The path to the child pipeline's configuration file.
|
||||
|
||||
**Example of `trigger:include`**:
|
||||
|
||||
```yaml
|
||||
trigger-child-pipeline:
|
||||
trigger:
|
||||
include: path/to/child-pipeline.gitlab-ci.yml
|
||||
```
|
||||
|
||||
**Related topics**:
|
||||
|
||||
- [Child pipeline configuration examples](../pipelines/downstream_pipelines.md#trigger-a-parent-child-pipeline).
|
||||
|
||||
#### `trigger:project`
|
||||
|
||||
Use `trigger:project` to declare that a job is a "trigger job" which starts a
|
||||
[multi-project pipeline](../pipelines/downstream_pipelines.md#multi-project-pipelines).
|
||||
|
||||
By default, the multi-project pipeline triggers for the default branch. Use `trigger:branch`
|
||||
to specify a different branch.
|
||||
|
||||
**Keyword type**: Job keyword. You can use it only as part of a job.
|
||||
|
||||
**Possible inputs**:
|
||||
|
||||
- The path to the downstream project. CI/CD variables [are supported](../variables/where_variables_can_be_used.md#gitlab-ciyml-file)
|
||||
in GitLab 15.3 and later, but not [job-level persisted variables](../variables/where_variables_can_be_used.md#persisted-variables).
|
||||
|
||||
**Example of `trigger:project`**:
|
||||
|
||||
```yaml
|
||||
trigger-multi-project-pipeline:
|
||||
trigger:
|
||||
project: my-group/my-project
|
||||
```
|
||||
|
||||
**Example of `trigger:project` for a different branch**:
|
||||
|
||||
```yaml
|
||||
trigger-multi-project-pipeline:
|
||||
trigger:
|
||||
project: my-group/my-project
|
||||
branch: development
|
||||
```
|
||||
|
||||
**Related topics**:
|
||||
|
||||
- [Multi-project pipeline configuration examples](../pipelines/downstream_pipelines.md#trigger-a-multi-project-pipeline-from-a-job-in-your-gitlab-ciyml-file).
|
||||
- To run a pipeline for a specific branch, tag, or commit, you can also use a [trigger token](../triggers/index.md)
|
||||
to authenticate with the [pipeline triggers API](../../api/pipeline_triggers.md).
|
||||
The trigger token is different than the `trigger` keyword.
|
||||
|
||||
#### `trigger:strategy`
|
||||
|
||||
Use `trigger:strategy` to force the `trigger` job to wait for the downstream pipeline to complete
|
||||
|
|
|
@ -53,8 +53,13 @@ end
|
|||
|
||||
## Add a `NOT NULL` constraint to an existing column
|
||||
|
||||
Adding `NOT NULL` to existing database columns requires multiple steps split into at least two
|
||||
different releases:
|
||||
Adding `NOT NULL` to existing database columns usually requires multiple steps split into at least two
|
||||
different releases. If your table is small enough that you don't need to
|
||||
use a background migration, you can include all these in the same merge
|
||||
request. We recommend to use separate migrations to reduce
|
||||
transaction durations.
|
||||
|
||||
The steps required are:
|
||||
|
||||
1. Release `N.M` (current release)
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ text = "foo\nbar"
|
|||
p text.match /^bar$/
|
||||
```
|
||||
|
||||
The output of this example is `#<MatchData "bar">`, as Ruby treats the input `text` line by line. In order to match the whole __string__ the Regex anchors `\A` and `\z` should be used.
|
||||
The output of this example is `#<MatchData "bar">`, as Ruby treats the input `text` line by line. To match the whole **string**, the Regex anchors `\A` and `\z` should be used.
|
||||
|
||||
#### Impact
|
||||
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
---
|
||||
stage: Systems
|
||||
group: Distribution
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Comparison of GitLab self-managed with GitLab SaaS
|
||||
|
||||
GitLab SaaS is the largest hosted instance of GitLab in the world, managed by an
|
||||
[all-remote team](https://about.gitlab.com/company/culture/all-remote/) that knows GitLab best. With GitLab SaaS, updates, maintenance, and patches are all performed by this team.
|
||||
|
||||
Self-managed GitLab gives you a deeper breadth of control over many of the functions and systems of the application.
|
||||
|
||||
## Administration
|
||||
|
||||
In GitLab SaaS, administration tasks are limited compared to a self-managed application.
|
||||
|
||||
In a self-managed instance:
|
||||
|
||||
- You have complete access and administrative control over the application, including the [Admin Area](../../user/admin_area/settings/index.md).
|
||||
- You can impersonate, create, add, and remove users.
|
||||
- You can assign the [`Auditor`](../../administration/auditor_users.md) user type and `External` role.
|
||||
|
||||
On GitLab SaaS:
|
||||
|
||||
- You have limited administrative control. For example, you cannot impersonate, create, add, or remove users.
|
||||
- You cannot access the [Admin Area](../../user/admin_area/settings/index.md).
|
||||
- You cannot assign the `Auditor` user type and `External` role.
|
||||
|
||||
## Logs
|
||||
|
||||
Logs give insight into your processes and can help GitLab Support maintain your application and resolve problems.
|
||||
|
||||
In a self-managed instance:
|
||||
|
||||
- You have full access to system logs.
|
||||
|
||||
On GitLab SaaS:
|
||||
|
||||
- You do not have access to system logs because they are at the instance level, and managed by the GitLab [infrastructure team](https://about.gitlab.com/handbook/engineering/infrastructure/).
|
||||
- You can view [Audit Events](../../administration/audit_events.md) and the [GitLab API](../../api/audit_events.md).
|
||||
- You must [request audit information](https://about.gitlab.com/handbook/support/workflows/log_requests.html) from the Support team.
|
||||
|
||||
## Runners
|
||||
|
||||
Runners are available for both SaaS and self-managed applications.
|
||||
|
||||
In a self-managed instance, your runner availability and options are broader, but there are more [security concerns](https://docs.gitlab.com/runner/security/#security-for-self-managed-runners) to consider.
|
||||
|
||||
On GitLab SaaS:
|
||||
|
||||
- Private [runners](../../ci/runners/index.md) are available for GitLab SaaS [groups](../../user/group/index.md) and [projects](../../user/project/index.md).
|
||||
- Shared runners provided by GitLab SaaS are not configurable. Each runner instance is used once for only one job, ensuring any sensitive data left on the system is destroyed after the job is complete.
|
||||
- Shared runners are subject to usage limits and are [plan specific](https://about.gitlab.com/pricing/).
|
||||
|
||||
## Custom Git hooks
|
||||
|
||||
In a self-managed instance you can use any custom Git hooks.
|
||||
|
||||
On GitLab SaaS:
|
||||
|
||||
- SaaS users do not have access to the file system, and cannot use custom Git hooks.
|
||||
- You can use [webhooks](../../user/project/integrations/webhooks.md) as an alternative.
|
||||
|
||||
## API and GraphQL
|
||||
|
||||
In a self-managed instance, users can access all API endpoints, including those that require instance `admin` permissions.
|
||||
|
||||
On GitLab SaaS:
|
||||
|
||||
- SaaS users have access to all of the [API endpoints](../../api/index.md) except those that require instance `admin` permissions.
|
||||
- Only authorized GitLab engineers have administrative access.
|
||||
|
||||
## Authentication
|
||||
|
||||
In a self-managed instance:
|
||||
|
||||
- You can use an internal encryption key for your data store.
|
||||
- You can view console logs.
|
||||
- You can enforce jobs on every pipeline across the group or organization.
|
||||
- You have control over your data backup.
|
||||
- You can use the [Interactive Web Terminal](../../ci/interactive_web_terminal/index.md#interactive-web-terminals) for shared runners.
|
||||
|
||||
On GitLab SaaS:
|
||||
|
||||
- You cannot use internal encryption key for the data store ([bring-your-own-key](https://about.gitlab.com/handbook/engineering/security/vulnerability_management/encryption-policy.html#rolling-your-own-crypto)).
|
||||
- You cannot view console logs.
|
||||
- You cannot enforce jobs on every pipeline across the group or organization.
|
||||
- You cannot configure or control data backups. You must use [group](../../api/group_import_export.md) and [project](../../api/project_import_export.md) export.
|
||||
- The [Interactive Web Terminal](../../ci/interactive_web_terminal/index.md#interactive-web-terminals) is not available for shared runners.
|
||||
|
||||
## Public or private projects
|
||||
|
||||
Project privacy is different when using a self-managed application or GitLab SaaS.
|
||||
|
||||
In a self-managed instance, you control who can view your projects.
|
||||
|
||||
On GitLab SaaS:
|
||||
|
||||
- The GitLab SaaS instance is open to the public.
|
||||
- When your projects are set as `Public`, they are open to everyone on the public internet.
|
||||
|
||||
## Encryption
|
||||
|
||||
In a self-managed instance, you control the encryption type and configuration.
|
||||
|
||||
On GitLab SaaS:
|
||||
|
||||
- An [Access Management Process](https://about.gitlab.com/handbook/engineering/security/#access-management-process) is in place.
|
||||
- All data on GitLab.com is encrypted at rest by default. Access to encryption keys is strictly managed by GitLab.
|
||||
- GitLab does not access your tenant data except as part of a verified service request from you.
|
||||
|
||||
## Support
|
||||
|
||||
In a self-managed instance:
|
||||
|
||||
- You can access any of your back-end systems.
|
||||
- Our Support team can request logs to assist you.
|
||||
|
||||
On GitLab SaaS:
|
||||
|
||||
- For your privacy and security, there is no public access to GitLab back-end systems.
|
||||
- Support staff work with [Site Reliability Engineers](https://about.gitlab.com/job-families/engineering/infrastructure/site-reliability-engineer/) to support the [infrastructure](https://about.gitlab.com/handbook/engineering/infrastructure/).
|
||||
- GitLab Support can access instance logs and view projects, as well as impersonate users. The Support Team can access your logs.
|
|
@ -55,9 +55,8 @@ You can prevent merge requests from being merged if they do not refer to a Jira
|
|||
To enforce this:
|
||||
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Merge requests**.
|
||||
1. Under **Merge checks**, select the **Require an associated issue from Jira** checkbox.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge checks** section, select **Require an associated issue from Jira**.
|
||||
1. Select **Save**.
|
||||
|
||||
After you enable this feature, a merge request that doesn't reference an associated
|
||||
|
|
|
@ -340,9 +340,8 @@ resolved. When this setting is enabled, the **Unresolved threads** counter in a
|
|||
is shown in orange when at least one thread remains unresolved.
|
||||
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Merge requests**.
|
||||
1. Under **Merge checks**, select the **All threads must be resolved** checkbox.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge checks** section, select the **All threads must be resolved** checkbox.
|
||||
1. Select **Save changes**.
|
||||
|
||||
### Automatically resolve threads in a merge request when they become outdated
|
||||
|
@ -351,10 +350,9 @@ You can set merge requests to automatically resolve threads when lines are modif
|
|||
with a new push.
|
||||
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Merge requests**.
|
||||
1. Under **Merge options**, select the
|
||||
**Automatically resolve merge request diff threads when they become outdated** checkbox.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge options** section, select
|
||||
**Automatically resolve merge request diff threads when they become outdated**.
|
||||
1. Select **Save changes**.
|
||||
|
||||
Threads are now resolved if a push makes a diff section outdated.
|
||||
|
|
|
@ -774,6 +774,8 @@ Combined emphasis with **asterisks and _underscores_**.
|
|||
Strikethrough uses two tildes. ~~Scratch this.~~
|
||||
```
|
||||
|
||||
<!-- markdownlint-disable MD050 -->
|
||||
|
||||
Emphasis, aka italics, with *asterisks* or _underscores_.
|
||||
|
||||
Strong emphasis, aka bold, with double **asterisks** or __underscores__.
|
||||
|
@ -782,6 +784,8 @@ Combined emphasis with **asterisks and _underscores_**.
|
|||
|
||||
Strikethrough uses two tildes. ~~Scratch this.~~
|
||||
|
||||
<!-- markdownlint-enable MD050 -->
|
||||
|
||||
#### Multiple underscores in words and mid-word emphasis
|
||||
|
||||
If this section isn't rendered correctly,
|
||||
|
|
|
@ -135,9 +135,8 @@ To set a default description template for merge requests, either:
|
|||
- Users on GitLab Premium and higher: set the default template in project settings:
|
||||
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings**.
|
||||
1. Expand **Merge requests**.
|
||||
1. Fill in the **Default description template for merge requests** text area.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge commit message template** section, fill in **Default description template for merge requests**.
|
||||
1. Select **Save changes**.
|
||||
|
||||
To set a default description template for issues, either:
|
||||
|
|
|
@ -32,8 +32,9 @@ use the default approval rules from the target (upstream) project, not the sourc
|
|||
|
||||
To add a merge request approval rule:
|
||||
|
||||
1. Go to your project and select **Settings > General**.
|
||||
1. Expand **Merge request (MR) approvals**, and then select **Add approval rule**.
|
||||
1. Go to your project and select **Settings > Merge requests**.
|
||||
1. In the **Merge request approvals** section, scroll to **Approval rules**.
|
||||
1. Select **Add approval rule**.
|
||||
1. Add a human-readable **Rule name**.
|
||||
1. Set the number of required approvals in **Approvals required**. A value of `0` makes
|
||||
[the rule optional](#configure-optional-approval-rules), and any number greater than `0`
|
||||
|
@ -65,8 +66,9 @@ to existing merge requests:
|
|||
|
||||
To edit a merge request approval rule:
|
||||
|
||||
1. Go to your project and select **Settings > General**.
|
||||
1. Expand **Merge request (MR) approvals**, and then select **Edit**.
|
||||
1. Go to your project and select **Settings > Merge requests**.
|
||||
1. In the **Merge request approvals** section, scroll to **Approval rules**.
|
||||
1. Select **Edit** next to the rule you want to edit.
|
||||
1. Optional. Change the **Rule name**.
|
||||
1. Set the number of required approvals in **Approvals required**. The minimum value is `0`.
|
||||
1. Add or remove eligible approvers, as needed:
|
||||
|
@ -155,11 +157,11 @@ approve in these ways:
|
|||
If you add [code owners](../../code_owners.md) to your repository, the owners of files
|
||||
become eligible approvers in the project. To enable this merge request approval rule:
|
||||
|
||||
1. Go to your project and select **Settings > General**.
|
||||
1. Expand **Merge request (MR) approvals**.
|
||||
1. Locate **All eligible users** and select the number of approvals required:
|
||||
1. Go to your project and select **Settings > Merge requests**.
|
||||
1. In the **Merge request approvals** section, scroll to **Approval rules**.
|
||||
1. Locate the **All eligible users** rule, and select the number of approvals required:
|
||||
|
||||
![MR approvals by Code Owners](img/mr_approvals_by_code_owners_v15_2.png)
|
||||
![MR approvals by Code Owners](img/mr_approvals_by_code_owners_v15_2.png)
|
||||
|
||||
You can also
|
||||
[require code owner approval](../../protected_branches.md#require-code-owner-approval-on-a-protected-branch)
|
||||
|
@ -182,9 +184,10 @@ granting them push access:
|
|||
and select the Reporter role for the user.
|
||||
1. [Share the project with your group](../../members/share_project_with_groups.md#share-a-project-with-a-group-of-users),
|
||||
based on the Reporter role.
|
||||
1. Go to your project and select **Settings > General**.
|
||||
1. Expand **Merge request (MR) approvals**.
|
||||
1. Select **Add approval rule** or **Update approval rule** and target the protected branch.
|
||||
1. Go to your project and select **Settings > Merge requests**.
|
||||
1. In the **Merge request approvals** section, scroll to **Approval rules**, and either:
|
||||
- For a new rule, select **Add approval rule** and target the protected branch.
|
||||
- For an existing rule, select **Edit** and target the protected branch.
|
||||
1. [Add the group](../../../group/manage.md#create-a-group) to the permission list.
|
||||
|
||||
![Update approval rule](img/update_approval_rule_v13_10.png)
|
||||
|
@ -226,12 +229,12 @@ Approval rules are often relevant only to specific branches, like your
|
|||
approval rule for certain branches:
|
||||
|
||||
1. [Create an approval rule](#add-an-approval-rule).
|
||||
1. Go to your project and select **Settings**.
|
||||
1. Expand **Merge request (MR) approvals**.
|
||||
1. Go to your project and select **Settings > Merge requests**.
|
||||
1. In the **Merge request approvals** section, scroll to **Approval rules**.
|
||||
1. Select a **Target branch**:
|
||||
- To apply the rule to all branches, select **All branches**.
|
||||
- To apply the rule to all protected branches, select **All protected branches** (GitLab 15.3 and later).
|
||||
- To apply the rule to a specific branch, select it from the list:
|
||||
- To apply the rule to a specific branch, select it from the list.
|
||||
|
||||
1. To enable this configuration, read
|
||||
[Code Owner's approvals for protected branches](../../protected_branches.md#require-code-owner-approval-on-a-protected-branch).
|
||||
|
|
|
@ -16,8 +16,8 @@ those rules are applied as a merge request moves toward completion.
|
|||
|
||||
To view or edit merge request approval settings:
|
||||
|
||||
1. Go to your project and select **Settings > General**.
|
||||
1. Expand **Merge request (MR) approvals**.
|
||||
1. Go to your project and select **Settings > Merge requests**.
|
||||
1. Expand **Approvals**.
|
||||
|
||||
### Approval settings
|
||||
|
||||
|
@ -44,9 +44,9 @@ You can further define what happens to existing approvals when commits are added
|
|||
|
||||
By default, the author of a merge request cannot approve it. To change this setting:
|
||||
|
||||
1. Go to your project and select **Settings > General**.
|
||||
1. Expand **Merge request (MR) approvals**.
|
||||
1. Clear the **Prevent approval by author** checkbox.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge request approvals** section, scroll to **Approval settings** and
|
||||
clear the **Prevent approval by author** checkbox.
|
||||
1. Select **Save changes**.
|
||||
|
||||
Authors can edit the approval rule in an individual merge request and override
|
||||
|
@ -68,9 +68,9 @@ the project level or [instance level](../../../admin_area/merge_requests_approva
|
|||
you can prevent committers from approving merge requests that are partially
|
||||
their own. To do this:
|
||||
|
||||
1. Go to your project and select **Settings > General**.
|
||||
1. Expand **Merge request (MR) approvals**.
|
||||
1. Select the **Prevent approvals by users who add commits** checkbox.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge request approvals** section, scroll to **Approval settings** and
|
||||
select **Prevent approvals by users who add commits**.
|
||||
If this checkbox is cleared, an administrator has disabled it
|
||||
[at the instance level](../../../admin_area/merge_requests_approvals.md), and
|
||||
it can't be changed at the project level.
|
||||
|
@ -94,9 +94,9 @@ By default, users can override the approval rules you [create for a project](rul
|
|||
on a per-merge-request basis. If you don't want users to change approval rules
|
||||
on merge requests, you can disable this setting:
|
||||
|
||||
1. Go to your project and select **Settings > General**.
|
||||
1. Expand **Merge request (MR) approvals**.
|
||||
1. Select the **Prevent editing approval rules in merge requests** checkbox.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge request approvals** section, scroll to **Approval settings** and
|
||||
select **Prevent editing approval rules in merge requests**.
|
||||
1. Select **Save changes**.
|
||||
|
||||
This change affects all open merge requests.
|
||||
|
@ -112,9 +112,9 @@ permission enables an electronic signature for approvals, such as the one define
|
|||
|
||||
1. Enable password authentication for the web interface, as described in the
|
||||
[sign-in restrictions documentation](../../../admin_area/settings/sign_in_restrictions.md#password-authentication-enabled).
|
||||
1. Go to your project and select **Settings > General**.
|
||||
1. Expand **Merge request (MR) approvals**.
|
||||
1. Select the **Require user password to approve** checkbox.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge request approvals** section, scroll to **Approval settings** and
|
||||
select **Require user password to approve**.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## Remove all approvals when commits are added to the source branch
|
||||
|
@ -123,9 +123,9 @@ By default, an approval on a merge request remains in place, even if you add mor
|
|||
after the approval. If you want to remove all existing approvals on a merge request
|
||||
when more changes are added to it:
|
||||
|
||||
1. Go to your project and select **Settings > General**.
|
||||
1. Expand **Merge request (MR) approvals**.
|
||||
1. Select the **Remove all approvals when commits are added to the source branch** checkbox.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge request approvals** section, scroll to **Approval settings** and
|
||||
select **Remove all approvals when commits are added to the source branch**.
|
||||
1. Select **Save changes**.
|
||||
|
||||
Approvals aren't removed when a merge request is [rebased from the UI](../methods/index.md#rebasing-in-semi-linear-merge-methods)
|
||||
|
@ -143,10 +143,9 @@ Prerequisite:
|
|||
|
||||
To do this:
|
||||
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Merge request approvals**.
|
||||
1. Select **Remove approvals by Code Owners if their files changed**.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge request approvals** section, scroll to **Approval settings** and
|
||||
select **Remove approvals by Code Owners if their files changed**.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## Code coverage check approvals
|
||||
|
|
|
@ -30,7 +30,7 @@ Prerequisite:
|
|||
To do this:
|
||||
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General** and expand **Merge requests**.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. Depending on the type of template you want to create, scroll to either
|
||||
[**Merge commit message template**](#default-template-for-merge-commits) or
|
||||
[**Squash commit message template**](#default-template-for-squash-commits).
|
||||
|
|
|
@ -57,9 +57,8 @@ does not disable this feature, as it is possible to use pipelines from external
|
|||
CI providers with this feature. To enable it, you must:
|
||||
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Merge requests**.
|
||||
1. Under **Merge checks**, select the **Pipelines must succeed** checkbox.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge checks** section, select **Pipelines must succeed**.
|
||||
1. Select **Save**.
|
||||
|
||||
This setting also prevents merge requests from being merged if there is no pipeline.
|
||||
|
@ -106,11 +105,10 @@ When the **Pipelines must succeed** checkbox is checked, [skipped pipelines](../
|
|||
merge requests from being merged. To change this behavior:
|
||||
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Merge requests**.
|
||||
1. Under **Merge checks**:
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge checks** section:
|
||||
- Ensure **Pipelines must succeed** is selected.
|
||||
- Select the **Skipped pipelines are considered successful** checkbox.
|
||||
- Select **Skipped pipelines are considered successful**.
|
||||
1. Select **Save**.
|
||||
|
||||
## From the command line
|
||||
|
|
|
@ -13,8 +13,7 @@ merge requests are merged into an existing branch.
|
|||
## Configure a project's merge method
|
||||
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Merge requests**.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Merge method** section, select your desired merge method.
|
||||
1. Select **Save changes**.
|
||||
|
||||
|
|
|
@ -61,8 +61,7 @@ squash the commits as part of the merge process:
|
|||
To configure the default squashing behavior for all merge requests in your project:
|
||||
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Merge requests**.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. In the **Squash commits when merging** section, select your desired behavior:
|
||||
- **Do not allow**: Squashing is never performed, and the option is not displayed.
|
||||
- **Allow**: Squashing is allowed, but cleared by default.
|
||||
|
|
|
@ -61,9 +61,8 @@ using the API. You don't need to wait for a merge request webhook payload to be
|
|||
|
||||
Within each project's settings, you can see a list of status checks added to the project:
|
||||
|
||||
1. In your project, go to **Settings > General**.
|
||||
1. Expand the **Merge requests** section.
|
||||
1. Scroll down to the **Status checks** sub-section.
|
||||
1. In your project, go to **Settings > Merge requests** section.
|
||||
1. Scroll down to **Status checks**.
|
||||
|
||||
![Status checks list](img/status_checks_list_view_v14_0.png)
|
||||
|
||||
|
|
|
@ -85,8 +85,20 @@ module Gitlab
|
|||
|
||||
target_commit = Gitlab::Git::Commit.decorate(@repository, branch.target_commit)
|
||||
Gitlab::Git::Branch.new(@repository, branch.name, target_commit.id, target_commit)
|
||||
rescue GRPC::FailedPrecondition => ex
|
||||
raise Gitlab::Git::Repository::InvalidRef, ex
|
||||
rescue GRPC::BadStatus => e
|
||||
detailed_error = GitalyClient.decode_detailed_error(e)
|
||||
|
||||
case detailed_error&.error
|
||||
when :custom_hook
|
||||
raise Gitlab::Git::PreReceiveError.new(custom_hook_error_message(detailed_error.custom_hook),
|
||||
fallback_message: e.details)
|
||||
else
|
||||
if e.code == GRPC::Core::StatusCodes::FAILED_PRECONDITION
|
||||
raise Gitlab::Git::Repository::InvalidRef, e
|
||||
end
|
||||
|
||||
raise
|
||||
end
|
||||
end
|
||||
|
||||
def user_update_branch(branch_name, user, newrev, oldrev)
|
||||
|
|
|
@ -26841,6 +26841,9 @@ msgstr ""
|
|||
msgid "Notify|A new GPG key was added to your account:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Notify|All discussions on merge request %{mr_link} were resolved by %{name}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -232,7 +232,7 @@
|
|||
"jest-raw-loader": "^1.0.1",
|
||||
"jest-transform-graphql": "^2.1.0",
|
||||
"jest-util": "^27.5.1",
|
||||
"markdownlint-cli": "0.31.0",
|
||||
"markdownlint-cli": "0.32.2",
|
||||
"miragejs": "^0.1.40",
|
||||
"mock-apollo-client": "1.2.0",
|
||||
"nodemon": "^2.0.19",
|
||||
|
|
|
@ -128,7 +128,7 @@ function run_locally_or_in_docker() {
|
|||
$cmd $args
|
||||
elif hash docker 2>/dev/null
|
||||
then
|
||||
docker run -t -v ${PWD}:/gitlab -w /gitlab --rm registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.15-vale-2.15.5-markdownlint-0.31.1 ${cmd} ${args}
|
||||
docker run -t -v ${PWD}:/gitlab -w /gitlab --rm registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.16-vale-2.20.1-markdownlint-0.32.2 ${cmd} ${args}
|
||||
else
|
||||
echo
|
||||
echo " ✖ ERROR: '${cmd}' not found. Install '${cmd}' or Docker to proceed." >&2
|
||||
|
|
|
@ -896,12 +896,13 @@ RSpec.describe Projects::MergeRequestsController do
|
|||
end
|
||||
|
||||
subject do
|
||||
get :exposed_artifacts, params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
get :exposed_artifacts,
|
||||
params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
end
|
||||
|
||||
describe 'permissions on a public project with private CI/CD' do
|
||||
|
@ -1031,12 +1032,13 @@ RSpec.describe Projects::MergeRequestsController do
|
|||
end
|
||||
|
||||
subject do
|
||||
get :coverage_reports, params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
get :coverage_reports,
|
||||
params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
end
|
||||
|
||||
describe 'permissions on a public project with private CI/CD' do
|
||||
|
@ -1161,12 +1163,13 @@ RSpec.describe Projects::MergeRequestsController do
|
|||
end
|
||||
|
||||
subject(:get_codequality_mr_diff_reports) do
|
||||
get :codequality_mr_diff_reports, params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
get :codequality_mr_diff_reports,
|
||||
params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
end
|
||||
|
||||
context 'permissions on a public project with private CI/CD' do
|
||||
|
@ -1264,12 +1267,13 @@ RSpec.describe Projects::MergeRequestsController do
|
|||
end
|
||||
|
||||
subject do
|
||||
get :terraform_reports, params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
get :terraform_reports,
|
||||
params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
end
|
||||
|
||||
describe 'permissions on a public project with private CI/CD' do
|
||||
|
@ -1394,12 +1398,13 @@ RSpec.describe Projects::MergeRequestsController do
|
|||
end
|
||||
|
||||
subject do
|
||||
get :test_reports, params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
get :test_reports,
|
||||
params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
end
|
||||
|
||||
before do
|
||||
|
@ -1522,12 +1527,13 @@ RSpec.describe Projects::MergeRequestsController do
|
|||
end
|
||||
|
||||
subject do
|
||||
get :accessibility_reports, params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
get :accessibility_reports,
|
||||
params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
end
|
||||
|
||||
context 'permissions on a public project with private CI/CD' do
|
||||
|
@ -1642,12 +1648,13 @@ RSpec.describe Projects::MergeRequestsController do
|
|||
end
|
||||
|
||||
subject do
|
||||
get :codequality_reports, params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
get :codequality_reports,
|
||||
params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project,
|
||||
id: merge_request.iid
|
||||
},
|
||||
format: :json
|
||||
end
|
||||
|
||||
context 'permissions on a public project with private CI/CD' do
|
||||
|
|
|
@ -8,6 +8,7 @@ RSpec.describe GitlabSchema.types['Environment'] do
|
|||
it 'has the expected fields' do
|
||||
expected_fields = %w[
|
||||
name id state metrics_dashboard latest_opened_most_severe_alert path external_url deployments
|
||||
slug createdAt updatedAt autoStopAt autoDeleteAt tier environmentType
|
||||
]
|
||||
|
||||
expect(described_class).to have_graphql_fields(*expected_fields)
|
||||
|
|
|
@ -19,7 +19,6 @@ RSpec.describe Projects::PipelineHelper do
|
|||
|
||||
it 'returns pipeline tabs data' do
|
||||
expect(pipeline_tabs_data).to include({
|
||||
can_generate_codequality_reports: pipeline.can_generate_codequality_reports?.to_json,
|
||||
failed_jobs_count: pipeline.failed_builds.count,
|
||||
failed_jobs_summary: prepare_failed_jobs_summary_data(pipeline.failed_builds),
|
||||
full_path: project.full_path,
|
||||
|
@ -33,7 +32,8 @@ RSpec.describe Projects::PipelineHelper do
|
|||
blob_path: project_blob_path(project, pipeline.sha),
|
||||
has_test_report: pipeline.has_reports?(Ci::JobArtifact.of_report_type(:test)),
|
||||
empty_state_image_path: match_asset_path('illustrations/empty-state/empty-test-cases-lg.svg'),
|
||||
artifacts_expired_image_path: match_asset_path('illustrations/pipeline.svg')
|
||||
artifacts_expired_image_path: match_asset_path('illustrations/pipeline.svg'),
|
||||
tests_count: pipeline.test_report_summary.total[:count]
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1147,37 +1147,23 @@ RSpec.describe ProjectsHelper do
|
|||
context 'with the setting enabled' do
|
||||
before do
|
||||
stub_application_setting(delete_inactive_projects: true)
|
||||
stub_application_setting(inactive_projects_min_size_mb: 0)
|
||||
stub_application_setting(inactive_projects_send_warning_email_after_months: 1)
|
||||
end
|
||||
|
||||
context 'with the feature flag disabled' do
|
||||
before do
|
||||
stub_feature_flags(inactive_projects_deletion: false)
|
||||
end
|
||||
|
||||
context 'with an active project' do
|
||||
it_behaves_like 'does not show the banner'
|
||||
end
|
||||
|
||||
context 'with the feature flag enabled' do
|
||||
context 'with an inactive project' do
|
||||
before do
|
||||
stub_feature_flags(inactive_projects_deletion: true)
|
||||
stub_application_setting(inactive_projects_min_size_mb: 0)
|
||||
stub_application_setting(inactive_projects_send_warning_email_after_months: 1)
|
||||
project.statistics.storage_size = 1.megabyte
|
||||
project.last_activity_at = 1.year.ago
|
||||
project.save!
|
||||
end
|
||||
|
||||
context 'with an active project' do
|
||||
it_behaves_like 'does not show the banner'
|
||||
end
|
||||
|
||||
context 'with an inactive project' do
|
||||
before do
|
||||
project.statistics.storage_size = 1.megabyte
|
||||
project.last_activity_at = 1.year.ago
|
||||
project.save!
|
||||
end
|
||||
|
||||
it 'shows the banner' do
|
||||
expect(helper.show_inactive_project_deletion_banner?(project)).to be(true)
|
||||
end
|
||||
it 'shows the banner' do
|
||||
expect(helper.show_inactive_project_deletion_banner?(project)).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -56,6 +56,85 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
|
|||
Gitlab::Git::PreReceiveError, "something failed")
|
||||
end
|
||||
end
|
||||
|
||||
context 'with structured errors' do
|
||||
context 'with CustomHookError' do
|
||||
let(:stdout) { nil }
|
||||
let(:stderr) { nil }
|
||||
let(:error_message) { "error_message" }
|
||||
|
||||
let(:custom_hook_error) do
|
||||
new_detailed_error(
|
||||
GRPC::Core::StatusCodes::PERMISSION_DENIED,
|
||||
error_message,
|
||||
Gitaly::UserCreateBranchError.new(
|
||||
custom_hook: Gitaly::CustomHookError.new(
|
||||
stdout: stdout,
|
||||
stderr: stderr,
|
||||
hook_type: Gitaly::CustomHookError::HookType::HOOK_TYPE_PRERECEIVE
|
||||
)))
|
||||
end
|
||||
|
||||
shared_examples 'failed branch creation' do
|
||||
it 'raised a PreRecieveError' do
|
||||
expect_any_instance_of(Gitaly::OperationService::Stub)
|
||||
.to receive(:user_create_branch)
|
||||
.and_raise(custom_hook_error)
|
||||
|
||||
expect { subject }.to raise_error do |error|
|
||||
expect(error).to be_a(Gitlab::Git::PreReceiveError)
|
||||
expect(error.message).to eq(expected_message)
|
||||
expect(error.raw_message).to eq(expected_raw_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when details contain stderr without prefix' do
|
||||
let(:stderr) { "something" }
|
||||
let(:stdout) { "GL-HOOK-ERR: stdout is overridden by stderr" }
|
||||
let(:expected_message) { error_message }
|
||||
let(:expected_raw_message) { stderr }
|
||||
|
||||
it_behaves_like 'failed branch creation'
|
||||
end
|
||||
|
||||
context 'when details contain stderr with prefix' do
|
||||
let(:stderr) { "GL-HOOK-ERR: something" }
|
||||
let(:stdout) { "GL-HOOK-ERR: stdout is overridden by stderr" }
|
||||
let(:expected_message) { "something" }
|
||||
let(:expected_raw_message) { stderr }
|
||||
|
||||
it_behaves_like 'failed branch creation'
|
||||
end
|
||||
|
||||
context 'when details contain stdout without prefix' do
|
||||
let(:stderr) { " \n" }
|
||||
let(:stdout) { "something" }
|
||||
let(:expected_message) { error_message }
|
||||
let(:expected_raw_message) { stdout }
|
||||
|
||||
it_behaves_like 'failed branch creation'
|
||||
end
|
||||
|
||||
context 'when details contain stdout with prefix' do
|
||||
let(:stderr) { " \n" }
|
||||
let(:stdout) { "GL-HOOK-ERR: something" }
|
||||
let(:expected_message) { "something" }
|
||||
let(:expected_raw_message) { stdout }
|
||||
|
||||
it_behaves_like 'failed branch creation'
|
||||
end
|
||||
|
||||
context 'when details contain no stderr or stdout' do
|
||||
let(:stderr) { " \n" }
|
||||
let(:stdout) { "\n \n" }
|
||||
let(:expected_message) { error_message }
|
||||
let(:expected_raw_message) { "\n \n" }
|
||||
|
||||
it_behaves_like 'failed branch creation'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#user_update_branch' do
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Preloaders::ProjectPolicyPreloader do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:root_parent) { create(:group, :private, name: 'root-1', path: 'root-1') }
|
||||
let_it_be(:guest_project) { create(:project, name: 'public guest', path: 'public-guest') }
|
||||
let_it_be(:private_maintainer_project) do
|
||||
create(:project, :private, name: 'b private maintainer', path: 'b-private-maintainer', namespace: root_parent)
|
||||
end
|
||||
|
||||
let_it_be(:private_developer_project) do
|
||||
create(:project, :private, name: 'c public developer', path: 'c-public-developer')
|
||||
end
|
||||
|
||||
let_it_be(:public_maintainer_project) do
|
||||
create(:project, :private, name: 'a public maintainer', path: 'a-public-maintainer')
|
||||
end
|
||||
|
||||
let(:base_projects) do
|
||||
Project.where(id: [guest_project, private_maintainer_project, private_developer_project, public_maintainer_project])
|
||||
end
|
||||
|
||||
before_all do
|
||||
guest_project.add_guest(user)
|
||||
private_maintainer_project.add_maintainer(user)
|
||||
private_developer_project.add_developer(user)
|
||||
public_maintainer_project.add_maintainer(user)
|
||||
end
|
||||
|
||||
it 'avoids N+1 queries when authorizing a list of projects', :request_store do
|
||||
preload_projects_for_policy(user)
|
||||
control = ActiveRecord::QueryRecorder.new { authorize_all_projects(user) }
|
||||
|
||||
new_project1 = create(:project, :private).tap { |project| project.add_maintainer(user) }
|
||||
new_project2 = create(:project, :private, namespace: root_parent)
|
||||
|
||||
another_root = create(:group, :private, name: 'root-3', path: 'root-3')
|
||||
new_project3 = create(:project, :private, namespace: another_root).tap { |project| project.add_maintainer(user) }
|
||||
|
||||
pristine_projects = Project.where(id: base_projects + [new_project1, new_project2, new_project3])
|
||||
|
||||
preload_projects_for_policy(user, pristine_projects)
|
||||
expect { authorize_all_projects(user, pristine_projects) }.not_to exceed_query_limit(control)
|
||||
end
|
||||
|
||||
def authorize_all_projects(current_user, project_list = base_projects)
|
||||
project_list.each { |project| current_user.can?(:read_project, project) }
|
||||
end
|
||||
|
||||
def preload_projects_for_policy(current_user, project_list = base_projects)
|
||||
described_class.new(project_list, current_user).execute
|
||||
end
|
||||
end
|
|
@ -0,0 +1,99 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Preloaders::ProjectRootAncestorPreloader do
|
||||
let_it_be(:root_parent1) { create(:group, :private, name: 'root-1', path: 'root-1') }
|
||||
let_it_be(:root_parent2) { create(:group, :private, name: 'root-2', path: 'root-2') }
|
||||
let_it_be(:guest_project) { create(:project, name: 'public guest', path: 'public-guest') }
|
||||
let_it_be(:private_maintainer_project) do
|
||||
create(:project, :private, name: 'b private maintainer', path: 'b-private-maintainer', namespace: root_parent1)
|
||||
end
|
||||
|
||||
let_it_be(:private_developer_project) do
|
||||
create(:project, :private, name: 'c public developer', path: 'c-public-developer')
|
||||
end
|
||||
|
||||
let_it_be(:public_maintainer_project) do
|
||||
create(:project, :private, name: 'a public maintainer', path: 'a-public-maintainer', namespace: root_parent2)
|
||||
end
|
||||
|
||||
let(:root_query_regex) { /\ASELECT.+FROM "namespaces" WHERE "namespaces"."id" = \d+/ }
|
||||
let(:additional_preloads) { [] }
|
||||
let(:projects) { [guest_project, private_maintainer_project, private_developer_project, public_maintainer_project] }
|
||||
let(:pristine_projects) { Project.where(id: projects) }
|
||||
|
||||
shared_examples 'executes N matching DB queries' do |expected_query_count, query_method = nil|
|
||||
it 'executes the specified root_ancestor queries' do
|
||||
expect do
|
||||
pristine_projects.each do |project|
|
||||
root_ancestor = project.root_ancestor
|
||||
|
||||
root_ancestor.public_send(query_method) if query_method.present?
|
||||
end
|
||||
end.to make_queries_matching(root_query_regex, expected_query_count)
|
||||
end
|
||||
|
||||
it 'strong_memoizes the correct root_ancestor' do
|
||||
pristine_projects.each do |project|
|
||||
expected_parent_id = project.root_ancestor&.id
|
||||
|
||||
expect(project.parent_id).to eq(expected_parent_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when use_traversal_ids FF is enabled' do
|
||||
context 'when the preloader is used' do
|
||||
before do
|
||||
preload_ancestors
|
||||
end
|
||||
|
||||
context 'when no additional preloads are provided' do
|
||||
it_behaves_like 'executes N matching DB queries', 0
|
||||
end
|
||||
|
||||
context 'when additional preloads are provided' do
|
||||
let(:additional_preloads) { [:route] }
|
||||
let(:root_query_regex) { /\ASELECT.+FROM "routes" WHERE "routes"."source_id" = \d+/ }
|
||||
|
||||
it_behaves_like 'executes N matching DB queries', 0, :full_path
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the preloader is not used' do
|
||||
it_behaves_like 'executes N matching DB queries', 4
|
||||
end
|
||||
end
|
||||
|
||||
context 'when use_traversal_ids FF is disabled' do
|
||||
before do
|
||||
stub_feature_flags(use_traversal_ids: false)
|
||||
end
|
||||
|
||||
context 'when the preloader is used' do
|
||||
before do
|
||||
preload_ancestors
|
||||
end
|
||||
|
||||
context 'when no additional preloads are provided' do
|
||||
it_behaves_like 'executes N matching DB queries', 4
|
||||
end
|
||||
|
||||
context 'when additional preloads are provided' do
|
||||
let(:additional_preloads) { [:route] }
|
||||
let(:root_query_regex) { /\ASELECT.+FROM "routes" WHERE "routes"."source_id" = \d+/ }
|
||||
|
||||
it_behaves_like 'executes N matching DB queries', 4, :full_path
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the preloader is not used' do
|
||||
it_behaves_like 'executes N matching DB queries', 4
|
||||
end
|
||||
end
|
||||
|
||||
def preload_ancestors
|
||||
described_class.new(pristine_projects, :namespace, additional_preloads).execute
|
||||
end
|
||||
end
|
|
@ -0,0 +1,48 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Project Environments query' do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:project) { create(:project, :private, :repository) }
|
||||
let_it_be(:environment) { create(:environment, project: project) }
|
||||
let_it_be(:developer) { create(:user).tap { |u| project.add_developer(u) } }
|
||||
|
||||
subject { post_graphql(query, current_user: user) }
|
||||
|
||||
let(:user) { developer }
|
||||
|
||||
let(:query) do
|
||||
%(
|
||||
query {
|
||||
project(fullPath: "#{project.full_path}") {
|
||||
environment(name: "#{environment.name}") {
|
||||
slug
|
||||
createdAt
|
||||
updatedAt
|
||||
autoStopAt
|
||||
autoDeleteAt
|
||||
tier
|
||||
environmentType
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
it 'returns the specified fields of the environment', :aggregate_failures do
|
||||
environment.update!(auto_stop_at: 1.day.ago, auto_delete_at: 2.days.ago, environment_type: 'review')
|
||||
|
||||
subject
|
||||
|
||||
environment_data = graphql_data.dig('project', 'environment')
|
||||
expect(environment_data['slug']).to eq(environment.slug)
|
||||
expect(environment_data['createdAt']).to eq(environment.created_at.iso8601)
|
||||
expect(environment_data['updatedAt']).to eq(environment.updated_at.iso8601)
|
||||
expect(environment_data['autoStopAt']).to eq(environment.auto_stop_at.iso8601)
|
||||
expect(environment_data['autoDeleteAt']).to eq(environment.auto_delete_at.iso8601)
|
||||
expect(environment_data['tier']).to eq(environment.tier.upcase)
|
||||
expect(environment_data['environmentType']).to eq(environment.environment_type)
|
||||
end
|
||||
end
|
|
@ -480,7 +480,7 @@ RSpec.describe 'project routing' do
|
|||
newline_file = "new\n\nline.txt"
|
||||
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
|
||||
assert_routing({ path: "/gitlab/gitlabhq/-/blame/master/#{url_encoded_newline_file}",
|
||||
method: :get },
|
||||
method: :get },
|
||||
{ controller: 'projects/blame', action: 'show',
|
||||
namespace_id: 'gitlab', project_id: 'gitlabhq',
|
||||
id: "master/#{newline_file}" })
|
||||
|
@ -499,7 +499,7 @@ RSpec.describe 'project routing' do
|
|||
newline_file = "new\n\nline.txt"
|
||||
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
|
||||
assert_routing({ path: "/gitlab/gitlabhq/-/blob/blob/master/blob/#{url_encoded_newline_file}",
|
||||
method: :get },
|
||||
method: :get },
|
||||
{ controller: 'projects/blob', action: 'show',
|
||||
namespace_id: 'gitlab', project_id: 'gitlabhq',
|
||||
id: "blob/master/blob/#{newline_file}" })
|
||||
|
@ -520,7 +520,7 @@ RSpec.describe 'project routing' do
|
|||
newline_file = "new\n\nline.txt"
|
||||
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
|
||||
assert_routing({ path: "/gitlab/gitlabhq/-/tree/master/#{url_encoded_newline_file}",
|
||||
method: :get },
|
||||
method: :get },
|
||||
{ controller: 'projects/tree', action: 'show',
|
||||
namespace_id: 'gitlab', project_id: 'gitlabhq',
|
||||
id: "master/#{newline_file}" })
|
||||
|
@ -540,7 +540,7 @@ RSpec.describe 'project routing' do
|
|||
newline_file = "new\n\nline.txt"
|
||||
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
|
||||
assert_routing({ path: "/gitlab/gitlabhq/-/find_file/#{url_encoded_newline_file}",
|
||||
method: :get },
|
||||
method: :get },
|
||||
{ controller: 'projects/find_file', action: 'show',
|
||||
namespace_id: 'gitlab', project_id: 'gitlabhq',
|
||||
id: "#{newline_file}" })
|
||||
|
@ -551,7 +551,7 @@ RSpec.describe 'project routing' do
|
|||
newline_file = "new\n\nline.txt"
|
||||
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
|
||||
assert_routing({ path: "/gitlab/gitlabhq/-/files/#{url_encoded_newline_file}",
|
||||
method: :get },
|
||||
method: :get },
|
||||
{ controller: 'projects/find_file', action: 'list',
|
||||
namespace_id: 'gitlab', project_id: 'gitlabhq',
|
||||
id: "#{newline_file}" })
|
||||
|
@ -570,7 +570,7 @@ RSpec.describe 'project routing' do
|
|||
newline_file = "new\n\nline.txt"
|
||||
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
|
||||
assert_routing({ path: "/gitlab/gitlabhq/-/edit/master/docs/#{url_encoded_newline_file}",
|
||||
method: :get },
|
||||
method: :get },
|
||||
{ controller: 'projects/blob', action: 'edit',
|
||||
namespace_id: 'gitlab', project_id: 'gitlabhq',
|
||||
id: "master/docs/#{newline_file}" })
|
||||
|
@ -584,7 +584,7 @@ RSpec.describe 'project routing' do
|
|||
newline_file = "new\n\nline.txt"
|
||||
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
|
||||
assert_routing({ path: "/gitlab/gitlabhq/-/edit/master/docs/#{url_encoded_newline_file}",
|
||||
method: :get },
|
||||
method: :get },
|
||||
{ controller: 'projects/blob', action: 'edit',
|
||||
namespace_id: 'gitlab', project_id: 'gitlabhq',
|
||||
id: "master/docs/#{newline_file}" })
|
||||
|
@ -600,7 +600,7 @@ RSpec.describe 'project routing' do
|
|||
newline_file = "new\n\nline.txt"
|
||||
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
|
||||
assert_routing({ path: "/gitlab/gitlabhq/-/raw/master/#{url_encoded_newline_file}",
|
||||
method: :get },
|
||||
method: :get },
|
||||
{ controller: 'projects/raw', action: 'show',
|
||||
namespace_id: 'gitlab', project_id: 'gitlabhq',
|
||||
id: "master/#{newline_file}" })
|
||||
|
@ -889,8 +889,8 @@ RSpec.describe 'project routing' do
|
|||
describe Projects::Snippets::BlobsController, "routing" do
|
||||
it "to #raw" do
|
||||
expect(get('/gitlab/gitlabhq/-/snippets/1/raw/master/lib/version.rb'))
|
||||
.to route_to('projects/snippets/blobs#raw', namespace_id: 'gitlab',
|
||||
project_id: 'gitlabhq', snippet_id: '1', ref: 'master', path: 'lib/version.rb')
|
||||
.to route_to('projects/snippets/blobs#raw',
|
||||
namespace_id: 'gitlab', project_id: 'gitlabhq', snippet_id: '1', ref: 'master', path: 'lib/version.rb')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ RSpec.describe Ci::Lint::JobEntity, :aggregate_failures do
|
|||
stage: 'test',
|
||||
before_script: ['bundle install', 'bundle exec rake db:create'],
|
||||
script: ["rake spec"],
|
||||
after_script: ["rake spec"],
|
||||
after_script: ["rake spec"],
|
||||
tag_list: %w[ruby postgres],
|
||||
environment: { name: 'hello', url: 'world' },
|
||||
when: 'on_success',
|
||||
|
|
|
@ -14,8 +14,7 @@ RSpec.describe ContainerRepositoryEntity do
|
|||
|
||||
before do
|
||||
stub_container_registry_config(enabled: true)
|
||||
stub_container_registry_tags(repository: :any,
|
||||
tags: %w[stable latest])
|
||||
stub_container_registry_tags(repository: :any, tags: %w[stable latest])
|
||||
allow(request).to receive(:project).and_return(project)
|
||||
allow(request).to receive(:current_user).and_return(user)
|
||||
end
|
||||
|
|
|
@ -61,8 +61,7 @@ RSpec.describe DeploymentEntity do
|
|||
|
||||
context 'when the pipeline has another manual action' do
|
||||
let!(:other_build) do
|
||||
create(:ci_build, :manual, name: 'another deploy',
|
||||
pipeline: pipeline, environment: build.environment)
|
||||
create(:ci_build, :manual, name: 'another deploy', pipeline: pipeline, environment: build.environment)
|
||||
end
|
||||
|
||||
let!(:other_deployment) { create(:deployment, deployable: build) }
|
||||
|
|
|
@ -57,9 +57,9 @@ RSpec.describe MergeRequestMetricsHelper do
|
|||
|
||||
expect(MergeRequest::Metrics).to receive(:new)
|
||||
.with(latest_closed_at: closed_event&.updated_at,
|
||||
latest_closed_by: closed_event&.author,
|
||||
merged_at: merge_event&.updated_at,
|
||||
merged_by: merge_event&.author)
|
||||
latest_closed_by: closed_event&.author,
|
||||
merged_at: merge_event&.updated_at,
|
||||
merged_by: merge_event&.author)
|
||||
.and_call_original
|
||||
|
||||
subject
|
||||
|
|
|
@ -85,86 +85,58 @@ RSpec.describe Projects::InactiveProjectsDeletionCronWorker do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when delete inactive projects feature is enabled' do
|
||||
context 'when delete inactive projects feature is enabled', :clean_gitlab_redis_shared_state, :sidekiq_inline do
|
||||
before do
|
||||
stub_application_setting(delete_inactive_projects: true)
|
||||
end
|
||||
|
||||
context 'when feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(inactive_projects_deletion: false)
|
||||
it 'invokes Projects::InactiveProjectsDeletionNotificationWorker for inactive projects' do
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
expect(redis).to receive(:hset).with('inactive_projects_deletion_warning_email_notified',
|
||||
"project:#{inactive_large_project.id}", Date.current)
|
||||
end
|
||||
expect(::Projects::InactiveProjectsDeletionNotificationWorker).to receive(:perform_async).with(
|
||||
inactive_large_project.id, deletion_date).and_call_original
|
||||
expect(::Projects::DestroyService).not_to receive(:new)
|
||||
|
||||
it 'does not invoke Projects::InactiveProjectsDeletionNotificationWorker' do
|
||||
expect(::Projects::InactiveProjectsDeletionNotificationWorker).not_to receive(:perform_async)
|
||||
expect(::Projects::DestroyService).not_to receive(:new)
|
||||
|
||||
worker.perform
|
||||
end
|
||||
|
||||
it 'does not delete the inactive projects' do
|
||||
worker.perform
|
||||
|
||||
expect(inactive_large_project.reload.pending_delete).to eq(false)
|
||||
end
|
||||
|
||||
it_behaves_like 'worker is running for more than 4 minutes'
|
||||
it_behaves_like 'worker finishes processing in less than 4 minutes'
|
||||
worker.perform
|
||||
end
|
||||
|
||||
context 'when feature flag is enabled', :clean_gitlab_redis_shared_state, :sidekiq_inline do
|
||||
before do
|
||||
stub_feature_flags(inactive_projects_deletion: true)
|
||||
it 'does not invoke InactiveProjectsDeletionNotificationWorker for already notified inactive projects' do
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.hset('inactive_projects_deletion_warning_email_notified', "project:#{inactive_large_project.id}",
|
||||
Date.current.to_s)
|
||||
end
|
||||
|
||||
it 'invokes Projects::InactiveProjectsDeletionNotificationWorker for inactive projects' do
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
expect(redis).to receive(:hset).with('inactive_projects_deletion_warning_email_notified',
|
||||
"project:#{inactive_large_project.id}", Date.current)
|
||||
end
|
||||
expect(::Projects::InactiveProjectsDeletionNotificationWorker).to receive(:perform_async).with(
|
||||
inactive_large_project.id, deletion_date).and_call_original
|
||||
expect(::Projects::DestroyService).not_to receive(:new)
|
||||
expect(::Projects::InactiveProjectsDeletionNotificationWorker).not_to receive(:perform_async)
|
||||
expect(::Projects::DestroyService).not_to receive(:new)
|
||||
|
||||
worker.perform
|
||||
end
|
||||
|
||||
it 'does not invoke InactiveProjectsDeletionNotificationWorker for already notified inactive projects' do
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.hset('inactive_projects_deletion_warning_email_notified', "project:#{inactive_large_project.id}",
|
||||
Date.current.to_s)
|
||||
end
|
||||
|
||||
expect(::Projects::InactiveProjectsDeletionNotificationWorker).not_to receive(:perform_async)
|
||||
expect(::Projects::DestroyService).not_to receive(:new)
|
||||
|
||||
worker.perform
|
||||
end
|
||||
|
||||
it 'invokes Projects::DestroyService for projects that are inactive even after being notified' do
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.hset('inactive_projects_deletion_warning_email_notified', "project:#{inactive_large_project.id}",
|
||||
15.months.ago.to_date.to_s)
|
||||
end
|
||||
|
||||
expect(::Projects::InactiveProjectsDeletionNotificationWorker).not_to receive(:perform_async)
|
||||
expect(::Projects::DestroyService).to receive(:new).with(inactive_large_project, admin_user, {})
|
||||
.at_least(:once).and_call_original
|
||||
|
||||
worker.perform
|
||||
|
||||
expect(inactive_large_project.reload.pending_delete).to eq(true)
|
||||
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
expect(redis.hget('inactive_projects_deletion_warning_email_notified',
|
||||
"project:#{inactive_large_project.id}")).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'worker is running for more than 4 minutes'
|
||||
it_behaves_like 'worker finishes processing in less than 4 minutes'
|
||||
worker.perform
|
||||
end
|
||||
|
||||
it 'invokes Projects::DestroyService for projects that are inactive even after being notified' do
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.hset('inactive_projects_deletion_warning_email_notified', "project:#{inactive_large_project.id}",
|
||||
15.months.ago.to_date.to_s)
|
||||
end
|
||||
|
||||
expect(::Projects::InactiveProjectsDeletionNotificationWorker).not_to receive(:perform_async)
|
||||
expect(::Projects::DestroyService).to receive(:new).with(inactive_large_project, admin_user, {})
|
||||
.at_least(:once).and_call_original
|
||||
|
||||
worker.perform
|
||||
|
||||
expect(inactive_large_project.reload.pending_delete).to eq(true)
|
||||
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
expect(redis.hget('inactive_projects_deletion_warning_email_notified',
|
||||
"project:#{inactive_large_project.id}")).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'worker is running for more than 4 minutes'
|
||||
it_behaves_like 'worker finishes processing in less than 4 minutes'
|
||||
|
||||
it_behaves_like 'an idempotent worker'
|
||||
end
|
||||
end
|
||||
|
|
127
yarn.lock
127
yarn.lock
|
@ -3021,6 +3021,13 @@ brace-expansion@^1.1.7:
|
|||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
brace-expansion@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
|
||||
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
|
||||
braces@^2.3.1:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
|
||||
|
@ -3565,16 +3572,11 @@ commander@^6.0.0:
|
|||
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
|
||||
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
|
||||
|
||||
commander@^9.4.0:
|
||||
commander@^9.4.0, commander@~9.4.0:
|
||||
version "9.4.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.0.tgz#bc4a40918fefe52e22450c111ecd6b7acce6f11c"
|
||||
integrity sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==
|
||||
|
||||
commander@~9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-9.0.0.tgz#86d58f24ee98126568936bd1d3574e0308a99a40"
|
||||
integrity sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==
|
||||
|
||||
commondir@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
|
||||
|
@ -4974,7 +4976,7 @@ enhanced-resolve@^4.5.0:
|
|||
memory-fs "^0.5.0"
|
||||
tapable "^1.0.0"
|
||||
|
||||
entities@^2.0.0, entities@~2.1.0:
|
||||
entities@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
|
||||
integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
|
||||
|
@ -5967,7 +5969,7 @@ glob-parent@^6.0.1:
|
|||
dependencies:
|
||||
is-glob "^4.0.3"
|
||||
|
||||
"glob@5 - 7", glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.2.0:
|
||||
"glob@5 - 7", glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
|
||||
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
|
||||
|
@ -5979,6 +5981,17 @@ glob-parent@^6.0.1:
|
|||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@~8.0.3:
|
||||
version "8.0.3"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e"
|
||||
integrity sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^5.0.1"
|
||||
once "^1.3.0"
|
||||
|
||||
global-modules@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
|
||||
|
@ -6596,10 +6609,10 @@ ini@^1.3.4, ini@^1.3.5:
|
|||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
|
||||
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
|
||||
|
||||
ini@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5"
|
||||
integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==
|
||||
ini@~3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ini/-/ini-3.0.1.tgz#c76ec81007875bc44d544ff7a11a55d12294102d"
|
||||
integrity sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==
|
||||
|
||||
inline-style-parser@0.1.1:
|
||||
version "0.1.1"
|
||||
|
@ -7569,10 +7582,10 @@ json5@^2.1.2, json5@^2.2.1:
|
|||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
|
||||
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
|
||||
|
||||
jsonc-parser@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22"
|
||||
integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==
|
||||
jsonc-parser@~3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.1.0.tgz#73b8f0e5c940b83d03476bc2e51a20ef0932615d"
|
||||
integrity sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==
|
||||
|
||||
jsonfile@^4.0.0:
|
||||
version "4.0.0"
|
||||
|
@ -7682,13 +7695,6 @@ lines-and-columns@^1.1.6:
|
|||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
|
||||
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
|
||||
|
||||
linkify-it@^3.0.1:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.2.tgz#f55eeb8bc1d3ae754049e124ab3bb56d97797fb8"
|
||||
integrity sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==
|
||||
dependencies:
|
||||
uc.micro "^1.0.1"
|
||||
|
||||
linkify-it@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-4.0.1.tgz#01f1d5e508190d06669982ba31a7d9f56a5751ec"
|
||||
|
@ -7991,18 +7997,7 @@ map-visit@^1.0.0:
|
|||
dependencies:
|
||||
object-visit "^1.0.0"
|
||||
|
||||
markdown-it@12.3.2:
|
||||
version "12.3.2"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90"
|
||||
integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
entities "~2.1.0"
|
||||
linkify-it "^3.0.1"
|
||||
mdurl "^1.0.1"
|
||||
uc.micro "^1.0.5"
|
||||
|
||||
markdown-it@^13.0.1:
|
||||
markdown-it@13.0.1, markdown-it@^13.0.1:
|
||||
version "13.0.1"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-13.0.1.tgz#c6ecc431cacf1a5da531423fc6a42807814af430"
|
||||
integrity sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==
|
||||
|
@ -8018,33 +8013,33 @@ markdown-table@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.2.tgz#9b59eb2c1b22fe71954a65ff512887065a7bb57c"
|
||||
integrity sha512-y8j3a5/DkJCmS5x4dMCQL+OR0+2EAq3DOtio1COSHsmW2BGXnNCK3v12hJt1LrUz5iZH5g0LmuYOjDdI+czghA==
|
||||
|
||||
markdownlint-cli@0.31.0:
|
||||
version "0.31.0"
|
||||
resolved "https://registry.yarnpkg.com/markdownlint-cli/-/markdownlint-cli-0.31.0.tgz#a44264a71066475228292b7af19d3d18b827676d"
|
||||
integrity sha512-UCNA10I2evrEqGWUGM4I6ae6LubLeySkKegP1GQaZSES516BYBgOn8Ai8MXU+5rSIeCvMyKi91alqHyRDuUnYA==
|
||||
markdownlint-cli@0.32.2:
|
||||
version "0.32.2"
|
||||
resolved "https://registry.yarnpkg.com/markdownlint-cli/-/markdownlint-cli-0.32.2.tgz#b7b5c5808039aef4022aef603efaa607caf8e0de"
|
||||
integrity sha512-xmJT1rGueUgT4yGNwk6D0oqQr90UJ7nMyakXtqjgswAkEhYYqjHew9RY8wDbOmh2R270IWjuKSeZzHDEGPAUkQ==
|
||||
dependencies:
|
||||
commander "~9.0.0"
|
||||
commander "~9.4.0"
|
||||
get-stdin "~9.0.0"
|
||||
glob "~7.2.0"
|
||||
glob "~8.0.3"
|
||||
ignore "~5.2.0"
|
||||
js-yaml "^4.1.0"
|
||||
jsonc-parser "~3.0.0"
|
||||
markdownlint "~0.25.1"
|
||||
markdownlint-rule-helpers "~0.16.0"
|
||||
minimatch "~3.0.4"
|
||||
run-con "~1.2.10"
|
||||
jsonc-parser "~3.1.0"
|
||||
markdownlint "~0.26.2"
|
||||
markdownlint-rule-helpers "~0.17.2"
|
||||
minimatch "~5.1.0"
|
||||
run-con "~1.2.11"
|
||||
|
||||
markdownlint-rule-helpers@~0.16.0:
|
||||
version "0.16.0"
|
||||
resolved "https://registry.yarnpkg.com/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.16.0.tgz#c327f72782bd2b9475127a240508231f0413a25e"
|
||||
integrity sha512-oEacRUVeTJ5D5hW1UYd2qExYI0oELdYK72k1TKGvIeYJIbqQWAz476NAc7LNixSySUhcNl++d02DvX0ccDk9/w==
|
||||
markdownlint-rule-helpers@~0.17.2:
|
||||
version "0.17.2"
|
||||
resolved "https://registry.yarnpkg.com/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.17.2.tgz#64d6e8c66e497e631b0e40cf1cef7ca622a0b654"
|
||||
integrity sha512-XaeoW2NYSlWxMCZM2B3H7YTG6nlaLfkEZWMBhr4hSPlq9MuY2sy83+Xr89jXOqZMZYjvi5nBCGoFh7hHoPKZmA==
|
||||
|
||||
markdownlint@~0.25.1:
|
||||
version "0.25.1"
|
||||
resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.25.1.tgz#df04536607ebeeda5ccd5e4f38138823ed623788"
|
||||
integrity sha512-AG7UkLzNa1fxiOv5B+owPsPhtM4D6DoODhsJgiaNg1xowXovrYgOnLqAgOOFQpWOlHFVQUzjMY5ypNNTeov92g==
|
||||
markdownlint@~0.26.2:
|
||||
version "0.26.2"
|
||||
resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.26.2.tgz#11d3d03e7f0dd3c2e239753ee8fd064a861d9237"
|
||||
integrity sha512-2Am42YX2Ex5SQhRq35HxYWDfz1NLEOZWWN25nqd2h3AHRKsGRE+Qg1gt1++exW792eXTrR4jCNHfShfWk9Nz8w==
|
||||
dependencies:
|
||||
markdown-it "12.3.2"
|
||||
markdown-it "13.0.1"
|
||||
|
||||
marked@^4.0.18:
|
||||
version "4.0.18"
|
||||
|
@ -8693,12 +8688,12 @@ minimatch@^3.0.4, minimatch@^3.1.2:
|
|||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimatch@~3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
minimatch@^5.0.1, minimatch@~5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7"
|
||||
integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimist-options@4.1.0:
|
||||
version "4.1.0"
|
||||
|
@ -10335,14 +10330,14 @@ route-recognizer@^0.3.3:
|
|||
resolved "https://registry.yarnpkg.com/route-recognizer/-/route-recognizer-0.3.4.tgz#39ab1ffbce1c59e6d2bdca416f0932611e4f3ca3"
|
||||
integrity sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g==
|
||||
|
||||
run-con@~1.2.10:
|
||||
version "1.2.10"
|
||||
resolved "https://registry.yarnpkg.com/run-con/-/run-con-1.2.10.tgz#90de9d43d20274d00478f4c000495bd72f417d22"
|
||||
integrity sha512-n7PZpYmMM26ZO21dd8y3Yw1TRtGABjRtgPSgFS/nhzfvbJMXFtJhJVyEgayMiP+w/23craJjsnfDvx4W4ue/HQ==
|
||||
run-con@~1.2.11:
|
||||
version "1.2.11"
|
||||
resolved "https://registry.yarnpkg.com/run-con/-/run-con-1.2.11.tgz#0014ed430bad034a60568dfe7de2235f32e3f3c4"
|
||||
integrity sha512-NEMGsUT+cglWkzEr4IFK21P4Jca45HqiAbIIZIBdX5+UZTB24Mb/21iNGgz9xZa8tL6vbW7CXmq7MFN42+VjNQ==
|
||||
dependencies:
|
||||
deep-extend "^0.6.0"
|
||||
ini "~2.0.0"
|
||||
minimist "^1.2.5"
|
||||
ini "~3.0.0"
|
||||
minimist "^1.2.6"
|
||||
strip-json-comments "~3.1.1"
|
||||
|
||||
run-parallel@^1.1.9:
|
||||
|
|
Loading…
Reference in New Issue