Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
		
							parent
							
								
									e67e43e958
								
							
						
					
					
						commit
						d298c12de5
					
				|  | @ -23,6 +23,7 @@ module ErrorTracking | |||
| 
 | ||||
|     self.reactive_cache_key = ->(setting) { [setting.class.model_name.singular, setting.project_id] } | ||||
|     self.reactive_cache_work_type = :external_dependency | ||||
|     self.reactive_cache_hard_limit = ErrorTracking::SentryClient::RESPONSE_SIZE_LIMIT | ||||
| 
 | ||||
|     self.table_name = 'project_error_tracking_settings' | ||||
| 
 | ||||
|  | @ -103,9 +104,18 @@ module ErrorTracking | |||
|       api_host | ||||
|     end | ||||
| 
 | ||||
|     def sentry_response_limit_enabled? | ||||
|       Feature.enabled?(:error_tracking_sentry_limit, project) | ||||
|     end | ||||
| 
 | ||||
|     def reactive_cache_limit_enabled? | ||||
|       sentry_response_limit_enabled? | ||||
|     end | ||||
| 
 | ||||
|     def sentry_client | ||||
|       strong_memoize(:sentry_client) do | ||||
|         ::ErrorTracking::SentryClient.new(api_url, token) | ||||
|         ::ErrorTracking::SentryClient | ||||
|           .new(api_url, token, validate_size_guarded_by_feature_flag: sentry_response_limit_enabled?) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|  | @ -127,14 +137,14 @@ module ErrorTracking | |||
| 
 | ||||
|     def issue_details(opts = {}) | ||||
|       with_reactive_cache('issue_details', opts.stringify_keys) do |result| | ||||
|         ensure_issue_belongs_to_project!(result[:issue].project_id) | ||||
|         ensure_issue_belongs_to_project!(result[:issue].project_id) if result[:issue] | ||||
|         result | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     def issue_latest_event(opts = {}) | ||||
|       with_reactive_cache('issue_latest_event', opts.stringify_keys) do |result| | ||||
|         ensure_issue_belongs_to_project!(result[:latest_event].project_id) | ||||
|         ensure_issue_belongs_to_project!(result[:latest_event].project_id) if result[:latest_event] | ||||
|         result | ||||
|       end | ||||
|     end | ||||
|  |  | |||
|  | @ -1,2 +1,2 @@ | |||
| %p | ||||
|   Milestone removed | ||||
|   = s_('Notify|Milestone removed') | ||||
|  |  | |||
|  | @ -0,0 +1,8 @@ | |||
| --- | ||||
| name: error_tracking_sentry_limit | ||||
| introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84209 | ||||
| rollout_issue_url:  https://gitlab.com/gitlab-org/gitlab/-/issues/372427 | ||||
| milestone: '15.4' | ||||
| type: development | ||||
| group: group::observability | ||||
| default_enabled: false | ||||
|  | @ -70,7 +70,7 @@ is the same as [getting the job's artifacts](#get-job-artifacts), but by | |||
| defining the job's name instead of its ID. | ||||
| 
 | ||||
| NOTE: | ||||
| If a pipeline is [parent of other child pipelines](../ci/pipelines/parent_child_pipelines.md), artifacts | ||||
| If a pipeline is [parent of other child pipelines](../ci/pipelines/downstream_pipelines.md#parent-child-pipelines), artifacts | ||||
| are searched in hierarchical order from parent to child. For example, if both parent and | ||||
| child pipelines have a job with the same name, the artifact from the parent pipeline is returned. | ||||
| 
 | ||||
|  | @ -175,7 +175,7 @@ The artifact file provides more detail than what is available in the | |||
| [CSV export](../user/application_security/vulnerability_report/index.md#export-vulnerability-details). | ||||
| 
 | ||||
| In [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/201784) and later, artifacts | ||||
| for [parent and child pipelines](../ci/pipelines/parent_child_pipelines.md) are searched in hierarchical | ||||
| for [parent and child pipelines](../ci/pipelines/downstream_pipelines.md#parent-child-pipelines) are searched in hierarchical | ||||
| order from parent to child. For example, if both parent and child pipelines have a | ||||
| job with the same name, the artifact from the parent pipeline is returned. | ||||
| 
 | ||||
|  |  | |||
|  | @ -303,7 +303,7 @@ Example of response | |||
| ``` | ||||
| 
 | ||||
| In GitLab 13.3 and later, this endpoint [returns data for any pipeline](pipelines.md#get-a-single-pipeline) | ||||
| including [child pipelines](../ci/pipelines/parent_child_pipelines.md). | ||||
| including [child pipelines](../ci/pipelines/downstream_pipelines.md#parent-child-pipelines). | ||||
| 
 | ||||
| In GitLab 13.5 and later, this endpoint does not return retried jobs in the response | ||||
| by default. Additionally, jobs are sorted by ID in descending order (newest first). | ||||
|  |  | |||
|  | @ -6,8 +6,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w | |||
| 
 | ||||
| # Merge requests API **(FREE)** | ||||
| 
 | ||||
| > - `reference` was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354) in GitLab 12.10 in favour of `references`. | ||||
| > - `reviewer_username` and `reviewer_id` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. | ||||
| > - `draft` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63473) as a replacement for `work_in_progress` in GitLab 14.0. | ||||
| > - `merge_user` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/349031) as an eventual replacement for `merged_by` in GitLab 14.7. | ||||
| 
 | ||||
|  | @ -40,38 +38,38 @@ GET /merge_requests?search=foo&in=title | |||
| 
 | ||||
| Parameters: | ||||
| 
 | ||||
| | Attribute                       | Type           | Required | Description                                                                                                            | | ||||
| | ------------------------------- | -------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- | | ||||
| | `state`                         | string         | no       | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`.                             | | ||||
| | `order_by`                      | string         | no       | Return requests ordered by `created_at`, `title`, or `updated_at` fields. Default is `created_at`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/331625) in GitLab 14.8.| | ||||
| | `sort`                          | string         | no       | Return requests sorted in `asc` or `desc` order. Default is `desc`.                                                     | | ||||
| | `milestone`                     | string         | no       | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. | | ||||
| | `view`                          | string         | no       | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request.                              | | ||||
| | `labels`                        | string         | no       | Return merge requests matching a comma-separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. Predefined names are case-insensitive. | | ||||
| | `with_labels_details`           | boolean        | no       | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) in GitLab 12.7. | | ||||
| | `with_merge_status_recheck`     | boolean        | no       | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0. | | ||||
| | `created_after`                 | datetime       | no       | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | ||||
| | `created_before`                | datetime       | no       | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | ||||
| | `updated_after`                 | datetime       | no       | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | ||||
| | `updated_before`                | datetime       | no       | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | ||||
| | `scope`                         | string         | no       | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`. | | ||||
| | `author_id`                     | integer        | no       | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. | | ||||
| | `author_username`               | string         | no       | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10. | | ||||
| | Attribute                       | Type           | Required | Description | | ||||
| | ------------------------------- | -------------- | -------- | ----------- | | ||||
| | `approved_by_ids` **(PREMIUM)** | integer array  | no       | Returns merge requests which have been approved by all the users with the given `id`. Maximum of 5. `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. | | ||||
| | `approver_ids` **(PREMIUM)**    | integer array  | no       | Returns merge requests which have specified all the users with the given `id` as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. | | ||||
| | `assignee_id`                   | integer        | no       | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. | | ||||
| | `approver_ids` **(PREMIUM)**    | integer array  | no       | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. | | ||||
| | `approved_by_ids` **(PREMIUM)** | integer array  | no       | Returns merge requests which have been approved by all the users with the given `id`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. | | ||||
| | `reviewer_id`                   | integer        | no       | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given user `id`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_username`.  | | ||||
| | `reviewer_username`             | string         | no       | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given `username`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. | | ||||
| | `my_reaction_emoji`             | string         | no       | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. | | ||||
| | `source_branch`                 | string         | no       | Return merge requests with the given source branch.                                                                     | | ||||
| | `target_branch`                 | string         | no       | Return merge requests with the given target branch.                                                                     | | ||||
| | `search`                        | string         | no       | Search merge requests against their `title` and `description`.                                                          | | ||||
| | `in`                            | string         | no       | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description`. | | ||||
| | `wip`                           | string         | no       | Filter merge requests against their `wip` status. `yes` to return *only* draft merge requests, `no` to return *non-draft* merge requests. | | ||||
| | `not`                           | Hash           | no       | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. | | ||||
| | `author_id`                     | integer        | no       | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. | | ||||
| | `author_username`               | string         | no       | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. | | ||||
| | `created_after`                 | datetime       | no       | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `created_before`                | datetime       | no       | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `deployed_after`                | datetime       | no       | Return merge requests deployed after the given date/time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `deployed_before`               | datetime       | no       | Return merge requests deployed before the given date/time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `environment`                   | string         | no       | Returns merge requests deployed to the given environment. | | ||||
| | `deployed_before`               | datetime       | no       | Return merge requests deployed before the given date/time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | ||||
| | `deployed_after`                | datetime       | no       | Return merge requests deployed after the given date/time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | ||||
| | `in`                            | string         | no       | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description`. | | ||||
| | `labels`                        | string         | no       | Return merge requests matching a comma-separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. Predefined names are case-insensitive. | | ||||
| | `milestone`                     | string         | no       | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. | | ||||
| | `my_reaction_emoji`             | string         | no       | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. | | ||||
| | `not`                           | Hash           | no       | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. | | ||||
| | `order_by`                      | string         | no       | Return requests ordered by `created_at`, `title`, or `updated_at` fields. Default is `created_at`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/331625) in GitLab 14.8.| | ||||
| | `reviewer_id`                   | integer        | no       | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given user `id`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_username`. | | ||||
| | `reviewer_username`             | string         | no       | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given `username`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. | | ||||
| | `scope`                         | string         | no       | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`. | | ||||
| | `search`                        | string         | no       | Search merge requests against their `title` and `description`. | | ||||
| | `sort`                          | string         | no       | Return requests sorted in `asc` or `desc` order. Default is `desc`. | | ||||
| | `source_branch`                 | string         | no       | Return merge requests with the given source branch. | | ||||
| | `state`                         | string         | no       | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`. | | ||||
| | `target_branch`                 | string         | no       | Return merge requests with the given target branch. | | ||||
| | `updated_after`                 | datetime       | no       | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `updated_before`                | datetime       | no       | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `view`                          | string         | no       | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. | | ||||
| | `with_labels_details`           | boolean        | no       | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. | | ||||
| | `with_merge_status_recheck`     | boolean        | no       | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0. | | ||||
| | `wip`                           | string         | no       | Filter merge requests against their `wip` status. `yes` to return *only* draft merge requests, `no` to return *non-draft* merge requests. | | ||||
| 
 | ||||
| ```json | ||||
| [ | ||||
|  | @ -241,37 +239,37 @@ are the same. In the case of a merge request from a fork, | |||
| 
 | ||||
| Parameters: | ||||
| 
 | ||||
| | Attribute                       | Type           | Required | Description                                                                                                                    | | ||||
| | ------------------------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ | | ||||
| | `id`                            | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user.                | | ||||
| | `iids[]`                        | integer array  | no       | Return the request having the given `iid`.                                                                                      | | ||||
| | `state`                         | string         | no       | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`.                                     | | ||||
| | `order_by`                      | string         | no       | Return requests ordered by `created_at`, `title` or `updated_at` fields. Default is `created_at`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/331625) in GitLab 14.8. | | ||||
| | `sort`                          | string         | no       | Return requests sorted in `asc` or `desc` order. Default is `desc`.                                                             | | ||||
| | `milestone`                     | string         | no       | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. | | ||||
| | `view`                          | string         | no       | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request.                                      | | ||||
| | `labels`                        | string         | no       | Return merge requests matching a comma-separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. Predefined names are case-insensitive. | | ||||
| | `with_labels_details`           | boolean        | no       | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) in GitLab 12.7. | | ||||
| | `with_merge_status_recheck`     | boolean        | no       | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0. | | ||||
| | `created_after`                 | datetime       | no       | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | ||||
| | `created_before`                | datetime       | no       | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | ||||
| | `updated_after`                 | datetime       | no       | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | ||||
| | `updated_before`                | datetime       | no       | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | ||||
| | `scope`                         | string         | no       | Return merge requests for the given scope: `created_by_me`, `assigned_to_me`, or `all`. | | ||||
| | `author_id`                     | integer        | no       | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. | | ||||
| | `author_username`               | string         | no       | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10. | | ||||
| | Attribute                       | Type           | Required | Description | | ||||
| | ------------------------------- | -------------- | -------- | ----------- | | ||||
| | `id`                            | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `approved_by_ids` **(PREMIUM)** | integer array  | no       | Returns merge requests which have been approved by all the users with the given `id`, with a maximum of 5. `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. | | ||||
| | `approver_ids` **(PREMIUM)**    | integer array  | no       | Returns merge requests which have specified all the users with the given `id` as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. | | ||||
| | `assignee_id`                   | integer        | no       | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. | | ||||
| | `approver_ids` **(PREMIUM)**    | integer array  | no       | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. | | ||||
| | `approved_by_ids` **(PREMIUM)** | integer array  | no       | Returns merge requests which have been approved by all the users with the given `id`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. | | ||||
| | `author_id`                     | integer        | no       | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. | | ||||
| | `author_username`               | string         | no       | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. | | ||||
| | `created_after`                 | datetime       | no       | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `created_before`                | datetime       | no       | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `environment`                   | string         | no       | Returns merge requests deployed to the given environment. | | ||||
| | `iids[]`                        | integer array  | no       | Return the request having the given `iid`. | | ||||
| | `labels`                        | string         | no       | Return merge requests matching a comma-separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. Predefined names are case-insensitive. | | ||||
| | `milestone`                     | string         | no       | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. | | ||||
| | `my_reaction_emoji`             | string         | no       | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. | | ||||
| | `not`                           | Hash           | no       | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. | | ||||
| | `order_by`                      | string         | no       | Return requests ordered by `created_at`, `title` or `updated_at` fields. Default is `created_at`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/331625) in GitLab 14.8. | | ||||
| | `reviewer_id`                   | integer        | no       | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given user `id`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_username`.  | | ||||
| | `reviewer_username`             | string         | no       | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given `username`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. | | ||||
| | `my_reaction_emoji`             | string         | no       | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. | | ||||
| | `source_branch`                 | string         | no       | Return merge requests with the given source branch.                                                                             | | ||||
| | `target_branch`                 | string         | no       | Return merge requests with the given target branch.                                                                             | | ||||
| | `search`                        | string         | no       | Search merge requests against their `title` and `description`.                                                                  | | ||||
| | `scope`                         | string         | no       | Return merge requests for the given scope: `created_by_me`, `assigned_to_me`, or `all`. | | ||||
| | `search`                        | string         | no       | Search merge requests against their `title` and `description`. | | ||||
| | `sort`                          | string         | no       | Return requests sorted in `asc` or `desc` order. Default is `desc`. | | ||||
| | `source_branch`                 | string         | no       | Return merge requests with the given source branch. | | ||||
| | `state`                         | string         | no       | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`. | | ||||
| | `target_branch`                 | string         | no       | Return merge requests with the given target branch. | | ||||
| | `updated_after`                 | datetime       | no       | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `updated_before`                | datetime       | no       | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `view`                          | string         | no       | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. | | ||||
| | `wip`                           | string         | no       | Filter merge requests against their `wip` status. `yes` to return *only* draft merge requests, `no` to return *non-draft* merge requests. | | ||||
| | `not`                           | Hash           | no       | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. | | ||||
| | `environment`                   | string         | no       | Returns merge requests deployed to the given environment. | | ||||
| | `with_labels_details`           | boolean        | no       | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. | | ||||
| | `with_merge_status_recheck`     | boolean        | no       | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0. | | ||||
| 
 | ||||
| ```json | ||||
| [ | ||||
|  | @ -429,36 +427,36 @@ GET /groups/:id/merge_requests?my_reaction_emoji=star | |||
| 
 | ||||
| Parameters: | ||||
| 
 | ||||
| | Attribute                       | Type           | Required | Description                                                                                                                    | | ||||
| | ------------------------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ | | ||||
| | `id`                            | integer/string | yes      | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user.                  | | ||||
| | `state`                         | string         | no       | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`.                                     | | ||||
| | `order_by`                      | string         | no       | Return merge requests ordered by `created_at`, `title` or `updated_at` fields. Default is `created_at`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/331625) in GitLab 14.8. | | ||||
| | `sort`                          | string         | no       | Return merge requests sorted in `asc` or `desc` order. Default is `desc`.                                                       | | ||||
| | `milestone`                     | string         | no       | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. | | ||||
| | `view`                          | string         | no       | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request.                                      | | ||||
| | `labels`                        | string         | no       | Return merge requests matching a comma-separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. Predefined names are case-insensitive. | | ||||
| | `with_labels_details`           | boolean        | no       | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) in GitLab 12.7. | | ||||
| | `with_merge_status_recheck`     | boolean        | no       | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0. | | ||||
| | Attribute                       | Type           | Required | Description | | ||||
| | ------------------------------- | -------------- | -------- | ----------- | | ||||
| | `id`                            | integer or string | yes      | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `approved_by_ids` **(PREMIUM)** | integer array  | no       | Returns merge requests which have been approved by all the users with the given `id`, with a maximum of 5. `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. | | ||||
| | `approved_by_usernames` **(PREMIUM)** | string array  | no       | Returns merge requests which have been approved by all the users with the given `username`, with a maximum of 5. `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. | | ||||
| | `approver_ids` **(PREMIUM)**    | integer array  | no       | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. | | ||||
| | `assignee_id`                   | integer        | no       | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. | | ||||
| | `author_id`                     | integer        | no       | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. | | ||||
| | `author_username`               | string         | no       | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. | | ||||
| | `created_after`                 | datetime       | no       | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `created_before`                | datetime       | no       | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `labels`                        | string         | no       | Return merge requests matching a comma-separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. Predefined names are case-insensitive. | | ||||
| | `milestone`                     | string         | no       | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. | | ||||
| | `my_reaction_emoji`             | string         | no       | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. | | ||||
| | `non_archived`                  | boolean        | no       | Return merge requests from non archived projects only. Default is `true`. | | ||||
| | `not`                           | Hash           | no       | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. | | ||||
| | `order_by`                      | string         | no       | Return merge requests ordered by `created_at`, `title` or `updated_at` fields. Default is `created_at`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/331625) in GitLab 14.8. | | ||||
| | `reviewer_id`                   | integer        | no       | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given user `id`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_username`. | | ||||
| | `reviewer_username`             | string         | no       | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given `username`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. | | ||||
| | `scope`                         | string         | no       | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`. | | ||||
| | `search`                        | string         | no       | Search merge requests against their `title` and `description`. | | ||||
| | `source_branch`                 | string         | no       | Return merge requests with the given source branch. | | ||||
| | `sort`                          | string         | no       | Return merge requests sorted in `asc` or `desc` order. Default is `desc`. | | ||||
| | `state`                         | string         | no       | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`. | | ||||
| | `target_branch`                 | string         | no       | Return merge requests with the given target branch. | | ||||
| | `updated_after`                 | datetime       | no       | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `updated_before`                | datetime       | no       | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | ||||
| | `scope`                         | string         | no       | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`.                                     | | ||||
| | `author_id`                     | integer        | no       | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. | | ||||
| | `author_username`               | string         | no       | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10. | | ||||
| | `assignee_id`                   | integer        | no       | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. | | ||||
| | `approver_ids` **(PREMIUM)**    | integer array  | no       | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. | | ||||
| | `approved_by_ids` **(PREMIUM)** | integer array  | no       | Returns merge requests which have been approved by all the users with the given `id`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. | | ||||
| | `approved_by_usernames` **(PREMIUM)** | string array  | no       | Returns merge requests which have been approved by all the users with the given `username`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. | | ||||
| | `reviewer_id`                   | integer        | no       | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given user `id`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_username`.  | | ||||
| | `reviewer_username`             | string         | no       | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given `username`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. | | ||||
| | `my_reaction_emoji`             | string         | no       | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. | | ||||
| | `source_branch`                 | string         | no       | Return merge requests with the given source branch.                                                                             | | ||||
| | `target_branch`                 | string         | no       | Return merge requests with the given target branch.                                                                             | | ||||
| | `search`                        | string         | no       | Search merge requests against their `title` and `description`. | | ||||
| | `non_archived`                  | boolean        | no       | Return merge requests from non archived projects only. Default is true. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23809) in GitLab 12.8)_.  | | ||||
| | `not`                           | Hash           | no       | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. | | ||||
| | `view`                          | string         | no       | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. | | ||||
| | `with_labels_details`           | boolean        | no       | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. | | ||||
| | `with_merge_status_recheck`     | boolean        | no       | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0. | | ||||
| 
 | ||||
| ```json | ||||
| [ | ||||
|  | @ -610,13 +608,13 @@ GET /projects/:id/merge_requests/:merge_request_iid | |||
| 
 | ||||
| Parameters: | ||||
| 
 | ||||
| | Attribute                        | Type           | Required | Description                                                                                                     | | ||||
| |----------------------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                             | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid`              | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | `render_html`                    | boolean        | no       | If `true` response includes rendered HTML for title and description.                                            | | ||||
| | `include_diverged_commits_count` | boolean        | no       | If `true` response includes the commits behind the target branch.                                               | | ||||
| | `include_rebase_in_progress`     | boolean        | no       | If `true` response includes whether a rebase operation is in progress.                                          | | ||||
| | Attribute                        | Type           | Required | Description | | ||||
| |----------------------------------|----------------|----------|-------------| | ||||
| | `id`                             | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid`              | integer        | yes      | The internal ID of the merge request. | | ||||
| | `include_diverged_commits_count` | boolean        | no       | If `true`, response includes the commits behind the target branch. | | ||||
| | `include_rebase_in_progress`     | boolean        | no       | If `true`, response includes whether a rebase operation is in progress. | | ||||
| | `render_html`                    | boolean        | no       | If `true`, response includes rendered HTML for title and description. | | ||||
| 
 | ||||
| ```json | ||||
| { | ||||
|  | @ -799,10 +797,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/participants | |||
| 
 | ||||
| Parameters: | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| 
 | ||||
| ```json | ||||
| [ | ||||
|  | @ -835,10 +833,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/reviewers | |||
| 
 | ||||
| Parameters: | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes   | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| 
 | ||||
| ```json | ||||
| [ | ||||
|  | @ -879,10 +877,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/commits | |||
| 
 | ||||
| Parameters: | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| 
 | ||||
| ```json | ||||
| [ | ||||
|  | @ -926,11 +924,11 @@ GET /projects/:id/merge_requests/:merge_request_iid/changes | |||
| 
 | ||||
| Parameters: | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | `access_raw_diffs`  | boolean        | no       | Retrieve change diffs via Gitaly.                                                                               | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| | `access_raw_diffs`  | boolean        | no       | Retrieve change diffs via Gitaly. | | ||||
| 
 | ||||
| ```json | ||||
| { | ||||
|  | @ -1048,10 +1046,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/pipelines | |||
| 
 | ||||
| Parameters: | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| 
 | ||||
| ```json | ||||
| [ | ||||
|  | @ -1066,8 +1064,6 @@ Parameters: | |||
| 
 | ||||
| ## Create MR Pipeline | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31722) in GitLab 12.3. | ||||
| 
 | ||||
| Create a new [pipeline for a merge request](../ci/pipelines/merge_request_pipelines.md). | ||||
| A pipeline created via this endpoint doesn't run a regular branch/tag pipeline. | ||||
| It requires `.gitlab-ci.yml` to be configured with `only: [merge_requests]` to create jobs. | ||||
|  | @ -1084,10 +1080,10 @@ POST /projects/:id/merge_requests/:merge_request_iid/pipelines | |||
| 
 | ||||
| Parameters: | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| 
 | ||||
| ```json | ||||
| { | ||||
|  | @ -1136,24 +1132,24 @@ Creates a new merge request. | |||
| POST /projects/:id/merge_requests | ||||
| ``` | ||||
| 
 | ||||
| | Attribute                  | Type    | Required | Description                                                                     | | ||||
| | ---------                  | ----    | -------- | -----------                                                                     | | ||||
| | `id`                       | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user | | ||||
| | `source_branch`            | string  | yes      | The source branch.                                                               | | ||||
| | `target_branch`            | string  | yes      | The target branch.                                                               | | ||||
| | `title`                    | string  | yes      | Title of MR.                                                                     | | ||||
| | `assignee_id`              | integer | no       | Assignee user ID.                                                                | | ||||
| | `assignee_ids`             | integer array | no | The ID of the users to assign the MR to. Set to `0` or provide an empty value to unassign all assignees. | | ||||
| | `reviewer_ids`             | integer array | no | The ID of the users added as a reviewer to the MR. If set to `0` or left empty, no reviewers are added. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. | | ||||
| | `description`              | string  | no       | Description of MR. Limited to 1,048,576 characters. | | ||||
| | `target_project_id`        | integer | no       | The target project (numeric ID).                                                 | | ||||
| | `labels`                   | string  | no       | Labels for MR as a comma-separated list.                                         | | ||||
| | `milestone_id`             | integer | no       | The global ID of a milestone.                                                           | | ||||
| | `remove_source_branch`     | boolean | no       | Flag indicating if a merge request should remove the source branch when merging. | | ||||
| | `allow_collaboration`      | boolean | no       | Allow commits from members who can merge to the target branch.                   | | ||||
| | `allow_maintainer_to_push` | boolean | no       | Alias of `allow_collaboration`.                                                  | | ||||
| | Attribute                  | Type    | Required | Description | | ||||
| | ---------                  | ----    | -------- | ----------- | | ||||
| | `id`                       | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user | | ||||
| | `source_branch`            | string  | yes      | The source branch. | | ||||
| | `target_branch`            | string  | yes      | The target branch. | | ||||
| | `title`                    | string  | yes      | Title of MR. | | ||||
| | `allow_collaboration`      | boolean | no       | Allow commits from members who can merge to the target branch. | | ||||
| | `allow_maintainer_to_push` | boolean | no       | Alias of `allow_collaboration`. | | ||||
| | `approvals_before_merge` **(PREMIUM)** | integer | no | Number of approvals required before this can be merged (see below). | | ||||
| | `squash`                   | boolean | no       | Squash commits into a single commit when merging.                                | | ||||
| | `assignee_id`              | integer | no       | Assignee user ID. | | ||||
| | `assignee_ids`             | integer array | no | The ID of the users to assign the MR to. Set to `0` or provide an empty value to unassign all assignees. | | ||||
| | `description`              | string  | no       | Description of the merge request. Limited to 1,048,576 characters. | | ||||
| | `labels`                   | string  | no       | Labels for the merge request, as a comma-separated list. | | ||||
| | `milestone_id`             | integer | no       | The global ID of a milestone. | | ||||
| | `remove_source_branch`     | boolean | no       | Flag indicating if a merge request should remove the source branch when merging. | | ||||
| | `reviewer_ids`             | integer array | no | The ID of the users added as a reviewer to the merge request. If set to `0` or left empty, no reviewers are added. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. | | ||||
| | `squash`                   | boolean | no       | Squash commits into a single commit when merging. | | ||||
| | `target_project_id`        | integer | no       | Numeric ID of the target project. | | ||||
| 
 | ||||
| If `approvals_before_merge` is not provided, it inherits the value from the target project. If provided, the following conditions must hold for it to take effect: | ||||
| 
 | ||||
|  | @ -1304,26 +1300,26 @@ Updates an existing merge request. You can change the target branch, title, or e | |||
| PUT /projects/:id/merge_requests/:merge_request_iid | ||||
| ``` | ||||
| 
 | ||||
| | Attribute                  | Type    | Required | Description                                                                     | | ||||
| | ---------                  | ----    | -------- | -----------                                                                     | | ||||
| | `id`                       | integer/string | yes  | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid`        | integer | yes      | The ID of a merge request.                                                       | | ||||
| | `target_branch`            | string  | no       | The target branch.                                                               | | ||||
| | `title`                    | string  | no       | Title of MR.                                                                     | | ||||
| | `assignee_id`              | integer | no       | The ID of the user to assign the merge request to. Set to `0` or provide an empty value to unassign all assignees.  | | ||||
| | `assignee_ids`             | integer array | no | The ID of the users to assign the MR to. Set to `0` or provide an empty value to unassign all assignees.  | | ||||
| | `reviewer_ids`             | integer array | no | The ID of the users set as a reviewer to the MR. Set the value to `0` or provide an empty value to unset all reviewers. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. | | ||||
| | `milestone_id`             | integer | no       | The global ID of a milestone to assign the merge request to. Set to `0` or provide an empty value to unassign a milestone.| | ||||
| | `labels`                   | string  | no       | Comma-separated label names for a merge request. Set to an empty string to unassign all labels.                    | | ||||
| | `add_labels`               | string  | no       | Comma-separated label names to add to a merge request.                          | | ||||
| | `remove_labels`            | string  | no       | Comma-separated label names to remove from a merge request.                     | | ||||
| | `description`              | string  | no       | Description of MR. Limited to 1,048,576 characters. | | ||||
| | `state_event`              | string  | no       | New state (close/reopen).                                                        | | ||||
| | `remove_source_branch`     | boolean | no       | Flag indicating if a merge request should remove the source branch when merging. | | ||||
| | `squash`                   | boolean | no       | Squash commits into a single commit when merging. | | ||||
| | Attribute                  | Type    | Required | Description | | ||||
| | ---------                  | ----    | -------- | ----------- | | ||||
| | `id`                       | integer or string | yes  | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid`        | integer | yes      | The ID of a merge request. | | ||||
| | `add_labels`               | string  | no       | Comma-separated label names to add to a merge request. | | ||||
| | `allow_collaboration`      | boolean | no       | Allow commits from members who can merge to the target branch. | | ||||
| | `allow_maintainer_to_push` | boolean | no       | Alias of `allow_collaboration`. | | ||||
| | `assignee_id`              | integer | no       | The ID of the user to assign the merge request to. Set to `0` or provide an empty value to unassign all assignees. | | ||||
| | `assignee_ids`             | integer array | no | The ID of the users to assign the merge request to. Set to `0` or provide an empty value to unassign all assignees. | | ||||
| | `description`              | string  | no       | Description of the merge request. Limited to 1,048,576 characters. | | ||||
| | `discussion_locked`        | boolean | no       | Flag indicating if the merge request's discussion is locked. If the discussion is locked only project members can add, edit or resolve comments. | | ||||
| | `allow_collaboration`      | boolean | no       | Allow commits from members who can merge to the target branch.                   | | ||||
| | `allow_maintainer_to_push` | boolean | no       | Alias of `allow_collaboration`.                                                  | | ||||
| | `labels`                   | string  | no       | Comma-separated label names for a merge request. Set to an empty string to unassign all labels.                    | | ||||
| | `milestone_id`             | integer | no       | The global ID of a milestone to assign the merge request to. Set to `0` or provide an empty value to unassign a milestone.| | ||||
| | `remove_labels`            | string  | no       | Comma-separated label names to remove from a merge request. | | ||||
| | `remove_source_branch`     | boolean | no       | Flag indicating if a merge request should remove the source branch when merging. | | ||||
| | `reviewer_ids`             | integer array | no | The ID of the users set as a reviewer to the merge request. Set the value to `0` or provide an empty value to unset all reviewers. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. | | ||||
| | `squash`                   | boolean | no       | Squash commits into a single commit when merging. | | ||||
| | `state_event`              | string  | no       | New state (close/reopen). | | ||||
| | `target_branch`            | string  | no       | The target branch. | | ||||
| | `title`                    | string  | no       | Title of MR. | | ||||
| 
 | ||||
| Must include at least one non-required attribute from above. | ||||
| 
 | ||||
|  | @ -1485,10 +1481,10 @@ Only for administrators and project owners. Deletes the merge request in questio | |||
| DELETE /projects/:id/merge_requests/:merge_request_iid | ||||
| ``` | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| 
 | ||||
| ```shell | ||||
| curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/4/merge_requests/85" | ||||
|  | @ -1504,16 +1500,16 @@ PUT /projects/:id/merge_requests/:merge_request_iid/merge | |||
| 
 | ||||
| Parameters: | ||||
| 
 | ||||
| | Attribute                      | Type           | Required | Description                                                                                                     | | ||||
| |--------------------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                           | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid`            | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | `merge_commit_message`         | string         | no       | Custom merge commit message.                                                                                    | | ||||
| | `squash_commit_message`        | string         | no       | Custom squash commit message.                                                                                   | | ||||
| | `squash`                       | boolean        | no       | If `true` the commits are squashed into a single commit on merge.                                               | | ||||
| | `should_remove_source_branch`  | boolean        | no       | If `true` removes the source branch.                                                                            | | ||||
| | `merge_when_pipeline_succeeds` | boolean        | no       | If `true` the MR is merged when the pipeline succeeds.                                                          | | ||||
| | `sha`                          | string         | no       | If present, then this SHA must match the HEAD of the source branch, otherwise the merge fails.                  | | ||||
| | Attribute                      | Type           | Required | Description | | ||||
| |--------------------------------|----------------|----------|-------------| | ||||
| | `id`                           | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid`            | integer        | yes      | The internal ID of the merge request. | | ||||
| | `merge_commit_message`         | string         | no       | Custom merge commit message. | | ||||
| | `merge_when_pipeline_succeeds` | boolean        | no       | If `true`, the merge request is merged when the pipeline succeeds. | | ||||
| | `sha`                          | string         | no       | If present, then this SHA must match the HEAD of the source branch, otherwise the merge fails. | | ||||
| | `should_remove_source_branch`  | boolean        | no       | If `true`, removes the source branch. | | ||||
| | `squash_commit_message`        | string         | no       | Custom squash commit message. | | ||||
| | `squash`                       | boolean        | no       | If `true`, the commits are squashed into a single commit on merge. | | ||||
| 
 | ||||
| ```json | ||||
| { | ||||
|  | @ -1665,12 +1661,12 @@ the `approvals_before_merge` parameter: | |||
| 
 | ||||
| This API returns specific HTTP status codes on failure: | ||||
| 
 | ||||
| | HTTP Status | Message                                    | Reason                                                                                                                                   | | ||||
| |:------------|--------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `401`       | `Unauthorized`                             | This user does not have permission to accept this merge request.                                                                         | | ||||
| | `405`       | `Method Not Allowed`                       | The merge request is not able to be merged. | | ||||
| | `409`       | `SHA does not match HEAD of source branch` | The provided `sha` parameter does not match the HEAD of the source.                                                                      | | ||||
| | `422`       | `Branch cannot be merged`                  | The merge request failed to merge.                                                                                           | | ||||
| | HTTP Status | Message | Reason | | ||||
| |:------------|---------|--------| | ||||
| | `401` | `Unauthorized` | This user does not have permission to accept this merge request. | | ||||
| | `405` | `Method Not Allowed` | The merge request is not able to be merged. | | ||||
| | `409` | `SHA does not match HEAD of source branch` | The provided `sha` parameter does not match the HEAD of the source. | | ||||
| | `422` | `Branch cannot be merged` | The merge request failed to merge. | | ||||
| 
 | ||||
| For additional important notes on response data, read [Single merge request response notes](#single-merge-request-response-notes). | ||||
| 
 | ||||
|  | @ -1695,10 +1691,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/merge_ref | |||
| 
 | ||||
| Parameters: | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| 
 | ||||
| ```json | ||||
| { | ||||
|  | @ -1722,10 +1718,10 @@ POST /projects/:id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_ | |||
| 
 | ||||
| Parameters: | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| 
 | ||||
| ```json | ||||
| { | ||||
|  | @ -1889,11 +1885,11 @@ you receive a `403 Forbidden` response. | |||
| PUT /projects/:id/merge_requests/:merge_request_iid/rebase | ||||
| ``` | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | `skip_ci`           | boolean        | no       | Set to `true` to skip creating a CI pipeline.                                                                   | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| | `skip_ci`           | boolean        | no       | Set to `true` to skip creating a CI pipeline. | | ||||
| 
 | ||||
| ```shell | ||||
| curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/76/merge_requests/1/rebase" | ||||
|  | @ -1952,10 +1948,10 @@ Get all the issues that would be closed by merging the provided merge request. | |||
| GET /projects/:id/merge_requests/:merge_request_iid/closes_issues | ||||
| ``` | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| 
 | ||||
| ```shell | ||||
| curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/76/merge_requests/1/closes_issues" | ||||
|  | @ -2028,10 +2024,10 @@ status code `HTTP 304 Not Modified` is returned. | |||
| POST /projects/:id/merge_requests/:merge_request_iid/subscribe | ||||
| ``` | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| 
 | ||||
| ```shell | ||||
| curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/17/subscribe" | ||||
|  | @ -2198,10 +2194,10 @@ not subscribed to the merge request, the status code `HTTP 304 Not Modified` is | |||
| POST /projects/:id/merge_requests/:merge_request_iid/unsubscribe | ||||
| ``` | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| 
 | ||||
| ```shell | ||||
| curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/17/unsubscribe" | ||||
|  | @ -2368,10 +2364,10 @@ status code `HTTP 304 Not Modified` is returned. | |||
| POST /projects/:id/merge_requests/:merge_request_iid/todo | ||||
| ``` | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| 
 | ||||
| ```shell | ||||
| curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/27/todo" | ||||
|  | @ -2532,8 +2528,8 @@ Example response: | |||
| 
 | ||||
| | SHA field          | Purpose                                                                             | | ||||
| |--------------------|-------------------------------------------------------------------------------------| | ||||
| | `head_commit_sha`  | The HEAD commit of the source branch.                                               | | ||||
| | `base_commit_sha`  | The merge-base commit SHA between the source branch and the target branches.        | | ||||
| | `head_commit_sha`  | The HEAD commit of the source branch.                                               | | ||||
| | `start_commit_sha` | The HEAD commit SHA of the target branch when this version of the diff was created. | | ||||
| 
 | ||||
| ## Get a single MR diff version | ||||
|  | @ -2613,11 +2609,11 @@ Sets an estimated time of work for this merge request. | |||
| POST /projects/:id/merge_requests/:merge_request_iid/time_estimate | ||||
| ``` | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | `duration`          | string         | yes      | The duration in human format, such as `3h30m`.                                                                  | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| | `duration`          | string         | yes      | The duration in human format, such as `3h30m`. | | ||||
| 
 | ||||
| ```shell | ||||
| curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_estimate?duration=3h30m" | ||||
|  | @ -2642,10 +2638,10 @@ Resets the estimated time for this merge request to 0 seconds. | |||
| POST /projects/:id/merge_requests/:merge_request_iid/reset_time_estimate | ||||
| ``` | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of a project's merge_request.                                                                   | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of a project's merge request. | | ||||
| 
 | ||||
| ```shell | ||||
| curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_time_estimate" | ||||
|  | @ -2670,12 +2666,12 @@ Adds spent time for this merge request. | |||
| POST /projects/:id/merge_requests/:merge_request_iid/add_spent_time | ||||
| ``` | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | `duration`          | string         | yes      | The duration in human format, such as `3h30m`                                                                   | | ||||
| | `summary`           | string         | no       | A summary of how the time was spent.                                                                            | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| | `duration`          | string         | yes      | The duration in human format, such as `3h30m` | | ||||
| | `summary`           | string         | no       | A summary of how the time was spent. | | ||||
| 
 | ||||
| ```shell | ||||
| curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/add_spent_time?duration=1h" | ||||
|  | @ -2700,10 +2696,10 @@ Resets the total spent time for this merge request to 0 seconds. | |||
| POST /projects/:id/merge_requests/:merge_request_iid/reset_spent_time | ||||
| ``` | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of a project's merge_request.                                                                   | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of a project's merge request. | | ||||
| 
 | ||||
| ```shell | ||||
| curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_spent_time" | ||||
|  | @ -2726,10 +2722,10 @@ Example response: | |||
| GET /projects/:id/merge_requests/:merge_request_iid/time_stats | ||||
| ``` | ||||
| 
 | ||||
| | Attribute           | Type           | Required | Description                                                                                                     | | ||||
| |---------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| | ||||
| | `id`                | integer/string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request.                                                                           | | ||||
| | Attribute           | Type           | Required | Description | | ||||
| |---------------------|----------------|----------|-------------| | ||||
| | `id`                | integer or string | yes      | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | ||||
| | `merge_request_iid` | integer        | yes      | The internal ID of the merge request. | | ||||
| 
 | ||||
| ```shell | ||||
| curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_stats" | ||||
|  |  | |||
|  | @ -80,7 +80,7 @@ Example of response | |||
| 
 | ||||
| Get one pipeline from a project. | ||||
| 
 | ||||
| You can also get a single [child pipeline](../ci/pipelines/parent_child_pipelines.md). | ||||
| You can also get a single [child pipeline](../ci/pipelines/downstream_pipelines.md#parent-child-pipelines). | ||||
| [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36494) in GitLab 13.3. | ||||
| 
 | ||||
| ```plaintext | ||||
|  | @ -427,7 +427,7 @@ related objects, such as builds, logs, artifacts, and triggers. | |||
| **This action cannot be undone.** | ||||
| 
 | ||||
| Deleting a pipeline does not automatically delete its | ||||
| [child pipelines](../ci/pipelines/parent_child_pipelines.md). | ||||
| [child pipelines](../ci/pipelines/downstream_pipelines.md#parent-child-pipelines). | ||||
| See the [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/39503) | ||||
| for details. | ||||
| 
 | ||||
|  |  | |||
|  | @ -243,7 +243,7 @@ check the value of the `$CI_PIPELINE_SOURCE` variable: | |||
| | `external`                    | When you use CI services other than GitLab.                                                                                                                                                                                        | | ||||
| | `external_pull_request_event` | When an external pull request on GitHub is created or updated. See [Pipelines for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests).                                            | | ||||
| | `merge_request_event`         | For pipelines created when a merge request is created or updated. Required to enable [merge request pipelines](../pipelines/merge_request_pipelines.md), [merged results pipelines](../pipelines/merged_results_pipelines.md), and [merge trains](../pipelines/merge_trains.md). | | ||||
| | `parent_pipeline`             | For pipelines triggered by a [parent/child pipeline](../pipelines/parent_child_pipelines.md) with `rules`. Use this pipeline source in the child pipeline configuration so that it can be triggered by the parent pipeline.                | | ||||
| | `parent_pipeline`             | For pipelines triggered by a [parent/child pipeline](../pipelines/downstream_pipelines.md#parent-child-pipelines) with `rules`. Use this pipeline source in the child pipeline configuration so that it can be triggered by the parent pipeline.                | | ||||
| | `pipeline`                    | For [multi-project pipelines](../pipelines/downstream_pipelines.md#multi-project-pipelines) created by [using the API with `CI_JOB_TOKEN`](../pipelines/downstream_pipelines.md#trigger-a-multi-project-pipeline-by-using-the-api), or the [`trigger`](../yaml/index.md#trigger) keyword. | | ||||
| | `push`                        | For pipelines triggered by a `git push` event, including for branches and tags.                                                                                                                                                  | | ||||
| | `schedule`                    | For [scheduled pipelines](../pipelines/schedules.md).                                                                                                                                                                            | | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w | |||
| A downstream pipeline is any GitLab CI/CD pipeline triggered by another pipeline. | ||||
| A downstream pipeline can be either: | ||||
| 
 | ||||
| - A [parent-child pipeline](parent_child_pipelines.md), which is a downstream pipeline triggered | ||||
| - A [parent-child pipeline](downstream_pipelines.md#parent-child-pipelines), which is a downstream pipeline triggered | ||||
|   in the same project as the first pipeline. | ||||
| - A [multi-project pipeline](#multi-project-pipelines), which is a downstream pipeline triggered | ||||
|   in a different project than the first pipeline. | ||||
|  | @ -172,6 +172,197 @@ When using: | |||
| - [`only/except`](../yaml/index.md#only--except) to control job behavior, use the | ||||
|   `pipelines` keyword. | ||||
| 
 | ||||
| ## Parent-child pipelines | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16094) in GitLab 12.7. | ||||
| 
 | ||||
| As pipelines grow more complex, a few related problems start to emerge: | ||||
| 
 | ||||
| - The staged structure, where all steps in a stage must be completed before the first | ||||
|   job in next stage begins, causes arbitrary waits, slowing things down. | ||||
| - Configuration for the single global pipeline becomes very long and complicated, | ||||
|   making it hard to manage. | ||||
| - Imports with [`include`](../yaml/index.md#include) increase the complexity of the configuration, and create the potential | ||||
|   for namespace collisions where jobs are unintentionally duplicated. | ||||
| - Pipeline UX can become unwieldy with so many jobs and stages to work with. | ||||
| 
 | ||||
| Additionally, sometimes the behavior of a pipeline needs to be more dynamic. The ability | ||||
| to choose to start sub-pipelines (or not) is a powerful ability, especially if the | ||||
| YAML is dynamically generated. | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| Similarly to [multi-project pipelines](#multi-project-pipelines), a pipeline can trigger a | ||||
| set of concurrently running downstream child pipelines, but in the same project: | ||||
| 
 | ||||
| - Child pipelines still execute each of their jobs according to a stage sequence, but | ||||
|   would be free to continue forward through their stages without waiting for unrelated | ||||
|   jobs in the parent pipeline to finish. | ||||
| - The configuration is split up into smaller child pipeline configurations. Each child pipeline contains only relevant steps which are | ||||
|   easier to understand. This reduces the cognitive load to understand the overall configuration. | ||||
| - Imports are done at the child pipeline level, reducing the likelihood of collisions. | ||||
| 
 | ||||
| Child pipelines work well with other GitLab CI/CD features: | ||||
| 
 | ||||
| - Use [`rules: changes`](../yaml/index.md#ruleschanges) to trigger pipelines only when | ||||
|   certain files change. This is useful for monorepos, for example. | ||||
| - Since the parent pipeline in `.gitlab-ci.yml` and the child pipeline run as normal | ||||
|   pipelines, they can have their own behaviors and sequencing in relation to triggers. | ||||
| 
 | ||||
| See the [`trigger`](../yaml/index.md#trigger) keyword documentation for full details on how to | ||||
| include the child pipeline configuration. | ||||
| 
 | ||||
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> | ||||
| For an overview, see [Parent-Child Pipelines feature demo](https://youtu.be/n8KpBSqZNbk). | ||||
| 
 | ||||
| NOTE: | ||||
| The artifact containing the generated YAML file must not be larger than 5MB. | ||||
| 
 | ||||
| ### Trigger a parent-child pipeline | ||||
| 
 | ||||
| The simplest case is [triggering a child pipeline](../yaml/index.md#trigger) using a | ||||
| local YAML file to define the pipeline configuration. In this case, the parent pipeline | ||||
| triggers the child pipeline, and continues without waiting: | ||||
| 
 | ||||
| ```yaml | ||||
| microservice_a: | ||||
|   trigger: | ||||
|     include: path/to/microservice_a.yml | ||||
| ``` | ||||
| 
 | ||||
| You can include multiple files when defining a child pipeline. The child pipeline's | ||||
| configuration is composed of all configuration files merged together: | ||||
| 
 | ||||
| ```yaml | ||||
| microservice_a: | ||||
|   trigger: | ||||
|     include: | ||||
|       - local: path/to/microservice_a.yml | ||||
|       - template: Security/SAST.gitlab-ci.yml | ||||
| ``` | ||||
| 
 | ||||
| In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/205157), | ||||
| you can use [`include:file`](../yaml/index.md#includefile) to trigger child pipelines | ||||
| with a configuration file in a different project: | ||||
| 
 | ||||
| ```yaml | ||||
| microservice_a: | ||||
|   trigger: | ||||
|     include: | ||||
|       - project: 'my-group/my-pipeline-library' | ||||
|         ref: 'main' | ||||
|         file: '/path/to/child-pipeline.yml' | ||||
| ``` | ||||
| 
 | ||||
| The maximum number of entries that are accepted for `trigger:include` is three. | ||||
| 
 | ||||
| ### Merge request child pipelines | ||||
| 
 | ||||
| To trigger a child pipeline as a [merge request pipeline](merge_request_pipelines.md) we need to: | ||||
| 
 | ||||
| - Set the trigger job to run on merge requests: | ||||
| 
 | ||||
| ```yaml | ||||
| # parent .gitlab-ci.yml | ||||
| microservice_a: | ||||
|   trigger: | ||||
|     include: path/to/microservice_a.yml | ||||
|   rules: | ||||
|     - if: $CI_MERGE_REQUEST_ID | ||||
| ``` | ||||
| 
 | ||||
| - Configure the child pipeline by either: | ||||
| 
 | ||||
|   - Setting all jobs in the child pipeline to evaluate in the context of a merge request: | ||||
| 
 | ||||
|     ```yaml | ||||
|     # child path/to/microservice_a.yml | ||||
|     workflow: | ||||
|       rules: | ||||
|         - if: $CI_MERGE_REQUEST_ID | ||||
| 
 | ||||
|     job1: | ||||
|       script: ... | ||||
| 
 | ||||
|     job2: | ||||
|       script: ... | ||||
|     ``` | ||||
| 
 | ||||
|   - Alternatively, setting the rule per job. For example, to create only `job1` in | ||||
|     the context of merge request pipelines: | ||||
| 
 | ||||
|     ```yaml | ||||
|     # child path/to/microservice_a.yml | ||||
|     job1: | ||||
|       script: ... | ||||
|       rules: | ||||
|         - if: $CI_MERGE_REQUEST_ID | ||||
| 
 | ||||
|     job2: | ||||
|       script: ... | ||||
|     ``` | ||||
| 
 | ||||
| ### Dynamic child pipelines | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35632) in GitLab 12.9. | ||||
| 
 | ||||
| Instead of running a child pipeline from a static YAML file, you can define a job that runs | ||||
| your own script to generate a YAML file, which is then used to trigger a child pipeline. | ||||
| 
 | ||||
| This technique can be very powerful in generating pipelines targeting content that changed or to | ||||
| build a matrix of targets and architectures. | ||||
| 
 | ||||
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> | ||||
| For an overview, see [Create child pipelines using dynamically generated configurations](https://youtu.be/nMdfus2JWHM). | ||||
| 
 | ||||
| We also have an example project using | ||||
| [Dynamic Child Pipelines with Jsonnet](https://gitlab.com/gitlab-org/project-templates/jsonnet) | ||||
| which shows how to use a data templating language to generate your `.gitlab-ci.yml` at runtime. | ||||
| You could use a similar process for other templating languages like | ||||
| [Dhall](https://dhall-lang.org/) or [ytt](https://get-ytt.io/). | ||||
| 
 | ||||
| The artifact path is parsed by GitLab, not the runner, so the path must match the | ||||
| syntax for the OS running GitLab. If GitLab is running on Linux but using a Windows | ||||
| runner for testing, the path separator for the trigger job would be `/`. Other CI/CD | ||||
| configuration for jobs, like scripts, that use the Windows runner would use `\`. | ||||
| 
 | ||||
| For example, to trigger a child pipeline from a dynamically generated configuration file: | ||||
| 
 | ||||
| ```yaml | ||||
| generate-config: | ||||
|   stage: build | ||||
|   script: generate-ci-config > generated-config.yml | ||||
|   artifacts: | ||||
|     paths: | ||||
|       - generated-config.yml | ||||
| 
 | ||||
| child-pipeline: | ||||
|   stage: test | ||||
|   trigger: | ||||
|     include: | ||||
|       - artifact: generated-config.yml | ||||
|         job: generate-config | ||||
| ``` | ||||
| 
 | ||||
| The `generated-config.yml` is extracted from the artifacts and used as the configuration | ||||
| for triggering the child pipeline. | ||||
| 
 | ||||
| In GitLab 12.9, the child pipeline could fail to be created in certain cases, causing the parent pipeline to fail. | ||||
| This is [resolved](https://gitlab.com/gitlab-org/gitlab/-/issues/209070) in GitLab 12.10. | ||||
| 
 | ||||
| ### Nested child pipelines | ||||
| 
 | ||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29651) in GitLab 13.4. | ||||
| > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/243747) in GitLab 13.5. | ||||
| 
 | ||||
| Parent and child pipelines were introduced with a maximum depth of one level of child | ||||
| pipelines, which was later increased to two. A parent pipeline can trigger many child | ||||
| pipelines, and these child pipelines can trigger their own child pipelines. It's not | ||||
| possible to trigger another level of child pipelines. | ||||
| 
 | ||||
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> | ||||
| For an overview, see [Nested Dynamic Pipelines](https://youtu.be/C5j3ju9je2M). | ||||
| 
 | ||||
| ## View a downstream pipeline | ||||
| 
 | ||||
| In the [pipeline graph view](index.md#view-full-pipeline-graph), downstream pipelines display | ||||
|  | @ -203,7 +394,11 @@ To cancel a downstream pipeline that is still running, select **Cancel** (**{can | |||
| > - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8. | ||||
| 
 | ||||
| You can mirror the pipeline status from the triggered pipeline to the source trigger job | ||||
| by using [`strategy: depend`](../yaml/index.md#triggerstrategy). For example: | ||||
| by using [`strategy: depend`](../yaml/index.md#triggerstrategy): | ||||
| 
 | ||||
| ::Tabs | ||||
| 
 | ||||
| :::TabTitle Multi-Project pipeline | ||||
| 
 | ||||
| ```yaml | ||||
| trigger_job: | ||||
|  | @ -212,6 +407,18 @@ trigger_job: | |||
|     strategy: depend | ||||
| ``` | ||||
| 
 | ||||
| :::TabTitle Parent-child pipeline | ||||
| 
 | ||||
| ```yaml | ||||
| trigger_job: | ||||
|   trigger: | ||||
|     include: | ||||
|       - local: path/to/child-pipeline.yml | ||||
|     strategy: depend | ||||
| ``` | ||||
| 
 | ||||
| ::EndTabs | ||||
| 
 | ||||
| ### View multi-project pipelines in pipeline graphs **(PREMIUM)** | ||||
| 
 | ||||
| When you trigger a multi-project pipeline, the downstream pipeline displays | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ Pipelines can be configured in many different ways: | |||
|   already been merged into the target branch. | ||||
| - [Merge trains](../pipelines/merge_trains.md) | ||||
|   use merged results pipelines to queue merges one after the other. | ||||
| - [Parent-child pipelines](parent_child_pipelines.md) break down complex pipelines | ||||
| - [Parent-child pipelines](downstream_pipelines.md#parent-child-pipelines) break down complex pipelines | ||||
|   into one parent pipeline that can trigger multiple child sub-pipelines, which all | ||||
|   run in the same project and with the same SHA. This pipeline architecture is commonly used for mono-repos. | ||||
| - [Multi-project pipelines](downstream_pipelines.md#multi-project-pipelines) combine pipelines for different projects together. | ||||
|  | @ -254,7 +254,7 @@ page, then selecting **Delete**. | |||
|  | ||||
| 
 | ||||
| Deleting a pipeline does not automatically delete its | ||||
| [child pipelines](parent_child_pipelines.md). | ||||
| [child pipelines](downstream_pipelines.md#parent-child-pipelines). | ||||
| See the [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/39503) | ||||
| for details. | ||||
| 
 | ||||
|  |  | |||
|  | @ -305,7 +305,7 @@ the artifact. | |||
| ## How searching for job artifacts works | ||||
| 
 | ||||
| In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/201784), artifacts | ||||
| for [parent and child pipelines](parent_child_pipelines.md) are searched in hierarchical | ||||
| for [parent and child pipelines](downstream_pipelines.md#parent-child-pipelines) are searched in hierarchical | ||||
| order from parent to child. For example, if both parent and child pipelines have a | ||||
| job with the same name, the job artifact from the parent pipeline is returned. | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,221 +1,11 @@ | |||
| --- | ||||
| stage: Verify | ||||
| group: Pipeline Authoring | ||||
| 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 | ||||
| type: reference | ||||
| redirect_to: 'downstream_pipelines.md' | ||||
| remove_date: '2022-12-05' | ||||
| --- | ||||
| 
 | ||||
| # Parent-child pipelines **(FREE)** | ||||
| This document was moved to [another location](downstream_pipelines.md). | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16094) in GitLab 12.7. | ||||
| 
 | ||||
| As pipelines grow more complex, a few related problems start to emerge: | ||||
| 
 | ||||
| - The staged structure, where all steps in a stage must be completed before the first | ||||
|   job in next stage begins, causes arbitrary waits, slowing things down. | ||||
| - Configuration for the single global pipeline becomes very long and complicated, | ||||
|   making it hard to manage. | ||||
| - Imports with [`include`](../yaml/index.md#include) increase the complexity of the configuration, and create the potential | ||||
|   for namespace collisions where jobs are unintentionally duplicated. | ||||
| - Pipeline UX can become unwieldy with so many jobs and stages to work with. | ||||
| 
 | ||||
| Additionally, sometimes the behavior of a pipeline needs to be more dynamic. The ability | ||||
| to choose to start sub-pipelines (or not) is a powerful ability, especially if the | ||||
| YAML is dynamically generated. | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| Similarly to [multi-project pipelines](downstream_pipelines.md#multi-project-pipelines), a pipeline can trigger a | ||||
| set of concurrently running [downstream](downstream_pipelines.md) child pipelines, but in the same project: | ||||
| 
 | ||||
| - Child pipelines still execute each of their jobs according to a stage sequence, but | ||||
|   would be free to continue forward through their stages without waiting for unrelated | ||||
|   jobs in the parent pipeline to finish. | ||||
| - The configuration is split up into smaller child pipeline configurations. Each child pipeline contains only relevant steps which are | ||||
|   easier to understand. This reduces the cognitive load to understand the overall configuration. | ||||
| - Imports are done at the child pipeline level, reducing the likelihood of collisions. | ||||
| 
 | ||||
| Child pipelines work well with other GitLab CI/CD features: | ||||
| 
 | ||||
| - Use [`rules: changes`](../yaml/index.md#ruleschanges) to trigger pipelines only when | ||||
|   certain files change. This is useful for monorepos, for example. | ||||
| - Since the parent pipeline in `.gitlab-ci.yml` and the child pipeline run as normal | ||||
|   pipelines, they can have their own behaviors and sequencing in relation to triggers. | ||||
| 
 | ||||
| See the [`trigger`](../yaml/index.md#trigger) keyword documentation for full details on how to | ||||
| include the child pipeline configuration. | ||||
| 
 | ||||
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> | ||||
| For an overview, see [Parent-Child Pipelines feature demo](https://youtu.be/n8KpBSqZNbk). | ||||
| 
 | ||||
| NOTE: | ||||
| The artifact containing the generated YAML file must not be larger than 5MB. | ||||
| 
 | ||||
| ## Examples | ||||
| 
 | ||||
| The simplest case is [triggering a child pipeline](../yaml/index.md#trigger) using a | ||||
| local YAML file to define the pipeline configuration. In this case, the parent pipeline | ||||
| triggers the child pipeline, and continues without waiting: | ||||
| 
 | ||||
| ```yaml | ||||
| microservice_a: | ||||
|   trigger: | ||||
|     include: path/to/microservice_a.yml | ||||
| ``` | ||||
| 
 | ||||
| You can include multiple files when defining a child pipeline. The child pipeline's | ||||
| configuration is composed of all configuration files merged together: | ||||
| 
 | ||||
| ```yaml | ||||
| microservice_a: | ||||
|   trigger: | ||||
|     include: | ||||
|       - local: path/to/microservice_a.yml | ||||
|       - template: Security/SAST.gitlab-ci.yml | ||||
| ``` | ||||
| 
 | ||||
| In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/205157), | ||||
| you can use [`include:file`](../yaml/index.md#includefile) to trigger child pipelines | ||||
| with a configuration file in a different project: | ||||
| 
 | ||||
| ```yaml | ||||
| microservice_a: | ||||
|   trigger: | ||||
|     include: | ||||
|       - project: 'my-group/my-pipeline-library' | ||||
|         ref: 'main' | ||||
|         file: '/path/to/child-pipeline.yml' | ||||
| ``` | ||||
| 
 | ||||
| The maximum number of entries that are accepted for `trigger:include` is three. | ||||
| 
 | ||||
| Similar to [multi-project pipelines](downstream_pipelines.md#multi-project-pipelines), we can set the | ||||
| parent pipeline to [depend on the status](downstream_pipelines.md#mirror-the-status-of-a-downstream-pipeline-in-the-trigger-job) | ||||
| of the child pipeline upon completion: | ||||
| 
 | ||||
| ```yaml | ||||
| microservice_a: | ||||
|   trigger: | ||||
|     include: | ||||
|       - local: path/to/microservice_a.yml | ||||
|       - template: Security/SAST.gitlab-ci.yml | ||||
|     strategy: depend | ||||
| ``` | ||||
| 
 | ||||
| ## Merge request child pipelines | ||||
| 
 | ||||
| To trigger a child pipeline as a [merge request pipeline](merge_request_pipelines.md) we need to: | ||||
| 
 | ||||
| - Set the trigger job to run on merge requests: | ||||
| 
 | ||||
| ```yaml | ||||
| # parent .gitlab-ci.yml | ||||
| microservice_a: | ||||
|   trigger: | ||||
|     include: path/to/microservice_a.yml | ||||
|   rules: | ||||
|     - if: $CI_MERGE_REQUEST_ID | ||||
| ``` | ||||
| 
 | ||||
| - Configure the child pipeline by either: | ||||
| 
 | ||||
|   - Setting all jobs in the child pipeline to evaluate in the context of a merge request: | ||||
| 
 | ||||
|     ```yaml | ||||
|     # child path/to/microservice_a.yml | ||||
|     workflow: | ||||
|       rules: | ||||
|         - if: $CI_MERGE_REQUEST_ID | ||||
| 
 | ||||
|     job1: | ||||
|       script: ... | ||||
| 
 | ||||
|     job2: | ||||
|       script: ... | ||||
|     ``` | ||||
| 
 | ||||
|   - Alternatively, setting the rule per job. For example, to create only `job1` in | ||||
|     the context of merge request pipelines: | ||||
| 
 | ||||
|     ```yaml | ||||
|     # child path/to/microservice_a.yml | ||||
|     job1: | ||||
|       script: ... | ||||
|       rules: | ||||
|         - if: $CI_MERGE_REQUEST_ID | ||||
| 
 | ||||
|     job2: | ||||
|       script: ... | ||||
|     ``` | ||||
| 
 | ||||
| ## Dynamic child pipelines | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35632) in GitLab 12.9. | ||||
| 
 | ||||
| Instead of running a child pipeline from a static YAML file, you can define a job that runs | ||||
| your own script to generate a YAML file, which is then used to trigger a child pipeline. | ||||
| 
 | ||||
| This technique can be very powerful in generating pipelines targeting content that changed or to | ||||
| build a matrix of targets and architectures. | ||||
| 
 | ||||
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> | ||||
| For an overview, see [Create child pipelines using dynamically generated configurations](https://youtu.be/nMdfus2JWHM). | ||||
| 
 | ||||
| We also have an example project using | ||||
| [Dynamic Child Pipelines with Jsonnet](https://gitlab.com/gitlab-org/project-templates/jsonnet) | ||||
| which shows how to use a data templating language to generate your `.gitlab-ci.yml` at runtime. | ||||
| You could use a similar process for other templating languages like | ||||
| [Dhall](https://dhall-lang.org/) or [ytt](https://get-ytt.io/). | ||||
| 
 | ||||
| The artifact path is parsed by GitLab, not the runner, so the path must match the | ||||
| syntax for the OS running GitLab. If GitLab is running on Linux but using a Windows | ||||
| runner for testing, the path separator for the trigger job would be `/`. Other CI/CD | ||||
| configuration for jobs, like scripts, that use the Windows runner would use `\`. | ||||
| 
 | ||||
| In GitLab 12.9, the child pipeline could fail to be created in certain cases, causing the parent pipeline to fail. | ||||
| This is [resolved](https://gitlab.com/gitlab-org/gitlab/-/issues/209070) in GitLab 12.10. | ||||
| 
 | ||||
| ### Dynamic child pipeline example | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35632) in GitLab 12.9. | ||||
| 
 | ||||
| You can trigger a child pipeline from a [dynamically generated configuration file](../pipelines/parent_child_pipelines.md#dynamic-child-pipelines): | ||||
| 
 | ||||
| ```yaml | ||||
| generate-config: | ||||
|   stage: build | ||||
|   script: generate-ci-config > generated-config.yml | ||||
|   artifacts: | ||||
|     paths: | ||||
|       - generated-config.yml | ||||
| 
 | ||||
| child-pipeline: | ||||
|   stage: test | ||||
|   trigger: | ||||
|     include: | ||||
|       - artifact: generated-config.yml | ||||
|         job: generate-config | ||||
| ``` | ||||
| 
 | ||||
| The `generated-config.yml` is extracted from the artifacts and used as the configuration | ||||
| for triggering the child pipeline. | ||||
| 
 | ||||
| ## Nested child pipelines | ||||
| 
 | ||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29651) in GitLab 13.4. | ||||
| > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/243747) in GitLab 13.5. | ||||
| 
 | ||||
| Parent and child pipelines were introduced with a maximum depth of one level of child | ||||
| pipelines, which was later increased to two. A parent pipeline can trigger many child | ||||
| pipelines, and these child pipelines can trigger their own child pipelines. It's not | ||||
| possible to trigger another level of child pipelines. | ||||
| 
 | ||||
| <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> | ||||
| For an overview, see [Nested Dynamic Pipelines](https://youtu.be/C5j3ju9je2M). | ||||
| 
 | ||||
| ## Pass CI/CD variables to a child pipeline | ||||
| 
 | ||||
| You can pass variables to a downstream pipeline: | ||||
| 
 | ||||
| - [By using the `variables` keyword](downstream_pipelines.md#pass-yaml-defined-cicd-variables). | ||||
| - [By using dotenv variable inheritance](downstream_pipelines.md#pass-dotenv-variables-created-in-a-job). | ||||
| <!-- This redirect file can be deleted after <2022-12-05>. --> | ||||
| <!-- Redirects that point to other docs in the same project expire in three months. --> | ||||
| <!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. --> | ||||
| <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html --> | ||||
|  |  | |||
|  | @ -162,7 +162,7 @@ deploy_b: | |||
| ## Child / Parent Pipelines | ||||
| 
 | ||||
| In the examples above, it's clear we've got two types of things that could be built independently. | ||||
| This is an ideal case for using [Child / Parent Pipelines](parent_child_pipelines.md)) via | ||||
| This is an ideal case for using [Child / Parent Pipelines](downstream_pipelines.md#parent-child-pipelines)) via | ||||
| the [`trigger` keyword](../yaml/index.md#trigger). It separates out the configuration | ||||
| into multiple files, keeping things very simple. You can also combine this with: | ||||
| 
 | ||||
|  |  | |||
|  | @ -187,7 +187,7 @@ shouldn't run, saving pipeline resources. | |||
| In a basic configuration, jobs always wait for all other jobs in earlier stages to complete | ||||
| before running. This is the simplest configuration, but it's also the slowest in most | ||||
| cases. [Directed Acyclic Graphs](../directed_acyclic_graph/index.md) and | ||||
| [parent/child pipelines](parent_child_pipelines.md) are more flexible and can | ||||
| [parent/child pipelines](downstream_pipelines.md#parent-child-pipelines) are more flexible and can | ||||
| be more efficient, but can also make pipelines harder to understand and analyze. | ||||
| 
 | ||||
| ### Caching | ||||
|  |  | |||
|  | @ -210,7 +210,7 @@ Read more how you can use GitLab for [safe deployments](../environments/deployme | |||
| Because [`oldest_first` process mode](#process-modes) enforces the jobs to be executed in a pipeline order, | ||||
| there is a case that it doesn't work well with the other CI features. | ||||
| 
 | ||||
| For example, when you run [a child pipeline](../pipelines/parent_child_pipelines.md) | ||||
| For example, when you run [a child pipeline](../pipelines/downstream_pipelines.md#parent-child-pipelines) | ||||
| that requires the same resource group with the parent pipeline, | ||||
| a dead lock could happen. Here is an example of a _bad_ setup: | ||||
| 
 | ||||
|  |  | |||
|  | @ -89,9 +89,9 @@ if you are using that type: | |||
| 
 | ||||
| - [Multi-project pipelines](pipelines/downstream_pipelines.md#multi-project-pipelines): Have your pipeline trigger | ||||
|   a pipeline in a different project. | ||||
| - [Parent/child pipelines](pipelines/parent_child_pipelines.md): Have your main pipeline trigger | ||||
| - [Parent/child pipelines](pipelines/downstream_pipelines.md#parent-child-pipelines): Have your main pipeline trigger | ||||
|   and run separate pipelines in the same project. You can also | ||||
|   [dynamically generate the child pipeline's configuration](pipelines/parent_child_pipelines.md#dynamic-child-pipelines) | ||||
|   [dynamically generate the child pipeline's configuration](pipelines/downstream_pipelines.md#dynamic-child-pipelines) | ||||
|   at runtime. | ||||
| - [Merge request pipelines](pipelines/merge_request_pipelines.md): Run a pipeline | ||||
|   in the context of a merge request. | ||||
|  | @ -316,7 +316,7 @@ To reduce the configuration size, you can: | |||
|   [merged YAML](pipeline_editor/index.md#view-expanded-configuration) tab. Look for | ||||
|   duplicated configuration that can be removed or simplified. | ||||
| - Move long or repeated `script` sections into standalone scripts in the project. | ||||
| - Use [parent and child pipelines](pipelines/parent_child_pipelines.md) to move some | ||||
| - Use [parent and child pipelines](pipelines/downstream_pipelines.md#parent-child-pipelines) to move some | ||||
|   work to jobs in an independent child pipeline. | ||||
| 
 | ||||
| On a self-managed instance, you can [increase the size limits](../administration/instance_limits.md#maximum-size-and-depth-of-cicd-configuration-yaml-files). | ||||
|  |  | |||
|  | @ -1384,7 +1384,7 @@ In this example: | |||
|   for the coverage number. | ||||
| - If there are multiple coverage numbers found in the matched fragment, the first number is used. | ||||
| - Leading zeros are removed. | ||||
| - Coverage output from [child pipelines](../pipelines/parent_child_pipelines.md) | ||||
| - Coverage output from [child pipelines](../pipelines/downstream_pipelines.md#parent-child-pipelines) | ||||
|   is not recorded or displayed. Check [the related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/280818) | ||||
|   for more details. | ||||
| 
 | ||||
|  | @ -2283,14 +2283,14 @@ build_job: | |||
| 
 | ||||
| **Related topics**: | ||||
| 
 | ||||
| - To download artifacts between [parent-child pipelines](../pipelines/parent_child_pipelines.md), | ||||
| - To download artifacts between [parent-child pipelines](../pipelines/downstream_pipelines.md#parent-child-pipelines), | ||||
|   use [`needs:pipeline:job`](#needspipelinejob). | ||||
| 
 | ||||
| #### `needs:pipeline:job` | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255983) in GitLab 13.7. | ||||
| 
 | ||||
| A [child pipeline](../pipelines/parent_child_pipelines.md) can download artifacts from a job in | ||||
| A [child pipeline](../pipelines/downstream_pipelines.md#parent-child-pipelines) can download artifacts from a job in | ||||
| its parent pipeline or another child pipeline in the same parent-child pipeline hierarchy. | ||||
| 
 | ||||
| **Keyword type**: Job keyword. You can use it only as part of a job. | ||||
|  | @ -3881,7 +3881,7 @@ 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/parent_child_pipelines.md). | ||||
| - [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. | ||||
| The keywords available for use in trigger jobs are: | ||||
|  | @ -3942,7 +3942,7 @@ 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/parent_child_pipelines.md#examples). | ||||
| - [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. | ||||
|  | @ -3987,7 +3987,7 @@ successfully complete before starting. | |||
| > - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/355572) in GitLab 15.1. [Feature flag `ci_trigger_forward_variables`](https://gitlab.com/gitlab-org/gitlab/-/issues/355572) removed. | ||||
| 
 | ||||
| Use `trigger:forward` to specify what to forward to the downstream pipeline. You can control | ||||
| what is forwarded to both [parent-child pipelines](../pipelines/parent_child_pipelines.md) | ||||
| what is forwarded to both [parent-child pipelines](../pipelines/downstream_pipelines.md#parent-child-pipelines) | ||||
| and [multi-project pipelines](../pipelines/downstream_pipelines.md#multi-project-pipelines). | ||||
| 
 | ||||
| **Possible inputs**: | ||||
|  |  | |||
|  | @ -231,6 +231,10 @@ To view the event timeline of an incident: | |||
| 
 | ||||
| #### Create a timeline event | ||||
| 
 | ||||
| You can create a timeline event in many ways in GitLab. | ||||
| 
 | ||||
| ##### Using the form | ||||
| 
 | ||||
| Create a timeline event manually using the form. | ||||
| 
 | ||||
| Prerequisites: | ||||
|  | @ -247,6 +251,24 @@ To create a timeline event: | |||
| 1. Complete the required fields. | ||||
| 1. Select **Save** or **Save and add another event**. | ||||
| 
 | ||||
| ##### From a comment on the incident | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/344058) in GitLab 15.4. | ||||
| 
 | ||||
| Prerequisites: | ||||
| 
 | ||||
| - You must have at least the Developer role for the project. | ||||
| 
 | ||||
| To create a timeline event from a comment on the incident: | ||||
| 
 | ||||
| 1. On the top bar, select **Menu > Projects** and find your project. | ||||
| 1. On the left sidebar, select **Monitor > Incidents**. | ||||
| 1. Select an incident. | ||||
| 1. Create a comment or choose an existing comment. | ||||
| 1. On the comment you want to add, select **Add comment to incident timeline** (**{clock}**). | ||||
| 
 | ||||
| The comment is shown on the incident timeline as a timeline event. | ||||
| 
 | ||||
| #### Delete a timeline event | ||||
| 
 | ||||
| You can also delete timeline events. | ||||
|  |  | |||
|  | @ -277,7 +277,7 @@ For a complete example, read the [Go coverage-guided fuzzing example](https://gi | |||
| 
 | ||||
| It's also possible to run the coverage-guided fuzzing jobs longer and without blocking your main | ||||
| pipeline. This configuration uses the GitLab | ||||
| [parent-child pipelines](../../../ci/pipelines/parent_child_pipelines.md). | ||||
| [parent-child pipelines](../../../ci/pipelines/downstream_pipelines.md#parent-child-pipelines). | ||||
| 
 | ||||
| The suggested workflow in this scenario is to have long-running, asynchronous fuzzing jobs on the | ||||
| main or development branch, and short synchronous fuzzing jobs on all other branches and MRs. This | ||||
|  |  | |||
|  | @ -128,7 +128,7 @@ Note the following: | |||
| - A container scanning and cluster image scanning scans configured for the `pipeline` rule type ignores the cluster defined in the `clusters` object. | ||||
|   They use predefined CI/CD variables defined for your project. Cluster selection with the `clusters` object is supported for the `schedule` rule type. | ||||
|   A cluster with a name provided in the `clusters` object must be created and configured for the project. | ||||
| - The SAST scan uses the default template and runs in a [child pipeline](../../../ci/pipelines/parent_child_pipelines.md). | ||||
| - The SAST scan uses the default template and runs in a [child pipeline](../../../ci/pipelines/downstream_pipelines.md#parent-child-pipelines). | ||||
| 
 | ||||
| ## Example security policies project | ||||
| 
 | ||||
|  |  | |||
|  | @ -214,7 +214,7 @@ Compliance pipelines start on the run of _every_ pipeline in a relevant project. | |||
| triggers a child pipeline, the compliance pipeline runs first. This can trigger the parent pipeline, instead of the child pipeline. | ||||
| 
 | ||||
| Therefore, in projects with compliance frameworks, we recommend replacing | ||||
| [parent-child pipelines](../../../ci/pipelines/parent_child_pipelines.md) with the following: | ||||
| [parent-child pipelines](../../../ci/pipelines/downstream_pipelines.md#parent-child-pipelines) with the following: | ||||
| 
 | ||||
| - Direct [`include`](../../../ci/yaml/index.md#include) statements that provide the parent pipeline with child pipeline configuration. | ||||
| - Child pipelines placed in another project that are run using the [trigger API](../../../ci/triggers/index.md) rather than the parent-child | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ module Banzai | |||
|         text.lines.map! do |line| | ||||
|           trailer, rest = line.split(':', 2) | ||||
| 
 | ||||
|           next line unless trailer.downcase.end_with?('-by') | ||||
|           next line unless trailer.downcase.end_with?('-by') && rest.present? | ||||
| 
 | ||||
|           chunks = rest.split | ||||
|           author_email = chunks.pop.delete_prefix('<').delete_suffix('>') | ||||
|  |  | |||
|  | @ -10,16 +10,32 @@ module ErrorTracking | |||
| 
 | ||||
|     Error = Class.new(StandardError) | ||||
|     MissingKeysError = Class.new(StandardError) | ||||
|     ResponseInvalidSizeError = Class.new(StandardError) | ||||
| 
 | ||||
|     RESPONSE_SIZE_LIMIT = 1.megabyte | ||||
| 
 | ||||
|     attr_accessor :url, :token | ||||
| 
 | ||||
|     def initialize(api_url, token) | ||||
|     def initialize(api_url, token, validate_size_guarded_by_feature_flag: false) | ||||
|       @url = api_url | ||||
|       @token = token | ||||
|       @validate_size_guarded_by_feature_flag = validate_size_guarded_by_feature_flag | ||||
|     end | ||||
| 
 | ||||
|     def validate_size_guarded_by_feature_flag? | ||||
|       @validate_size_guarded_by_feature_flag | ||||
|     end | ||||
| 
 | ||||
|     private | ||||
| 
 | ||||
|     def validate_size(response) | ||||
|       return if Gitlab::Utils::DeepSize.new(response, max_size: RESPONSE_SIZE_LIMIT).valid? | ||||
| 
 | ||||
|       limit = ActiveSupport::NumberHelper.number_to_human_size(RESPONSE_SIZE_LIMIT) | ||||
|       message = "Sentry API response is too big. Limit is #{limit}." | ||||
|       raise ResponseInvalidSizeError, message | ||||
|     end | ||||
| 
 | ||||
|     def api_urls | ||||
|       @api_urls ||= SentryClient::ApiUrls.new(@url) | ||||
|     end | ||||
|  | @ -86,6 +102,8 @@ module ErrorTracking | |||
|     def handle_response(response) | ||||
|       raise_error "Sentry response status code: #{response.code}" unless response.code.between?(200, 204) | ||||
| 
 | ||||
|       validate_size(response.parsed_response) if validate_size_guarded_by_feature_flag? | ||||
| 
 | ||||
|       { body: response.parsed_response, headers: response.headers } | ||||
|     end | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ module ErrorTracking | |||
|   class SentryClient | ||||
|     module Issue | ||||
|       BadRequestError = Class.new(StandardError) | ||||
|       ResponseInvalidSizeError = Class.new(StandardError) | ||||
| 
 | ||||
|       SENTRY_API_SORT_VALUE_MAP = { | ||||
|         # <accepted_by_client> => <accepted_by_sentry_api> | ||||
|  | @ -19,7 +18,9 @@ module ErrorTracking | |||
|         issues = response[:issues] | ||||
|         pagination = response[:pagination] | ||||
| 
 | ||||
|         validate_size(issues) | ||||
|         # We check validate size only with feture flag disabled because when | ||||
|         # enabled we already check it when parsing the response. | ||||
|         validate_size(issues) unless validate_size_guarded_by_feature_flag? | ||||
| 
 | ||||
|         handle_mapping_exceptions do | ||||
|           { | ||||
|  | @ -64,13 +65,6 @@ module ErrorTracking | |||
|         }.compact | ||||
|       end | ||||
| 
 | ||||
|       def validate_size(issues) | ||||
|         return if Gitlab::Utils::DeepSize.new(issues).valid? | ||||
| 
 | ||||
|         message = "Sentry API response is too big. Limit is #{Gitlab::Utils::DeepSize.human_default_max_size}." | ||||
|         raise ResponseInvalidSizeError, message | ||||
|       end | ||||
| 
 | ||||
|       def get_issue(issue_id:) | ||||
|         http_get(api_urls.issue_url(issue_id))[:body] | ||||
|       end | ||||
|  |  | |||
|  | @ -25,10 +25,6 @@ module Gitlab | |||
|         !too_big? && !too_deep? | ||||
|       end | ||||
| 
 | ||||
|       def self.human_default_max_size | ||||
|         ActiveSupport::NumberHelper.number_to_human_size(DEFAULT_MAX_SIZE) | ||||
|       end | ||||
| 
 | ||||
|       private | ||||
| 
 | ||||
|       def evaluate | ||||
|  |  | |||
|  | @ -26898,6 +26898,9 @@ msgstr "" | |||
| msgid "Notify|Milestone changed to %{milestone}" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Notify|Milestone removed" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Notify|New issue: %{project_issue_url}" | ||||
| msgstr "" | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,7 +17,11 @@ module QA | |||
|         merge_request.fork.remove_via_api! | ||||
|       end | ||||
| 
 | ||||
|       it 'can merge feature branch fork to mainline', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347818' do | ||||
|       it 'can merge feature branch fork to mainline', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347818', quarantine: { | ||||
|         only: { subdomain: :production }, | ||||
|         type: :investigating, | ||||
|         issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/372258' | ||||
|       } do | ||||
|         merge_request.visit! | ||||
| 
 | ||||
|         Page::MergeRequest::Show.perform do |merge_request| | ||||
|  |  | |||
|  | @ -137,6 +137,13 @@ RSpec.describe Banzai::Filter::CommitTrailersFilter do | |||
|       expect(doc.to_html).to match Regexp.escape(exp) | ||||
|     end | ||||
| 
 | ||||
|     it 'trailers without emails' do | ||||
|       exp = message = commit_html(Array.new(5) { 'Merged-By:' }.join("\n")) | ||||
|       doc = filter(message) | ||||
| 
 | ||||
|       expect(doc.to_html).to match Regexp.escape(exp) | ||||
|     end | ||||
| 
 | ||||
|     it 'trailers that are inline the commit message body' do | ||||
|       message = commit_html %( | ||||
|         #{FFaker::Lorem.sentence} #{commit_message} #{FFaker::Lorem.sentence} | ||||
|  |  | |||
|  | @ -32,6 +32,7 @@ RSpec.describe ErrorTracking::SentryClient do | |||
|     subject { client.issue_latest_event(issue_id: issue_id) } | ||||
| 
 | ||||
|     it_behaves_like 'calls sentry api' | ||||
|     it_behaves_like 'Sentry API response size limit' | ||||
| 
 | ||||
|     it 'has correct return type' do | ||||
|       expect(subject).to be_a(Gitlab::ErrorTracking::ErrorEvent) | ||||
|  | @ -50,7 +51,7 @@ RSpec.describe ErrorTracking::SentryClient do | |||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'error object created from sentry response' do | ||||
|     context 'with error object created from sentry response' do | ||||
|       it_behaves_like 'assigns error tracking event correctly' | ||||
| 
 | ||||
|       it 'parses the stack trace' do | ||||
|  | @ -58,7 +59,7 @@ RSpec.describe ErrorTracking::SentryClient do | |||
|         expect(subject.stack_trace_entries).not_to be_empty | ||||
|       end | ||||
| 
 | ||||
|       context 'error without stack trace' do | ||||
|       context 'with error without stack trace' do | ||||
|         before do | ||||
|           sample_response['entries'] = [] | ||||
|           stub_sentry_request(sentry_request_url, body: sample_response) | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ RSpec.describe ErrorTracking::SentryClient::IssueLink do | |||
|   let_it_be(:error_tracking_setting) { create(:project_error_tracking_setting, api_url: sentry_url) } | ||||
|   let_it_be(:issue) { create(:issue, project: error_tracking_setting.project) } | ||||
| 
 | ||||
|   let(:token) { 'test-token' } | ||||
|   let(:client) { error_tracking_setting.sentry_client } | ||||
|   let(:sentry_issue_id) { 11111111 } | ||||
| 
 | ||||
|  | @ -22,11 +23,12 @@ RSpec.describe ErrorTracking::SentryClient::IssueLink do | |||
| 
 | ||||
|     subject { client.create_issue_link(integration_id, sentry_issue_id, issue) } | ||||
| 
 | ||||
|     it_behaves_like 'Sentry API response size limit' | ||||
|     it_behaves_like 'calls sentry api' | ||||
| 
 | ||||
|     it { is_expected.to be_present } | ||||
| 
 | ||||
|     context 'redirects' do | ||||
|     context 'with redirects' do | ||||
|       let(:sentry_api_url) { sentry_issue_link_url } | ||||
| 
 | ||||
|       it_behaves_like 'no Sentry redirects', :put | ||||
|  | @ -45,11 +47,12 @@ RSpec.describe ErrorTracking::SentryClient::IssueLink do | |||
|       let(:issue_link_sample_response) { Gitlab::Json.parse(fixture_file('sentry/plugin_link_sample_response.json')) } | ||||
|       let!(:sentry_api_request) { stub_sentry_request(sentry_issue_link_url, :post, body: sentry_api_response) } | ||||
| 
 | ||||
|       it_behaves_like 'Sentry API response size limit' | ||||
|       it_behaves_like 'calls sentry api' | ||||
| 
 | ||||
|       it { is_expected.to be_present } | ||||
| 
 | ||||
|       context 'redirects' do | ||||
|       context 'with redirects' do | ||||
|         let(:sentry_api_url) { sentry_issue_link_url } | ||||
| 
 | ||||
|         it_behaves_like 'no Sentry redirects', :post | ||||
|  |  | |||
|  | @ -58,6 +58,8 @@ RSpec.describe ErrorTracking::SentryClient::Issue do | |||
| 
 | ||||
|     it_behaves_like 'issues have correct return type', Gitlab::ErrorTracking::Error | ||||
|     it_behaves_like 'issues have correct length', 3 | ||||
|     it_behaves_like 'maps Sentry exceptions' | ||||
|     it_behaves_like 'Sentry API response size limit', enabled_by_default: true | ||||
| 
 | ||||
|     shared_examples 'has correct external_url' do | ||||
|       describe '#external_url' do | ||||
|  | @ -178,18 +180,6 @@ RSpec.describe ErrorTracking::SentryClient::Issue do | |||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'when sentry api response is too large' do | ||||
|       it 'raises exception' do | ||||
|         deep_size = instance_double(Gitlab::Utils::DeepSize, valid?: false) | ||||
|         allow(Gitlab::Utils::DeepSize).to receive(:new).with(sentry_api_response).and_return(deep_size) | ||||
| 
 | ||||
|         expect { subject }.to raise_error(ErrorTracking::SentryClient::ResponseInvalidSizeError, | ||||
|                                           'Sentry API response is too big. Limit is 1 MB.') | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     it_behaves_like 'maps Sentry exceptions' | ||||
| 
 | ||||
|     context 'when search term is present' do | ||||
|       let(:search_term) { 'NoMethodError' } | ||||
|       let(:sentry_request_url) { "#{sentry_url}/issues/?limit=20&query=is:unresolved NoMethodError" } | ||||
|  | @ -219,10 +209,14 @@ RSpec.describe ErrorTracking::SentryClient::Issue do | |||
|     end | ||||
| 
 | ||||
|     let(:sentry_request_url) { "#{sentry_url}/issues/#{issue_id}/" } | ||||
|     let!(:sentry_api_request) { stub_sentry_request(sentry_request_url, body: issue_sample_response) } | ||||
|     let(:sentry_api_response) { issue_sample_response } | ||||
|     let!(:sentry_api_request) { stub_sentry_request(sentry_request_url, body: sentry_api_response) } | ||||
| 
 | ||||
|     subject { client.issue_details(issue_id: issue_id) } | ||||
| 
 | ||||
|     it_behaves_like 'maps Sentry exceptions' | ||||
|     it_behaves_like 'Sentry API response size limit' | ||||
| 
 | ||||
|     context 'with error object created from sentry response' do | ||||
|       using RSpec::Parameterized::TableSyntax | ||||
| 
 | ||||
|  | @ -321,6 +315,10 @@ RSpec.describe ErrorTracking::SentryClient::Issue do | |||
| 
 | ||||
|     subject { client.update_issue(issue_id: issue_id, params: params) } | ||||
| 
 | ||||
|     it_behaves_like 'Sentry API response size limit' do | ||||
|       let(:sentry_api_response) { {} } | ||||
|     end | ||||
| 
 | ||||
|     it_behaves_like 'calls sentry api' do | ||||
|       let(:sentry_api_request) { stub_sentry_request(sentry_request_url, :put) } | ||||
|     end | ||||
|  |  | |||
|  | @ -35,6 +35,7 @@ RSpec.describe ErrorTracking::SentryClient::Projects do | |||
| 
 | ||||
|     it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Project | ||||
|     it_behaves_like 'has correct length', 2 | ||||
|     it_behaves_like 'Sentry API response size limit' | ||||
| 
 | ||||
|     context 'essential keys missing in API response' do | ||||
|       let(:sentry_api_response) do | ||||
|  |  | |||
|  | @ -19,12 +19,13 @@ RSpec.describe ErrorTracking::SentryClient::Repo do | |||
|     subject { client.repos(organization_slug) } | ||||
| 
 | ||||
|     it_behaves_like 'calls sentry api' | ||||
|     it_behaves_like 'Sentry API response size limit' | ||||
| 
 | ||||
|     it { is_expected.to all( be_a(Gitlab::ErrorTracking::Repo)) } | ||||
| 
 | ||||
|     it { expect(subject.length).to eq(1) } | ||||
| 
 | ||||
|     context 'redirects' do | ||||
|     context 'with redirects' do | ||||
|       let(:sentry_api_url) { sentry_repos_url } | ||||
| 
 | ||||
|       it_behaves_like 'no Sentry redirects' | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ RSpec.describe Gitlab::Gfm::UploadsRewriter do | |||
|     end | ||||
| 
 | ||||
|     let(:text) do | ||||
|       "Text and #{image_uploader.markdown_link} and #{zip_uploader.markdown_link}" | ||||
|       "Text and #{image_uploader.markdown_link} and #{zip_uploader.markdown_link}".freeze # rubocop:disable Style/RedundantFreeze | ||||
|     end | ||||
| 
 | ||||
|     def referenced_files(text, project) | ||||
|  |  | |||
|  | @ -58,10 +58,4 @@ RSpec.describe Gitlab::Utils::DeepSize do | |||
|       it { is_expected.not_to be_valid } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '.human_default_max_size' do | ||||
|     it 'returns 1 MB' do | ||||
|       expect(described_class.human_default_max_size).to eq('1 MB') | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -187,9 +187,38 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do | |||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#reactive_cache_limit_enabled?' do | ||||
|     subject { setting.reactive_cache_limit_enabled? } | ||||
| 
 | ||||
|     it { is_expected.to eq(true) } | ||||
| 
 | ||||
|     context 'when feature flag disabled' do | ||||
|       before do | ||||
|         stub_feature_flags(error_tracking_sentry_limit: false) | ||||
|       end | ||||
| 
 | ||||
|       it { is_expected.to eq(false) } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#sentry_client' do | ||||
|     it 'returns sentry client' do | ||||
|       expect(subject.sentry_client).to be_a(ErrorTracking::SentryClient) | ||||
|     subject { setting.sentry_client } | ||||
| 
 | ||||
|     it { is_expected.to be_a(ErrorTracking::SentryClient) } | ||||
|     it { is_expected.to have_attributes(url: setting.api_url, token: setting.token) } | ||||
| 
 | ||||
|     describe '#validate_size_guarded_by_feature_flag?' do | ||||
|       subject { setting.sentry_client.validate_size_guarded_by_feature_flag? } | ||||
| 
 | ||||
|       it { is_expected.to eq(true) } | ||||
| 
 | ||||
|       context 'when feature flag disabled' do | ||||
|         before do | ||||
|           stub_feature_flags(error_tracking_sentry_limit: false) | ||||
|         end | ||||
| 
 | ||||
|         it { is_expected.to eq(false) } | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  | @ -222,70 +251,39 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do | |||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'when sentry client raises ErrorTracking::SentryClient::Error' do | ||||
|       before do | ||||
|         synchronous_reactive_cache(subject) | ||||
|     describe 'client errors' do | ||||
|       using RSpec::Parameterized::TableSyntax | ||||
| 
 | ||||
|         allow(subject).to receive(:sentry_client).and_return(sentry_client) | ||||
|         allow(sentry_client).to receive(:list_issues).with(opts) | ||||
|           .and_raise(ErrorTracking::SentryClient::Error, 'error message') | ||||
|       end | ||||
| 
 | ||||
|       it 'returns error' do | ||||
|         expect(result).to eq( | ||||
|           error: 'error message', | ||||
|           error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_NON_20X_RESPONSE | ||||
|         ) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'when sentry client raises ErrorTracking::SentryClient::MissingKeysError' do | ||||
|       before do | ||||
|         synchronous_reactive_cache(subject) | ||||
| 
 | ||||
|         allow(subject).to receive(:sentry_client).and_return(sentry_client) | ||||
|         allow(sentry_client).to receive(:list_issues).with(opts) | ||||
|           .and_raise(ErrorTracking::SentryClient::MissingKeysError, | ||||
|                      'Sentry API response is missing keys. key not found: "id"') | ||||
|       end | ||||
| 
 | ||||
|       it 'returns error' do | ||||
|         expect(result).to eq( | ||||
|           error: 'Sentry API response is missing keys. key not found: "id"', | ||||
|           error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_MISSING_KEYS | ||||
|         ) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'when sentry client raises ErrorTracking::SentryClient::ResponseInvalidSizeError' do | ||||
|       let(:error_msg) { "Sentry API response is too big. Limit is #{Gitlab::Utils::DeepSize.human_default_max_size}." } | ||||
|       sc = ErrorTracking::SentryClient | ||||
|       pets = described_class | ||||
|       msg = 'something' | ||||
| 
 | ||||
|       before do | ||||
|         synchronous_reactive_cache(subject) | ||||
| 
 | ||||
|         allow(subject).to receive(:sentry_client).and_return(sentry_client) | ||||
|         allow(sentry_client).to receive(:list_issues).with(opts) | ||||
|           .and_raise(ErrorTracking::SentryClient::ResponseInvalidSizeError, error_msg) | ||||
|       end | ||||
| 
 | ||||
|       it 'returns error' do | ||||
|         expect(result).to eq( | ||||
|           error: error_msg, | ||||
|           error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_INVALID_SIZE | ||||
|         ) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'when sentry client raises StandardError' do | ||||
|       before do | ||||
|         synchronous_reactive_cache(subject) | ||||
| 
 | ||||
|         allow(subject).to receive(:sentry_client).and_return(sentry_client) | ||||
|         allow(sentry_client).to receive(:list_issues).with(opts).and_raise(StandardError) | ||||
|       where(:exception, :error_type, :error_message) do | ||||
|         sc::Error                    | pets::SENTRY_API_ERROR_TYPE_NON_20X_RESPONSE | msg | ||||
|         sc::MissingKeysError         | pets::SENTRY_API_ERROR_TYPE_MISSING_KEYS     | msg | ||||
|         sc::ResponseInvalidSizeError | pets::SENTRY_API_ERROR_INVALID_SIZE          | msg | ||||
|         sc::BadRequestError          | pets::SENTRY_API_ERROR_TYPE_BAD_REQUEST      | msg | ||||
|         StandardError                | nil                                          | 'Unexpected Error' | ||||
|       end | ||||
| 
 | ||||
|       it 'returns error' do | ||||
|         expect(result).to eq(error: 'Unexpected Error') | ||||
|       with_them do | ||||
|         it 'returns an error' do | ||||
|           allow(sentry_client).to receive(:list_issues).with(opts) | ||||
|             .and_raise(exception, msg) | ||||
| 
 | ||||
|           expected_result = { | ||||
|             error: error_message, | ||||
|             error_type: error_type | ||||
|           }.compact | ||||
| 
 | ||||
|           expect(result).to eq(expected_result) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  |  | |||
|  | @ -43,7 +43,7 @@ RSpec.shared_examples 'maps Sentry exceptions' do |http_method| | |||
|   } | ||||
| 
 | ||||
|   exceptions.each do |exception, message| | ||||
|     context "#{exception}" do | ||||
|     context exception do | ||||
|       before do | ||||
|         stub_request( | ||||
|           http_method || :get, | ||||
|  | @ -58,3 +58,50 @@ RSpec.shared_examples 'maps Sentry exceptions' do |http_method| | |||
|     end | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| # Expects to following variables: | ||||
| #   - subject | ||||
| #   - sentry_api_response | ||||
| #   - sentry_url, token - only if enabled_by_default: false | ||||
| RSpec.shared_examples 'Sentry API response size limit' do |enabled_by_default: false| | ||||
|   let(:invalid_deep_size) { instance_double(Gitlab::Utils::DeepSize, valid?: false) } | ||||
| 
 | ||||
|   before do | ||||
|     allow(Gitlab::Utils::DeepSize) | ||||
|       .to receive(:new) | ||||
|       .with(sentry_api_response, any_args) | ||||
|       .and_return(invalid_deep_size) | ||||
|   end | ||||
| 
 | ||||
|   if enabled_by_default | ||||
|     it 'raises an exception when response is too large' do | ||||
|       expect { subject }.to raise_error(ErrorTracking::SentryClient::ResponseInvalidSizeError, | ||||
|                                         'Sentry API response is too big. Limit is 1 MB.') | ||||
|     end | ||||
|   else | ||||
|     context 'when guarded by feature flag' do | ||||
|       let(:client) do | ||||
|         ErrorTracking::SentryClient.new(sentry_url, token, validate_size_guarded_by_feature_flag: feature_flag) | ||||
|       end | ||||
| 
 | ||||
|       context 'with feature flag enabled' do | ||||
|         let(:feature_flag) { true } | ||||
| 
 | ||||
|         it 'raises an exception when response is too large' do | ||||
|           expect { subject }.to raise_error(ErrorTracking::SentryClient::ResponseInvalidSizeError, | ||||
|                                             'Sentry API response is too big. Limit is 1 MB.') | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|       context 'with feature flag disabled' do | ||||
|         let(:feature_flag) { false } | ||||
| 
 | ||||
|         it 'does not check the limit and thus not raise' do | ||||
|           expect { subject }.not_to raise_error | ||||
| 
 | ||||
|           expect(Gitlab::Utils::DeepSize).not_to have_received(:new) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue