Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
		
							parent
							
								
									abd8aecf4b
								
							
						
					
					
						commit
						ce16444418
					
				|  | @ -50,6 +50,8 @@ module Types | |||
|             null: true, | ||||
|             description: 'How long the job was enqueued before starting.' | ||||
| 
 | ||||
|       field :downstream_pipeline, Types::Ci::PipelineType, null: true, | ||||
|             description: 'Downstream pipeline for a bridge.' | ||||
|       field :previous_stage_jobs_or_needs, Types::Ci::JobNeedUnion.connection_type, null: true, | ||||
|             description: 'Jobs that must complete before the job runs. Returns `BuildNeed`, which is the needed jobs if the job uses the `needs` keyword, or the previous stage jobs otherwise.' | ||||
|       field :detailed_status, Types::Ci::DetailedStatusType, null: true, | ||||
|  | @ -89,6 +91,10 @@ module Types | |||
|         Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Pipeline, object.pipeline_id).find | ||||
|       end | ||||
| 
 | ||||
|       def downstream_pipeline | ||||
|         object.downstream_pipeline if object.respond_to?(:downstream_pipeline) | ||||
|       end | ||||
| 
 | ||||
|       def tags | ||||
|         object.tags.map(&:name) if object.is_a?(::Ci::Build) | ||||
|       end | ||||
|  |  | |||
|  | @ -54,6 +54,10 @@ module Types | |||
|             description: "Number of jobs processed by the runner (limited to #{JOB_COUNT_LIMIT}, plus one to indicate that more items exist)." | ||||
|       field :admin_url, GraphQL::Types::String, null: true, | ||||
|             description: 'Admin URL of the runner. Only available for administrators.' | ||||
|       field :executor_name, GraphQL::Types::String, null: true, | ||||
|             description: 'Executor last advertised by the runner.', | ||||
|             method: :executor_name, | ||||
|             feature_flag: :graphql_ci_runner_executor | ||||
| 
 | ||||
|       def job_count | ||||
|         # We limit to 1 above the JOB_COUNT_LIMIT to indicate that more items exist after JOB_COUNT_LIMIT | ||||
|  |  | |||
|  | @ -441,6 +441,7 @@ module Ci | |||
|     private | ||||
| 
 | ||||
|     EXECUTOR_NAME_TO_TYPES = { | ||||
|       'unknown' => :unknown, | ||||
|       'custom' => :custom, | ||||
|       'shell' => :shell, | ||||
|       'docker' => :docker, | ||||
|  | @ -454,6 +455,8 @@ module Ci | |||
|       'kubernetes' => :kubernetes | ||||
|     }.freeze | ||||
| 
 | ||||
|     EXECUTOR_TYPE_TO_NAMES = EXECUTOR_NAME_TO_TYPES.invert.freeze | ||||
| 
 | ||||
|     def cleanup_runner_queue | ||||
|       Gitlab::Redis::SharedState.with do |redis| | ||||
|         redis.del(runner_queue_key) | ||||
|  |  | |||
|  | @ -11,5 +11,9 @@ module Ci | |||
| 
 | ||||
|     delegator_override :locked | ||||
|     alias_method :locked, :locked? | ||||
| 
 | ||||
|     def executor_name | ||||
|       Ci::Runner::EXECUTOR_TYPE_TO_NAMES[executor_type&.to_sym] | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -0,0 +1,8 @@ | |||
| --- | ||||
| name: graphql_ci_runner_executor | ||||
| introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76534 | ||||
| rollout_issue_url: | ||||
| milestone: '14.7' | ||||
| type: development | ||||
| group: group::runner | ||||
| default_enabled: false | ||||
|  | @ -1,13 +1,13 @@ | |||
| --- | ||||
| data_category: optional | ||||
| key_path: usage_activity_by_stage_monthly.manage.bulk_imports.gitlab | ||||
| description: DEPRECATED - Count of projects imported using bulk imports | ||||
| description: REMOVED - Count of projects imported using bulk imports | ||||
| product_section: dev | ||||
| product_stage: manage | ||||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: 28d | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ product_stage: manage | |||
| product_group: group::import | ||||
| product_category: importers | ||||
| value_type: number | ||||
| status: deprecated | ||||
| status: removed | ||||
| time_frame: all | ||||
| data_source: database | ||||
| distribution: | ||||
|  |  | |||
|  | @ -1,14 +1,11 @@ | |||
| --- | ||||
| stage: Create | ||||
| group: Editor | ||||
| 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 | ||||
| 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 | ||||
| --- | ||||
| 
 | ||||
| # Merge request diffs storage **(FREE SELF)** | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52568) in GitLab 11.8. | ||||
| 
 | ||||
| Merge request diffs are size-limited copies of diffs associated with merge | ||||
| requests. When viewing a merge request, diffs are sourced from these copies | ||||
| wherever possible as a performance optimization. | ||||
|  |  | |||
|  | @ -8813,6 +8813,7 @@ Represents the total number of issues and their weights for a particular day. | |||
| | <a id="cijobcreatedat"></a>`createdAt` | [`Time!`](#time) | When the job was created. | | ||||
| | <a id="cijobcreatedbytag"></a>`createdByTag` | [`Boolean!`](#boolean) | Whether the job was created by a tag. | | ||||
| | <a id="cijobdetailedstatus"></a>`detailedStatus` | [`DetailedStatus`](#detailedstatus) | Detailed status of the job. | | ||||
| | <a id="cijobdownstreampipeline"></a>`downstreamPipeline` | [`Pipeline`](#pipeline) | Downstream pipeline for a bridge. | | ||||
| | <a id="cijobduration"></a>`duration` | [`Int`](#int) | Duration of the job in seconds. | | ||||
| | <a id="cijobfinishedat"></a>`finishedAt` | [`Time`](#time) | When a job has finished running. | | ||||
| | <a id="cijobid"></a>`id` | [`JobID`](#jobid) | ID of the job. | | ||||
|  | @ -8887,6 +8888,7 @@ Represents the total number of issues and their weights for a particular day. | |||
| | <a id="cirunneradminurl"></a>`adminUrl` | [`String`](#string) | Admin URL of the runner. Only available for administrators. | | ||||
| | <a id="cirunnercontactedat"></a>`contactedAt` | [`Time`](#time) | Last contact from the runner. | | ||||
| | <a id="cirunnerdescription"></a>`description` | [`String`](#string) | Description of the runner. | | ||||
| | <a id="cirunnerexecutorname"></a>`executorName` | [`String`](#string) | Executor last advertised by the runner. Available only when feature flag `graphql_ci_runner_executor` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. | | ||||
| | <a id="cirunnerid"></a>`id` | [`CiRunnerID!`](#cirunnerid) | ID of the runner. | | ||||
| | <a id="cirunneripaddress"></a>`ipAddress` | [`String`](#string) | IP address of the runner. | | ||||
| | <a id="cirunnerjobcount"></a>`jobCount` | [`Int`](#int) | Number of jobs processed by the runner (limited to 1000, plus one to indicate that more items exist). | | ||||
|  |  | |||
|  | @ -1,8 +1,7 @@ | |||
| --- | ||||
| stage: Create | ||||
| group: Editor | ||||
| 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, api | ||||
| 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 | ||||
| --- | ||||
| 
 | ||||
| # Project snippets **(FREE)** | ||||
|  | @ -247,8 +246,6 @@ curl "https://gitlab.com/api/v4/projects/1/snippets/2/files/master/snippet%2Erb/ | |||
| 
 | ||||
| ## Get user agent details | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29508) in GitLab 9.4. | ||||
| 
 | ||||
| Available only for users with the Administrator [role](../user/permissions.md). | ||||
| 
 | ||||
| ```plaintext | ||||
|  |  | |||
|  | @ -1,14 +1,11 @@ | |||
| --- | ||||
| stage: Create | ||||
| group: Editor | ||||
| 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, api | ||||
| 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 | ||||
| --- | ||||
| 
 | ||||
| # Snippets API **(FREE)** | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6373) in GitLab 8.15. | ||||
| 
 | ||||
| Snippets API operates on [snippets](../user/snippets.md). Related APIs exist for | ||||
| [project snippets](project_snippets.md) and | ||||
| [moving snippets between storages](snippet_repository_storage_moves.md). | ||||
|  | @ -449,8 +446,6 @@ Example response: | |||
| 
 | ||||
| ## Get user agent details | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12655) in GitLab 9.4. | ||||
| 
 | ||||
| NOTE: | ||||
| Available only for administrators. | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,14 +1,11 @@ | |||
| --- | ||||
| stage: Create | ||||
| group: Editor | ||||
| 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, api | ||||
| 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 | ||||
| --- | ||||
| 
 | ||||
| # Project wikis API **(FREE)** | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13372) in GitLab 10.0. | ||||
| 
 | ||||
| The project [wikis](../user/project/wiki/index.md) API is available only in APIv4. | ||||
| An API for [group wikis](group_wikis.md) is also available. | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,4 @@ | |||
| --- | ||||
| type: reference, dev | ||||
| stage: Create | ||||
| group: Editor | ||||
| 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 | ||||
|  | @ -91,8 +90,6 @@ Only some data is persisted in the database: | |||
| 
 | ||||
| The web UI uploads attachments through the REST API, which stores the files as commits in the wiki repository. | ||||
| 
 | ||||
| Prior to GitLab 11.3 attachments were stored outside of the repository, [see this issue](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33475). | ||||
| 
 | ||||
| ## Related topics | ||||
| 
 | ||||
| - [Gollum installation instructions](https://github.com/gollum/gollum/wiki/Installation) | ||||
|  |  | |||
|  | @ -22,10 +22,6 @@ NOTE: | |||
| By default, all Git operations are first tried unauthenticated. Because of this, HTTP Git operations | ||||
| may trigger the rate limits configured for unauthenticated requests. | ||||
| 
 | ||||
| NOTE: | ||||
| The rate limits for API requests don't affect requests made by the frontend, as these are always | ||||
| counted as web traffic. | ||||
| 
 | ||||
| ## Enable unauthenticated API request rate limit | ||||
| 
 | ||||
| To enable the unauthenticated request rate limit: | ||||
|  |  | |||
|  | @ -110,6 +110,7 @@ The certificate [fingerprint algorithm](../../../integration/saml.md#notes-on-co | |||
| > - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/292811) in GitLab 13.8, with an updated timeout experience. | ||||
| > - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/211962) in GitLab 13.8 with allowing group owners to not go through SSO. | ||||
| > - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/9152) in GitLab 13.11 with enforcing open SSO session to use Git if this setting is switched on. | ||||
| > - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/339888) in GitLab 14.7 to not enforce SSO checks for Git activity originating from CI/CD jobs. | ||||
| 
 | ||||
| With this option enabled, users (except users with the Owner role) must access GitLab using your group GitLab single sign-on URL to access group resources. Users added manually as members can't access group resources. | ||||
| 
 | ||||
|  | @ -127,6 +128,7 @@ SSO has the following effects when enabled: | |||
|   even if the project is forked. | ||||
| - For Git activity over SSH and HTTPS, users must have at least one active session signed-in through SSO before they can push to or | ||||
|   pull from a GitLab repository. | ||||
| - Git activity originating from CI/CD jobs do not have the SSO check enforced. | ||||
| - Credentials that are not tied to regular users (for example, access tokens and deploy keys) do not have the SSO check enforced. | ||||
| - Users must be signed-in through SSO before they can pull images using the [Dependency Proxy](../../packages/dependency_proxy/index.md). | ||||
| <!-- Add bullet for API activity when https://gitlab.com/gitlab-org/gitlab/-/issues/9152 is complete --> | ||||
|  |  | |||
|  | @ -2,13 +2,10 @@ | |||
| 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/engineering/ux/technical-writing/#assignments | ||||
| type: reference, howto | ||||
| --- | ||||
| 
 | ||||
| # Allow collaboration on merge requests across forks **(FREE)** | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17395) in GitLab 10.6. | ||||
| 
 | ||||
| When a user opens a merge request from a fork, they are given the option to allow | ||||
| upstream members to collaborate with them on the source branch. This allows | ||||
| the members of the upstream project to make small fixes or rebase branches | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
| 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/engineering/ux/technical-writing/#assignments | ||||
| type: howto | ||||
| description: "How to create merge requests in GitLab." | ||||
| disqus_identifier: 'https://docs.gitlab.com/ee/gitlab-basics/add-merge-request.html' | ||||
| --- | ||||
|  | @ -111,10 +110,6 @@ For more information, [see the forking workflow documentation](../repository/for | |||
| 
 | ||||
| ## By sending an email | ||||
| 
 | ||||
| > The format of the generated email address changed in GitLab 11.7. | ||||
|   The earlier format is still supported so existing aliases | ||||
|   or contacts still work. | ||||
| 
 | ||||
| You can create a merge request by sending an email message to GitLab. | ||||
| The merge request target branch is the project's default branch. | ||||
| 
 | ||||
|  | @ -142,8 +137,6 @@ A merge request is created. | |||
| 
 | ||||
| ### Add attachments when creating a merge request by email | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22723) in GitLab 11.5. | ||||
| 
 | ||||
| You can add commits to a merge request by adding | ||||
| patches as attachments to the email. All attachments with a filename | ||||
| ending in `.patch` are considered patches and are processed | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
| 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/engineering/ux/technical-writing/#assignments | ||||
| type: index, reference | ||||
| description: "Getting started with merge requests." | ||||
| --- | ||||
| 
 | ||||
|  | @ -92,8 +91,7 @@ and the merge request is added to their | |||
| 
 | ||||
| #### Multiple assignees **(PREMIUM)** | ||||
| 
 | ||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2004) in GitLab 11.11. | ||||
| > - Moved to GitLab Premium in 13.9 | ||||
| > Moved to GitLab Premium in 13.9 | ||||
| 
 | ||||
| Multiple people often review merge requests at the same time. | ||||
| GitLab allows you to have multiple assignees for merge requests | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
| 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/engineering/ux/technical-writing/#assignments | ||||
| type: reference, concepts | ||||
| --- | ||||
| 
 | ||||
| # Revert changes **(FREE)** | ||||
|  | @ -12,11 +11,6 @@ by clicking the **Revert** button in merge requests and commit details. | |||
| 
 | ||||
| ## Revert a merge request | ||||
| 
 | ||||
| NOTE: | ||||
| The **Revert** button is available only for merge requests | ||||
| created in GitLab 8.5 and later. However, you can still revert a merge request | ||||
| by reverting the merge commit from the list of Commits page. | ||||
| 
 | ||||
| NOTE: | ||||
| The **Revert** button is shown only for projects that use the | ||||
| merge method "Merge Commit", which can be set under the project's | ||||
|  |  | |||
|  | @ -39,8 +39,6 @@ changes appears as a system note. | |||
| 
 | ||||
| ## Find the merge request that introduced a change | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/2383) in GitLab 10.5. | ||||
| 
 | ||||
| When viewing the commit details page, GitLab links to the merge request (or | ||||
| merge requests, if it's in more than one) containing that commit. | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ | |||
| stage: Create | ||||
| group: Editor | ||||
| 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: howto | ||||
| --- | ||||
| 
 | ||||
| # GitLab Web Editor **(FREE)** | ||||
|  | @ -118,8 +117,6 @@ There are multiple ways to create a branch from the GitLab web interface. | |||
| 
 | ||||
| ### Create a new branch from an issue | ||||
| 
 | ||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2808) in GitLab 8.6. | ||||
| 
 | ||||
| If your development workflow requires an issue for every merge | ||||
| request, you can create a branch directly from the issue to speed the process up. | ||||
| The new branch, and later its merge request, are marked as related to this issue. | ||||
|  |  | |||
|  | @ -1,8 +1,7 @@ | |||
| --- | ||||
| stage: Create | ||||
| group: Editor | ||||
| 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, how-to | ||||
| 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 | ||||
| --- | ||||
| 
 | ||||
| # Wiki **(FREE)** | ||||
|  | @ -87,11 +86,7 @@ Users with the [Developer role](../../permissions.md) can create new wiki pages: | |||
|    [special characters](#special-characters-in-page-titles) for subdirectories and formatting, | ||||
|    and have [length restrictions](#length-restrictions-for-file-and-directory-names). | ||||
| 1. Add content to your wiki page. | ||||
| 1. Optional. Attach a file, and GitLab stores it according to your installed version of GitLab: | ||||
|    - *Files added in [GitLab 11.3 and later](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33475):* | ||||
|      Files are stored in the wiki's Git repository. | ||||
|    - *Files added GitLab 11.2 and earlier:* Files are stored in GitLab itself. To add | ||||
|      the file to the wiki's Git repository, you must re-upload the file. | ||||
| 1. Optional. Attach a file, and GitLab stores it in the wiki's Git repository. | ||||
| 1. Add a **Commit message**. Git requires a commit message, so GitLab creates one | ||||
|    if you don't enter one yourself. | ||||
| 1. Select **Create page**. | ||||
|  | @ -227,9 +222,9 @@ You can see the changes made in a version of a wiki page, similar to versioned d | |||
| 
 | ||||
| ## Track wiki events | ||||
| 
 | ||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14902) in **GitLab 12.10.** | ||||
| > - Git events were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216014) in **GitLab 13.0.** | ||||
| > - [Feature flag for Git events was removed](https://gitlab.com/gitlab-org/gitlab/-/issues/258665) in **GitLab 13.5** | ||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14902) in GitLab 12.10. | ||||
| > - Git events were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216014) in GitLab 13.0. | ||||
| > - [Feature flag for Git events was removed](https://gitlab.com/gitlab-org/gitlab/-/issues/258665) in GitLab 13.5. | ||||
| 
 | ||||
| GitLab tracks wiki creation, deletion, and update events. These events are displayed on these pages: | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,8 +1,7 @@ | |||
| --- | ||||
| stage: Create | ||||
| group: Editor | ||||
| 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: index, reference, howto | ||||
| 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 | ||||
| --- | ||||
| 
 | ||||
| # Searching in GitLab **(FREE)** | ||||
|  | @ -102,8 +101,7 @@ You can filter the **Issues** list to individual instances by their ID. For exam | |||
| 
 | ||||
| ### Filtering merge requests by approvers **(PREMIUM)** | ||||
| 
 | ||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9468) in GitLab 11.9. | ||||
| > - Moved to GitLab Premium in 13.9. | ||||
| > Moved to GitLab Premium in 13.9. | ||||
| 
 | ||||
| To filter merge requests by an individual approver, you can type (or select from | ||||
| the dropdown) **Approver** and select the user. | ||||
|  |  | |||
|  | @ -3,8 +3,6 @@ | |||
| module Gitlab | ||||
|   module RackAttack | ||||
|     module Request | ||||
|       include ::Gitlab::Utils::StrongMemoize | ||||
| 
 | ||||
|       FILES_PATH_REGEX = %r{^/api/v\d+/projects/[^/]+/repository/files/.+}.freeze | ||||
|       GROUP_PATH_REGEX = %r{^/api/v\d+/groups/[^/]+/?$}.freeze | ||||
| 
 | ||||
|  | @ -32,15 +30,15 @@ module Gitlab | |||
|       end | ||||
| 
 | ||||
|       def api_internal_request? | ||||
|         path.match?(%r{^/api/v\d+/internal/}) | ||||
|         path =~ %r{^/api/v\d+/internal/} | ||||
|       end | ||||
| 
 | ||||
|       def health_check_request? | ||||
|         path.match?(%r{^/-/(health|liveness|readiness|metrics)}) | ||||
|         path =~ %r{^/-/(health|liveness|readiness|metrics)} | ||||
|       end | ||||
| 
 | ||||
|       def container_registry_event? | ||||
|         path.match?(%r{^/api/v\d+/container_registry_event/}) | ||||
|         path =~ %r{^/api/v\d+/container_registry_event/} | ||||
|       end | ||||
| 
 | ||||
|       def product_analytics_collector_request? | ||||
|  | @ -60,7 +58,7 @@ module Gitlab | |||
|       end | ||||
| 
 | ||||
|       def protected_path_regex | ||||
|         path.match?(protected_paths_regex) | ||||
|         path =~ protected_paths_regex | ||||
|       end | ||||
| 
 | ||||
|       def throttle?(throttle, authenticated:) | ||||
|  | @ -72,7 +70,6 @@ module Gitlab | |||
|       def throttle_unauthenticated_api? | ||||
|         api_request? && | ||||
|         !should_be_skipped? && | ||||
|         !frontend_request? && | ||||
|         !throttle_unauthenticated_packages_api? && | ||||
|         !throttle_unauthenticated_files_api? && | ||||
|         !throttle_unauthenticated_deprecated_api? && | ||||
|  | @ -81,7 +78,7 @@ module Gitlab | |||
|       end | ||||
| 
 | ||||
|       def throttle_unauthenticated_web? | ||||
|         (web_request? || frontend_request?) && | ||||
|         web_request? && | ||||
|         !should_be_skipped? && | ||||
|         # TODO: Column will be renamed in https://gitlab.com/gitlab-org/gitlab/-/issues/340031 | ||||
|         Gitlab::Throttle.settings.throttle_unauthenticated_enabled && | ||||
|  | @ -90,7 +87,6 @@ module Gitlab | |||
| 
 | ||||
|       def throttle_authenticated_api? | ||||
|         api_request? && | ||||
|         !frontend_request? && | ||||
|         !throttle_authenticated_packages_api? && | ||||
|         !throttle_authenticated_files_api? && | ||||
|         !throttle_authenticated_deprecated_api? && | ||||
|  | @ -98,7 +94,7 @@ module Gitlab | |||
|       end | ||||
| 
 | ||||
|       def throttle_authenticated_web? | ||||
|         (web_request? || frontend_request?) && | ||||
|         web_request? && | ||||
|         !throttle_authenticated_git_lfs? && | ||||
|         Gitlab::Throttle.settings.throttle_authenticated_web_enabled | ||||
|       end | ||||
|  | @ -182,24 +178,15 @@ module Gitlab | |||
|       end | ||||
| 
 | ||||
|       def packages_api_path? | ||||
|         path.match?(::Gitlab::Regex::Packages::API_PATH_REGEX) | ||||
|         path =~ ::Gitlab::Regex::Packages::API_PATH_REGEX | ||||
|       end | ||||
| 
 | ||||
|       def git_lfs_path? | ||||
|         path.match?(Gitlab::PathRegex.repository_git_lfs_route_regex) | ||||
|         path =~ Gitlab::PathRegex.repository_git_lfs_route_regex | ||||
|       end | ||||
| 
 | ||||
|       def files_api_path? | ||||
|         path.match?(FILES_PATH_REGEX) | ||||
|       end | ||||
| 
 | ||||
|       def frontend_request? | ||||
|         strong_memoize(:frontend_request) do | ||||
|           next false unless env.include?('HTTP_X_CSRF_TOKEN') && session.include?(:_csrf_token) | ||||
| 
 | ||||
|           # CSRF tokens are not verified for GET/HEAD requests, so we pretend that we always have a POST request. | ||||
|           Gitlab::RequestForgeryProtection.verified?(env.merge('REQUEST_METHOD' => 'POST')) | ||||
|         end | ||||
|         path =~ FILES_PATH_REGEX | ||||
|       end | ||||
| 
 | ||||
|       def deprecated_api_request? | ||||
|  | @ -208,7 +195,7 @@ module Gitlab | |||
|         with_projects = params['with_projects'] | ||||
|         with_projects = true if with_projects.blank? | ||||
| 
 | ||||
|         path.match?(GROUP_PATH_REGEX) && Gitlab::Utils.to_boolean(with_projects) | ||||
|         path =~ GROUP_PATH_REGEX && Gitlab::Utils.to_boolean(with_projects) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  |  | |||
|  | @ -553,33 +553,11 @@ module Gitlab | |||
|           user_auth_by_provider: distinct_count_user_auth_by_provider(time_period), | ||||
|           unique_users_all_imports: unique_users_all_imports(time_period), | ||||
|           bulk_imports: { | ||||
|             gitlab: DEPRECATED_VALUE, | ||||
|             gitlab_v1: count(::BulkImport.where(**time_period, source_type: :gitlab)) | ||||
|           }, | ||||
|           project_imports: project_imports(time_period), | ||||
|           issue_imports: issue_imports(time_period), | ||||
|           group_imports: group_imports(time_period), | ||||
| 
 | ||||
|           # Deprecated data to be removed | ||||
|           projects_imported: { | ||||
|             total: DEPRECATED_VALUE, | ||||
|             gitlab_project: DEPRECATED_VALUE, | ||||
|             gitlab: DEPRECATED_VALUE, | ||||
|             github: DEPRECATED_VALUE, | ||||
|             bitbucket: DEPRECATED_VALUE, | ||||
|             bitbucket_server: DEPRECATED_VALUE, | ||||
|             gitea: DEPRECATED_VALUE, | ||||
|             git: DEPRECATED_VALUE, | ||||
|             manifest: DEPRECATED_VALUE | ||||
|           }, | ||||
|           issues_imported: { | ||||
|             jira: DEPRECATED_VALUE, | ||||
|             fogbugz: DEPRECATED_VALUE, | ||||
|             phabricator: DEPRECATED_VALUE, | ||||
|             csv: DEPRECATED_VALUE | ||||
|           }, | ||||
|           groups_imported: DEPRECATED_VALUE | ||||
|           # End of deprecated keys | ||||
|           group_imports: group_imports(time_period) | ||||
|         } | ||||
|       end | ||||
|       # rubocop: enable CodeReuse/ActiveRecord | ||||
|  |  | |||
|  | @ -3,11 +3,15 @@ | |||
| require 'spec_helper' | ||||
| 
 | ||||
| RSpec.describe ApplicationCable::Connection, :clean_gitlab_redis_sessions do | ||||
|   include SessionHelpers | ||||
|   let(:session_id) { Rack::Session::SessionId.new('6919a6f1bb119dd7396fadc38fd18d0d') } | ||||
| 
 | ||||
|   context 'when session cookie is set' do | ||||
|     before do | ||||
|       stub_session(session_hash) | ||||
|       Gitlab::Redis::Sessions.with do |redis| | ||||
|         redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash)) | ||||
|       end | ||||
| 
 | ||||
|       cookies[Gitlab::Application.config.session_options[:key]] = session_id.public_id | ||||
|     end | ||||
| 
 | ||||
|     context 'when user is logged in' do | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ RSpec.describe Types::Ci::JobType do | |||
|       created_by_tag | ||||
|       detailedStatus | ||||
|       duration | ||||
|       downstreamPipeline | ||||
|       finished_at | ||||
|       id | ||||
|       manual_job | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ RSpec.describe GitlabSchema.types['CiRunner'] do | |||
|     expected_fields = %w[ | ||||
|       id description contacted_at maximum_timeout access_level active status | ||||
|       version short_sha revision locked run_untagged ip_address runner_type tag_list | ||||
|       project_count job_count admin_url user_permissions | ||||
|       project_count job_count admin_url user_permissions executor_name | ||||
|     ] | ||||
| 
 | ||||
|     expect(described_class).to include_graphql_fields(*expected_fields) | ||||
|  |  | |||
|  | @ -5,19 +5,6 @@ require 'spec_helper' | |||
| RSpec.describe Gitlab::RackAttack::Request do | ||||
|   using RSpec::Parameterized::TableSyntax | ||||
| 
 | ||||
|   let(:env) { {} } | ||||
|   let(:session) { {} } | ||||
|   let(:request) do | ||||
|     ::Rack::Attack::Request.new( | ||||
|       env.reverse_merge( | ||||
|         'REQUEST_METHOD' => 'GET', | ||||
|         'PATH_INFO' => path, | ||||
|         'rack.input' => StringIO.new, | ||||
|         'rack.session' => session | ||||
|       ) | ||||
|     ) | ||||
|   end | ||||
| 
 | ||||
|   describe 'FILES_PATH_REGEX' do | ||||
|     subject { described_class::FILES_PATH_REGEX } | ||||
| 
 | ||||
|  | @ -29,63 +16,11 @@ RSpec.describe Gitlab::RackAttack::Request do | |||
|     it { is_expected.not_to match('/api/v4/projects/some/nested/repo/repository/files/README') } | ||||
|   end | ||||
| 
 | ||||
|   describe '#api_request?' do | ||||
|     subject { request.api_request? } | ||||
| 
 | ||||
|     where(:path, :env, :expected) do | ||||
|       '/'       | {} | false | ||||
|       '/groups' | {} | false | ||||
| 
 | ||||
|       '/api'             | {} | true | ||||
|       '/api/v4/groups/1' | {} | true | ||||
|     end | ||||
| 
 | ||||
|     with_them do | ||||
|       it { is_expected.to eq(expected) } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#web_request?' do | ||||
|     subject { request.web_request? } | ||||
| 
 | ||||
|     where(:path, :env, :expected) do | ||||
|       '/'       | {} | true | ||||
|       '/groups' | {} | true | ||||
| 
 | ||||
|       '/api'             | {} | false | ||||
|       '/api/v4/groups/1' | {} | false | ||||
|     end | ||||
| 
 | ||||
|     with_them do | ||||
|       it { is_expected.to eq(expected) } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#frontend_request?', :allow_forgery_protection do | ||||
|     subject { request.send(:frontend_request?) } | ||||
| 
 | ||||
|     let(:path) { '/' } | ||||
| 
 | ||||
|     # Define these as local variables so we can use them in the `where` block. | ||||
|     valid_token = SecureRandom.base64(ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH) | ||||
|     other_token = SecureRandom.base64(ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH) | ||||
| 
 | ||||
|     where(:session, :env, :expected) do | ||||
|       {}                           | {}                                     | false # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands | ||||
|       {}                           | { 'HTTP_X_CSRF_TOKEN' => valid_token } | false | ||||
|       { _csrf_token: valid_token } | { 'HTTP_X_CSRF_TOKEN' => other_token } | false | ||||
|       { _csrf_token: valid_token } | { 'HTTP_X_CSRF_TOKEN' => valid_token } | true | ||||
|     end | ||||
| 
 | ||||
|     with_them do | ||||
|       it { is_expected.to eq(expected) } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#deprecated_api_request?' do | ||||
|     subject { request.send(:deprecated_api_request?) } | ||||
|     let(:env) { { 'REQUEST_METHOD' => 'GET', 'rack.input' => StringIO.new, 'PATH_INFO' => path, 'QUERY_STRING' => query } } | ||||
|     let(:request) { ::Rack::Attack::Request.new(env) } | ||||
| 
 | ||||
|     let(:env) { { 'QUERY_STRING' => query } } | ||||
|     subject { !!request.__send__(:deprecated_api_request?) } | ||||
| 
 | ||||
|     where(:path, :query, :expected) do | ||||
|       '/' | '' | false | ||||
|  |  | |||
|  | @ -279,8 +279,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do | |||
|       expect(described_class.usage_activity_by_stage_manage({})).to include( | ||||
|         { | ||||
|           bulk_imports: { | ||||
|             gitlab_v1: 2, | ||||
|             gitlab: Gitlab::UsageData::DEPRECATED_VALUE | ||||
|             gitlab_v1: 2 | ||||
|           }, | ||||
|           project_imports: { | ||||
|             bitbucket: 2, | ||||
|  | @ -303,32 +302,13 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do | |||
|           group_imports: { | ||||
|             group_import: 2, | ||||
|             gitlab_migration: 2 | ||||
|           }, | ||||
|           projects_imported: { | ||||
|             total: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             gitlab_project: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             gitlab: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             github: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             bitbucket: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             bitbucket_server: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             gitea: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             git: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             manifest: Gitlab::UsageData::DEPRECATED_VALUE | ||||
|           }, | ||||
|           issues_imported: { | ||||
|             jira: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             fogbugz: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             phabricator: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             csv: Gitlab::UsageData::DEPRECATED_VALUE | ||||
|           }, | ||||
|           groups_imported: Gitlab::UsageData::DEPRECATED_VALUE | ||||
|           } | ||||
|         } | ||||
|       ) | ||||
|       expect(described_class.usage_activity_by_stage_manage(described_class.monthly_time_range_db_params)).to include( | ||||
|         { | ||||
|           bulk_imports: { | ||||
|             gitlab_v1: 1, | ||||
|             gitlab: Gitlab::UsageData::DEPRECATED_VALUE | ||||
|             gitlab_v1: 1 | ||||
|           }, | ||||
|           project_imports: { | ||||
|             bitbucket: 1, | ||||
|  | @ -351,25 +331,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do | |||
|           group_imports: { | ||||
|             group_import: 1, | ||||
|             gitlab_migration: 1 | ||||
|           }, | ||||
|           projects_imported: { | ||||
|             total: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             gitlab_project: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             gitlab: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             github: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             bitbucket: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             bitbucket_server: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             gitea: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             git: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             manifest: Gitlab::UsageData::DEPRECATED_VALUE | ||||
|           }, | ||||
|           issues_imported: { | ||||
|             jira: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             fogbugz: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             phabricator: Gitlab::UsageData::DEPRECATED_VALUE, | ||||
|             csv: Gitlab::UsageData::DEPRECATED_VALUE | ||||
|           }, | ||||
|           groups_imported: Gitlab::UsageData::DEPRECATED_VALUE | ||||
|           } | ||||
|         } | ||||
|       ) | ||||
|     end | ||||
|  |  | |||
|  | @ -5,7 +5,6 @@ require 'mime/types' | |||
| 
 | ||||
| RSpec.describe API::Commits do | ||||
|   include ProjectForksHelper | ||||
|   include SessionHelpers | ||||
| 
 | ||||
|   let(:user) { create(:user) } | ||||
|   let(:guest) { create(:user).tap { |u| project.add_guest(u) } } | ||||
|  | @ -379,7 +378,14 @@ RSpec.describe API::Commits do | |||
| 
 | ||||
|       context 'when using warden' do | ||||
|         it 'increments usage counters', :clean_gitlab_redis_sessions do | ||||
|           stub_session('warden.user.user.key' => [[user.id], user.encrypted_password[0, 29]]) | ||||
|           session_id = Rack::Session::SessionId.new('6919a6f1bb119dd7396fadc38fd18d0d') | ||||
|           session_hash = { 'warden.user.user.key' => [[user.id], user.encrypted_password[0, 29]] } | ||||
| 
 | ||||
|           Gitlab::Redis::Sessions.with do |redis| | ||||
|             redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash)) | ||||
|           end | ||||
| 
 | ||||
|           cookies[Gitlab::Application.config.session_options[:key]] = session_id.public_id | ||||
| 
 | ||||
|           expect(::Gitlab::UsageDataCounters::WebIdeCounter).to receive(:increment_commits_count) | ||||
|           expect(::Gitlab::UsageDataCounters::EditorUniqueCounter).to receive(:track_web_ide_edit_action) | ||||
|  |  | |||
|  | @ -44,6 +44,10 @@ RSpec.describe 'Query.project.pipeline' do | |||
|             name | ||||
|             jobs { | ||||
|               nodes { | ||||
|                 downstreamPipeline { | ||||
|                   id | ||||
|                   path | ||||
|                 } | ||||
|                 name | ||||
|                 needs { | ||||
|                   nodes { #{all_graphql_fields_for('CiBuildNeed')} } | ||||
|  | @ -131,6 +135,8 @@ RSpec.describe 'Query.project.pipeline' do | |||
|       end | ||||
| 
 | ||||
|       it 'does not generate N+1 queries', :request_store, :use_sql_query_cache do | ||||
|         create(:ci_bridge, name: 'bridge-1', pipeline: pipeline, downstream_pipeline: create(:ci_pipeline)) | ||||
| 
 | ||||
|         post_graphql(query, current_user: user) | ||||
| 
 | ||||
|         control = ActiveRecord::QueryRecorder.new(skip_cached: false) do | ||||
|  | @ -139,6 +145,8 @@ RSpec.describe 'Query.project.pipeline' do | |||
| 
 | ||||
|         create(:ci_build, name: 'test-a', pipeline: pipeline) | ||||
|         create(:ci_build, name: 'test-b', pipeline: pipeline) | ||||
|         create(:ci_bridge, name: 'bridge-2', pipeline: pipeline, downstream_pipeline: create(:ci_pipeline)) | ||||
|         create(:ci_bridge, name: 'bridge-3', pipeline: pipeline, downstream_pipeline: create(:ci_pipeline)) | ||||
| 
 | ||||
|         expect do | ||||
|           post_graphql(query, current_user: user) | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ RSpec.describe 'Query.runner(id)' do | |||
|   let_it_be(:active_instance_runner) do | ||||
|     create(:ci_runner, :instance, description: 'Runner 1', contacted_at: 2.hours.ago, | ||||
|            active: true, version: 'adfe156', revision: 'a', locked: true, ip_address: '127.0.0.1', maximum_timeout: 600, | ||||
|            access_level: 0, tag_list: %w[tag1 tag2], run_untagged: true) | ||||
|            access_level: 0, tag_list: %w[tag1 tag2], run_untagged: true, executor_type: :custom) | ||||
|   end | ||||
| 
 | ||||
|   let_it_be(:inactive_instance_runner) do | ||||
|  | @ -22,7 +22,7 @@ RSpec.describe 'Query.runner(id)' do | |||
|   let_it_be(:active_group_runner) do | ||||
|     create(:ci_runner, :group, groups: [group], description: 'Group runner 1', contacted_at: 2.hours.ago, | ||||
|            active: true, version: 'adfe156', revision: 'a', locked: true, ip_address: '127.0.0.1', maximum_timeout: 600, | ||||
|            access_level: 0, tag_list: %w[tag1 tag2], run_untagged: true) | ||||
|            access_level: 0, tag_list: %w[tag1 tag2], run_untagged: true, executor_type: :shell) | ||||
|   end | ||||
| 
 | ||||
|   def get_runner(id) | ||||
|  | @ -69,6 +69,7 @@ RSpec.describe 'Query.runner(id)' do | |||
|         'runUntagged' => runner.run_untagged, | ||||
|         'ipAddress' => runner.ip_address, | ||||
|         'runnerType' => runner.instance_type? ? 'INSTANCE_TYPE' : 'PROJECT_TYPE', | ||||
|         'executorName' => runner.executor_type&.dasherize, | ||||
|         'jobCount' => 0, | ||||
|         'projectCount' => nil, | ||||
|         'adminUrl' => "http://localhost/admin/runners/#{runner.id}", | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ require 'spec_helper' | |||
| 
 | ||||
| RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_caching do | ||||
|   include RackAttackSpecHelpers | ||||
|   include SessionHelpers | ||||
| 
 | ||||
|   let(:settings) { Gitlab::CurrentSettings.current_application_settings } | ||||
| 
 | ||||
|  | @ -64,22 +63,6 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac | |||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe 'API requests from the frontend', :api, :clean_gitlab_redis_sessions do | ||||
|     context 'when unauthenticated' do | ||||
|       it_behaves_like 'rate-limited frontend API requests' do | ||||
|         let(:throttle_setting_prefix) { 'throttle_unauthenticated' } | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'when authenticated' do | ||||
|       it_behaves_like 'rate-limited frontend API requests' do | ||||
|         let_it_be(:personal_access_token) { create(:personal_access_token) } | ||||
| 
 | ||||
|         let(:throttle_setting_prefix) { 'throttle_authenticated' } | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe 'API requests authenticated with personal access token', :api do | ||||
|     let_it_be(:user) { create(:user) } | ||||
|     let_it_be(:token) { create(:personal_access_token, user: user) } | ||||
|  |  | |||
|  | @ -26,14 +26,14 @@ module RackAttackSpecHelpers | |||
|     { 'AUTHORIZATION' => "Basic #{encoded_login}" } | ||||
|   end | ||||
| 
 | ||||
|   def expect_rejection(name = nil, &block) | ||||
|   def expect_rejection(&block) | ||||
|     yield | ||||
| 
 | ||||
|     expect(response).to have_gitlab_http_status(:too_many_requests) | ||||
| 
 | ||||
|     expect(response.headers.to_h).to include( | ||||
|       'RateLimit-Limit' => a_string_matching(/^\d+$/), | ||||
|       'RateLimit-Name' => name || a_string_matching(/^throttle_.*$/), | ||||
|       'RateLimit-Name' => a_string_matching(/^throttle_.*$/), | ||||
|       'RateLimit-Observed' => a_string_matching(/^\d+$/), | ||||
|       'RateLimit-Remaining' => a_string_matching(/^\d+$/), | ||||
|       'Retry-After' => a_string_matching(/^\d+$/) | ||||
|  |  | |||
|  | @ -1,22 +1,6 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| module SessionHelpers | ||||
|   # Stub a session in Redis, for use in request specs where we can't mock the session directly. | ||||
|   # This also needs the :clean_gitlab_redis_sessions tag on the spec. | ||||
|   def stub_session(session_hash) | ||||
|     unless RSpec.current_example.metadata[:clean_gitlab_redis_sessions] | ||||
|       raise 'Add :clean_gitlab_redis_sessions to your spec!' | ||||
|     end | ||||
| 
 | ||||
|     session_id = Rack::Session::SessionId.new(SecureRandom.hex) | ||||
| 
 | ||||
|     Gitlab::Redis::Sessions.with do |redis| | ||||
|       redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash)) | ||||
|     end | ||||
| 
 | ||||
|     cookies[Gitlab::Application.config.session_options[:key]] = session_id.public_id | ||||
|   end | ||||
| 
 | ||||
|   def expect_single_session_with_authenticated_ttl | ||||
|     expect_single_session_with_expiration(Settings.gitlab['session_expire_delay'] * 60) | ||||
|   end | ||||
|  |  | |||
|  | @ -10,8 +10,6 @@ RSpec.shared_examples 'when the snippet is not found' do | |||
| end | ||||
| 
 | ||||
| RSpec.shared_examples 'snippet edit usage data counters' do | ||||
|   include SessionHelpers | ||||
| 
 | ||||
|   context 'when user is sessionless' do | ||||
|     it 'does not track usage data actions' do | ||||
|       expect(::Gitlab::UsageDataCounters::EditorUniqueCounter).not_to receive(:track_snippet_editor_edit_action) | ||||
|  | @ -22,7 +20,14 @@ RSpec.shared_examples 'snippet edit usage data counters' do | |||
| 
 | ||||
|   context 'when user is not sessionless', :clean_gitlab_redis_sessions do | ||||
|     before do | ||||
|       stub_session('warden.user.user.key' => [[current_user.id], current_user.encrypted_password[0, 29]]) | ||||
|       session_id = Rack::Session::SessionId.new('6919a6f1bb119dd7396fadc38fd18d0d') | ||||
|       session_hash = { 'warden.user.user.key' => [[current_user.id], current_user.encrypted_password[0, 29]] } | ||||
| 
 | ||||
|       Gitlab::Redis::Sessions.with do |redis| | ||||
|         redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash)) | ||||
|       end | ||||
| 
 | ||||
|       cookies[Gitlab::Application.config.session_options[:key]] = session_id.public_id | ||||
|     end | ||||
| 
 | ||||
|     it 'tracks usage data actions', :clean_gitlab_redis_sessions do | ||||
|  |  | |||
|  | @ -580,88 +580,3 @@ RSpec.shared_examples 'rate-limited unauthenticated requests' do | |||
|     end | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| # Requires let variables: | ||||
| # * throttle_setting_prefix: "throttle_authenticated", "throttle_unauthenticated" | ||||
| RSpec.shared_examples 'rate-limited frontend API requests' do | ||||
|   let(:requests_per_period) { 1 } | ||||
|   let(:csrf_token) { SecureRandom.base64(ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH) } | ||||
|   let(:csrf_session) { { _csrf_token: csrf_token } } | ||||
|   let(:personal_access_token) { nil } | ||||
| 
 | ||||
|   let(:api_path) { '/projects' } | ||||
| 
 | ||||
|   # These don't actually exist, so a 404 is the expected response. | ||||
|   let(:files_api_path) { '/projects/1/repository/files/ref/path' } | ||||
|   let(:packages_api_path) { '/projects/1/packages/foo' } | ||||
|   let(:deprecated_api_path) { '/groups/1?with_projects=true' } | ||||
| 
 | ||||
|   def get_api(path: api_path, csrf: false) | ||||
|     headers = csrf ? { 'X-CSRF-Token' => csrf_token } : nil | ||||
|     get api(path, personal_access_token: personal_access_token), headers: headers | ||||
|   end | ||||
| 
 | ||||
|   def expect_not_found(&block) | ||||
|     yield | ||||
| 
 | ||||
|     expect(response).to have_gitlab_http_status(:not_found) | ||||
|   end | ||||
| 
 | ||||
|   before do | ||||
|     stub_application_setting( | ||||
|       "#{throttle_setting_prefix}_enabled" => true, | ||||
|       "#{throttle_setting_prefix}_requests_per_period" => requests_per_period, | ||||
|       "#{throttle_setting_prefix}_api_enabled" => true, | ||||
|       "#{throttle_setting_prefix}_api_requests_per_period" => requests_per_period, | ||||
|       "#{throttle_setting_prefix}_web_enabled" => true, | ||||
|       "#{throttle_setting_prefix}_web_requests_per_period" => requests_per_period, | ||||
|       "#{throttle_setting_prefix}_files_api_enabled" => true, | ||||
|       "#{throttle_setting_prefix}_packages_api_enabled" => true, | ||||
|       "#{throttle_setting_prefix}_deprecated_api_enabled" => true | ||||
|     ) | ||||
| 
 | ||||
|     stub_session(csrf_session) | ||||
|   end | ||||
| 
 | ||||
|   context 'with a CSRF token' do | ||||
|     it 'uses the rate limit for web requests' do | ||||
|       requests_per_period.times { get_api csrf: true } | ||||
| 
 | ||||
|       expect_rejection("#{throttle_setting_prefix}_web") { get_api csrf: true } | ||||
|       expect_rejection("#{throttle_setting_prefix}_web") { get_api csrf: true, path: files_api_path } | ||||
|       expect_rejection("#{throttle_setting_prefix}_web") { get_api csrf: true, path: packages_api_path } | ||||
|       expect_rejection("#{throttle_setting_prefix}_web") { get_api csrf: true, path: deprecated_api_path } | ||||
| 
 | ||||
|       # API rate limit is not triggered yet | ||||
|       expect_ok { get_api } | ||||
|       expect_not_found { get_api path: files_api_path } | ||||
|       expect_not_found { get_api path: packages_api_path } | ||||
|       expect_not_found { get_api path: deprecated_api_path } | ||||
|     end | ||||
| 
 | ||||
|     context 'without a CSRF session' do | ||||
|       let(:csrf_session) { nil } | ||||
| 
 | ||||
|       it 'always uses the rate limit for API requests' do | ||||
|         requests_per_period.times { get_api csrf: true } | ||||
| 
 | ||||
|         expect_rejection("#{throttle_setting_prefix}_api") { get_api csrf: true } | ||||
|         expect_rejection("#{throttle_setting_prefix}_api") { get_api } | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   context 'without a CSRF token' do | ||||
|     it 'uses the rate limit for API requests' do | ||||
|       requests_per_period.times { get_api } | ||||
| 
 | ||||
|       expect_rejection("#{throttle_setting_prefix}_api") { get_api } | ||||
| 
 | ||||
|       # Web and custom API rate limits are not triggered yet | ||||
|       expect_ok { get_api csrf: true } | ||||
|       expect_not_found { get_api path: files_api_path } | ||||
|       expect_not_found { get_api path: packages_api_path } | ||||
|       expect_not_found { get_api path: deprecated_api_path } | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue