diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-01 03:07:51 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-01 03:07:51 +0300 |
commit | 4aaadcc49070b085d63377c004c5632b6d1b2b4c (patch) | |
tree | 0d8c890fd1ce0ca22ec579a91fcd84f92c50404f | |
parent | 9e83d078577a9c066f21fcef1355f800ad895c9c (diff) |
Add latest changes from gitlab-org/gitlab@master
47 files changed, 344 insertions, 407 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index dafdd717c19..e65521e892a 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -f6a9d44f05809aaa59fc9aff9b0465cf3cb7aea9 +1d669a6318f40ac765abc82e9064e9479fc22540 @@ -163,6 +163,7 @@ gem 'gitlab-fog-azure-rm', '~> 1.4.0', require: 'fog/azurerm' # for Google storage gem 'google-api-client', '~> 0.33' +gem 'google-cloud-storage', '~> 1.44.0' # for aws storage gem 'unf', '~> 0.1.4' diff --git a/Gemfile.checksum b/Gemfile.checksum index 4f04c233ca4..846355950bc 100644 --- a/Gemfile.checksum +++ b/Gemfile.checksum @@ -111,6 +111,7 @@ {"name":"diff-lcs","version":"1.5.0","platform":"ruby","checksum":"49b934001c8c6aedb37ba19daec5c634da27b318a7a3c654ae979d6ba1929b67"}, {"name":"diff_match_patch","version":"0.1.0","platform":"ruby","checksum":"b36057bfcfeaedf19dcb7b2c28c19ee625bd6ec6d0d182717d3ef22b3879c40e"}, {"name":"diffy","version":"3.4.2","platform":"ruby","checksum":"36b42ffbe5138ddc56182107c24ad8d6b066ecfd2876829f391e3a4993d89ae1"}, +{"name":"digest-crc","version":"0.6.4","platform":"ruby","checksum":"a283a60ad466f621b130c516a664df744207ee1b0283ec821fc1223eca54eab3"}, {"name":"discordrb-webhooks","version":"3.4.2","platform":"ruby","checksum":"cfdba8a4b28236b6ab34e37389f881a59c241aeb5be0a4447249efd4e4383c6e"}, {"name":"docile","version":"1.4.0","platform":"ruby","checksum":"5f1734bde23721245c20c3d723e76c104208e1aa01277a69901ce770f0ebb8d3"}, {"name":"domain_name","version":"0.5.20190701","platform":"ruby","checksum":"000a600454cb4a344769b2f10b531765ea7bd3a304fe47ed12e5ca1eab969851"}, @@ -226,8 +227,11 @@ {"name":"google-apis-monitoring_v3","version":"0.37.0","platform":"ruby","checksum":"2d9262ae8dfa83ac7db895b03c7deeaae9f13107e94c8781a432202fbc20736a"}, {"name":"google-apis-pubsub_v1","version":"0.30.0","platform":"ruby","checksum":"b8905915388041bf54f9b7e988c8cc64fe00c2132475d5c753d10479415ee13d"}, {"name":"google-apis-sqladmin_v1beta4","version":"0.38.0","platform":"ruby","checksum":"d00279cdcc5548bf4f4e40cc29cbd942b79708011e59c75a18726b6826be1665"}, -{"name":"google-apis-storage_v1","version":"0.20.0","platform":"ruby","checksum":"8a1ace07fc909966d6f76e777d6adc7d86dddd91a629fef8914ebd5baf86d850"}, +{"name":"google-apis-storage_v1","version":"0.19.0","platform":"ruby","checksum":"522b6172722c7b18ad7a440d1949efbafdf984422f99f002df5f086725ab0a9f"}, +{"name":"google-cloud-core","version":"1.6.0","platform":"ruby","checksum":"ea1744cd5a3085d3072de3fab9106afc769cd198609ebb5c6eeb5f13da46b72a"}, {"name":"google-cloud-env","version":"1.6.0","platform":"ruby","checksum":"6179acb946975892c7908748df5722a4ebadfc8cf5bb7b0d8d933ca67183fa15"}, +{"name":"google-cloud-errors","version":"1.3.0","platform":"ruby","checksum":"450b681e24c089a20721a01acc4408bb4a7b0df28c175aaab488da917480d64b"}, +{"name":"google-cloud-storage","version":"1.44.0","platform":"ruby","checksum":"299a1e055c9277c8120f7c10d21d37e4d8c17c7b963350c0e0bff7e9d9a570ea"}, {"name":"google-protobuf","version":"3.21.12","platform":"java","checksum":"35362ef8abf98ad597dffee588390b8b3b2f0f3d70261c3eed3f99e564f3289d"}, {"name":"google-protobuf","version":"3.21.12","platform":"ruby","checksum":"4b09bb7e3168cda689efebcd3373304e124b14aabf776fbf1f0a7615259c8fb5"}, {"name":"google-protobuf","version":"3.21.12","platform":"x64-mingw-ucrt","checksum":"e4444119acd56bf4661b3f38dc2795abae2cd5c2ade88154d5fc405008fbdcf7"}, diff --git a/Gemfile.lock b/Gemfile.lock index f38f2a2871d..49e6977020d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -368,6 +368,8 @@ GEM diff-lcs (1.5.0) diff_match_patch (0.1.0) diffy (3.4.2) + digest-crc (0.6.4) + rake (>= 12.0.0, < 14.0.0) discordrb-webhooks (3.4.2) rest-client (>= 2.0.0) docile (1.4.0) @@ -652,10 +654,22 @@ GEM google-apis-core (>= 0.9.1, < 2.a) google-apis-sqladmin_v1beta4 (0.38.0) google-apis-core (>= 0.9.0, < 2.a) - google-apis-storage_v1 (0.20.0) - google-apis-core (>= 0.9.1, < 2.a) + google-apis-storage_v1 (0.19.0) + google-apis-core (>= 0.9.0, < 2.a) + google-cloud-core (1.6.0) + google-cloud-env (~> 1.0) + google-cloud-errors (~> 1.0) google-cloud-env (1.6.0) faraday (>= 0.17.3, < 3.0) + google-cloud-errors (1.3.0) + google-cloud-storage (1.44.0) + addressable (~> 2.8) + digest-crc (~> 0.4) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.19.0) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) + mini_mime (~> 1.0) google-protobuf (3.21.12) googleapis-common-protos-types (1.3.0) google-protobuf (~> 3.14) @@ -1679,6 +1693,7 @@ DEPENDENCIES gitlab_omniauth-ldap (~> 2.2.0) gon (~> 6.4.0) google-api-client (~> 0.33) + google-cloud-storage (~> 1.44.0) google-protobuf (~> 3.21, >= 3.21.12) gpgme (~> 2.0.22) grape (~> 1.5.2) diff --git a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue index 271cfd210a6..52a5d6e1b86 100644 --- a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue +++ b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue @@ -42,11 +42,6 @@ export default { required: false, default: true, }, - iconClasses: { - type: String, - required: false, - default: '', - }, }, computed: { title() { @@ -73,7 +68,7 @@ export default { :href="detailsPath" @click="$emit('ciStatusBadgeClick')" > - <ci-icon :status="status" :css-classes="iconClasses" /> + <ci-icon :status="status" /> <template v-if="showText"> <span class="gl-ml-2">{{ status.text }}</span> diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md index 531d679a34d..0b39e30885e 100644 --- a/doc/api/api_resources.md +++ b/doc/api/api_resources.md @@ -40,6 +40,7 @@ The following API resources are available in the project context: | [Deploy tokens](deploy_tokens.md) | `/projects/:id/deploy_tokens` (also available for groups and standalone) | | [Deployments](deployments.md) | `/projects/:id/deployments` | | [Discussions](discussions.md) (threaded comments) | `/projects/:id/issues/.../discussions`, `/projects/:id/snippets/.../discussions`, `/projects/:id/merge_requests/.../discussions`, `/projects/:id/commits/.../discussions` (also available for groups) | +| [Draft Notes](draft_notes.md) (comments) | `/projects/:id/merge_requests/.../draft_notes` | [Environments](environments.md) | `/projects/:id/environments` | | [Error Tracking](error_tracking.md) | `/projects/:id/error_tracking/settings` | | [Events](events.md) | `/projects/:id/events` (also available for users and standalone) | diff --git a/doc/api/draft_notes.md b/doc/api/draft_notes.md new file mode 100644 index 00000000000..423ba2bb31d --- /dev/null +++ b/doc/api/draft_notes.md @@ -0,0 +1,51 @@ +--- +stage: Create +group: Code Review +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Draft Notes API **(FREE)** + +Draft notes are pending, unpublished comments on merge requests. They can be either start a discussion, or be associated with an existing discussion as a reply. They are viewable only by the author until they are published. + +## List all merge request draft notes + +Gets a list of all draft notes for a single merge request. + +```plaintext +GET /projects/:id/merge_requests/:merge_request_iid/draft_notes +``` + +| Attribute | Type | Required | Description | +| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | integer or string | yes | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding) +| `merge_request_iid` | integer | yes | The IID of a project merge request + +```json +{ + id: 5, + author_id: 23, + merge_request_id: 11, + resolve_discussion: false, + discussion_id: nil, + note: "Example title", + commit_id: nil, + line_code: nil, + position: + { + base_sha: nil, + start_sha: nil, + head_sha: nil, + old_path: nil, + new_path: nil, + position_type: "text", + old_line: nil, + new_line: nil, + line_range: nil + } +} +``` + +```shell +curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/draft_notes" +``` diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 1a8b39db062..024593b2c6b 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -59,8 +59,8 @@ Supported attributes: | `my_reaction_emoji` | string | **{dotted-circle}** No | Returns 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 | **{dotted-circle}** No | Returns 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 | **{dotted-circle}** No | Returns 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 | **{dotted-circle}** 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 | **{dotted-circle}** 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. | +| `reviewer_id` | integer | **{dotted-circle}** No | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/reviews/index.md) 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 | **{dotted-circle}** No | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/reviews/index.md) 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 | **{dotted-circle}** No | Returns merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`. | | `search` | string | **{dotted-circle}** No | Search merge requests against their `title` and `description`. | | `sort` | string | **{dotted-circle}** No | Returns requests sorted in `asc` or `desc` order. Default is `desc`. | @@ -260,8 +260,8 @@ Supported attributes: | `my_reaction_emoji` | string | **{dotted-circle}** No | Returns 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 | **{dotted-circle}** No | Returns 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 | **{dotted-circle}** No | Returns 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 | **{dotted-circle}** 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 | **{dotted-circle}** 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. | +| `reviewer_id` | integer | **{dotted-circle}** No | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/reviews/index.md) 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 | **{dotted-circle}** No | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/reviews/index.md) 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 | **{dotted-circle}** No | Returns merge requests for the given scope: `created_by_me`, `assigned_to_me`, or `all`. | | `search` | string | **{dotted-circle}** No | Search merge requests against their `title` and `description`. | | `sort` | string | **{dotted-circle}** No | Returns requests sorted in `asc` or `desc` order. Default is `desc`. | @@ -449,8 +449,8 @@ Supported attributes: | `non_archived` | boolean | **{dotted-circle}** No | Returns merge requests from non archived projects only. Default is `true`. | | `not` | Hash | **{dotted-circle}** No | Returns 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 | **{dotted-circle}** No | Returns 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 | **{dotted-circle}** 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 | **{dotted-circle}** 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. | +| `reviewer_id` | integer | **{dotted-circle}** No | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/reviews/index.md) 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 | **{dotted-circle}** No | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/reviews/index.md) 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 | **{dotted-circle}** No | Returns merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`. | | `search` | string | **{dotted-circle}** No | Search merge requests against their `title` and `description`. | | `source_branch` | string | **{dotted-circle}** No | Returns merge requests with the given source branch. | diff --git a/doc/development/code_review.md b/doc/development/code_review.md index e194453565a..398f0c17bac 100644 --- a/doc/development/code_review.md +++ b/doc/development/code_review.md @@ -37,7 +37,7 @@ also to spread the workload. For assistance with security scans or comments, include the Application Security Team (`@gitlab-com/gl-security/appsec`). -The reviewers use the [reviewer functionality](../user/project/merge_requests/getting_started.md#reviewer) in the sidebar. +The reviewers use the [reviewer functionality](../user/project/merge_requests/reviews/index.md) in the sidebar. Reviewers can add their approval by [approving additionally](../user/project/merge_requests/approvals/index.md#approve-a-merge-request). Depending on the areas your merge request touches, it must be **approved** by one @@ -459,7 +459,7 @@ first time. ### Requesting a review When you are ready to have your merge request reviewed, -you should [request an initial review](../user/project/merge_requests/getting_started.md#reviewer) by selecting a reviewer based on the [approval guidelines](#approval-guidelines). +you should [request an initial review](../user/project/merge_requests/reviews/index.md) by selecting a reviewer based on the [approval guidelines](#approval-guidelines). When a merge request has multiple areas for review, it is recommended you specify which area a reviewer should be reviewing, and at which stage (first or second). This will help team members who qualify as a reviewer for multiple areas to know which area they're being requested to review. diff --git a/doc/development/database/avoiding_downtime_in_migrations.md b/doc/development/database/avoiding_downtime_in_migrations.md index a18e998f1d2..fc1f94cbc2c 100644 --- a/doc/development/database/avoiding_downtime_in_migrations.md +++ b/doc/development/database/avoiding_downtime_in_migrations.md @@ -451,10 +451,11 @@ to keep in sync both columns for any new records ([see an example](https://gitla ```ruby class InitializeConversionOfCiStagesToBigint < Gitlab::Database::Migration[2.1] - TABLE = :ci_stages COLUMNS = %i[id] + enable_lock_retries! + def up initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS) end @@ -475,19 +476,16 @@ module Ci end ``` -To migrate existing data, we introduced new type of _batched background migrations_. -Unlike the classic background migrations, built on top of Sidekiq, batched background migrations -don't have to enqueue and schedule all the background jobs at the beginning. -They also have other advantages, like automatic tuning of the batch size, better progress visibility, -and collecting metrics. To start the process, use the provided `backfill_conversion_of_integer_to_bigint` -helper ([example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/migrate/20210608072346_backfill_ci_stages_for_bigint_conversion.rb)): +Enqueue batched background migration ([another example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/migrate/20210608072346_backfill_ci_stages_for_bigint_conversion.rb)) +to migrate the existing data: ```ruby class BackfillCiStagesForBigintConversion < Gitlab::Database::Migration[2.1] - TABLE = :ci_stages COLUMNS = %i[id] + restrict_gitlab_migration gitlab_schema: :gitlab_ci + def up backfill_conversion_of_integer_to_bigint(TABLE, COLUMNS) end diff --git a/doc/gitlab-basics/feature_branch_workflow.md b/doc/gitlab-basics/feature_branch_workflow.md index 06d88cf14f6..ce4aa0007c6 100644 --- a/doc/gitlab-basics/feature_branch_workflow.md +++ b/doc/gitlab-basics/feature_branch_workflow.md @@ -7,19 +7,23 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/workflow.html' # Feature branch workflow **(FREE)** -1. Clone project: +To merge changes from a local branch to a feature branch, follow this workflow. + +1. Clone the project if you haven't already: ```shell git clone git@example.com:project-name.git ``` -1. Create branch with your feature: +1. Change directories so you are in the project directory. +1. Create a branch for your feature: ```shell git checkout -b feature_name ``` -1. Write code. Commit changes: +1. Write code for the feature. +1. Add the code to the staging area and add a commit message for your changes: ```shell git commit -am "My feature is ready" @@ -31,6 +35,6 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/workflow.html' git push origin feature_name ``` -1. Review your code on commits page. -1. Create a merge request. +1. Review your code: On the left sidebar, go to **Repository > Commits**. +1. [Create a merge request](../user/project/merge_requests/creating_merge_requests.md). 1. Your team lead reviews the code and merges it to the main branch. diff --git a/doc/topics/git/feature_branch_development.md b/doc/topics/git/feature_branch_development.md index d53c8eae835..4125d8e8fdb 100644 --- a/doc/topics/git/feature_branch_development.md +++ b/doc/topics/git/feature_branch_development.md @@ -1,108 +1,11 @@ --- -stage: Create -group: Source Code -info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments" -type: how-tos +redirect_to: 'index.md' +remove_date: '2023-03-31' --- -# Develop on a feature branch **(FREE)** +This document was moved to [another location](index.md). -GitLab values encourage the use of [Minimal Viable Change (MVC)](https://about.gitlab.com/handbook/values/#minimal-viable-change-mvc). -However, viable changes are not always small. In such cases, it can help to set up a dedicated feature branch. -People can contribute MRs to that feature branch, without affecting the functionality of the [default branch](../../user/project/repository/branches/default.md). - -Once work on the development branch is complete, then the feature branch can be finally merged into the default branch. - -GitLab frequently implements this process whenever there is an MVC that requires multiple MRs. - -## Use case: GitLab release posts - -This section describes the use case with GitLab [release posts](https://about.gitlab.com/handbook/marketing/blog/release-posts/). -Dozens of GitLab team members contribute to each monthly release post. -In such cases, it may be more efficient to submit an MR on the release post feature branch instead of the [default branch](../../user/project/repository/branches/default.md). - -In this case, the feature branch would be `release-X-Y`. Assuming the `release-X-Y` branch already exists, you can set up an MR against that branch, with the following steps: - -1. Navigate to the [default branch](../../user/project/repository/branches/default.md) (here, `main`): - - ```shell - git checkout main - ``` - -1. Make sure you have the latest version of your repository: - - ```shell - git fetch - git pull - ``` - -1. Check out the feature branch: - - ```shell - git checkout release-x-y - ``` - -1. Create a new branch (`test-branch`) against the feature branch (`release-x-y`): - - ```shell - git checkout -b test-branch release-x-y - ``` - - You should now be on a branch named `test-branch`. - -1. Make desired changes on the `test-branch`. -1. Add your changes, commit, and push to the `test-branch`: - - ```shell - git add . - ``` - -1. Commit your changes: - - ```shell - git commit -m "Some good reason" - ``` - -1. Push your changes to the repository: - - ```shell - git push --set-upstream origin test-branch - ``` - -1. Navigate to the URL for your repository. In this case, the repository is `www-gitlab-com`, available at `https://gitlab.com/gitlab-com/www-gitlab-com`. - - If needed, sign in to GitLab. You should then see an option to **Create merge request**: - - ![Create merge request](img/create_merge_request_v13_1.png) - -1. After you select **Create merge request**, an option to **Change branches** displays. Select that option. - -1. In the **New merge request** screen, you can now select the **Source** and **Target** branches. -In the screenshot shown, -we have selected `test-branch` as the source, and `release-13-0` as the target. - - ![Modify branches](img/modify_branches_v13_1.png) - -1. Once you've selected the Source and Target branches, select **Compare branches and continue**. - You should see an entry similar to: - - ```plaintext - New merge request - - From test-branch into release-13-0 - ``` - - An entry like this confirms your merge request's destination. - -1. Make any additional changes in the **New merge request** screen, and select **Create merge request**. -1. In the new merge request, look for **Request to merge**. An entry similar to this displays: - - ```plaintext - Request to merge test-branch into release-13-0 - ``` - - That confirms you've set up the MR to merge into the specified branch, not the [default branch](../../user/project/repository/branches/default.md). - -1. Proceed with the change as you would with any other MR. -1. When your MR is approved, and an appropriate user merges that MR, you can rest assured that your work is incorporated directly into the feature branch. -When the feature branch is ready, it can then be merged into the [default branch](../../user/project/repository/branches/default.md). +<!-- This redirect file can be deleted after <2023-03-31>. --> +<!-- Redirects that point to other docs in the same project expire in three months. --> +<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html --> diff --git a/doc/topics/git/img/create_merge_request_v13_1.png b/doc/topics/git/img/create_merge_request_v13_1.png Binary files differdeleted file mode 100644 index d59cfc74290..00000000000 --- a/doc/topics/git/img/create_merge_request_v13_1.png +++ /dev/null diff --git a/doc/topics/git/img/modify_branches_v13_1.png b/doc/topics/git/img/modify_branches_v13_1.png Binary files differdeleted file mode 100644 index 781f54fc3c0..00000000000 --- a/doc/topics/git/img/modify_branches_v13_1.png +++ /dev/null diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md index a5399b70c8f..53f19d544dc 100644 --- a/doc/user/project/issues/managing_issues.md +++ b/doc/user/project/issues/managing_issues.md @@ -218,7 +218,7 @@ description: - Issues `#4` and `#6` are closed automatically when the MR is merged. - Issue `#5` is marked as a [related issue](related_issues.md), but it's not closed automatically. -Alternatively, when you [create a merge request from an issue](../merge_requests/getting_started.md#merge-requests-to-close-issues), +Alternatively, when you [create a merge request from an issue](../merge_requests/creating_merge_requests.md#from-an-issue), it inherits the issue's milestone and labels. For performance reasons, automatic issue closing is disabled for the very first diff --git a/doc/user/project/merge_requests/approvals/settings.md b/doc/user/project/merge_requests/approvals/settings.md index a8acab3898b..bfc854b9f2c 100644 --- a/doc/user/project/merge_requests/approvals/settings.md +++ b/doc/user/project/merge_requests/approvals/settings.md @@ -121,13 +121,17 @@ permission enables an electronic signature for approvals, such as the one define ## Remove all approvals when commits are added to the source branch -By default, an approval on a merge request remains in place, even if you add more changes -after the approval. If you want to remove all existing approvals on a merge request -when more changes are added to it: +By default, an approval on a merge request is removed when you add more changes +after the approval. In GitLab Premium and higher tiers, to keep existing approvals +after more changes are added to the merge request: 1. On the left sidebar, select **Settings > Merge requests**. 1. In the **Merge request approvals** section, scroll to **Approval settings** and - select **Remove all approvals**. + clear the **Remove all approvals** checkbox. + + NOTE: + This setting is not available in GitLab Free. + 1. Select **Save changes**. Approvals aren't removed when a merge request is [rebased from the UI](../methods/index.md#rebasing-in-semi-linear-merge-methods) diff --git a/doc/user/project/merge_requests/getting_started.md b/doc/user/project/merge_requests/getting_started.md index 470c4ab9c2f..4125d8e8fdb 100644 --- a/doc/user/project/merge_requests/getting_started.md +++ b/doc/user/project/merge_requests/getting_started.md @@ -1,155 +1,11 @@ --- -stage: Create -group: Code Review -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments -description: "Getting started with merge requests." +redirect_to: 'index.md' +remove_date: '2023-03-31' --- -# Getting started with merge requests **(FREE)** +This document was moved to [another location](index.md). -A merge request (**MR**) is the basis of GitLab as a tool for code -collaboration and version control. - -When working in a Git-based platform, you can use branching -strategies to collaborate on code. - -A repository is composed by its _default branch_, which contains -the major version of the codebase, from which you create minor -branches, also called _feature branches_, to propose changes to -the codebase without introducing them directly into the major -version of the codebase. - -Branching is especially important when collaborating with others, -avoiding changes to be pushed directly to the default branch -without prior reviews, tests, and approvals. - -When you create a new feature branch, change the files, and push -it to GitLab, you have the option to create a **merge request**, -which is essentially a _request_ to merge one branch into another. - -The branch you added your changes into is called _source branch_ -while the branch you request to merge your changes into is -called _target branch_. - -The target branch can be the default or any other branch, depending -on the branching strategies you choose. - -In a merge request, beyond visualizing the differences between the -original content and your proposed changes, you can execute a -[significant number of tasks](#what-you-can-do-with-merge-requests) -before concluding your work and merging the merge request. - -You can watch our [GitLab Flow video](https://www.youtube.com/watch?v=InKNIvky2KE) for -a quick overview of working with merge requests. - -## What you can do with merge requests - -When you start a new merge request, you can immediately include the following -options. You can also add them later by either selecting **Edit** on the merge -request's page at the top-right side, or by using -[keyboard shortcuts for merge requests](../../shortcuts.md#merge-requests): - -- [Assign](index.md#assign-a-user-to-a-merge-request) the merge request to a colleague for review. With [multiple assignees](index.md#assign-multiple-users), you can assign it to more than one person at a time. -- Set a [milestone](../milestones/index.md) to track time-sensitive changes. -- Add [labels](../labels.md) to help contextualize and filter your merge requests over time. -- [Require approval](approvals/index.md#required-approvals) from your team. -- [Close issues automatically](#merge-requests-to-close-issues) when they are merged. -- Enable the [delete source branch when merge request is accepted](#deleting-the-source-branch) option to keep your repository clean. -- Enable the [squash commits when merge request is accepted](squash_and_merge.md) option to combine all the commits into one before merging, thus keep a clean commit history in your repository. -- Set the merge request as a [**Draft**](drafts.md) to avoid accidental merges before it is ready. - -After you have created the merge request, you can also: - -- [Discuss](../../discussions/index.md) your implementation with your team in the merge request thread. -- [Perform inline code reviews](reviews/index.md). -- Add [merge request dependencies](dependencies.md) to restrict it to be merged only when other merge requests have been merged. -- Preview continuous integration [pipelines on the merge request widget](widgets.md). -- Preview how your changes look directly on your deployed application with [Review Apps](widgets.md#live-preview-with-review-apps). -- [Allow collaboration on merge requests across forks](allow_collaboration.md). -- Perform a [Review](reviews/index.md) to create multiple comments on a diff and publish them when you're ready. -- Add [code suggestions](reviews/suggestions.md) to change the content of merge requests directly into merge request threads, and easily apply them to the codebase directly from the UI. -- Add a time estimation and the time spent with that merge request with [Time Tracking](../time_tracking.md#time-tracking). - -Many of these options can be set: - -- From the merge request page, with [keyboard shortcuts](../../shortcuts.md#merge-requests). -- When pushing changes from the command line, with [Git push options](../push_options.md). - -See also other [features associated to merge requests](reviews/index.md#associated-features). - -### Reviewer - -WARNING: -Requesting a code review is an important part of contributing code. However, deciding who should review -your code and asking for a review are no easy tasks. Using the "assignee" field for both authors and -reviewers makes it hard for others to determine who's doing what on a merge request. - -The merge request Reviewers feature enables you to request a review of your work, and -see the status of the review. Reviewers help distinguish the roles of the users -involved in the merge request. In comparison to an **Assignee**, who is directly -responsible for creating or merging a merge request, a **Reviewer** is a team member -who may only be involved in one aspect of the merge request, such as a peer review. - -To request a review of a merge request, expand the **Reviewers** select box in -the right-hand sidebar. Search for the users you want to request a review from. -When selected, GitLab creates a [to-do list item](../../todos.md) for each reviewer. - -To learn more, read [Review a merge request](reviews/index.md). - -#### Multiple reviewers for merge requests **(PREMIUM)** - -> Introduced in GitLab 13.7. - -Merge requests may often require multiple team members to review parts of the -proposed changes. You can add multiple reviewers to a merge request, making it -easier to see who is reviewing changes and who has approved changes. - -### Merge requests to close issues - -To create a merge request to close an issue when it's merged, you can either: - -- [Add a note in the MR description](../issues/managing_issues.md#closing-issues-automatically). -- In the issue, select **Create a merge request**. Then, you can either: - - - Create a new branch and [a draft merge request](../merge_requests/drafts.md) - in one action. The branch is named `issuenumber-title` by default, but you can - choose any name, and GitLab verifies that it's not already in use. The merge request - inherits the milestone and labels of the issue, and is set to automatically - close the issue when it is merged. - - Create a [new branch](creating_merge_requests.md#from-an-issue) - only, with its name starting with the issue number. - -If the issue is [confidential](../issues/confidential_issues.md), -you may want to use a different workflow for -[merge requests for confidential issues](confidential.md) -to prevent confidential information from being exposed. - -### Deleting the source branch - -When creating a merge request, select the -**Delete source branch when merge request accepted** option, and the source -branch is deleted when the merge request is merged. To make this option -enabled by default for all new merge requests, enable it in the -[project's settings](../settings/index.md#configure-merge-request-settings-for-a-project). - -This option is also visible in an existing merge request next to -the merge request button and can be selected or cleared before merging. -It is only visible to users with the Maintainer role -in the source project. - -If the user viewing the merge request does not have the correct -permissions to delete the source branch and the source branch -is set for deletion, the merge request widget displays the -**Deletes source branch** text. - -![Delete source branch status](img/remove_source_branch_status.png) - -## Recommendations and best practices for merge requests - -- When working locally in your branch, add multiple commits and only push when - you're done, so GitLab runs only one pipeline for all the commits pushed - at once. By doing so, you save CI/CD minutes. -- Delete feature branches on merge or after merging them to keep your repository clean. -- Take one thing at a time and ship the smallest changes possible. By doing so, - reviews are faster and your changes are less prone to errors. -- Do not use capital letters nor special chars in branch names. +<!-- This redirect file can be deleted after <2023-03-31>. --> +<!-- Redirects that point to other docs in the same project expire in three months. --> +<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html --> diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md index 6fcc696285d..2193440d3a2 100644 --- a/doc/user/project/merge_requests/index.md +++ b/doc/user/project/merge_requests/index.md @@ -7,8 +7,9 @@ type: index, reference # Merge requests **(FREE)** -Merge requests (MRs) are the way you check source code changes into a branch. -When you open a merge request, you can visualize and collaborate on the code changes before merge. +To incorporate changes from a source branch to a target branch, you use a *merge request* (MR). + +When you open a merge request, you can visualize and collaborate on the changes before merge. Merge requests include: - A description of the request. @@ -17,7 +18,9 @@ Merge requests include: - A comment section for discussion threads. - The list of commits. -Read more about [how to get started](getting_started.md). +<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> +For a quick overview of merge requests, +view [this GitLab Flow video](https://www.youtube.com/watch?v=InKNIvky2KE). ## Create a merge request @@ -205,6 +208,15 @@ To delete a merge request: 1. Go to the merge request you want to delete, and select **Edit**. 1. Scroll to the bottom of the page, and select **Delete merge request**. +### Delete the source branch on merge + +You can delete the source branch for a merge request: + +- When you create a merge request, by selecting **Delete source branch when merge request accepted**. +- When you merge a merge request, if you have the Maintainer role, by selecting **Delete source branch**. + +An administrator can make this option the default in the project's settings. + ### Update merge requests when target branch merges **(FREE SELF)** > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/320902) in GitLab 13.9. diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md index 39c14b333c2..ed4eea56514 100644 --- a/doc/user/project/settings/index.md +++ b/doc/user/project/settings/index.md @@ -158,7 +158,7 @@ Configure your project's merge request settings: - Enable [merge only if pipeline succeeds](../merge_requests/merge_when_pipeline_succeeds.md). - Enable [merge only when all threads are resolved](../../discussions/index.md#prevent-merge-unless-all-threads-are-resolved). - Enable [require an associated issue from Jira](../../../integration/jira/issues.md#require-associated-jira-issue-for-merge-requests-to-be-merged). -- Enable [`delete source branch after merge` option by default](../merge_requests/getting_started.md#deleting-the-source-branch). +- Enable [**Delete source branch when merge request is accepted** option by default](#delete-the-source-branch-on-merge-by-default). - Configure [suggested changes commit messages](../merge_requests/reviews/suggestions.md#configure-the-commit-message-for-applied-suggestions). - Configure [merge and squash commit message templates](../merge_requests/commit_templates.md). - Configure [the default target project](../merge_requests/creating_merge_requests.md#set-the-default-target-project) for merge requests coming from forks. @@ -230,6 +230,18 @@ To rename a repository: 1. In the **Change path** text box, edit the path. 1. Select **Change path**. +## Delete the source branch on merge by default + +In merge requests, you can change the default behavior so that the +**Delete the source branch** checkbox is always selected. + +To set this default: + +1. On the top bar, select **Main menu > Projects** and find your project. +1. On the left sidebar, select **Settings > Merge requests**. +1. Select **Enable "Delete source branch" option by default**. +1. Select **Save changes**. + ## Transfer a project to another namespace When you transfer a project to another namespace, you move the project to a different group. diff --git a/qa/Gemfile b/qa/Gemfile index af48b27f9eb..06bb6f6e6a1 100644 --- a/qa/Gemfile +++ b/qa/Gemfile @@ -38,7 +38,7 @@ gem 'chemlab', '~> 0.10' gem 'chemlab-library-www-gitlab-com', '~> 0.1', '>= 0.1.1' # dependencies for jenkins client -gem 'nokogiri', '~> 1.14' +gem 'nokogiri', '~> 1.14', '>= 1.14.1' gem 'deprecation_toolkit', '~> 2.0.1', require: false diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock index 717fbc4c133..ae98caecee6 100644 --- a/qa/Gemfile.lock +++ b/qa/Gemfile.lock @@ -180,7 +180,7 @@ GEM multi_json (1.15.0) multi_xml (0.6.0) netrc (0.11.0) - nokogiri (1.14.0) + nokogiri (1.14.1) mini_portile2 (~> 2.8.0) racc (~> 1.4) octokit (6.0.1) @@ -320,7 +320,7 @@ DEPENDENCIES gitlab-qa (~> 8, >= 8.15.2) influxdb-client (~> 2.9) knapsack (~> 4.0) - nokogiri (~> 1.14) + nokogiri (~> 1.14, >= 1.14.1) octokit (~> 6.0.1) parallel (~> 1.22, >= 1.22.1) parallel_tests (~> 4.1) @@ -342,4 +342,4 @@ DEPENDENCIES zeitwerk (~> 2.6, >= 2.6.6) BUNDLED WITH - 2.4.5 + 2.4.4 diff --git a/qa/qa/page/trials/new.rb b/qa/lib/gitlab/page/trials/new.rb index 40f593a7aa7..b2e6cbdb682 100644 --- a/qa/qa/page/trials/new.rb +++ b/qa/lib/gitlab/page/trials/new.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module QA +module Gitlab module Page module Trials class New < Chemlab::Page diff --git a/qa/qa/page/trials/select.rb b/qa/lib/gitlab/page/trials/select.rb index 39ef604a781..6eaf6003837 100644 --- a/qa/qa/page/trials/select.rb +++ b/qa/lib/gitlab/page/trials/select.rb @@ -1,16 +1,23 @@ # frozen_string_literal: true -module QA +module Gitlab module Page module Trials class Select < Chemlab::Page path '/-/trials/select' - select :subscription_for + button :select_group, 'data-testid': 'base-dropdown-toggle' + div :group_dropdown, 'data-testid': 'base-dropdown-menu' text_field :new_group_name button :start_your_free_trial radio :trial_company radio :trial_individual + + def subscription_for=(group_name) + select_group + + group_dropdown_element.span(text: /#{group_name}/).click + end end end end diff --git a/qa/qa/flow/trial.rb b/qa/qa/flow/trial.rb index 2fdd09d0d2d..109afeffaa3 100644 --- a/qa/qa/flow/trial.rb +++ b/qa/qa/flow/trial.rb @@ -13,8 +13,8 @@ module QA state: 'CA' }.freeze - def register_for_trial(skip_select: false) - Page::Trials::New.perform do |new| + def register_for_trial(group: nil) + Gitlab::Page::Trials::New.perform do |new| new.company_name = CUSTOMER_TRIAL_INFO[:company_name] new.number_of_employees = CUSTOMER_TRIAL_INFO[:number_of_employees] new.country = CUSTOMER_TRIAL_INFO[:country] @@ -24,10 +24,10 @@ module QA new.continue end - return if skip_select + return unless group - Page::Trials::Select.perform do |select| - select.subscription_for = group_for_trial.path + Gitlab::Page::Trials::Select.perform do |select| + select.subscription_for = group.path select.trial_company select.start_your_free_trial end diff --git a/qa/qa/page/group/menu.rb b/qa/qa/page/group/menu.rb index de065ca187d..9418593133e 100644 --- a/qa/qa/page/group/menu.rb +++ b/qa/qa/page/group/menu.rb @@ -44,6 +44,14 @@ module QA end end + def go_to_runners + hover_group_ci_cd do + within_submenu do + click_element(:sidebar_menu_item_link, menu_item: 'Runners') + end + end + end + def go_to_package_settings hover_group_settings do within_submenu do @@ -120,6 +128,14 @@ module QA end end + def hover_group_ci_cd + within_sidebar do + find_element(:sidebar_menu_link, menu_item: 'CI/CD').hover + + yield + end + end + def hover_group_packages within_sidebar do scroll_to_element(:sidebar_menu_link, menu_item: 'Packages and registries') diff --git a/qa/qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb new file mode 100644 index 00000000000..fba2f22b3e5 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Verify', :runner, product_group: :runner do + describe 'Group runner registration' do + let(:executor) { "qa-runner-#{Time.now.to_i}" } + + let!(:runner) do + Resource::GroupRunner.fabricate! do |runner| + runner.name = executor + end + end + + after do + runner.remove_via_api! + end + + it( + 'user registers a new group runner', + testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/388740' + ) do + Flow::Login.sign_in + + runner.group.visit! + + Page::Group::Menu.perform(&:go_to_runners) + + expect(page).to have_content(executor) + end + end + end +end diff --git a/spec/frontend/api/projects_api_spec.js b/spec/frontend/api/projects_api_spec.js index 649adfbcc56..0a6392bdc5b 100644 --- a/spec/frontend/api/projects_api_spec.js +++ b/spec/frontend/api/projects_api_spec.js @@ -39,7 +39,7 @@ describe('~/api/projects_api.js', () => { const expectedParams = { params: { per_page: 20, search: '', simple: true } }; const query = ''; - mock.onGet(expectedUrl).reply(200, { data: expectedProjects }); + mock.onGet(expectedUrl).reply(HTTP_STATUS_OK, { data: expectedProjects }); return projectsApi.getProjects(query, options).then(({ data }) => { expect(axios.get).toHaveBeenCalledWith(expectedUrl, expectedParams); @@ -50,7 +50,7 @@ describe('~/api/projects_api.js', () => { it('omits search param if query is undefined', () => { const expectedParams = { params: { per_page: 20, simple: true } }; - mock.onGet(expectedUrl).reply(200, { data: expectedProjects }); + mock.onGet(expectedUrl).reply(HTTP_STATUS_OK, { data: expectedProjects }); return projectsApi.getProjects(undefined, options).then(({ data }) => { expect(axios.get).toHaveBeenCalledWith(expectedUrl, expectedParams); @@ -64,7 +64,7 @@ describe('~/api/projects_api.js', () => { }; const query = 'group/project1'; - mock.onGet(expectedUrl).reply(200, { data: expectedProjects }); + mock.onGet(expectedUrl).reply(HTTP_STATUS_OK, { data: expectedProjects }); return projectsApi.getProjects(query, options).then(({ data }) => { expect(axios.get).toHaveBeenCalledWith(expectedUrl, expectedParams); diff --git a/spec/frontend/ci_secure_files/components/secure_files_list_spec.js b/spec/frontend/ci_secure_files/components/secure_files_list_spec.js index 5273aafbb04..ab6200ca6f4 100644 --- a/spec/frontend/ci_secure_files/components/secure_files_list_spec.js +++ b/spec/frontend/ci_secure_files/components/secure_files_list_spec.js @@ -2,6 +2,7 @@ import { GlLoadingIcon, GlModal } from '@gitlab/ui'; import MockAdapter from 'axios-mock-adapter'; import { mount } from '@vue/test-utils'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; import SecureFilesList from '~/ci_secure_files/components/secure_files_list.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; @@ -64,7 +65,7 @@ describe('SecureFilesList', () => { describe('when secure files exist in a project', () => { beforeEach(async () => { mock = new MockAdapter(axios); - mock.onGet(expectedUrl).reply(200, secureFiles); + mock.onGet(expectedUrl).reply(HTTP_STATUS_OK, secureFiles); createWrapper(); await waitForPromises(); @@ -116,7 +117,7 @@ describe('SecureFilesList', () => { describe('when no secure files exist in a project', () => { beforeEach(async () => { mock = new MockAdapter(axios); - mock.onGet(expectedUrl).reply(200, []); + mock.onGet(expectedUrl).reply(HTTP_STATUS_OK, []); createWrapper(); await waitForPromises(); @@ -137,7 +138,7 @@ describe('SecureFilesList', () => { describe('pagination', () => { it('displays the pagination component with there are more than 20 items', async () => { mock = new MockAdapter(axios); - mock.onGet(expectedUrl).reply(200, secureFiles, { 'x-total': 30 }); + mock.onGet(expectedUrl).reply(HTTP_STATUS_OK, secureFiles, { 'x-total': 30 }); createWrapper(); await waitForPromises(); @@ -147,7 +148,7 @@ describe('SecureFilesList', () => { it('does not display the pagination component with there are 20 items', async () => { mock = new MockAdapter(axios); - mock.onGet(expectedUrl).reply(200, secureFiles, { 'x-total': 20 }); + mock.onGet(expectedUrl).reply(HTTP_STATUS_OK, secureFiles, { 'x-total': 20 }); createWrapper(); await waitForPromises(); @@ -159,7 +160,7 @@ describe('SecureFilesList', () => { describe('loading state', () => { it('displays the loading icon while waiting for the backend request', () => { mock = new MockAdapter(axios); - mock.onGet(expectedUrl).reply(200, secureFiles); + mock.onGet(expectedUrl).reply(HTTP_STATUS_OK, secureFiles); createWrapper(); expect(findLoadingIcon().exists()).toBe(true); @@ -167,7 +168,7 @@ describe('SecureFilesList', () => { it('does not display the loading icon after the backend request has completed', async () => { mock = new MockAdapter(axios); - mock.onGet(expectedUrl).reply(200, secureFiles); + mock.onGet(expectedUrl).reply(HTTP_STATUS_OK, secureFiles); createWrapper(); await waitForPromises(); @@ -180,7 +181,7 @@ describe('SecureFilesList', () => { describe('with admin permissions', () => { beforeEach(async () => { mock = new MockAdapter(axios); - mock.onGet(expectedUrl).reply(200, secureFiles); + mock.onGet(expectedUrl).reply(HTTP_STATUS_OK, secureFiles); createWrapper(); await waitForPromises(); @@ -198,7 +199,7 @@ describe('SecureFilesList', () => { describe('without admin permissions', () => { beforeEach(async () => { mock = new MockAdapter(axios); - mock.onGet(expectedUrl).reply(200, secureFiles); + mock.onGet(expectedUrl).reply(HTTP_STATUS_OK, secureFiles); createWrapper(false); await waitForPromises(); diff --git a/spec/frontend/clusters_list/store/actions_spec.js b/spec/frontend/clusters_list/store/actions_spec.js index 8e03f8105c2..360fd3b2842 100644 --- a/spec/frontend/clusters_list/store/actions_spec.js +++ b/spec/frontend/clusters_list/store/actions_spec.js @@ -7,7 +7,7 @@ import * as actions from '~/clusters_list/store/actions'; import * as types from '~/clusters_list/store/mutation_types'; import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; -import { HTTP_STATUS_BAD_REQUEST } from '~/lib/utils/http_status'; +import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_OK } from '~/lib/utils/http_status'; import Poll from '~/lib/utils/poll'; import { apiData } from '../mock_data'; @@ -66,7 +66,7 @@ describe('Clusters store actions', () => { afterEach(() => mock.restore()); it('should commit SET_CLUSTERS_DATA with received response', () => { - mock.onGet().reply(200, apiData, headers); + mock.onGet().reply(HTTP_STATUS_OK, apiData, headers); return testAction( actions.fetchClusters, @@ -119,7 +119,7 @@ describe('Clusters store actions', () => { pollRequest = jest.spyOn(Poll.prototype, 'makeRequest'); pollStop = jest.spyOn(Poll.prototype, 'stop'); - mock.onGet().reply(200, apiData, pollHeaders); + mock.onGet().reply(HTTP_STATUS_OK, apiData, pollHeaders); }); afterEach(() => { @@ -172,7 +172,7 @@ describe('Clusters store actions', () => { it('should stop polling and report to Sentry when data is invalid', async () => { const badApiResponse = { clusters: {} }; - mock.onGet().reply(200, badApiResponse, pollHeaders); + mock.onGet().reply(HTTP_STATUS_OK, badApiResponse, pollHeaders); await testAction( actions.fetchClusters, diff --git a/spec/frontend/commit/pipelines/pipelines_table_spec.js b/spec/frontend/commit/pipelines/pipelines_table_spec.js index 6ad1c308b01..4bffb6a0fd3 100644 --- a/spec/frontend/commit/pipelines/pipelines_table_spec.js +++ b/spec/frontend/commit/pipelines/pipelines_table_spec.js @@ -10,6 +10,7 @@ import PipelinesTable from '~/commit/pipelines/pipelines_table.vue'; import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_INTERNAL_SERVER_ERROR, + HTTP_STATUS_OK, HTTP_STATUS_UNAUTHORIZED, } from '~/lib/utils/http_status'; import { createAlert } from '~/flash'; @@ -69,7 +70,7 @@ describe('Pipelines table in Commits and Merge requests', () => { describe('successful request', () => { describe('without pipelines', () => { beforeEach(async () => { - mock.onGet('endpoint.json').reply(200, []); + mock.onGet('endpoint.json').reply(HTTP_STATUS_OK, []); createComponent(); @@ -96,7 +97,7 @@ describe('Pipelines table in Commits and Merge requests', () => { describe('with pipelines', () => { beforeEach(async () => { - mock.onGet('endpoint.json').reply(200, [pipeline], { 'x-total': 10 }); + mock.onGet('endpoint.json').reply(HTTP_STATUS_OK, [pipeline], { 'x-total': 10 }); createComponent(); @@ -168,7 +169,7 @@ describe('Pipelines table in Commits and Merge requests', () => { pipelineCopy.flags.detached_merge_request_pipeline = true; pipelineCopy.flags.merge_request_pipeline = true; - mock.onGet('endpoint.json').reply(200, [pipelineCopy]); + mock.onGet('endpoint.json').reply(HTTP_STATUS_OK, [pipelineCopy]); createComponent(); @@ -184,7 +185,7 @@ describe('Pipelines table in Commits and Merge requests', () => { pipelineCopy.flags.detached_merge_request_pipeline = false; pipelineCopy.flags.merge_request_pipeline = false; - mock.onGet('endpoint.json').reply(200, [pipelineCopy]); + mock.onGet('endpoint.json').reply(HTTP_STATUS_OK, [pipelineCopy]); createComponent(); @@ -199,7 +200,7 @@ describe('Pipelines table in Commits and Merge requests', () => { beforeEach(async () => { pipelineCopy.flags.detached_merge_request_pipeline = true; - mock.onGet('endpoint.json').reply(200, [pipelineCopy]); + mock.onGet('endpoint.json').reply(HTTP_STATUS_OK, [pipelineCopy]); createComponent({ canRunPipeline: true, @@ -277,7 +278,7 @@ describe('Pipelines table in Commits and Merge requests', () => { beforeEach(async () => { pipelineCopy.flags.detached_merge_request_pipeline = true; - mock.onGet('endpoint.json').reply(200, [pipelineCopy]); + mock.onGet('endpoint.json').reply(HTTP_STATUS_OK, [pipelineCopy]); createComponent({ projectId: '5', @@ -309,7 +310,7 @@ describe('Pipelines table in Commits and Merge requests', () => { describe('when no pipelines were created on a forked merge request', () => { beforeEach(async () => { - mock.onGet('endpoint.json').reply(200, []); + mock.onGet('endpoint.json').reply(HTTP_STATUS_OK, []); createComponent({ projectId: '5', diff --git a/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js b/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js index bd4ed950f9d..7d9ae548c9a 100644 --- a/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js +++ b/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js @@ -4,6 +4,7 @@ import MockAdapter from 'axios-mock-adapter'; import { TEST_HOST } from 'helpers/test_constants'; import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; describe('custom metrics form fields component', () => { let wrapper; @@ -46,7 +47,7 @@ describe('custom metrics form fields component', () => { }); it('checks form validity', async () => { - mockAxios.onPost(validateQueryPath).reply(200, validQueryResponse); + mockAxios.onPost(validateQueryPath).reply(HTTP_STATUS_OK, validQueryResponse); mountComponent({ metricPersisted: true, ...makeFormData({ @@ -143,7 +144,7 @@ describe('custom metrics form fields component', () => { describe('when query validation is in flight', () => { beforeEach(() => { mountComponent({ metricPersisted: true, ...makeFormData({ query: 'validQuery' }) }); - mockAxios.onPost(validateQueryPath).reply(200, validQueryResponse); + mockAxios.onPost(validateQueryPath).reply(HTTP_STATUS_OK, validQueryResponse); }); it('expect loading message to display', async () => { @@ -168,7 +169,7 @@ describe('custom metrics form fields component', () => { const invalidQueryResponse = { success: true, query: { valid: false, error: errorMessage } }; beforeEach(() => { - mockAxios.onPost(validateQueryPath).reply(200, invalidQueryResponse); + mockAxios.onPost(validateQueryPath).reply(HTTP_STATUS_OK, invalidQueryResponse); mountComponent({ metricPersisted: true, ...makeFormData({ query: 'invalidQuery' }) }); return axios.waitForAll(); }); @@ -180,7 +181,7 @@ describe('custom metrics form fields component', () => { describe('when query is valid', () => { beforeEach(() => { - mockAxios.onPost(validateQueryPath).reply(200, validQueryResponse); + mockAxios.onPost(validateQueryPath).reply(HTTP_STATUS_OK, validQueryResponse); mountComponent({ metricPersisted: true, ...makeFormData({ query: 'validQuery' }) }); }); diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js index eca56325366..4e6ddd89a55 100644 --- a/spec/frontend/groups/components/app_spec.js +++ b/spec/frontend/groups/components/app_spec.js @@ -15,6 +15,7 @@ import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_FORBIDDEN, HTTP_STATUS_INTERNAL_SERVER_ERROR, + HTTP_STATUS_OK, } from '~/lib/utils/http_status'; import * as urlUtilities from '~/lib/utils/url_utility'; import setWindowLocation from 'helpers/set_window_location_helper'; @@ -71,7 +72,7 @@ describe('AppComponent', () => { beforeEach(async () => { mock = new AxiosMockAdapter(axios); - mock.onGet('/dashboard/groups.json').reply(200, mockGroups); + mock.onGet('/dashboard/groups.json').reply(HTTP_STATUS_OK, mockGroups); Vue.component('GroupFolder', groupFolderComponent); Vue.component('GroupItem', groupItemComponent); setWindowLocation('?filter=foobar'); @@ -106,7 +107,7 @@ describe('AppComponent', () => { }); it('should set headers to store for building pagination info when called with `updatePagination`', () => { - mock.onGet('/dashboard/groups.json').reply(200, { headers: mockRawPageInfo }); + mock.onGet('/dashboard/groups.json').reply(HTTP_STATUS_OK, { headers: mockRawPageInfo }); jest.spyOn(vm, 'updatePagination').mockImplementation(() => {}); @@ -150,7 +151,7 @@ describe('AppComponent', () => { }); it('should fetch matching set of groups when app is loaded with search query', () => { - mock.onGet('/dashboard/groups.json').reply(200, mockSearchedGroups); + mock.onGet('/dashboard/groups.json').reply(HTTP_STATUS_OK, mockSearchedGroups); const fetchPromise = vm.fetchAllGroups(); @@ -221,7 +222,7 @@ describe('AppComponent', () => { }); it('should fetch children of given group and expand it if group is collapsed and children are not loaded', () => { - mock.onGet('/dashboard/groups.json').reply(200, mockRawChildren); + mock.onGet('/dashboard/groups.json').reply(HTTP_STATUS_OK, mockRawChildren); jest.spyOn(vm, 'fetchGroups'); jest.spyOn(vm.store, 'setGroupChildren').mockImplementation(() => {}); diff --git a/spec/frontend/ide/services/index_spec.js b/spec/frontend/ide/services/index_spec.js index cf373ed46de..623dee387e5 100644 --- a/spec/frontend/ide/services/index_spec.js +++ b/spec/frontend/ide/services/index_spec.js @@ -109,7 +109,7 @@ describe('IDE services', () => { }; mock = new MockAdapter(axios); - mock.onGet(file.rawPath).reply(200, 'raw content'); + mock.onGet(file.rawPath).reply(HTTP_STATUS_OK, 'raw content'); jest.spyOn(axios, 'get'); }); @@ -206,7 +206,7 @@ describe('IDE services', () => { filePath, )}`, ) - .reply(200, TEST_FILE_CONTENTS); + .reply(HTTP_STATUS_OK, TEST_FILE_CONTENTS); }); it('fetches file content', () => @@ -231,7 +231,7 @@ describe('IDE services', () => { mock .onGet(`${TEST_RELATIVE_URL_ROOT}/${TEST_PROJECT_ID}/-/files/${TEST_COMMIT_SHA}`) - .reply(200, [TEST_FILE_PATH]); + .reply(HTTP_STATUS_OK, [TEST_FILE_PATH]); }); afterEach(() => { diff --git a/spec/frontend/ide/stores/actions/merge_request_spec.js b/spec/frontend/ide/stores/actions/merge_request_spec.js index f1b2a7b881a..fbae84631ee 100644 --- a/spec/frontend/ide/stores/actions/merge_request_spec.js +++ b/spec/frontend/ide/stores/actions/merge_request_spec.js @@ -16,6 +16,7 @@ import { } from '~/ide/stores/actions/merge_request'; import * as types from '~/ide/stores/mutation_types'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; const TEST_PROJECT = 'abcproject'; const TEST_PROJECT_ID = 17; @@ -63,7 +64,9 @@ describe('IDE store merge request actions', () => { describe('base case', () => { beforeEach(() => { jest.spyOn(service, 'getProjectMergeRequests'); - mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests/).reply(200, mockData); + mock + .onGet(/api\/(.*)\/projects\/abcproject\/merge_requests/) + .reply(HTTP_STATUS_OK, mockData); }); it('calls getProjectMergeRequests service method', async () => { @@ -113,7 +116,7 @@ describe('IDE store merge request actions', () => { describe('no merge requests for branch available case', () => { beforeEach(() => { jest.spyOn(service, 'getProjectMergeRequests'); - mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests/).reply(200, []); + mock.onGet(/api\/(.*)\/projects\/abcproject\/merge_requests/).reply(HTTP_STATUS_OK, []); }); it('does not fail if there are no merge requests for current branch', async () => { @@ -155,7 +158,7 @@ describe('IDE store merge request actions', () => { mock .onGet(/api\/(.*)\/projects\/abcproject\/merge_requests\/1/) - .reply(200, { title: 'mergerequest' }); + .reply(HTTP_STATUS_OK, { title: 'mergerequest' }); }); it('calls getProjectMergeRequestData service method', async () => { @@ -212,7 +215,7 @@ describe('IDE store merge request actions', () => { mock .onGet(/api\/(.*)\/projects\/abcproject\/merge_requests\/1\/changes/) - .reply(200, { title: 'mergerequest' }); + .reply(HTTP_STATUS_OK, { title: 'mergerequest' }); }); it('calls getProjectMergeRequestChanges service method', async () => { @@ -276,7 +279,7 @@ describe('IDE store merge request actions', () => { beforeEach(() => { mock .onGet(/api\/(.*)\/projects\/abcproject\/merge_requests\/1\/versions/) - .reply(200, [{ id: 789 }]); + .reply(HTTP_STATUS_OK, [{ id: 789 }]); jest.spyOn(service, 'getProjectMergeRequestVersions'); }); diff --git a/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js b/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js index f541e579810..8d8afda7014 100644 --- a/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js +++ b/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js @@ -15,6 +15,7 @@ import { HTTP_STATUS_FORBIDDEN, HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_NOT_FOUND, + HTTP_STATUS_OK, HTTP_STATUS_UNPROCESSABLE_ENTITY, } from '~/lib/utils/http_status'; @@ -131,7 +132,7 @@ describe('IDE store terminal check actions', () => { describe('fetchConfigCheck', () => { it('dispatches request and receive', () => { - mock.onPost(/.*\/ide_terminals\/check_config/).reply(200, {}); + mock.onPost(/.*\/ide_terminals\/check_config/).reply(HTTP_STATUS_OK, {}); return testAction( actions.fetchConfigCheck, @@ -254,7 +255,9 @@ describe('IDE store terminal check actions', () => { describe('fetchRunnersCheck', () => { it('dispatches request and receive', () => { - mock.onGet(/api\/.*\/projects\/.*\/runners/, { params: { scope: 'active' } }).reply(200, []); + mock + .onGet(/api\/.*\/projects\/.*\/runners/, { params: { scope: 'active' } }) + .reply(HTTP_STATUS_OK, []); return testAction( actions.fetchRunnersCheck, @@ -266,7 +269,9 @@ describe('IDE store terminal check actions', () => { }); it('does not dispatch request when background is true', () => { - mock.onGet(/api\/.*\/projects\/.*\/runners/, { params: { scope: 'active' } }).reply(200, []); + mock + .onGet(/api\/.*\/projects\/.*\/runners/, { params: { scope: 'active' } }) + .reply(HTTP_STATUS_OK, []); return testAction( actions.fetchRunnersCheck, diff --git a/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js b/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js index 3bc51e5840c..0287e5269ee 100644 --- a/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js +++ b/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js @@ -9,6 +9,7 @@ import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_NOT_FOUND, + HTTP_STATUS_OK, HTTP_STATUS_UNPROCESSABLE_ENTITY, } from '~/lib/utils/http_status'; @@ -115,7 +116,7 @@ describe('IDE store terminal session controls actions', () => { }); it('dispatches request and receive on success', () => { - mock.onPost(/.*\/ide_terminals/).reply(200, TEST_SESSION); + mock.onPost(/.*\/ide_terminals/).reply(HTTP_STATUS_OK, TEST_SESSION); return testAction( actions.startSession, @@ -179,7 +180,7 @@ describe('IDE store terminal session controls actions', () => { describe('stopSession', () => { it('dispatches request and receive on success', () => { - mock.onPost(TEST_SESSION.cancel_path).reply(200, {}); + mock.onPost(TEST_SESSION.cancel_path).reply(HTTP_STATUS_OK, {}); const state = { session: { cancelPath: TEST_SESSION.cancel_path }, @@ -258,7 +259,7 @@ describe('IDE store terminal session controls actions', () => { it('dispatches request and receive on success', () => { mock .onPost(state.session.retryPath, { branch: rootState.currentBranchId, format: 'json' }) - .reply(200, TEST_SESSION); + .reply(HTTP_STATUS_OK, TEST_SESSION); return testAction( actions.restartSession, diff --git a/spec/frontend/import_entities/import_projects/store/actions_spec.js b/spec/frontend/import_entities/import_projects/store/actions_spec.js index e50e3bb3de9..990587d4af7 100644 --- a/spec/frontend/import_entities/import_projects/store/actions_spec.js +++ b/spec/frontend/import_entities/import_projects/store/actions_spec.js @@ -98,7 +98,7 @@ describe('import_projects store actions', () => { describe('with a successful request', () => { it('commits REQUEST_REPOS, SET_PAGE, RECEIVE_REPOS_SUCCESS mutations', () => { - mock.onGet(MOCK_ENDPOINT).reply(200, payload); + mock.onGet(MOCK_ENDPOINT).reply(HTTP_STATUS_OK, payload); return testAction( fetchRepos, @@ -122,7 +122,7 @@ describe('import_projects store actions', () => { }); it('commits SET_PAGE_CURSORS instead of SET_PAGE', () => { - mock.onGet(MOCK_ENDPOINT).reply(200, payload); + mock.onGet(MOCK_ENDPOINT).reply(HTTP_STATUS_OK, payload); return testAction( fetchRepos, @@ -162,7 +162,7 @@ describe('import_projects store actions', () => { let requestedUrl; mock.onGet().reply((config) => { requestedUrl = config.url; - return [200, payload]; + return [HTTP_STATUS_OK, payload]; }); const localStateWithPage = { ...localState, pageInfo: { page: 2 } }; @@ -187,7 +187,7 @@ describe('import_projects store actions', () => { let requestedUrl; mock.onGet().reply((config) => { requestedUrl = config.url; - return [200, payload]; + return [HTTP_STATUS_OK, payload]; }); const localStateWithPage = { ...localState, pageInfo: { endCursor: 'endTest' } }; @@ -238,7 +238,7 @@ describe('import_projects store actions', () => { describe('when filtered', () => { it('fetches repos with filter applied', () => { - mock.onGet(`${TEST_HOST}/endpoint.json?filter=filter`).reply(200, payload); + mock.onGet(`${TEST_HOST}/endpoint.json?filter=filter`).reply(HTTP_STATUS_OK, payload); return testAction( fetchRepos, @@ -269,7 +269,7 @@ describe('import_projects store actions', () => { it('commits REQUEST_IMPORT and REQUEST_IMPORT_SUCCESS mutations on a successful request', () => { const importedProject = { name: 'imported/project' }; - mock.onPost(MOCK_ENDPOINT).reply(200, importedProject); + mock.onPost(MOCK_ENDPOINT).reply(HTTP_STATUS_OK, importedProject); return testAction( fetchImport, @@ -356,7 +356,7 @@ describe('import_projects store actions', () => { afterEach(() => mock.restore()); it('commits RECEIVE_JOBS_SUCCESS mutation on a successful request', async () => { - mock.onGet(MOCK_ENDPOINT).reply(200, updatedProjects); + mock.onGet(MOCK_ENDPOINT).reply(HTTP_STATUS_OK, updatedProjects); await testAction( fetchJobs, @@ -378,7 +378,9 @@ describe('import_projects store actions', () => { }); it('fetches realtime changes with filter applied', () => { - mock.onGet(`${TEST_HOST}/endpoint.json?filter=filter`).reply(200, updatedProjects); + mock + .onGet(`${TEST_HOST}/endpoint.json?filter=filter`) + .reply(HTTP_STATUS_OK, updatedProjects); return testAction( fetchJobs, diff --git a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js index 313bc464f11..96c0b87e2cb 100644 --- a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js +++ b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js @@ -9,7 +9,11 @@ import { } from 'jest/issuable/components/related_issuable_mock_data'; import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; -import { HTTP_STATUS_CONFLICT, HTTP_STATUS_UNPROCESSABLE_ENTITY } from '~/lib/utils/http_status'; +import { + HTTP_STATUS_CONFLICT, + HTTP_STATUS_OK, + HTTP_STATUS_UNPROCESSABLE_ENTITY, +} from '~/lib/utils/http_status'; import { linkedIssueTypesMap } from '~/related_issues/constants'; import RelatedIssuesBlock from '~/related_issues/components/related_issues_block.vue'; import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue'; @@ -25,7 +29,7 @@ describe('RelatedIssuesRoot', () => { beforeEach(() => { mock = new MockAdapter(axios); - mock.onGet(defaultProps.endpoint).reply(200, []); + mock.onGet(defaultProps.endpoint).reply(HTTP_STATUS_OK, []); }); afterEach(() => { @@ -60,7 +64,7 @@ describe('RelatedIssuesRoot', () => { }); it('removes related issue on API success', async () => { - mock.onDelete(issuable1.referencePath).reply(200, { issues: [] }); + mock.onDelete(issuable1.referencePath).reply(HTTP_STATUS_OK, { issues: [] }); findRelatedIssuesBlock().vm.$emit('relatedIssueRemoveRequest', issuable1.id); await axios.waitForAll(); @@ -164,7 +168,7 @@ describe('RelatedIssuesRoot', () => { }); it('submits pending issue as related issue', async () => { - mock.onPost(defaultProps.endpoint).reply(200, { + mock.onPost(defaultProps.endpoint).reply(HTTP_STATUS_OK, { issuables: [issuable1], result: { message: 'something was successfully related', @@ -183,7 +187,7 @@ describe('RelatedIssuesRoot', () => { }); it('submits multiple pending issues as related issues', async () => { - mock.onPost(defaultProps.endpoint).reply(200, { + mock.onPost(defaultProps.endpoint).reply(HTTP_STATUS_OK, { issuables: [issuable1, issuable2], result: { message: 'something was successfully related', diff --git a/spec/frontend/lib/utils/ajax_cache_spec.js b/spec/frontend/lib/utils/ajax_cache_spec.js index d4b95172d18..338302642ff 100644 --- a/spec/frontend/lib/utils/ajax_cache_spec.js +++ b/spec/frontend/lib/utils/ajax_cache_spec.js @@ -1,6 +1,7 @@ import MockAdapter from 'axios-mock-adapter'; import AjaxCache from '~/lib/utils/ajax_cache'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; describe('AjaxCache', () => { const dummyEndpoint = '/AjaxCache/dummyEndpoint'; @@ -102,7 +103,7 @@ describe('AjaxCache', () => { }); it('stores and returns data from Ajax call if cache is empty', () => { - mock.onGet(dummyEndpoint).reply(200, dummyResponse); + mock.onGet(dummyEndpoint).reply(HTTP_STATUS_OK, dummyResponse); return AjaxCache.retrieve(dummyEndpoint).then((data) => { expect(data).toEqual(dummyResponse); @@ -111,7 +112,7 @@ describe('AjaxCache', () => { }); it('makes no Ajax call if request is pending', () => { - mock.onGet(dummyEndpoint).reply(200, dummyResponse); + mock.onGet(dummyEndpoint).reply(HTTP_STATUS_OK, dummyResponse); return Promise.all([ AjaxCache.retrieve(dummyEndpoint), @@ -148,7 +149,7 @@ describe('AjaxCache', () => { AjaxCache.internalStorage[dummyEndpoint] = oldDummyResponse; - mock.onGet(dummyEndpoint).reply(200, dummyResponse); + mock.onGet(dummyEndpoint).reply(HTTP_STATUS_OK, dummyResponse); return Promise.all([ AjaxCache.retrieve(dummyEndpoint), diff --git a/spec/frontend/merge_conflicts/store/actions_spec.js b/spec/frontend/merge_conflicts/store/actions_spec.js index 4399436b2c5..19ef4b7db25 100644 --- a/spec/frontend/merge_conflicts/store/actions_spec.js +++ b/spec/frontend/merge_conflicts/store/actions_spec.js @@ -1,7 +1,7 @@ import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; import Cookies from '~/lib/utils/cookies'; -import { HTTP_STATUS_BAD_REQUEST } from '~/lib/utils/http_status'; +import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_OK } from '~/lib/utils/http_status'; import { useMockLocationHelper } from 'helpers/mock_window_location_helper'; import testAction from 'helpers/vuex_action_helper'; import { createAlert } from '~/flash'; @@ -36,7 +36,7 @@ describe('merge conflicts actions', () => { const conflictsPath = 'conflicts/path/mock'; it('on success dispatches setConflictsData', () => { - mock.onGet(conflictsPath).reply(200, {}); + mock.onGet(conflictsPath).reply(HTTP_STATUS_OK, {}); return testAction( actions.fetchConflictsData, conflictsPath, @@ -50,7 +50,7 @@ describe('merge conflicts actions', () => { }); it('when data has type equal to error', () => { - mock.onGet(conflictsPath).reply(200, { type: 'error', message: 'error message' }); + mock.onGet(conflictsPath).reply(HTTP_STATUS_OK, { type: 'error', message: 'error message' }); return testAction( actions.fetchConflictsData, conflictsPath, @@ -103,7 +103,7 @@ describe('merge conflicts actions', () => { const resolveConflictsPath = 'resolve/conflicts/path/mock'; it('on success reloads the page', async () => { - mock.onPost(resolveConflictsPath).reply(200, { redirect_to: 'hrefPath' }); + mock.onPost(resolveConflictsPath).reply(HTTP_STATUS_OK, { redirect_to: 'hrefPath' }); await testAction( actions.submitResolvedConflicts, resolveConflictsPath, diff --git a/spec/frontend/monitoring/store/actions_spec.js b/spec/frontend/monitoring/store/actions_spec.js index 598cd61eb5c..8eda46a2ff1 100644 --- a/spec/frontend/monitoring/store/actions_spec.js +++ b/spec/frontend/monitoring/store/actions_spec.js @@ -206,7 +206,7 @@ describe('Monitoring store actions', () => { it('on success, dispatches receive and success actions, then fetches dashboard warnings', () => { document.body.dataset.page = 'projects:environments:metrics'; - mock.onGet(state.dashboardEndpoint).reply(200, response); + mock.onGet(state.dashboardEndpoint).reply(HTTP_STATUS_OK, response); return testAction( fetchDashboard, @@ -420,7 +420,7 @@ describe('Monitoring store actions', () => { }); it('commits result', () => { - mock.onGet(prometheusEndpointPath).reply(200, { data }); // One attempt + mock.onGet(prometheusEndpointPath).reply(HTTP_STATUS_OK, { data }); // One attempt return testAction( fetchPrometheusMetric, @@ -453,7 +453,7 @@ describe('Monitoring store actions', () => { }; it('uses calculated step', async () => { - mock.onGet(prometheusEndpointPath).reply(200, { data }); // One attempt + mock.onGet(prometheusEndpointPath).reply(HTTP_STATUS_OK, { data }); // One attempt await testAction( fetchPrometheusMetric, @@ -492,7 +492,7 @@ describe('Monitoring store actions', () => { }; it('uses metric step', async () => { - mock.onGet(prometheusEndpointPath).reply(200, { data }); // One attempt + mock.onGet(prometheusEndpointPath).reply(HTTP_STATUS_OK, { data }); // One attempt await testAction( fetchPrometheusMetric, @@ -555,7 +555,7 @@ describe('Monitoring store actions', () => { describe('fetchDeploymentsData', () => { it('dispatches receiveDeploymentsDataSuccess on success', () => { state.deploymentsEndpoint = '/success'; - mock.onGet(state.deploymentsEndpoint).reply(200, { + mock.onGet(state.deploymentsEndpoint).reply(HTTP_STATUS_OK, { deployments: deploymentData, }); @@ -1068,7 +1068,7 @@ describe('Monitoring store actions', () => { }, ]; - mock.onGet('/series?match[]=metric_name').reply(200, { + mock.onGet('/series?match[]=metric_name').reply(HTTP_STATUS_OK, { status: 'success', data, }); diff --git a/spec/frontend/notes/deprecated_notes_spec.js b/spec/frontend/notes/deprecated_notes_spec.js index f52c3e28691..4756a107a15 100644 --- a/spec/frontend/notes/deprecated_notes_spec.js +++ b/spec/frontend/notes/deprecated_notes_spec.js @@ -7,6 +7,7 @@ import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; import { TEST_HOST } from 'helpers/test_constants'; import waitForPromises from 'helpers/wait_for_promises'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; import * as urlUtility from '~/lib/utils/url_utility'; // These must be imported synchronously because they pull dependencies @@ -75,7 +76,7 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => { describe('task lists', () => { beforeEach(() => { - mockAxios.onAny().reply(200, {}); + mockAxios.onAny().reply(HTTP_STATUS_OK, {}); new Notes('', []); }); @@ -181,7 +182,7 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => { const $form = $('form.js-main-target-form'); $form.find('textarea.js-note-text').val(sampleComment); - mockAxios.onPost(NOTES_POST_PATH).reply(200, noteEntity); + mockAxios.onPost(NOTES_POST_PATH).reply(HTTP_STATUS_OK, noteEntity); }); it('updates note and resets edit form', () => { @@ -546,7 +547,7 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => { let $notesContainer; function mockNotesPost() { - mockAxios.onPost(NOTES_POST_PATH).reply(200, note); + mockAxios.onPost(NOTES_POST_PATH).reply(HTTP_STATUS_OK, note); } function mockNotesPostError() { @@ -591,7 +592,7 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => { }; mockAxios.onPost(NOTES_POST_PATH).replyOnce(() => { expect($submitButton).toBeDisabled(); - return [200, note]; + return [HTTP_STATUS_OK, note]; }); await notes.postComment(dummyEvent); @@ -650,7 +651,7 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => { beforeEach(() => { loadHTMLFixture('commit/show.html'); - mockAxios.onPost(NOTES_POST_PATH).reply(200, note); + mockAxios.onPost(NOTES_POST_PATH).reply(HTTP_STATUS_OK, note); new Notes('', []); window.gon.current_username = 'root'; @@ -695,7 +696,7 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => { note: sampleComment, valid: true, }; - mockAxios.onPost(NOTES_POST_PATH).reply(200, note); + mockAxios.onPost(NOTES_POST_PATH).reply(HTTP_STATUS_OK, note); new Notes('', []); $form = $('form.js-main-target-form'); @@ -730,7 +731,7 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => { let $notesContainer; beforeEach(() => { - mockAxios.onPost(NOTES_POST_PATH).reply(200, note); + mockAxios.onPost(NOTES_POST_PATH).reply(HTTP_STATUS_OK, note); new Notes('', []); window.gon.current_username = 'root'; diff --git a/spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js b/spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js index 1a157beebe4..da3954b4918 100644 --- a/spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js +++ b/spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js @@ -2,6 +2,7 @@ import { GlEmptyState, GlLoadingIcon, GlTableLite } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; import PaginationBar from '~/vue_shared/components/pagination_bar/pagination_bar.vue'; import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; import BulkImportsHistoryApp from '~/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue'; @@ -78,7 +79,7 @@ describe('BulkImportsHistoryApp', () => { beforeEach(() => { mock = new MockAdapter(axios); - mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS); + mock.onGet(API_URL).reply(HTTP_STATUS_OK, DUMMY_RESPONSE, DEFAULT_HEADERS); }); afterEach(() => { @@ -93,7 +94,7 @@ describe('BulkImportsHistoryApp', () => { }); it('renders empty state when no data is available', async () => { - mock.onGet(API_URL).reply(200, [], DEFAULT_HEADERS); + mock.onGet(API_URL).reply(HTTP_STATUS_OK, [], DEFAULT_HEADERS); createComponent(); await axios.waitForAll(); @@ -167,7 +168,7 @@ describe('BulkImportsHistoryApp', () => { it('renders loading icon when destination namespace is not defined', async () => { const RESPONSE = [{ ...DUMMY_RESPONSE[0], destination_full_path: null }]; - mock.onGet(API_URL).reply(200, RESPONSE, DEFAULT_HEADERS); + mock.onGet(API_URL).reply(HTTP_STATUS_OK, RESPONSE, DEFAULT_HEADERS); createComponent({ shallow: false }); await axios.waitForAll(); @@ -192,7 +193,7 @@ describe('BulkImportsHistoryApp', () => { describe('details button', () => { beforeEach(() => { - mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS); + mock.onGet(API_URL).reply(HTTP_STATUS_OK, DUMMY_RESPONSE, DEFAULT_HEADERS); createComponent({ shallow: false }); return axios.waitForAll(); }); diff --git a/spec/frontend/pages/import/history/components/import_history_app_spec.js b/spec/frontend/pages/import/history/components/import_history_app_spec.js index 8d2891750e9..7d79583be19 100644 --- a/spec/frontend/pages/import/history/components/import_history_app_spec.js +++ b/spec/frontend/pages/import/history/components/import_history_app_spec.js @@ -2,6 +2,7 @@ import { GlEmptyState, GlLoadingIcon, GlTable } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; import ImportErrorDetails from '~/pages/import/history/components/import_error_details.vue'; import ImportHistoryApp from '~/pages/import/history/components/import_history_app.vue'; import PaginationBar from '~/vue_shared/components/pagination_bar/pagination_bar.vue'; @@ -84,7 +85,7 @@ describe('ImportHistoryApp', () => { }); it('renders empty state when no data is available', async () => { - mock.onGet(API_URL).reply(200, [], DEFAULT_HEADERS); + mock.onGet(API_URL).reply(HTTP_STATUS_OK, [], DEFAULT_HEADERS); createComponent(); await axios.waitForAll(); @@ -93,7 +94,7 @@ describe('ImportHistoryApp', () => { }); it('renders table with data when history is available', async () => { - mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS); + mock.onGet(API_URL).reply(HTTP_STATUS_OK, DUMMY_RESPONSE, DEFAULT_HEADERS); createComponent(); await axios.waitForAll(); @@ -105,7 +106,7 @@ describe('ImportHistoryApp', () => { it('changes page when requested by pagination bar', async () => { const NEW_PAGE = 4; - mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS); + mock.onGet(API_URL).reply(HTTP_STATUS_OK, DUMMY_RESPONSE, DEFAULT_HEADERS); createComponent(); await axios.waitForAll(); mock.resetHistory(); @@ -121,7 +122,7 @@ describe('ImportHistoryApp', () => { }, ]; - mock.onGet(API_URL).reply(200, FAKE_NEXT_PAGE_REPLY, DEFAULT_HEADERS); + mock.onGet(API_URL).reply(HTTP_STATUS_OK, FAKE_NEXT_PAGE_REPLY, DEFAULT_HEADERS); wrapper.findComponent(PaginationBar).vm.$emit('set-page', NEW_PAGE); await axios.waitForAll(); @@ -135,7 +136,7 @@ describe('ImportHistoryApp', () => { it('changes page size when requested by pagination bar', async () => { const NEW_PAGE_SIZE = 4; - mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS); + mock.onGet(API_URL).reply(HTTP_STATUS_OK, DUMMY_RESPONSE, DEFAULT_HEADERS); createComponent(); await axios.waitForAll(); mock.resetHistory(); @@ -152,7 +153,7 @@ describe('ImportHistoryApp', () => { it('resets page to 1 when page size is changed', async () => { const NEW_PAGE_SIZE = 4; - mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS); + mock.onGet(API_URL).reply(HTTP_STATUS_OK, DUMMY_RESPONSE, DEFAULT_HEADERS); createComponent(); await axios.waitForAll(); wrapper.findComponent(PaginationBar).vm.$emit('set-page', 2); @@ -170,7 +171,7 @@ describe('ImportHistoryApp', () => { describe('details button', () => { beforeEach(() => { - mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS); + mock.onGet(API_URL).reply(HTTP_STATUS_OK, DUMMY_RESPONSE, DEFAULT_HEADERS); createComponent({ shallow: false }); return axios.waitForAll(); }); diff --git a/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stage_spec.js b/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stage_spec.js index 6bc19b592cd..ab2056b4035 100644 --- a/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stage_spec.js +++ b/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stage_spec.js @@ -73,7 +73,7 @@ describe('Pipelines stage component', () => { beforeEach(async () => { createComponent({ updateDropdown: true }); - mock.onGet(dropdownPath).reply(200, stageReply); + mock.onGet(dropdownPath).reply(HTTP_STATUS_OK, stageReply); await openStageDropdown(); }); @@ -122,7 +122,7 @@ describe('Pipelines stage component', () => { describe('when user opens dropdown and stage request is successful', () => { beforeEach(async () => { - mock.onGet(dropdownPath).reply(200, stageReply); + mock.onGet(dropdownPath).reply(HTTP_STATUS_OK, stageReply); createComponent(); await openStageDropdown(); @@ -164,7 +164,7 @@ describe('Pipelines stage component', () => { beforeEach(async () => { const copyStage = { ...stageReply }; copyStage.latest_statuses[0].name = 'this is the updated content'; - mock.onGet('bar.json').reply(200, copyStage); + mock.onGet('bar.json').reply(HTTP_STATUS_OK, copyStage); createComponent({ stage: { status: { @@ -215,7 +215,7 @@ describe('Pipelines stage component', () => { describe('With merge trains enabled', () => { it('shows a warning on the dropdown', async () => { - mock.onGet(dropdownPath).reply(200, stageReply); + mock.onGet(dropdownPath).reply(HTTP_STATUS_OK, stageReply); createComponent({ isMergeTrain: true, }); @@ -232,7 +232,7 @@ describe('Pipelines stage component', () => { describe('With merge trains disabled', () => { beforeEach(async () => { - mock.onGet(dropdownPath).reply(200, stageReply); + mock.onGet(dropdownPath).reply(HTTP_STATUS_OK, stageReply); createComponent(); await openStageDropdown(); diff --git a/spec/frontend/vue_shared/components/markdown/field_spec.js b/spec/frontend/vue_shared/components/markdown/field_spec.js index 3b8e78bbadd..3dc52730bb4 100644 --- a/spec/frontend/vue_shared/components/markdown/field_spec.js +++ b/spec/frontend/vue_shared/components/markdown/field_spec.js @@ -2,6 +2,7 @@ import { nextTick } from 'vue'; import AxiosMockAdapter from 'axios-mock-adapter'; import { TEST_HOST, FIXTURES_PATH } from 'spec/test_constants'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; import MarkdownField from '~/vue_shared/components/markdown/field.vue'; import MarkdownFieldHeader from '~/vue_shared/components/markdown/header.vue'; import MarkdownToolbar from '~/vue_shared/components/markdown/toolbar.vue'; @@ -107,7 +108,7 @@ describe('Markdown field component', () => { it('renders referenced commands on markdown preview', async () => { axiosMock .onPost(markdownPreviewPath) - .reply(200, { references: { users: [], commands: 'test command' } }); + .reply(HTTP_STATUS_OK, { references: { users: [], commands: 'test command' } }); previewLink = getPreviewLink(); previewLink.vm.$emit('click', { target: {} }); @@ -121,7 +122,7 @@ describe('Markdown field component', () => { describe('markdown preview', () => { beforeEach(() => { - axiosMock.onPost(markdownPreviewPath).reply(200, { body: previewHTML }); + axiosMock.onPost(markdownPreviewPath).reply(HTTP_STATUS_OK, { body: previewHTML }); }); it('sets preview link as active', async () => { @@ -267,7 +268,7 @@ describe('Markdown field component', () => { const users = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map((i) => `user_${i}`); it('shows warning on mention of all users', async () => { - axiosMock.onPost(markdownPreviewPath).reply(200, { references: { users } }); + axiosMock.onPost(markdownPreviewPath).reply(HTTP_STATUS_OK, { references: { users } }); subject.setProps({ textareaValue: 'hello @all' }); @@ -279,7 +280,7 @@ describe('Markdown field component', () => { }); it('removes warning when all mention is removed', async () => { - axiosMock.onPost(markdownPreviewPath).reply(200, { references: { users } }); + axiosMock.onPost(markdownPreviewPath).reply(HTTP_STATUS_OK, { references: { users } }); subject.setProps({ textareaValue: 'hello @all' }); @@ -298,7 +299,7 @@ describe('Markdown field component', () => { }); it('removes warning when all mention is removed while endpoint is loading', async () => { - axiosMock.onPost(markdownPreviewPath).reply(200, { references: { users } }); + axiosMock.onPost(markdownPreviewPath).reply(HTTP_STATUS_OK, { references: { users } }); jest.spyOn(axios, 'post'); subject.setProps({ textareaValue: 'hello @all' }); diff --git a/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb b/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb index 2b0f437d198..f085da26927 100644 --- a/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb +++ b/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb @@ -14,8 +14,10 @@ RSpec.shared_examples 'Generate Debian Distribution and component files' do expect(distribution.file_signature).to end_with("\n-----END PGP SIGNATURE-----\n") distribution.signed_file.use_file do |file_path| - expect(File.read(file_path)).to start_with("-----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA512\n\n#{expected_release_content}-----BEGIN PGP SIGNATURE-----\n") - expect(File.read(file_path)).to end_with("\n-----END PGP SIGNATURE-----\n") + signed_file_content = File.read(file_path) + expect(signed_file_content).to start_with("-----BEGIN PGP SIGNED MESSAGE-----\nHash:") + expect(signed_file_content).to include("\n\n#{expected_release_content}-----BEGIN PGP SIGNATURE-----\n") + expect(signed_file_content).to end_with("\n-----END PGP SIGNATURE-----\n") end end |