Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-08-28 18:11:00 +00:00
parent 8b992ba228
commit 672c5fcf46
50 changed files with 826 additions and 294 deletions

View File

@ -1,6 +1,7 @@
.as-if-jh-sandbox-variables:
variables:
AS_IF_JH_BRANCH: "as-if-jh/${CI_COMMIT_REF_NAME}"
JH_MIRROR_REPOSITORY: "https://dummy:${ADD_JH_FILES_TOKEN}@gitlab.com/gitlab-org/gitlab-jh-mirrors/gitlab.git"
SANDBOX_REPOSITORY: "https://dummy:${AS_IF_JH_TOKEN}@gitlab.com/gitlab-org-sandbox/gitlab-jh-validation.git"
.shared-as-if-jh:
@ -22,18 +23,22 @@ add-jh-files:
- source ./scripts/setup/as-if-jh.sh
- install_gitlab_gem
script:
- prepare_jh_branch
- download_jh_path ${JH_FILES_TO_COMMIT}
- set_jh_branch_env_variable
- download_jh_files ${JH_FILES_TO_COMMIT}
- echoinfo "Changes after downloading JiHu files:"
- git diff
- git status
artifacts:
expire_in: 2d
when: always # We also want the artifacts when we exit with error 3 (detached pipeline in that case)
paths:
# This should match JH_FILES_TO_COMMIT
- jh/
- package.json
- yarn.lock
allow_failure:
exit_codes:
- 3 # Set in the download_jh_files_from_git_clone function
prepare-as-if-jh-branch:
extends:

View File

@ -2,8 +2,6 @@
module PreferredLanguageSwitcher
extend ActiveSupport::Concern
include Gitlab::Utils::StrongMemoize
include PreferredLanguageSwitcherHelper
private
@ -13,36 +11,8 @@ module PreferredLanguageSwitcher
def preferred_language
cookies[:preferred_language].presence_in(Gitlab::I18n.available_locales) ||
selectable_language(marketing_site_language) ||
selectable_language(browser_languages) ||
Gitlab::CurrentSettings.default_preferred_language
end
def selectable_language(language_options)
language_options.find { |lan| ordered_selectable_locales_codes.include?(lan) }
end
def browser_languages
http_language_header = request.env['HTTP_ACCEPT_LANGUAGE']
return [] unless http_language_header
http_language_header.tr!('-', '_').split(%r{[;,]}).reject { |str| str.start_with?('q') }
end
strong_memoize_attr :browser_languages
def marketing_site_language
return [] unless params[:glm_source]
locale = params[:glm_source].scan(%r{(\w{2})-(\w{2})/}).flatten
return [] if locale.empty?
[locale[0], "#{locale[0]}_#{locale[1]}"]
end
def ordered_selectable_locales_codes
ordered_selectable_locales.map { |locale| locale[:value] } # rubocop:disable Rails/Pluck
end
end
PreferredLanguageSwitcher.prepend_mod

View File

@ -11,6 +11,8 @@ class ProjectAuthorization < ApplicationRecord
validates :access_level, inclusion: { in: Gitlab::Access.all_values }, presence: true
validates :user, uniqueness: { scope: :project }, presence: true
scope :non_guests, -> { where('access_level > ?', ::Gitlab::Access::GUEST) }
def self.select_from_union(relations)
from_union(relations)
.select(['project_id', 'MAX(access_level) AS access_level'])

View File

@ -1,8 +0,0 @@
---
name: namespace_storage_forks_cost_factor
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/126775
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/419181
milestone: '16.3'
type: development
group: group::utilization
default_enabled: false

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
class RemovePagesDeploymentsProjectIdPathPrefixUniqueIndex < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
def up
remove_concurrent_index_by_name :pages_deployments,
'index_pages_deployments_unique_path_prefix_by_project'
end
def down
# no op
end
end

View File

@ -0,0 +1 @@
ecc37b7f9517923afa19a5e965819f70e73908e24c2f1d8cd5875137e6199966

View File

@ -32852,8 +32852,6 @@ CREATE INDEX index_pages_deployments_on_file_store_and_id ON pages_deployments U
CREATE INDEX index_pages_deployments_on_project_id ON pages_deployments USING btree (project_id);
CREATE UNIQUE INDEX index_pages_deployments_unique_path_prefix_by_project ON pages_deployments USING btree (project_id, path_prefix);
CREATE INDEX index_pages_domain_acme_orders_on_challenge_token ON pages_domain_acme_orders USING btree (challenge_token);
CREATE INDEX index_pages_domain_acme_orders_on_pages_domain_id ON pages_domain_acme_orders USING btree (pages_domain_id);

View File

@ -156,12 +156,12 @@ For the storage-specific form,
[direct upload may become the default](https://gitlab.com/gitlab-org/gitlab/-/issues/27331)
because it does not require a shared folder.
For configuring object storage in GitLab 13.1 and earlier, or for storage types not
supported by consolidated form, refer to the following guides:
For configuring object storage in GitLab 13.1 and earlier, _or_ for storage types not
For storage types not supported by the consolidated form, refer to the following guides:
| Object storage type | Supported by consolidated form? |
|---------------------|------------------------------------------|
| [Project-level Secure Files](secure_files.md#using-object-storage) | **{dotted-circle}** No |
| [Secure Files](secure_files.md#using-object-storage) | **{dotted-circle}** No |
| [Backups](../administration/backup_restore/backup_gitlab.md#upload-backups-to-a-remote-cloud-storage) | **{dotted-circle}** No |
| [Container Registry](packages/container_registry.md#use-object-storage) (optional feature) | **{dotted-circle}** No |
| [Mattermost](https://docs.mattermost.com/configure/file-storage-configuration-settings.html)| **{dotted-circle}** No |

View File

@ -2383,6 +2383,7 @@ Input type: `CreateTestCaseInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationcreatetestcaseclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcreatetestcaseconfidential"></a>`confidential` | [`Boolean`](#boolean) | Sets the test case confidentiality. |
| <a id="mutationcreatetestcasedescription"></a>`description` | [`String`](#string) | Test case description. |
| <a id="mutationcreatetestcaselabelids"></a>`labelIds` | [`[ID!]`](#id) | IDs of labels to be added to the test case. |
| <a id="mutationcreatetestcaseprojectpath"></a>`projectPath` | [`ID!`](#id) | Project full path to create the test case in. |

View File

@ -542,9 +542,9 @@ listed in the descriptions of the relevant settings.
| `shared_runners_enabled` | boolean | no | (**If enabled, requires:** `shared_runners_text` and `shared_runners_minutes`) Enable shared runners for new projects. |
| `shared_runners_minutes` **(PREMIUM ALL)** | integer | required by: `shared_runners_enabled` | Set the maximum number of compute minutes that a group can use on shared runners per month. |
| `shared_runners_text` | string | required by: `shared_runners_enabled` | Shared runners text. |
| `runner_token_expiration_interval` | integer | no | Set the expiration time (in seconds) of authentication tokens of newly registered instance runners. Minimum value is 7200 seconds. For more information, see [Automatically rotate authentication tokens](../ci/runners/configure_runners.md#automatically-rotate-authentication-tokens). |
| `group_runner_token_expiration_interval` | integer | no | Set the expiration time (in seconds) of authentication tokens of newly registered group runners. Minimum value is 7200 seconds. For more information, see [Automatically rotate authentication tokens](../ci/runners/configure_runners.md#automatically-rotate-authentication-tokens). |
| `project_runner_token_expiration_interval` | integer | no | Set the expiration time (in seconds) of authentication tokens of newly registered project runners. Minimum value is 7200 seconds. For more information, see [Automatically rotate authentication tokens](../ci/runners/configure_runners.md#automatically-rotate-authentication-tokens). |
| `runner_token_expiration_interval` | integer | no | Set the expiration time (in seconds) of authentication tokens of newly registered instance runners. Minimum value is 7200 seconds. For more information, see [Automatically rotate authentication tokens](../ci/runners/configure_runners.md#automatically-rotate-runner-authentication-tokens). |
| `group_runner_token_expiration_interval` | integer | no | Set the expiration time (in seconds) of authentication tokens of newly registered group runners. Minimum value is 7200 seconds. For more information, see [Automatically rotate authentication tokens](../ci/runners/configure_runners.md#automatically-rotate-runner-authentication-tokens). |
| `project_runner_token_expiration_interval` | integer | no | Set the expiration time (in seconds) of authentication tokens of newly registered project runners. Minimum value is 7200 seconds. For more information, see [Automatically rotate authentication tokens](../ci/runners/configure_runners.md#automatically-rotate-runner-authentication-tokens). |
| `sidekiq_job_limiter_mode` | string | no | `track` or `compress`. Sets the behavior for [Sidekiq job size limits](../administration/settings/sidekiq_job_limits.md). Default: 'compress'. |
| `sidekiq_job_limiter_compression_threshold_bytes` | integer | no | The threshold in bytes at which Sidekiq jobs are compressed before being stored in Redis. Default: 100,000 bytes (100 KB). |
| `sidekiq_job_limiter_limit_bytes` | integer | no | The threshold in bytes at which Sidekiq jobs are rejected. Default: 0 bytes (doesn't reject any job). |

View File

@ -187,11 +187,11 @@ The response is `404 Not Found` if the vulnerability export is not finished yet
Example response:
```csv
Group Name,Project Name,Tool,Scanner Name,Status,Vulnerability,Details,Additional Info,Severity,CVE,CWE,Other Identifiers,Detected At,Location,Activity,Comments,
Gitlab.org,Defend,container_scanning,Trivy,resolved,CVE-2019-14697 in musl-utils-1.1.20-r4,"musl libc through 1.1.23 has an x87 floating-point stack adjustment imbalance, related to the math/i386/ directory. In some cases, use of this library could introduce out-of-bounds writes that are not present in an application's source code.",CVE-2019-14697 in musl-utils-1.1.20-r4,critical,CVE-2019-14697,,"",2022-10-07 13:34:41 UTC,"{""image""=>""python:3.4-alpine"", ""dependency""=>{""package""=>{""name""=>""musl-utils""}, ""version""=>""1.1.20-r4""}, ""operating_system""=>""alpine 3.9.2""}",true,"2022-10-07 13:41:08 UTC|root|resolved|changed vulnerability status to resolved",
Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2019-19242 in sqlite-libs-3.26.0-r3,"SQLite 3.30.1 mishandles pExpr->y.pTab, as demonstrated by the TK_COLUMN case in sqlite3ExprCodeTarget in expr.c.",CVE-2019-19242 in sqlite-libs-3.26.0-r3,medium,CVE-2019-19242,,"",2022-10-07 13:34:41 UTC,"{""image""=>""python:3.4-alpine"", ""dependency""=>{""package""=>{""name""=>""sqlite-libs""}, ""version""=>""3.26.0-r3""}, ""operating_system""=>""alpine 3.9.2""}",true,"",
Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2020-28928 in musl-1.1.20-r4,"In musl libc through 1.2.1, wcsnrtombs mishandles particular combinations of destination buffer size and source character limit, as demonstrated by an invalid write access (buffer overflow).",CVE-2020-28928 in musl-1.1.20-r4,medium,CVE-2020-28928,,"",2022-10-07 13:34:41 UTC,"{""image""=>""python:3.4-alpine"", ""dependency""=>{""package""=>{""name""=>""musl""}, ""version""=>""1.1.20-r4""}, ""operating_system""=>""alpine 3.9.2""}",true,"",
Gitlab.org,Defend,dependency_scanning,Gemnasium,detected,Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') in rack,Carefully crafted requests can cause shell escape sequences to be written to the terminal via Rack's Lint middleware and CommonLogger middleware. These escape sequences can be leveraged to possibly execute commands in the victim's terminal.,Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') in rack,unknown,Gemfile.lock:rack:gemnasium:60b5a27f-4e4d-4ab4-8ae7-74b4b212e177,,Gemnasium-60b5a27f-4e4d-4ab4-8ae7-74b4b212e177; GHSA-wq4h-7r42-5hrr,2022-10-14 13:16:00 UTC,"{""file""=>""Gemfile.lock"", ""dependency""=>{""package""=>{""name""=>""rack""}, ""version""=>""2.2.3""}}",false,"",
Gitlab.org,Defend,dependency_scanning,Gemnasium,detected,Denial of Service Vulnerability in Rack Multipart Parsing in rack,"Carefully crafted multipart POST requests can cause Rack's multipart parser to take much longer than expected, leading to a possible denial of service vulnerability. Impacted code will use Rack's multipart parser to parse multipart posts.",Denial of Service Vulnerability in Rack Multipart Parsing in rack,unknown,Gemfile.lock:rack:gemnasium:20daa17a-47b5-4f79-80c2-cd8f2db9805c,,Gemnasium-20daa17a-47b5-4f79-80c2-cd8f2db9805c; GHSA-hxqx-xwvh-44m2,2022-10-14 13:16:00 UTC,"{""file""=>""Gemfile.lock"", ""dependency""=>{""package""=>{""name""=>""rack""}, ""version""=>""2.2.3""}}",false,"",
Gitlab.org,Defend,sast,Brakeman,detected,Possible SQL injection,,Possible SQL injection,medium,e52f23a259cd489168b4313317ac94a3f13bffde57b9635171c1a44a9f329e9a,,"""Brakeman Warning Code 0""",2022-10-13 15:16:36 UTC,"{""file""=>""main.rb"", ""class""=>""User"", ""method""=>""index"", ""start_line""=>3}",false,""
Group Name,Project Name,Tool,Scanner Name,Status,Vulnerability,Details,Additional Info,Severity,CVE,CWE,Other Identifiers,Detected At,Location,Activity,Comments,Full Path
Gitlab.org,Defend,container_scanning,Trivy,resolved,CVE-2019-14697 in musl-utils-1.1.20-r4,"musl libc through 1.1.23 has an x87 floating-point stack adjustment imbalance, related to the math/i386/ directory. In some cases, use of this library could introduce out-of-bounds writes that are not present in an application's source code.",CVE-2019-14697 in musl-utils-1.1.20-r4,critical,CVE-2019-14697,,"",2022-10-07 13:34:41 UTC,"{""image""=>""python:3.4-alpine"", ""dependency""=>{""package""=>{""name""=>""musl-utils""}, ""version""=>""1.1.20-r4""}, ""operating_system""=>""alpine 3.9.2""}",true,"2022-10-07 13:41:08 UTC|root|resolved|changed vulnerability status to resolved",group/project/1
Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2019-19242 in sqlite-libs-3.26.0-r3,"SQLite 3.30.1 mishandles pExpr->y.pTab, as demonstrated by the TK_COLUMN case in sqlite3ExprCodeTarget in expr.c.",CVE-2019-19242 in sqlite-libs-3.26.0-r3,medium,CVE-2019-19242,,"",2022-10-07 13:34:41 UTC,"{""image""=>""python:3.4-alpine"", ""dependency""=>{""package""=>{""name""=>""sqlite-libs""}, ""version""=>""3.26.0-r3""}, ""operating_system""=>""alpine 3.9.2""}",true,"",group/project/2
Gitlab.org,Defend,container_scanning,Trivy,detected,CVE-2020-28928 in musl-1.1.20-r4,"In musl libc through 1.2.1, wcsnrtombs mishandles particular combinations of destination buffer size and source character limit, as demonstrated by an invalid write access (buffer overflow).",CVE-2020-28928 in musl-1.1.20-r4,medium,CVE-2020-28928,,"",2022-10-07 13:34:41 UTC,"{""image""=>""python:3.4-alpine"", ""dependency""=>{""package""=>{""name""=>""musl""}, ""version""=>""1.1.20-r4""}, ""operating_system""=>""alpine 3.9.2""}",true,"",group/project/3
Gitlab.org,Defend,dependency_scanning,Gemnasium,detected,Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') in rack,Carefully crafted requests can cause shell escape sequences to be written to the terminal via Rack's Lint middleware and CommonLogger middleware. These escape sequences can be leveraged to possibly execute commands in the victim's terminal.,Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') in rack,unknown,Gemfile.lock:rack:gemnasium:60b5a27f-4e4d-4ab4-8ae7-74b4b212e177,,Gemnasium-60b5a27f-4e4d-4ab4-8ae7-74b4b212e177; GHSA-wq4h-7r42-5hrr,2022-10-14 13:16:00 UTC,"{""file""=>""Gemfile.lock"", ""dependency""=>{""package""=>{""name""=>""rack""}, ""version""=>""2.2.3""}}",false,"",group/project/4
Gitlab.org,Defend,dependency_scanning,Gemnasium,detected,Denial of Service Vulnerability in Rack Multipart Parsing in rack,"Carefully crafted multipart POST requests can cause Rack's multipart parser to take much longer than expected, leading to a possible denial of service vulnerability. Impacted code will use Rack's multipart parser to parse multipart posts.",Denial of Service Vulnerability in Rack Multipart Parsing in rack,unknown,Gemfile.lock:rack:gemnasium:20daa17a-47b5-4f79-80c2-cd8f2db9805c,,Gemnasium-20daa17a-47b5-4f79-80c2-cd8f2db9805c; GHSA-hxqx-xwvh-44m2,2022-10-14 13:16:00 UTC,"{""file""=>""Gemfile.lock"", ""dependency""=>{""package""=>{""name""=>""rack""}, ""version""=>""2.2.3""}}",false,"",group/project/5
Gitlab.org,Defend,sast,Brakeman,detected,Possible SQL injection,,Possible SQL injection,medium,e52f23a259cd489168b4313317ac94a3f13bffde57b9635171c1a44a9f329e9a,,"""Brakeman Warning Code 0""",2022-10-13 15:16:36 UTC,"{""file""=>""main.rb"", ""class""=>""User"", ""method""=>""index"", ""start_line""=>3}",false,"",group/project/6
```

View File

@ -78,7 +78,7 @@ graph TD
<!-- vale gitlab.Spelling = NO -->
In this proposal, runners created in the GitLab UI are assigned
[authentication tokens](../../../security/token_overview.md#runner-authentication-tokens-also-called-runner-tokens)
[authentication tokens](../../../security/token_overview.md#runner-authentication-tokens)
prefixed with `glrt-` (**G**it**L**ab **R**unner **T**oken).
<!-- vale gitlab.Spelling = YES -->
The prefix allows the existing `register` command to use the authentication token _in lieu_
@ -97,8 +97,8 @@ token in the `--registration-token` argument:
| Token type | Behavior |
| ---------- | -------- |
| [Registration token](../../../security/token_overview.md#runner-authentication-tokens-also-called-runner-tokens) | Leverages the `POST /api/v4/runners` REST endpoint to create a new runner, creating a new entry in `config.toml`. |
| [Authentication token](../../../security/token_overview.md#runner-authentication-tokens-also-called-runner-tokens) | Leverages the `POST /api/v4/runners/verify` REST endpoint to ensure the validity of the authentication token. Creates an entry in `config.toml` file and a `system_id` value in a sidecar file if missing (`.runner_system_id`). |
| [Registration token](../../../security/token_overview.md#runner-authentication-tokens) | Leverages the `POST /api/v4/runners` REST endpoint to create a new runner, creating a new entry in `config.toml`. |
| [Runner authentication token](../../../security/token_overview.md#runner-authentication-tokens) | Leverages the `POST /api/v4/runners/verify` REST endpoint to ensure the validity of the authentication token. Creates an entry in `config.toml` file and a `system_id` value in a sidecar file if missing (`.runner_system_id`). |
### Transition period
@ -427,7 +427,7 @@ scope.
| GitLab Rails app | `%16.6` | Disable registration tokens on the instance level by running database migration (except GitLab.com) | |
| GitLab Rails app | `%16.8` | Disable registration tokens on the instance level for GitLab.com | |
| GitLab Rails app | `%16.3` | Implement new `:create_runner` PPGAT scope so that we don't require a full `api` scope. |
| GitLab Rails app | | Document gotchas when [automatically rotating runner tokens](../../../ci/runners/configure_runners.md#automatically-rotate-authentication-tokens) with multiple machines. |
| GitLab Rails app | | Document gotchas when [automatically rotating runner tokens](../../../ci/runners/configure_runners.md#automatically-rotate-runner-authentication-tokens) with multiple machines. |
### Stage 7 - Removals

View File

@ -64,9 +64,9 @@ of shared runners on large GitLab instances. This ensures that you
control access to your GitLab instances and secure [runner executors](https://docs.gitlab.com/runner/executors/).
If certain executors run a job, the file system, the code the runner executes,
and the runner token may be exposed. This means that anyone that runs jobs
and the runner authentication token may be exposed. This means that anyone that runs jobs
on a _shared runner_ can access another user's code that runs on the runner.
Users with access to the runner token can use it to create a clone of
Users with access to the runner authentication token can use it to create a clone of
a runner and submit false jobs in a vector attack. For more information, see [Security Considerations](https://docs.gitlab.com/runner/security/).
### Prevent runners from revealing sensitive information
@ -124,19 +124,19 @@ you use to provision and register new values.
### Reset the runner authentication token
If an authentication token is revealed, an attacker could use the token to [clone a runner](https://docs.gitlab.com/runner/security/#cloning-a-runner).
If a runner authentication token is revealed, an attacker could use the token to [clone a runner](https://docs.gitlab.com/runner/security/#cloning-a-runner).
To reset the authentication token:
To reset the runner authentication token:
1. Delete the runner:
- [Delete a shared runner](runners_scope.md#delete-shared-runners).
- [Delete a group runner](runners_scope.md#delete-a-group-runner).
- [Delete a project runner](runners_scope.md#delete-a-project-runner).
1. Create a new runner so that it is assigned a new authentication token:
- [Create a shared runner](runners_scope.md#create-a-shared-runner-with-an-authentication-token).
- [Create a group runner](runners_scope.md#create-a-group-runner-with-an-authentication-token).
- [Create a project runner](runners_scope.md#create-a-project-runner-with-an-authentication-token).
1. Optional. To verify that the previous authentication token has been revoked, use the [Runners API](../../api/runners.md#verify-authentication-for-a-registered-runner).
1. Create a new runner so that it is assigned a new runner authentication token:
- [Create a shared runner](runners_scope.md#create-a-shared-runner-with-a-runner-authentication-token).
- [Create a group runner](runners_scope.md#create-a-group-runner-with-a-runner-authentication-token).
- [Create a project runner](runners_scope.md#create-a-project-runner-with-a-runner-authentication-token).
1. Optional. To verify that the previous runner authentication token has been revoked, use the [Runners API](../../api/runners.md#verify-authentication-for-a-registered-runner).
## Use tags to control which jobs a runner can run
@ -874,7 +874,7 @@ defaults to the number of CPUs available.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30942) in GitLab 15.3 [with a flag](../../administration/feature_flags.md) named `enforce_runner_token_expires_at`. Disabled by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/377902) in GitLab 15.5. Feature flag `enforce_runner_token_expires_at` removed.
Each runner has an [authentication token](../../api/runners.md#registration-and-authentication-tokens)
Each runner has an [runner authentication token](../../api/runners.md#registration-and-authentication-tokens)
to connect with the GitLab instance.
To help prevent the token from being compromised, you can have the
@ -883,12 +883,12 @@ they are updated for each runner, regardless of the runner's status (`online` or
No manual intervention should be required, and no running jobs should be affected.
If you need to manually update the authentication token, you can run a
If you need to manually update the runner authentication token, you can run a
command to [reset the token](https://docs.gitlab.com/runner/commands/#gitlab-runner-reset-token).
### Automatically rotate authentication tokens
### Automatically rotate runner authentication tokens
You can specify an interval for authentication tokens to rotate.
You can specify an interval for runner authentication tokens to rotate.
This rotation helps ensure the security of the tokens assigned to your runners.
Prerequisites:
@ -904,4 +904,4 @@ To automatically rotate runner authentication tokens:
1. Set a **Runners expiration** time for runners, leave empty for no expiration.
1. Select **Save**.
Before the interval expires, runners automatically request a new authentication token.
Before the interval expires, runners automatically request a new runner authentication token.

View File

@ -14,7 +14,7 @@ As with all projects, the items mentioned on this page are subject to change or
The development, release, and timing of any products, features, or functionality remain at the
sole discretion of GitLab Inc.
In GitLab 16.0, we introduced a new runner creation workflow that uses authentication tokens to register
In GitLab 16.0, we introduced a new runner creation workflow that uses runner authentication tokens to register
runners. The legacy workflow that uses registration tokens is deprecated and will be removed in GitLab 17.0.
For information about the current development status of the new workflow, see [epic 7663](https://gitlab.com/groups/gitlab-org/-/epics/7663).
@ -30,8 +30,8 @@ you can let us know in the [feedback issue](https://gitlab.com/gitlab-org/gitlab
For the new runner registration workflow, you:
1. [Create a runner](register_runner.md) directly in the GitLab UI.
1. Receive an authentication token.
1. Use the authentication token instead of the registration token when you register
1. Receive a runner authentication token.
1. Use the runner authentication token instead of the registration token when you register
a runner with this configuration. Runner managers registered in multiple hosts appear
under the same runner in the GitLab UI, but with an identifying system ID.
@ -59,7 +59,7 @@ workflow will break.
To avoid a broken workflow, you must:
1. [Create a shared runner](runners_scope.md#create-a-shared-runner-with-an-authentication-token) and obtain the authentication token.
1. [Create a shared runner](runners_scope.md#create-a-shared-runner-with-a-runner-authentication-token) and obtain the authentication token.
1. Replace the registration token in your runner registration workflow with the
authentication token.
@ -74,15 +74,15 @@ Plans to implement a UI setting to re-enable registration tokens are proposed in
## Changes to the `gitlab-runner register` command syntax
The `gitlab-runner register` command will stop accepting registration tokens and instead accept new
The `gitlab-runner register` command will stop accepting registration tokens and instead accept new runner
authentication tokens generated in the GitLab runners administration page.
These authentication tokens are recognizable by their `glrt-` prefix.
The runner authentication tokens are recognizable by their `glrt-` prefix.
When you create a runner in the GitLab UI, you specify configuration values that were previously command-line options
prompted by the `gitlab-runner register` command.
These command-line options have been [deprecated](../../update/deprecations.md#registration-tokens-and-server-side-runner-arguments-in-post-apiv4runners-endpoint).
If you specify an authentication token with:
If you specify a runner authentication token with:
- the `--token` command-line option, the `gitlab-runner register` command does not accept the configuration values.
- the `--registration-token` command-line option, the `gitlab-runner register` command ignores the configuration values.
@ -91,7 +91,7 @@ Authentication tokens have the prefix, `glrt-`.
To ensure minimal disruption to your automation workflow,
[legacy-compatible registration processing](https://docs.gitlab.com/runner/register/#legacy-compatible-registration-processing)
triggers if an authentication token is specified in the legacy parameter `--registration-token`.
triggers if a runner authentication token is specified in the legacy parameter `--registration-token`.
Example command for GitLab 15.9:
@ -124,7 +124,7 @@ gitlab-runner register \
## Impact on autoscaling
In autoscaling scenarios such as GitLab Runner Operator or GitLab Runner Helm Chart, the
registration token is replaced with the authentication token generated from the UI.
registration token is replaced with the runner authentication token generated from the UI.
This means that the same runner configuration is reused across jobs, instead of creating a runner
for each job.
The specific runner can be identified by the unique system ID that is generated when the runner
@ -137,7 +137,7 @@ Existing runners will continue to work as usual. This change only affects regist
## Creating runners programmatically
In GitLab 15.11 and later, you can use the [POST /user/runners REST API](../../api/users.md#create-a-runner) to create a runner as an authenticated user. This should only be used if the runner configuration is dynamic or not reusable. If the runner configuration is static, you should
reuse the authentication token of an existing runner. For more information, see [How to automate the creation of GitLab Runners](https://about.gitlab.com/blog/2023/07/06/how-to-automate-creation-of-runners/).
reuse the runner authentication token of an existing runner. For more information, see [How to automate the creation of GitLab Runners](https://about.gitlab.com/blog/2023/07/06/how-to-automate-creation-of-runners/).
The following snippet shows how a group runner could be created and registered with a
[Group Access Token](../../user/group/settings/group_access_tokens.md) using the new creation flow.
@ -181,7 +181,7 @@ runUntagged: true
protected: true
```
If you store the runner token in `secrets`, you must also modify them.
If you store the runner authentication token in `secrets`, you must also modify them.
In the legacy runner registration workflow, fields were specified with:

View File

@ -34,7 +34,7 @@ If you are using GitLab.com:
- The shared runners consume the [compute minutes](../pipelines/cicd_minutes.md)
included with your account.
### Create a shared runner with an authentication token
### Create a shared runner with a runner authentication token
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/383139) in GitLab 15.10. Deployed behind the `create_runner_workflow_for_admin` [flag](../../administration/feature_flags.md)
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/389269) in GitLab 16.0.
@ -44,7 +44,7 @@ Prerequisite:
- You must be an administrator.
When you create a runner, it is assigned an authentication token that you use to register it. The runner uses the token to authenticate with GitLab when picking up jobs from the job queue.
When you create a runner, it is assigned a runner authentication token that you use to register it. The runner uses the token to authenticate with GitLab when picking up jobs from the job queue.
To create a shared runner:
@ -57,10 +57,10 @@ To create a shared runner:
1. Select **Submit**.
1. Follow the on-screen instructions to register the runner from the command line.
You can also [create a runner](../../api/users.md#create-a-runner) with the API to generate an authentication token.
You can also [create a runner](../../api/users.md#create-a-runner) with the API to generate a runner authentication token.
NOTE:
The authentication token displays in the UI for only a short period of time during registration.
The runner authentication token displays in the UI for only a short period of time during registration.
### Create a shared runner with a registration token (deprecated)
@ -222,7 +222,7 @@ to have access to a set of runners.
Group runners process jobs by using a first in, first out queue.
### Create a group runner with an authentication token
### Create a group runner with a runner authentication token
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/383143) in GitLab 15.10. Deployed behind the `create_runner_workflow_for_namespace` [flag](../../administration/feature_flags.md). Disabled by default.
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/393919) in GitLab 16.0.
@ -233,7 +233,7 @@ Prerequisites:
- You must have the Owner role for the group.
You can create a group runner for your self-managed GitLab instance or for GitLab.com.
When you create a runner, it is assigned an authentication token that you use to register it. The runner uses the token to authenticate with GitLab when picking up jobs from the job queue.
When you create a runner, it is assigned a runner authentication token that you use to register it. The runner uses the token to authenticate with GitLab when picking up jobs from the job queue.
To create a group runner:
@ -248,7 +248,7 @@ To create a group runner:
You can also [create a runner](../../api/users.md#create-a-runner) with the API to generate an authentication token.
NOTE:
The authentication token displays in the UI for only a short period of time during registration.
The runner authentication token displays in the UI for only a short period of time during registration.
### Create a group runner with a registration token (deprecated)
@ -399,7 +399,7 @@ NOTE:
Project runners do not get shared with forked projects automatically.
A fork *does* copy the CI/CD settings of the cloned repository.
### Create a project runner with an authentication token
### Create a project runner with a runner authentication token
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/383143) in GitLab 15.10. Deployed behind the `create_runner_workflow_for_namespace` [flag](../../administration/feature_flags.md). Disabled by default.
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/393919) in GitLab 16.0.
@ -409,7 +409,7 @@ Prerequisites:
- You must have the Maintainer role for the project.
You can create a project runner for your self-managed GitLab instance or for GitLab.com. When you create a runner, it is assigned an authentication token that you use to register to the runner. The runner uses the token to authenticate with GitLab when picking up jobs from the job queue.
You can create a project runner for your self-managed GitLab instance or for GitLab.com. When you create a runner, it is assigned a runner authentication token that you use to register to the runner. The runner uses the token to authenticate with GitLab when picking up jobs from the job queue.
To create a project runner:
@ -422,10 +422,10 @@ To create a project runner:
1. Select **Submit**.
1. Follow the on-screen instructions to register the runner from the command line.
You can also [create a runner](../../api/users.md#create-a-runner) with the API to generate an authentication token.
You can also [create a runner](../../api/users.md#create-a-runner) with the API to generate a runner authentication token.
NOTE:
The authentication token displays in the UI for only a short period of time during registration.
The runner authentication token displays in the UI for only a short period of time during registration.
### Create a project runner with a registration token (deprecated)

View File

@ -984,7 +984,7 @@ To be consistent, use these templates when you write navigation steps in a task
To open project settings:
```markdown
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Settings > CI/CD**.
1. Expand **General pipelines**.
```
@ -992,7 +992,7 @@ To open project settings:
To open group settings:
```markdown
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your group.
1. On the left sidebar, select **Search or go to** and find your group.
1. Select **Settings > CI/CD**.
1. Expand **General pipelines**.
```
@ -1000,7 +1000,7 @@ To open group settings:
To open either project or group settings:
```markdown
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project or group.
1. On the left sidebar, select **Search or go to** and find your project or group.
1. Select **Settings > CI/CD**.
1. Expand **General pipelines**.
```
@ -1020,14 +1020,14 @@ To create a group:
To open the Admin Area:
```markdown
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. On the left sidebar, select **Search or go to**.
1. Select **Admin Area**.
```
To open the **Your work** menu item:
```markdown
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. On the left sidebar, select **Search or go to**.
1. Select **Your work**.
```
@ -1049,15 +1049,15 @@ To save the selection in some dropdown lists:
To view all your projects:
```markdown
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **View all your projects**.
1. On the left sidebar, select **Search or go to**.
1. Select **View all my projects**.
```
To view all your groups:
```markdown
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **View all your groups**.
1. On the left sidebar, select **Search or go to**.
1. Select **View all my groups**.
```
### Optional steps
@ -1089,7 +1089,7 @@ Use the phrase **Complete the fields**.
For example:
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Settings > Repository**.
1. Expand **Push rules**.
1. Complete the fields.

View File

@ -1279,7 +1279,7 @@ Credentials can be:
- Login details like username and password.
- Private keys.
- Tokens (PAT, runner tokens, JWT token, CSRF tokens, project access tokens, etc).
- Tokens (PAT, runner authentication tokens, JWT token, CSRF tokens, project access tokens, etc).
- Session cookies.
- Any other piece of information that can be used for authentication or authorization purposes.

View File

@ -206,3 +206,15 @@ To rectify the following error, specify the deprecated DSN in **Sentry.io > Proj
```plaintext
ERROR: Sentry failure builds=0 error=raven: dsn missing private key
```
## Troubleshooting
When working with Error Tracking, you might encounter the following issues.
### Error `Connection failed. Check auth token and try again`
If the Monitor feature is disabled in the [project settings](../user/project/settings/index.md#configure-project-features-and-permissions),
you might see an error when you try to [enable Sentry integration for a project](#enable-sentry-integration-for-a-project).
The resulting request to `/project/path/-/error_tracking/projects.json?api_host=https:%2F%2Fsentry.example.com%2F&token=<token>` returns a 404 status.
To fix this issue, enable the Monitor feature for the project.

View File

@ -99,20 +99,20 @@ Runner registration tokens are used to [register](https://docs.gitlab.com/runner
You can use the runner registration token to add runners that execute jobs in a project or group. The runner has access to the project's code, so be careful when assigning project and group-level permissions.
## Runner authentication tokens (also called runner tokens)
## Runner authentication tokens
Once created, the runner receives an authentication token, which it uses to authenticate with GitLab when picking up jobs from the job queue. The authentication token is stored locally in the runner's [`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) file.
Once created, the runner receives a runner authentication token, which it uses to authenticate with GitLab when picking up jobs from the job queue. The runner authentication token is stored locally in the runner's [`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) file.
After authentication with GitLab, the runner receives a [job token](../ci/jobs/ci_job_token.md), which it uses to execute the job.
In case of Docker Machine/Kubernetes/VirtualBox/Parallels/SSH executors, the execution environment has no access to the runner authentication token, because it stays on the runner machine. They have access to the job token only, which is needed to execute the job.
Malicious access to a runner's file system may expose the `config.toml` file and thus the authentication token, allowing an attacker to [clone the runner](https://docs.gitlab.com/runner/security/#cloning-a-runner).
Malicious access to a runner's file system may expose the `config.toml` file and thus the runner authentication token, allowing an attacker to [clone the runner](https://docs.gitlab.com/runner/security/#cloning-a-runner).
In GitLab 16.0 and later, you can use an authentication token to register runners instead of a
registration token. Runner registration tokens have been [deprecated](../update/deprecations.md#registration-tokens-and-server-side-runner-arguments-in-gitlab-runner-register-command).
To generate an authentication token, you create a runner in the GitLab UI and use the authentication token
To generate a runner authentication token, you create a runner in the GitLab UI and use the authentication token
instead of the registration token.
| Process | Registration command |

View File

@ -107,7 +107,7 @@ To create a project runner:
### Check the runner configuration file
After you register the runner, the configuration and authentication token is saved to your `config.toml`. The runner uses the
After you register the runner, the configuration and runner authentication token is saved to your `config.toml`. The runner uses the
token to authenticate with GitLab when picking up jobs from the job queue.
You can use the `config.toml` to

View File

@ -139,7 +139,7 @@ You'll see that GitLab has run your `test` and `pages` jobs.
To view your site, on the left-hand navigation, select **Settings > Pages**
The `pages` job in your pipeline has deployed the contents of your `public` directory to GitLab Pages. Under **Access pages**, you should see the link in the format: `https://<your-namespace>.gitlab.io/<project-name>`.
The `pages` job in your pipeline has deployed the contents of your `public` directory to GitLab Pages. Under **Access pages**, you should see the link in the format: `https://<your-namespace>.gitlab.io/<project-path>`.
You won't see this link if you haven't yet run your pipeline.

View File

@ -275,6 +275,7 @@ epics:
| Merge Request | New note | Participants, Watchers, Subscribers, and Custom notification level with this event selected. Also anyone mentioned by username in the comment, with notification level "Mention" or higher. |
| Merge Request | Pushed | Participants and Custom notification level with this event selected. |
| Merge Request | Reassigned | Participants, Watchers, Subscribers, Custom notification level with this event selected, and the old assignee. |
| Merge Request | Review requested | Participants, Watchers, Subscribers, Custom notification level with this event selected, and the old reviewer. |
| Merge Request | Reopened | Subscribers and participants. |
| Merge Request | Title or description changed | Any new mentions by username. |
| Pipeline | Failed | The author of the pipeline. |

View File

@ -113,7 +113,7 @@ Subdomains (`subdomain.example.com`) require:
Whether it's a user or a project website, the DNS record
should point to your Pages domain (`namespace.gitlab.io`),
without any `/project-name`.
without any path (for example, `/project-slug`).
![DNS `CNAME` record pointing to GitLab.com project](img/dns_cname_record_example.png)

View File

@ -25,13 +25,14 @@ For GitLab self-managed instances, replace `example.io`
with your instance's Pages domain. For GitLab.com,
Pages domains are `*.gitlab.io`.
| Type of GitLab Pages | The name of the project created in GitLab | Website URL |
| Type of GitLab Pages | The path of the project created in GitLab | Website URL |
| -------------------- | ------------ | ----------- |
| User pages | `username.example.io` | `http(s)://username.example.io` |
| Group pages | `groupname.example.io` | `http(s)://groupname.example.io` |
| Project pages owned by a user | `projectname` | `http(s)://username.example.io/projectname` |
| Project pages owned by a group | `projectname` | `http(s)://groupname.example.io/projectname`|
| Project pages owned by a subgroup | `subgroup/projectname` | `http(s)://groupname.example.io/subgroup/projectname`|
| User pages | `username/username.example.io` | `http(s)://username.example.io` |
| Group pages | `acmecorp/acmecorp.example.io` | `http(s)://acmecorp.example.io` |
| Project pages owned by a user | `username/my-website` | `http(s)://username.example.io/my-website` |
| Project pages owned by a group | `acmecorp/webshop` | `http(s)://acmecorp.example.io/webshop`|
| Project pages owned by a subgroup | `acmecorp/documentation/product-manual` | `http(s)://acmecorp.example.io/documentation/product-manual`|
| Project pages owned by a subgroup | `group-path/subgroup-slug/project-slug` | `http(s)://group-path.example.io/subgroup-slug/project-slug`|
WARNING:
There are some known [limitations](introduction.md#subdomains-of-subdomains)
@ -72,7 +73,7 @@ To understand Pages domains clearly, read the examples below.
**General example:**
- On GitLab.com, a project site is always available under
`https://namespace.gitlab.io/project-name`
`https://namespace.gitlab.io/project-slug`
- On GitLab.com, a user or group website is available under
`https://namespace.gitlab.io/`
- On your GitLab instance, replace `gitlab.io` above with your
@ -86,7 +87,7 @@ The `baseurl` option might be named differently in some static site generators.
Every Static Site Generator (SSG) default configuration expects
to find your website under a (sub)domain (`example.com`), not
in a subdirectory of that domain (`example.com/subdir`). Therefore,
whenever you publish a project website (`namespace.gitlab.io/project-name`),
whenever you publish a project website (for example, `namespace.gitlab.io/project-slug`),
you must look for this configuration (base URL) on your static site generator's
documentation and set it up to reflect this pattern.

View File

@ -47,9 +47,9 @@ depending on your static generator configuration.
If the case of `404.html`, there are different scenarios. For example:
- If you use project Pages (served under `/projectname/`) and try to access
`/projectname/non/existing_file`, GitLab Pages tries to serve first
`/projectname/404.html`, and then `/404.html`.
- If you use project Pages (served under `/project-slug/`) and try to access
`/project-slug/non/existing_file`, GitLab Pages tries to serve first
`/project-slug/404.html`, and then `/404.html`.
- If you use user or group Pages (served under `/`) and try to access
`/non/existing_file` GitLab Pages tries to serve `/404.html`.
- If you use a custom domain and try to access `/non/existing_file`, GitLab
@ -87,7 +87,7 @@ For [group websites](../../project/pages/getting_started_part_one.md#user-and-gr
the group must be at the top level and not a subgroup.
For [project websites](../../project/pages/getting_started_part_one.md#project-website-examples),
you can create your project first and access it under `http(s)://namespace.example.io/projectname`.
you can create your project first and access it under `http(s)://namespace.example.io/project-path`.
## Enable unique domains
@ -308,7 +308,7 @@ For a list of known issues, see the GitLab [public issue tracker](https://gitlab
This problem most likely results from a missing `index.html` file in the public directory. If after deploying a Pages site
a 404 is encountered, confirm that the public directory contains an `index.html` file. If the file contains a different name
such as `test.html`, the Pages site can still be accessed, but the full path would be needed. For example: `https//group-name.pages.example.com/project-name/test.html`.
such as `test.html`, the Pages site can still be accessed, but the full path would be needed. For example: `https//group-name.pages.example.com/project-slug/test.html`.
The contents of the public directory can be confirmed by [browsing the artifacts](../../../ci/jobs/job_artifacts.md#download-job-artifacts) from the latest pipeline.

View File

@ -47,14 +47,14 @@ To create redirects, create a configuration file named `_redirects` in the
configured at the instance level. Only the first matching rules within the configured maximum are processed.
The default file size limit is 64 KB, and the default maximum number of rules is 1,000.
- If your GitLab Pages site uses the default domain name (such as
`namespace.gitlab.io/projectname`) you must prefix every rule with the project name:
`namespace.gitlab.io/project-slug`) you must prefix every rule with the path:
```plaintext
/projectname/wardrobe.html /projectname/narnia.html 302
/project-slug/wardrobe.html /project-slug/narnia.html 302
```
- If your GitLab Pages site uses [custom domains](custom_domains_ssl_tls_certification/index.md),
no project name prefix is needed. For example, if your custom domain is `example.com`,
no project path prefix is needed. For example, if your custom domain is `example.com`,
your `_redirects` file would look like:
```plaintext
@ -69,7 +69,7 @@ the file instead of your redirect. For example, if the files `hello.html` and
is ignored because `hello.html` exists:
```plaintext
/projectname/hello.html /projectname/world.html 302
/project-slug/hello.html /project-slug/world.html 302
```
GitLab does not support Netlify
@ -210,8 +210,7 @@ would **not** match a request URL like `/old/file`:
## Debug redirect rules
If a redirect isn't working as expected, or you want to check your redirect syntax, visit
`https://[namespace.gitlab.io]/projectname/_redirects`, replacing `[namespace.gitlab.io]` with
your domain name. The `_redirects` file isn't served directly, but your browser
`[your pages url]/_redirects`. The `_redirects` file isn't served directly, but your browser
displays a numbered list of your redirect rules, and whether the rule is valid or invalid:
```plaintext

View File

@ -58,6 +58,15 @@ module Gitlab
properties = data.dig('metadata', 'properties')
source = CyclonedxProperties.parse_source(properties)
report.set_source(source) if source
tools = data.dig('metadata', 'tools')
authors = data.dig('metadata', 'authors')
report.metadata = ::Gitlab::Ci::Reports::Sbom::Metadata.new.tap do |metadata|
metadata.tools = tools if tools
metadata.authors = authors if authors
metadata.properties = properties if properties
end
end
def parse_components

View File

@ -7,7 +7,7 @@ module Gitlab
class Component
include Gitlab::Utils::StrongMemoize
attr_reader :component_type, :version
attr_reader :component_type, :version, :path
def initialize(type:, name:, purl:, version:)
@component_type = type

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
module Gitlab
module Ci
module Reports
module Sbom
class Metadata
attr_accessor :tools, :authors, :properties
def initialize(tools: [], authors: [], properties: [])
@tools = tools
@authors = authors
@properties = properties
end
end
end
end
end
end

View File

@ -5,10 +5,24 @@ module Gitlab
module Reports
module Sbom
class Report
attr_reader :components, :source, :errors
# This represents the attributes defined in cycloneDX Schema
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/validators/json_schemas/cyclonedx_report.json#L7
BOM_FORMAT = 'CycloneDX'
SPEC_VERSION = '1.4'
VERSION = 1
attr_reader :source, :errors
attr_accessor :sbom_attributes, :metadata, :components
def initialize
@sbom_attributes = {
bom_format: BOM_FORMAT,
spec_version: SPEC_VERSION,
serial_number: "urn:uuid:#{SecureRandom.uuid}",
version: VERSION
}
@components = []
@metadata = ::Gitlab::Ci::Reports::Sbom::Metadata.new
@errors = []
end

View File

@ -67,10 +67,18 @@ module Gitlab
end
# Returns the details of a GitHub user.
# 304 (Not Modified) status means the user is cached - API won't return user data.
#
# username - The username of the user.
def user(username)
with_rate_limit { octokit.user(username).to_h }
# @param username[String] the username of the user.
# @param options[Hash] the optional parameters.
def user(username, options = {})
with_rate_limit do
user = octokit.user(username, options)
next if octokit.last_response&.status == 304
user.to_h
end
end
def pull_request_reviews(repo_name, iid)

View File

@ -28,6 +28,17 @@ module Gitlab
EMAIL_FOR_USERNAME_CACHE_KEY =
'github-import/user-finder/email-for-username/%s'
# The base cache key to use for caching the user ETAG response headers
USERNAME_ETAG_CACHE_KEY = 'github-import/user-finder/user-etag/%s'
# The base cache key to store whether an email has been fetched for a project
EMAIL_FETCHED_FOR_PROJECT_CACHE_KEY = 'github-import/user-finder/%{project}/email-fetched/%{username}'
EMAIL_API_CALL_LOGGING_MESSAGE = {
true => 'Fetching email from GitHub with ETAG header',
false => 'Fetching email from GitHub'
}.freeze
# project - An instance of `Project`
# client - An instance of `Gitlab::GithubImport::Client`
def initialize(project, client)
@ -109,24 +120,39 @@ module Gitlab
id_for_github_id(id) || id_for_github_email(email)
end
# Find the public email of a given username in GitHub. The public email is cached to avoid multiple calls to
# GitHub. In case the username does not exist or the public email is nil, a blank value is cached to also prevent
# multiple calls to GitHub.
# Find the public email of a given username in GitHub.
# The email is cached to avoid multiple calls to GitHub. The cache is shared among all projects.
# If the email was not found, a blank email is cached.
# If the email is blank, we attempt to fetch it from GitHub using an ETAG request once for every project.
# @param username [String] The username of the GitHub user.
#
# @return [String] If public email is found
# @return [Nil] If public email or username does not exist
def email_for_github_username(username)
cache_key = EMAIL_FOR_USERNAME_CACHE_KEY % username
email = Gitlab::Cache::Import::Caching.read(cache_key)
email = read_email_from_cache(username)
if email.nil?
user = client.user(username)
email = Gitlab::Cache::Import::Caching.write(cache_key, user[:email].to_s, timeout: timeout(user[:email]))
if email.blank? && !email_fetched_for_project?(username)
# If an ETAG is available, make an API call with the ETAG.
# Only make a rate-limited API call if the ETAG is not available and the email is nil.
etag = read_etag_from_cache(username)
email = fetch_email_from_github(username, etag: etag) || email
cache_email!(username, email)
cache_etag!(username) if email.blank? && etag.nil?
# If a non-blank email is cached, we don't need the ETAG or project check caches.
# Otherwise, indicate that the project has been checked.
if email.present?
clear_caches!(username)
else
set_project_as_checked!(username)
end
end
email.presence
rescue ::Octokit::NotFound
Gitlab::Cache::Import::Caching.write(cache_key, '')
cache_email!(username, '')
nil
end
@ -192,12 +218,66 @@ module Gitlab
private
def timeout(email)
if email
Gitlab::Cache::Import::Caching::TIMEOUT
else
Gitlab::Cache::Import::Caching::SHORTER_TIMEOUT
end
def read_email_from_cache(username)
Gitlab::Cache::Import::Caching.read(email_cache_key(username))
end
def read_etag_from_cache(username)
Gitlab::Cache::Import::Caching.read(etag_cache_key(username))
end
def email_fetched_for_project?(username)
email_fetched_for_project_cache_key = email_fetched_for_project_cache_key(username)
Gitlab::Cache::Import::Caching.read(email_fetched_for_project_cache_key)
end
def fetch_email_from_github(username, etag: nil)
log(EMAIL_API_CALL_LOGGING_MESSAGE[etag.present?], username: username)
user = client.user(username, { headers: { 'If-None-Match' => etag }.compact })
user[:email] || '' if user
end
def cache_email!(username, email)
return unless email
Gitlab::Cache::Import::Caching.write(email_cache_key(username), email)
end
def cache_etag!(username)
etag = client.octokit.last_response.headers[:etag]
Gitlab::Cache::Import::Caching.write(etag_cache_key(username), etag)
end
def set_project_as_checked!(username)
Gitlab::Cache::Import::Caching.write(email_fetched_for_project_cache_key(username), 1)
end
def clear_caches!(username)
Gitlab::Cache::Import::Caching.expire(etag_cache_key(username), 0)
Gitlab::Cache::Import::Caching.expire(email_fetched_for_project_cache_key(username), 0)
end
def email_cache_key(username)
EMAIL_FOR_USERNAME_CACHE_KEY % username
end
def etag_cache_key(username)
USERNAME_ETAG_CACHE_KEY % username
end
def email_fetched_for_project_cache_key(username)
format(EMAIL_FETCHED_FOR_PROJECT_CACHE_KEY, project: project.id, username: username)
end
def log(message, username: nil)
Gitlab::Import::Logger.info(
import_type: :github,
project_id: project.id,
class: self.class.name,
username: username,
message: message
)
end
end
end

View File

@ -52194,6 +52194,9 @@ msgstr ""
msgid "VulnerabilityExport|Detected At"
msgstr ""
msgid "VulnerabilityExport|Full Path"
msgstr ""
msgid "VulnerabilityExport|Group Name"
msgstr ""

View File

@ -59,7 +59,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/fonts": "^1.3.0",
"@gitlab/svgs": "3.60.0",
"@gitlab/ui": "65.3.1",
"@gitlab/ui": "66.0.1",
"@gitlab/visual-review-tools": "1.7.3",
"@gitlab/web-ide": "0.0.1-dev-20230821141730",
"@mattiasbuelens/web-streams-adapter": "^0.1.0",

View File

@ -1,6 +1,6 @@
#!/bin/sh
prepare_jh_branch() {
set_jh_branch_env_variable() {
set -eu # https://explainshell.com/explain?cmd=set+-eu
JH_BRANCH="$(./scripts/setup/find-jh-branch.rb)"
@ -9,7 +9,15 @@ prepare_jh_branch() {
echoinfo "JH_BRANCH: ${JH_BRANCH}"
}
download_jh_path() {
download_jh_files() {
if [ "${JH_BRANCH}" = "main-jh" ]; then
download_jh_files_from_api "$@"
else
download_jh_files_from_git_clone "$@"
fi
}
download_jh_files_from_api() {
set -eu # https://explainshell.com/explain?cmd=set+-eu
for path in "$@"; do
@ -17,11 +25,50 @@ download_jh_path() {
# shellcheck disable=SC3043
local output="${path}.tar.gz"
echoinfo "Downloading ${path}"
echoinfo "Downloading ${path} via API"
# Note: We are limited to 5 downloads/minute on this endpoint.
# (see https://docs.gitlab.com/ee/api/repositories.html#get-file-archive)
#
# If we run this command more than 5 times/minute, we will receive HTTP 429 errors.
#
# If this problem happens too often, we might want to either download files from
# another endpoint, and only download the folders with this endpoint. We could also
# do a git clone in all cases.
curl -f --location --output "${output}" --header "Private-Token: ${ADD_JH_FILES_TOKEN}" --get --data-urlencode "sha=${JH_BRANCH}" --data-urlencode "path=${path}" "https://gitlab.com/api/v4/projects/${GITLAB_JH_MIRROR_PROJECT}/repository/archive"
tar -zxf "${output}" --strip-component 1
rm "${output}"
done
}
# The JiHu mirror project is private, so we would need to be authenticated to download files from the API.
#
# When being authenticated and downloading files via the API, we are limited to 5 requests per minute
# (see https://docs.gitlab.com/ee/api/repositories.html#get-file-archive), and we would need to download 6 files
# (3 archives for two branches). This job can also be run in parallel between many pipelines.
download_jh_files_from_git_clone() {
return_code=0
git_merge_status_code=0
echoinfo "Cloning JH mirror repo to download JH files"
git config --global user.email "${GITLAB_USER_EMAIL}";
git config --global user.name "${GITLAB_USER_NAME}";
git clone --filter=tree:0 "${JH_MIRROR_REPOSITORY}" gitlab-jh
cd gitlab-jh
git checkout "${JH_BRANCH}"
git merge main-jh || git_merge_status_code=$?
if [ "${git_merge_status_code}" -ne 0 ]; then
git merge --abort || true
return_code=3
fi
mv ${JH_FILES_TO_COMMIT} ./..
cd ..
# We explicitly use exit instead of return, otherwise the job would exit with a 1 error code
exit "${return_code}"
}

View File

@ -14,52 +14,13 @@ RSpec.describe PreferredLanguageSwitcher, type: :controller do
end
context 'when first visit' do
let(:glm_source) { 'about.gitlab.com' }
let(:accept_language_header) { nil }
before do
request.env['HTTP_ACCEPT_LANGUAGE'] = accept_language_header.dup
get :new, params: { glm_source: glm_source }
get :new
end
it 'sets preferred_language to default' do
expect(cookies[:preferred_language]).to eq Gitlab::CurrentSettings.default_preferred_language
end
context 'when language param is valid' do
let(:glm_source) { 'about.gitlab.com/fr-fr/' }
it 'sets preferred_language accordingly' do
expect(cookies[:preferred_language]).to eq 'fr'
end
context 'when language param is invalid' do
let(:glm_source) { 'about.gitlab.com/ko-ko/' }
it 'sets preferred_language to default' do
expect(cookies[:preferred_language]).to eq Gitlab::CurrentSettings.default_preferred_language
end
end
end
context 'when browser preferred language is not english' do
context 'with selectable language' do
let(:accept_language_header) { 'zh-CN,zh;q=0.8,zh-TW;q=0.7' }
it 'sets preferred_language accordingly' do
expect(cookies[:preferred_language]).to eq 'zh_CN'
end
end
context 'with unselectable language' do
let(:accept_language_header) { 'nl-NL;q=0.8' }
it 'sets preferred_language to default' do
expect(cookies[:preferred_language]).to eq Gitlab::CurrentSettings.default_preferred_language
end
end
end
end
context 'when preferred language in cookies has been modified' do

View File

@ -0,0 +1,44 @@
# frozen_string_literal: true
FactoryBot.define do
factory :ci_reports_sbom_metadata, class: '::Gitlab::Ci::Reports::Sbom::Metadata' do
transient do
vendor { generate(:name) }
author_name { generate(:name) }
end
tools do
[
{
vendor: vendor,
name: "Gemnasium",
version: "2.34.0"
}
]
end
authors do
[
{
name: author_name,
email: "support@gitlab.com"
}
]
end
properties do
[
{
name: "gitlab:dependency_scanning:input_file:path",
value: "package-lock.json"
},
{
name: "gitlab:dependency_scanning:package_manager:name",
value: "npm"
}
]
end
skip_create
initialize_with { new(tools: tools, authors: authors, properties: properties) }
end
end

View File

@ -3,6 +3,14 @@
FactoryBot.define do
factory :ci_reports_sbom_report, class: '::Gitlab::Ci::Reports::Sbom::Report' do
transient do
sbom_attributes do
{
bom_format: 'CycloneDX',
spec_version: '1.4',
serial_number: "urn:uuid:aec33827-20ae-40d0-ae83-18ee846364d2",
version: 1
}
end
num_components { 5 }
components { build_list :ci_reports_sbom_component, num_components }
source { association :ci_reports_sbom_source }
@ -14,8 +22,18 @@ FactoryBot.define do
end
end
trait(:with_metadata) do
transient do
metadata { association(:ci_reports_sbom_metadata) }
end
after(:build) do |report, options|
report.metadata = options.metadata
end
end
after(:build) do |report, options|
options.components.each { |component| report.add_component(component) }
options.components.each { |component| report.add_component(component) } if options.components
report.set_source(options.source)
end

View File

@ -7,7 +7,9 @@ FactoryBot.define do
access_level { Gitlab::Access::REPORTER }
end
trait :owner do
access_level { Gitlab::Access::OWNER }
end
trait(:guest) { access_level { Gitlab::Access::GUEST } }
trait(:reporter) { access_level { Gitlab::Access::REPORTER } }
trait(:developer) { access_level { Gitlab::Access::DEVELOPER } }
trait(:maintainer) { access_level { Gitlab::Access::MAINTAINER } }
trait(:owner) { access_level { Gitlab::Access::OWNER } }
end

View File

@ -3,52 +3,44 @@
exports[`Keep latest artifact toggle when application keep latest artifact setting is enabled sets correct setting value in toggle with query result 1`] = `
<div>
<div
class="flex-grow-1 gl-display-flex gl-flex-direction-column gl-mb-0 gl-toggle-wrapper"
class="gl-display-flex gl-flex-direction-column gl-mb-0 gl-toggle-wrapper"
data-testid="toggle-wrapper"
>
<span
class="gl-mb-3 gl-toggle-label-container"
class="gl-flex-shrink-0 gl-mb-3 gl-toggle-label"
data-testid="toggle-label"
id="reference-0"
>
<span
class="gl-toggle-label"
data-testid="toggle-label"
id="reference-0"
>
Keep artifacts from most recent successful jobs
</span>
Keep artifacts from most recent successful jobs
</span>
<span
class="gl-toggle-switch-container"
<button
aria-checked="true"
aria-describedby="toggle-help-2"
aria-labelledby="reference-0"
class="gl-flex-shrink-0 gl-toggle is-checked"
role="switch"
type="button"
>
<button
aria-checked="true"
aria-describedby="toggle-help-2"
aria-labelledby="reference-0"
class="gl-flex-shrink-0 gl-toggle is-checked"
role="switch"
type="button"
>
<span
class="toggle-icon"
>
<gl-icon-stub
name="mobile-issue-close"
size="16"
/>
</span>
</button>
<span
class="gl-help-label"
data-testid="toggle-help"
id="reference-1"
class="toggle-icon"
>
The latest artifacts created by jobs in the most recent successful pipeline will be stored.
<gl-link-stub
href="/help/ci/pipelines/job_artifacts"
>
Learn more.
</gl-link-stub>
<gl-icon-stub
name="mobile-issue-close"
size="16"
/>
</span>
</button>
<span
class="gl-help-label"
data-testid="toggle-help"
id="reference-1"
>
The latest artifacts created by jobs in the most recent successful pipeline will be stored.
<gl-link-stub
href="/help/ci/pipelines/job_artifacts"
>
Learn more.
</gl-link-stub>
</span>
</div>
</div>

View File

@ -3,18 +3,20 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Parsers::Sbom::Cyclonedx, feature_category: :dependency_management do
let(:report) { instance_double('Gitlab::Ci::Reports::Sbom::Report') }
let(:report) { Gitlab::Ci::Reports::Sbom::Report.new }
let(:report_data) { base_report_data }
let(:raw_report_data) { report_data.to_json }
let(:report_valid?) { true }
let(:validator_errors) { [] }
let(:properties_parser) { class_double('Gitlab::Ci::Parsers::Sbom::CyclonedxProperties') }
let(:uuid) { 'c9d550a3-feb8-483b-a901-5aa892d039f9' }
let(:base_report_data) do
{
'bomFormat' => 'CycloneDX',
'specVersion' => '1.4',
'version' => 1
'version' => 1,
'serialNumber' => "urn:uuid:#{uuid}"
}
end
@ -28,6 +30,7 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Cyclonedx, feature_category: :dependen
allow(properties_parser).to receive(:parse_source)
stub_const('Gitlab::Ci::Parsers::Sbom::CyclonedxProperties', properties_parser)
allow(SecureRandom).to receive(:uuid).and_return(uuid)
end
context 'when report JSON is invalid' do
@ -149,8 +152,22 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Cyclonedx, feature_category: :dependen
end
end
context 'when report has metadata properties' do
let(:report_data) { base_report_data.merge({ 'metadata' => { 'properties' => properties } }) }
context 'when report has metadata tools, author and properties' do
let(:report_data) { base_report_data.merge(metadata) }
let(:tools) do
[
{ name: 'Gemnasium', vendor: 'vendor-1', version: '2.34.0' },
{ name: 'Gemnasium', vendor: 'vendor-2', version: '2.34.0' }
]
end
let(:authors) do
[
{ name: 'author-1', email: 'support@gitlab.com' },
{ name: 'author-2', email: 'support@gitlab.com' }
]
end
let(:properties) do
[
@ -163,10 +180,44 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Cyclonedx, feature_category: :dependen
]
end
it 'passes them to the properties parser' do
expect(properties_parser).to receive(:parse_source).with(properties)
context 'when metadata attributes are present' do
let(:metadata) do
{
'metadata' => {
'tools' => tools,
'authors' => authors,
'properties' => properties
}
}
end
parse!
it 'passes them to the report' do
expect(properties_parser).to receive(:parse_source).with(properties)
parse!
expect(report.metadata).to have_attributes(
tools: tools.map(&:with_indifferent_access),
authors: authors.map(&:with_indifferent_access),
properties: properties.map(&:with_indifferent_access)
)
end
end
context 'when metadata attributes are not present' do
let(:metadata) { { 'metadata' => {} } }
it 'passes them to the report' do
expect(properties_parser).to receive(:parse_source).with(nil)
parse!
expect(report.metadata).to have_attributes(
tools: [],
authors: [],
properties: []
)
end
end
end
end

View File

@ -0,0 +1,49 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Ci::Reports::Sbom::Metadata, feature_category: :dependency_management do
let(:tools) do
[
{
vendor: "vendor",
name: "Gemnasium",
version: "2.34.0"
}
]
end
let(:authors) do
[
{
name: "author_name",
email: "support@gitlab.com"
}
]
end
let(:properties) do
[
{
name: "property_name",
value: "package-lock.json"
}
]
end
subject(:metadata) do
described_class.new(
tools: tools,
authors: authors,
properties: properties
)
end
it 'has correct attributes' do
expect(metadata).to have_attributes(
tools: tools,
authors: authors,
properties: properties
)
end
end

View File

@ -20,11 +20,29 @@ RSpec.describe Gitlab::GithubImport::Client, feature_category: :importers do
end
describe '#user' do
it 'returns the details for the given username' do
expect(client.octokit).to receive(:user).with('foo')
expect(client).to receive(:with_rate_limit).and_yield
let(:status_code) { 200 }
let(:body) { { id: 1 } }
let(:headers) { { 'Content-Type' => 'application/json' } }
client.user('foo')
before do
stub_request(:get, 'https://api.github.com/users/foo')
.to_return(status: status_code, body: body.to_json, headers: headers)
end
subject(:user) { client.user('foo') }
it 'returns the details for the given username' do
expect(client).to receive(:with_rate_limit).and_yield
expect(user).to eq({ id: 1 })
end
context 'when a not modified response is returned' do
let(:status_code) { 304 }
it 'returns nil' do
expect(client).to receive(:with_rate_limit).and_yield
expect(user).to eq(nil)
end
end
end

View File

@ -26,6 +26,10 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequests::MergedByImporter,
subject { described_class.new(pull_request, project, client_double) }
before do
allow(client_double).to receive_message_chain(:octokit, :last_response, :headers).and_return({ etag: nil })
end
shared_examples 'adds a note referencing the merger user' do
it 'adds a note referencing the merger user' do
expect { subject.execute }

View File

@ -17,6 +17,10 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequests::ReviewImporter,
)
end
before do
allow(client_double).to receive_message_chain(:octokit, :last_response, :headers).and_return({ etag: nil })
end
subject { described_class.new(review, project, client_double) }
shared_examples 'imports a reviewer for the Merge Request' do

View File

@ -208,56 +208,253 @@ RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache, feat
describe '#email_for_github_username' do
let(:email) { 'kittens@example.com' }
let(:username) { 'kittens' }
let(:user) { {} }
let(:etag) { 'etag' }
let(:cache_key) { described_class::EMAIL_FOR_USERNAME_CACHE_KEY % username }
let(:etag_cache_key) { described_class::USERNAME_ETAG_CACHE_KEY % username }
let(:email_fetched_for_project_key) do
format(described_class::EMAIL_FETCHED_FOR_PROJECT_CACHE_KEY, project: project.id, username: username)
end
context 'when an Email address is cached' do
it 'reads the Email address from the cache' do
expect(Gitlab::Cache::Import::Caching)
.to receive(:read)
.and_return(email)
subject(:email_for_github_username) { finder.email_for_github_username(username) }
expect(client).not_to receive(:user)
expect(finder.email_for_github_username('kittens')).to eq(email)
shared_examples 'returns and caches the email' do
it 'returns the email' do
expect(email_for_github_username).to eq(email)
end
it 'caches the email and expires the etag and project check caches' do
expect(Gitlab::Cache::Import::Caching).to receive(:write).with(cache_key, email).once
expect(Gitlab::Cache::Import::Caching).to receive(:expire).with(etag_cache_key, 0).once
expect(Gitlab::Cache::Import::Caching).to receive(:expire).with(email_fetched_for_project_key, 0).once
email_for_github_username
email_for_github_username
end
end
context 'when an Email address is not cached' do
let(:user) { { email: email } }
it 'retrieves and caches the Email address when an Email address is available' do
expect(client).to receive(:user).with('kittens').and_return(user).once
expect(Gitlab::Cache::Import::Caching)
.to receive(:write)
.with(an_instance_of(String), email, timeout: Gitlab::Cache::Import::Caching::TIMEOUT).and_call_original
expect(finder.email_for_github_username('kittens')).to eq(email)
expect(finder.email_for_github_username('kittens')).to eq(email)
shared_examples 'returns nil and caches a negative lookup' do
it 'returns nil' do
expect(email_for_github_username).to be_nil
end
it 'shortens the timeout for Email address in cache when an Email address is private/nil from GitHub' do
user = { email: nil }
expect(client).to receive(:user).with('kittens').and_return(user).once
it 'caches a blank email and marks the project as checked' do
expect(Gitlab::Cache::Import::Caching).to receive(:write).with(cache_key, '').once
expect(Gitlab::Cache::Import::Caching).not_to receive(:write).with(etag_cache_key, anything)
expect(Gitlab::Cache::Import::Caching).to receive(:write).with(email_fetched_for_project_key, 1).once
expect(Gitlab::Cache::Import::Caching)
.to receive(:write)
.with(an_instance_of(String), '', timeout: Gitlab::Cache::Import::Caching::SHORTER_TIMEOUT)
.and_call_original
email_for_github_username
email_for_github_username
end
end
expect(finder.email_for_github_username('kittens')).to be_nil
expect(finder.email_for_github_username('kittens')).to be_nil
shared_examples 'does not change caches' do
it 'does not write to any of the caches' do
expect(Gitlab::Cache::Import::Caching).not_to receive(:write).with(cache_key, anything)
expect(Gitlab::Cache::Import::Caching).not_to receive(:write).with(etag_cache_key, anything)
expect(Gitlab::Cache::Import::Caching).not_to receive(:write).with(email_fetched_for_project_key, anything)
email_for_github_username
email_for_github_username
end
end
shared_examples 'a user resource not found on GitHub' do
before do
allow(client).to receive(:user).and_raise(::Octokit::NotFound)
end
context 'when a username does not exist on GitHub' do
it 'caches github username inexistence' do
expect(client)
.to receive(:user)
.with('kittens')
.and_raise(::Octokit::NotFound)
.once
it 'returns nil' do
expect(email_for_github_username).to be_nil
end
expect(finder.email_for_github_username('kittens')).to be_nil
expect(finder.email_for_github_username('kittens')).to be_nil
it 'caches a blank email' do
expect(Gitlab::Cache::Import::Caching).to receive(:write).with(cache_key, '').once
expect(Gitlab::Cache::Import::Caching).not_to receive(:write).with(etag_cache_key, anything)
expect(Gitlab::Cache::Import::Caching).not_to receive(:write).with(email_fetched_for_project_key, anything)
email_for_github_username
email_for_github_username
end
end
context 'when the email is cached' do
before do
Gitlab::Cache::Import::Caching.write(cache_key, email)
end
it 'returns the email from the cache' do
expect(email_for_github_username).to eq(email)
end
it 'does not make a rate-limited API call' do
expect(client).not_to receive(:user).with(username, { headers: {} })
email_for_github_username
email_for_github_username
end
end
context 'when the email cache is nil' do
context 'if the email has not been checked for the project' do
context 'if the cached etag is nil' do
before do
allow(client).to receive_message_chain(:octokit, :last_response, :headers).and_return({ etag: etag })
end
it 'makes an API call' do
expect(client).to receive(:user).with(username, { headers: {} }).and_return({ email: email }).once
email_for_github_username
end
context 'if the response contains an email' do
before do
allow(client).to receive(:user).and_return({ email: email })
end
it_behaves_like 'returns and caches the email'
end
context 'if the response does not contain an email' do
before do
allow(client).to receive(:user).and_return({})
end
it 'returns nil' do
expect(email_for_github_username).to be_nil
end
it 'caches a blank email and etag and marks the project as checked' do
expect(Gitlab::Cache::Import::Caching).to receive(:write).with(cache_key, '').once
expect(Gitlab::Cache::Import::Caching).to receive(:write).with(etag_cache_key, etag).once
expect(Gitlab::Cache::Import::Caching).to receive(:write).with(email_fetched_for_project_key, 1).once
email_for_github_username
email_for_github_username
end
end
end
context 'if the cached etag is not nil' do
before do
Gitlab::Cache::Import::Caching.write(etag_cache_key, etag)
end
it 'makes a non-rate-limited API call' do
expect(client).to receive(:user).with(username, { headers: { 'If-None-Match' => etag } }).once
email_for_github_username
end
context 'if the response contains an email' do
before do
allow(client).to receive(:user).and_return({ email: email })
end
it_behaves_like 'returns and caches the email'
end
context 'if the response does not contain an email' do
before do
allow(client).to receive(:user).and_return({})
end
it_behaves_like 'returns nil and caches a negative lookup'
end
context 'if the response is nil' do
before do
allow(client).to receive(:user).and_return(nil)
end
it 'returns nil' do
expect(email_for_github_username).to be_nil
end
it 'marks the project as checked' do
expect(Gitlab::Cache::Import::Caching).not_to receive(:write).with(cache_key, anything)
expect(Gitlab::Cache::Import::Caching).not_to receive(:write).with(etag_cache_key, anything)
expect(Gitlab::Cache::Import::Caching).to receive(:write).with(email_fetched_for_project_key, 1).once
email_for_github_username
email_for_github_username
end
end
end
end
context 'if the email has been checked for the project' do
before do
Gitlab::Cache::Import::Caching.write(email_fetched_for_project_key, 1)
end
it 'returns nil' do
expect(email_for_github_username).to be_nil
end
it_behaves_like 'does not change caches'
end
it_behaves_like 'a user resource not found on GitHub'
end
context 'when the email cache is blank' do
before do
Gitlab::Cache::Import::Caching.write(cache_key, '')
end
context 'if the email has not been checked for the project' do
context 'if the cached etag is not nil' do
before do
Gitlab::Cache::Import::Caching.write(etag_cache_key, etag)
end
it 'makes a non-rate-limited API call' do
expect(client).to receive(:user).with(username, { headers: { 'If-None-Match' => etag } }).once
email_for_github_username
end
context 'if the response contains an email' do
before do
allow(client).to receive(:user).and_return({ email: email })
end
it_behaves_like 'returns and caches the email'
end
context 'if the response does not contain an email' do
before do
allow(client).to receive(:user).and_return({})
end
it_behaves_like 'returns nil and caches a negative lookup'
end
context 'if the response is nil' do
before do
allow(client).to receive(:user).and_return(nil)
end
it_behaves_like 'returns nil and caches a negative lookup'
end
it_behaves_like 'a user resource not found on GitHub'
end
end
context 'if the email has been checked for the project' do
before do
Gitlab::Cache::Import::Caching.write(email_fetched_for_project_key, 1)
end
it 'returns nil' do
expect(email_for_github_username).to be_nil
end
it_behaves_like 'does not change caches'
end
end
end

View File

@ -65,6 +65,26 @@ RSpec.describe ProjectAuthorization, feature_category: :groups_and_projects do
it { is_expected.to validate_inclusion_of(:access_level).in_array(Gitlab::Access.all_values) }
end
describe 'scopes' do
describe '.non_guests' do
let_it_be(:project) { create(:project) }
let_it_be(:project_original_owner_authorization) { project.owner.project_authorizations.first }
let_it_be(:project_authorization_guest) { create(:project_authorization, :guest, project: project) }
let_it_be(:project_authorization_reporter) { create(:project_authorization, :reporter, project: project) }
let_it_be(:project_authorization_developer) { create(:project_authorization, :developer, project: project) }
let_it_be(:project_authorization_maintainer) { create(:project_authorization, :maintainer, project: project) }
let_it_be(:project_authorization_owner) { create(:project_authorization, :owner, project: project) }
it 'returns all records which are greater than Guests access' do
expect(described_class.non_guests.map(&:attributes)).to match_array([
project_authorization_reporter, project_authorization_developer,
project_authorization_maintainer, project_authorization_owner,
project_original_owner_authorization
].map(&:attributes))
end
end
end
describe '.insert_all' do
let_it_be(:user) { create(:user) }
let_it_be(:project_1) { create(:project) }

View File

@ -145,9 +145,6 @@ packages_debian_project_distributions:
packages_tags:
index_packages_tags_on_package_id_and_updated_at:
- index_packages_tags_on_package_id
pages_deployments:
index_pages_deployments_unique_path_prefix_by_project:
- index_pages_deployments_on_project_id
pages_domains:
index_pages_domains_on_project_id_and_enabled_until:
- index_pages_domains_on_project_id

View File

@ -17,8 +17,7 @@ module Tooling
WARNING_COMMENT = <<~COMMENT.freeze
Finalizing data migration might be time consuming and require a [required stop](#{DOC_URL}).
Check the timings of the underlying data migration.
If possible postpone the finalization to the scheduled required stop.
If postponing is impossible please create new required stop as documentation suggests.
If possible schedule finalization for the first minor version after the next required stop.
COMMENT
def add_comment_for_finalized_migrations

View File

@ -1147,10 +1147,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.60.0.tgz#f03dbdf779e4434e136fca0e764ccf0f6fb295c6"
integrity sha512-Plgq1a1hquGZ74t/JamsOZf4RW8geBmNFSnn9HSnyjfBpz1Ue5r02RB0IQw7Xu4pW1AAei8gVb2nLtODSUBrnQ==
"@gitlab/ui@65.3.1":
version "65.3.1"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-65.3.1.tgz#5dd995549f32e67f6d286d29cff7445884a351bb"
integrity sha512-3mGY76IfS7RiAeb9U/j8/7c35lJ3AX0utFQDEWV39ttwylArpNCRuNsjgFaWI7o2RgRhohM0ZBoNKmIm3haJaA==
"@gitlab/ui@66.0.1":
version "66.0.1"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-66.0.1.tgz#8ad2fb8197eff2230654323e776f28c7fbe9e299"
integrity sha512-LHAqBAiXfoXL8B61xtVLdGhQH9XvuH1F2VQdArqfamXmj05w8BVMr66KgssTYyXCmLZiBq0qPjRDTyO7qt0V+A==
dependencies:
"@floating-ui/dom" "1.2.9"
bootstrap-vue "2.23.1"