diff --git a/app/models/error_tracking/project_error_tracking_setting.rb b/app/models/error_tracking/project_error_tracking_setting.rb index 4953f24755c..12d73ef0d72 100644 --- a/app/models/error_tracking/project_error_tracking_setting.rb +++ b/app/models/error_tracking/project_error_tracking_setting.rb @@ -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 diff --git a/app/views/notify/removed_milestone_issue_email.html.haml b/app/views/notify/removed_milestone_issue_email.html.haml index 7e9205b6491..f411ea23832 100644 --- a/app/views/notify/removed_milestone_issue_email.html.haml +++ b/app/views/notify/removed_milestone_issue_email.html.haml @@ -1,2 +1,2 @@ %p - Milestone removed + = s_('Notify|Milestone removed') diff --git a/config/feature_flags/development/error_tracking_sentry_limit.yml b/config/feature_flags/development/error_tracking_sentry_limit.yml new file mode 100644 index 00000000000..75a32fa2114 --- /dev/null +++ b/config/feature_flags/development/error_tracking_sentry_limit.yml @@ -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 diff --git a/doc/api/job_artifacts.md b/doc/api/job_artifacts.md index 31da0638d23..d1bd40b91b9 100644 --- a/doc/api/job_artifacts.md +++ b/doc/api/job_artifacts.md @@ -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. diff --git a/doc/api/jobs.md b/doc/api/jobs.md index 3173b8f8e70..1548045d7c2 100644 --- a/doc/api/jobs.md +++ b/doc/api/jobs.md @@ -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). diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 66a9a19e691..1df140979ae 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -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: " "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: " "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: " "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: " "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: " "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: " "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: " "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: " "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: " "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: " "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: " "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_stats" diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md index 2e601f6e24a..23c55cfb177 100644 --- a/doc/api/pipelines.md +++ b/doc/api/pipelines.md @@ -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. diff --git a/doc/ci/jobs/job_control.md b/doc/ci/jobs/job_control.md index 217d12e4c26..ca8755550fe 100644 --- a/doc/ci/jobs/job_control.md +++ b/doc/ci/jobs/job_control.md @@ -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). | diff --git a/doc/ci/pipelines/downstream_pipelines.md b/doc/ci/pipelines/downstream_pipelines.md index 4fc7adfaae3..8554a725bde 100644 --- a/doc/ci/pipelines/downstream_pipelines.md +++ b/doc/ci/pipelines/downstream_pipelines.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. + +![Parent pipeline graph expanded](img/parent_pipeline_graph_expanded_v14_3.png) + +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. + + +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. + + +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. + + +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 diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md index 59ad47765b1..1e2b68901b3 100644 --- a/doc/ci/pipelines/index.md +++ b/doc/ci/pipelines/index.md @@ -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**. ![Pipeline Delete](img/pipeline-delete.png) 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. diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md index 00c898a7e0e..c6520f259c3 100644 --- a/doc/ci/pipelines/job_artifacts.md +++ b/doc/ci/pipelines/job_artifacts.md @@ -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. diff --git a/doc/ci/pipelines/parent_child_pipelines.md b/doc/ci/pipelines/parent_child_pipelines.md index 56c51d7b119..be8ed8ba6d7 100644 --- a/doc/ci/pipelines/parent_child_pipelines.md +++ b/doc/ci/pipelines/parent_child_pipelines.md @@ -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. - -![Parent pipeline graph expanded](img/parent_pipeline_graph_expanded_v14_3.png) - -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. - - -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. - - -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. - - -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). + + + + diff --git a/doc/ci/pipelines/pipeline_architectures.md b/doc/ci/pipelines/pipeline_architectures.md index 3ff22a16900..4058df6ec1b 100644 --- a/doc/ci/pipelines/pipeline_architectures.md +++ b/doc/ci/pipelines/pipeline_architectures.md @@ -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: diff --git a/doc/ci/pipelines/pipeline_efficiency.md b/doc/ci/pipelines/pipeline_efficiency.md index ad43895d7ef..72711f9b9dd 100644 --- a/doc/ci/pipelines/pipeline_efficiency.md +++ b/doc/ci/pipelines/pipeline_efficiency.md @@ -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 diff --git a/doc/ci/resource_groups/index.md b/doc/ci/resource_groups/index.md index c215ef412a1..dff52a742a8 100644 --- a/doc/ci/resource_groups/index.md +++ b/doc/ci/resource_groups/index.md @@ -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: diff --git a/doc/ci/troubleshooting.md b/doc/ci/troubleshooting.md index 34bd0602ca5..33dc77c45a9 100644 --- a/doc/ci/troubleshooting.md +++ b/doc/ci/troubleshooting.md @@ -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). diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md index a5d881b6864..a8154a7ae4e 100644 --- a/doc/ci/yaml/index.md +++ b/doc/ci/yaml/index.md @@ -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**: diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md index c1a4c1eb93e..b12e4439865 100644 --- a/doc/operations/incident_management/incidents.md +++ b/doc/operations/incident_management/incidents.md @@ -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. diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md index 0297dc161e3..b7f3d273e32 100644 --- a/doc/user/application_security/coverage_fuzzing/index.md +++ b/doc/user/application_security/coverage_fuzzing/index.md @@ -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 diff --git a/doc/user/application_security/policies/scan-execution-policies.md b/doc/user/application_security/policies/scan-execution-policies.md index c253b8a1092..0ca38fe5f48 100644 --- a/doc/user/application_security/policies/scan-execution-policies.md +++ b/doc/user/application_security/policies/scan-execution-policies.md @@ -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 diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md index ec408081d68..900e2bd1ca9 100644 --- a/doc/user/project/settings/index.md +++ b/doc/user/project/settings/index.md @@ -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 diff --git a/lib/banzai/filter/commit_trailers_filter.rb b/lib/banzai/filter/commit_trailers_filter.rb index 0525527bb6f..817bea42757 100644 --- a/lib/banzai/filter/commit_trailers_filter.rb +++ b/lib/banzai/filter/commit_trailers_filter.rb @@ -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('>') diff --git a/lib/error_tracking/sentry_client.rb b/lib/error_tracking/sentry_client.rb index 6a341ddbe86..029389ab5d6 100644 --- a/lib/error_tracking/sentry_client.rb +++ b/lib/error_tracking/sentry_client.rb @@ -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 diff --git a/lib/error_tracking/sentry_client/issue.rb b/lib/error_tracking/sentry_client/issue.rb index d0e6bd783f3..3c846eb0635 100644 --- a/lib/error_tracking/sentry_client/issue.rb +++ b/lib/error_tracking/sentry_client/issue.rb @@ -4,7 +4,6 @@ module ErrorTracking class SentryClient module Issue BadRequestError = Class.new(StandardError) - ResponseInvalidSizeError = Class.new(StandardError) SENTRY_API_SORT_VALUE_MAP = { # => @@ -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 diff --git a/lib/gitlab/utils/deep_size.rb b/lib/gitlab/utils/deep_size.rb index e185786e638..20f2d699e2b 100644 --- a/lib/gitlab/utils/deep_size.rb +++ b/lib/gitlab/utils/deep_size.rb @@ -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 diff --git a/locale/gitlab.pot b/locale/gitlab.pot index c4e6a38f750..2b23af4a038 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -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 "" diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb index d198d79c5fe..0f65647e168 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb @@ -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| diff --git a/spec/lib/banzai/filter/commit_trailers_filter_spec.rb b/spec/lib/banzai/filter/commit_trailers_filter_spec.rb index 2bdf702083a..c22517621c1 100644 --- a/spec/lib/banzai/filter/commit_trailers_filter_spec.rb +++ b/spec/lib/banzai/filter/commit_trailers_filter_spec.rb @@ -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} diff --git a/spec/lib/error_tracking/sentry_client/event_spec.rb b/spec/lib/error_tracking/sentry_client/event_spec.rb index 64e674f1e9b..d65bfa31018 100644 --- a/spec/lib/error_tracking/sentry_client/event_spec.rb +++ b/spec/lib/error_tracking/sentry_client/event_spec.rb @@ -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) diff --git a/spec/lib/error_tracking/sentry_client/issue_link_spec.rb b/spec/lib/error_tracking/sentry_client/issue_link_spec.rb index f86d328ef89..75e7ac8304e 100644 --- a/spec/lib/error_tracking/sentry_client/issue_link_spec.rb +++ b/spec/lib/error_tracking/sentry_client/issue_link_spec.rb @@ -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 diff --git a/spec/lib/error_tracking/sentry_client/issue_spec.rb b/spec/lib/error_tracking/sentry_client/issue_spec.rb index 8c02557b57b..1468a1ff7eb 100644 --- a/spec/lib/error_tracking/sentry_client/issue_spec.rb +++ b/spec/lib/error_tracking/sentry_client/issue_spec.rb @@ -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 diff --git a/spec/lib/error_tracking/sentry_client/projects_spec.rb b/spec/lib/error_tracking/sentry_client/projects_spec.rb index 81b44d0f6b1..52f8cdc915e 100644 --- a/spec/lib/error_tracking/sentry_client/projects_spec.rb +++ b/spec/lib/error_tracking/sentry_client/projects_spec.rb @@ -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 diff --git a/spec/lib/error_tracking/sentry_client/repo_spec.rb b/spec/lib/error_tracking/sentry_client/repo_spec.rb index 9a1c7a69c3d..445a8e35f8e 100644 --- a/spec/lib/error_tracking/sentry_client/repo_spec.rb +++ b/spec/lib/error_tracking/sentry_client/repo_spec.rb @@ -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' diff --git a/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb b/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb index 763e6f1b5f4..a16f96a7d11 100644 --- a/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb +++ b/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb @@ -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) diff --git a/spec/lib/gitlab/utils/deep_size_spec.rb b/spec/lib/gitlab/utils/deep_size_spec.rb index 473efbc1eae..6b0be4590f1 100644 --- a/spec/lib/gitlab/utils/deep_size_spec.rb +++ b/spec/lib/gitlab/utils/deep_size_spec.rb @@ -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 diff --git a/spec/models/error_tracking/project_error_tracking_setting_spec.rb b/spec/models/error_tracking/project_error_tracking_setting_spec.rb index 0685144dea6..30e73d84cfb 100644 --- a/spec/models/error_tracking/project_error_tracking_setting_spec.rb +++ b/spec/models/error_tracking/project_error_tracking_setting_spec.rb @@ -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 diff --git a/spec/support/shared_examples/lib/sentry/client_shared_examples.rb b/spec/support/shared_examples/lib/sentry/client_shared_examples.rb index d73c7b6848d..1c0e0061385 100644 --- a/spec/support/shared_examples/lib/sentry/client_shared_examples.rb +++ b/spec/support/shared_examples/lib/sentry/client_shared_examples.rb @@ -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