Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
		
							parent
							
								
									2c6206c961
								
							
						
					
					
						commit
						3cef8119b3
					
				|  | @ -238,6 +238,7 @@ module ApplicationSettingsHelper | ||||||
|       :container_expiration_policies_enable_historic_entries, |       :container_expiration_policies_enable_historic_entries, | ||||||
|       :container_registry_expiration_policies_caching, |       :container_registry_expiration_policies_caching, | ||||||
|       :container_registry_token_expire_delay, |       :container_registry_token_expire_delay, | ||||||
|  |       :decompress_archive_file_timeout, | ||||||
|       :default_artifacts_expire_in, |       :default_artifacts_expire_in, | ||||||
|       :default_branch_name, |       :default_branch_name, | ||||||
|       :default_branch_protection, |       :default_branch_protection, | ||||||
|  |  | ||||||
|  | @ -300,6 +300,10 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord | ||||||
|     presence: true, |     presence: true, | ||||||
|     numericality: { only_integer: true, greater_than: 0 } |     numericality: { only_integer: true, greater_than: 0 } | ||||||
| 
 | 
 | ||||||
|  |   validates :decompress_archive_file_timeout, | ||||||
|  |     presence: true, | ||||||
|  |     numericality: { only_integer: true, greater_than_or_equal_to: 0 } | ||||||
|  | 
 | ||||||
|   validates :repository_storages, presence: true |   validates :repository_storages, presence: true | ||||||
|   validate :check_repository_storages |   validate :check_repository_storages | ||||||
|   validate :check_repository_storages_weighted |   validate :check_repository_storages_weighted | ||||||
|  | @ -794,10 +798,8 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord | ||||||
|   attr_encrypted :arkose_labs_public_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) |   attr_encrypted :arkose_labs_public_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) | ||||||
|   attr_encrypted :arkose_labs_private_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) |   attr_encrypted :arkose_labs_private_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) | ||||||
|   attr_encrypted :cube_api_key, encryption_options_base_32_aes_256_gcm |   attr_encrypted :cube_api_key, encryption_options_base_32_aes_256_gcm | ||||||
|   attr_encrypted :jitsu_administrator_password, encryption_options_base_32_aes_256_gcm |  | ||||||
|   attr_encrypted :telesign_customer_xid, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) |   attr_encrypted :telesign_customer_xid, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) | ||||||
|   attr_encrypted :telesign_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) |   attr_encrypted :telesign_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) | ||||||
|   attr_encrypted :product_analytics_clickhouse_connection_string, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) |  | ||||||
|   attr_encrypted :product_analytics_configurator_connection_string, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) |   attr_encrypted :product_analytics_configurator_connection_string, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) | ||||||
|   attr_encrypted :openai_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) |   attr_encrypted :openai_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) | ||||||
|   attr_encrypted :anthropic_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) |   attr_encrypted :anthropic_api_key, encryption_options_base_32_aes_256_gcm.merge(encode: false, encode_iv: false) | ||||||
|  |  | ||||||
|  | @ -53,6 +53,7 @@ module ApplicationSettingImplementation | ||||||
|         container_registry_vendor: '', |         container_registry_vendor: '', | ||||||
|         container_registry_version: '', |         container_registry_version: '', | ||||||
|         custom_http_clone_url_root: nil, |         custom_http_clone_url_root: nil, | ||||||
|  |         decompress_archive_file_timeout: 210, | ||||||
|         default_artifacts_expire_in: '30 days', |         default_artifacts_expire_in: '30 days', | ||||||
|         default_branch_name: nil, |         default_branch_name: nil, | ||||||
|         default_branch_protection: Settings.gitlab['default_branch_protection'], |         default_branch_protection: Settings.gitlab['default_branch_protection'], | ||||||
|  |  | ||||||
|  | @ -17,20 +17,6 @@ class ProjectSetting < ApplicationRecord | ||||||
|     encode: false, |     encode: false, | ||||||
|     encode_iv: false |     encode_iv: false | ||||||
| 
 | 
 | ||||||
|   attr_encrypted :jitsu_administrator_password, |  | ||||||
|     mode: :per_attribute_iv, |  | ||||||
|     key: Settings.attr_encrypted_db_key_base_32, |  | ||||||
|     algorithm: 'aes-256-gcm', |  | ||||||
|     encode: false, |  | ||||||
|     encode_iv: false |  | ||||||
| 
 |  | ||||||
|   attr_encrypted :product_analytics_clickhouse_connection_string, |  | ||||||
|     mode: :per_attribute_iv, |  | ||||||
|     key: Settings.attr_encrypted_db_key_base_32, |  | ||||||
|     algorithm: 'aes-256-gcm', |  | ||||||
|     encode: false, |  | ||||||
|     encode_iv: false |  | ||||||
| 
 |  | ||||||
|   attr_encrypted :product_analytics_configurator_connection_string, |   attr_encrypted :product_analytics_configurator_connection_string, | ||||||
|     mode: :per_attribute_iv, |     mode: :per_attribute_iv, | ||||||
|     key: Settings.attr_encrypted_db_key_base_32, |     key: Settings.attr_encrypted_db_key_base_32, | ||||||
|  |  | ||||||
|  | @ -37,6 +37,10 @@ | ||||||
|       = f.label :max_decompressed_archive_size, s_('Import|Maximum decompressed size (MiB)'), class: 'label-light' |       = f.label :max_decompressed_archive_size, s_('Import|Maximum decompressed size (MiB)'), class: 'label-light' | ||||||
|       = f.number_field :max_decompressed_archive_size, class: 'form-control gl-form-input', title: s_('Import|Maximum size of decompressed archive.'), data: { toggle: 'tooltip', container: 'body' } |       = f.number_field :max_decompressed_archive_size, class: 'form-control gl-form-input', title: s_('Import|Maximum size of decompressed archive.'), data: { toggle: 'tooltip', container: 'body' } | ||||||
|       %span.form-text.text-muted= _('Set to 0 for no size limit.') |       %span.form-text.text-muted= _('Set to 0 for no size limit.') | ||||||
|  |     .form-group | ||||||
|  |       = f.label :decompress_archive_file_timeout, s_('Import|Timeout for decompressing archived files (seconds)'), class: 'label-light' | ||||||
|  |       = f.number_field :decompress_archive_file_timeout, class: 'form-control gl-form-input', title: s_('Import|Timeout for decompressing archived files.'), data: { toggle: 'tooltip', container: 'body' } | ||||||
|  |       %span.form-text.text-muted= _('Set to 0 to disable timeout.') | ||||||
|     .form-group |     .form-group | ||||||
|       = f.label :session_expire_delay, _('Session duration (minutes)'), class: 'label-light' |       = f.label :session_expire_delay, _('Session duration (minutes)'), class: 'label-light' | ||||||
|       = f.number_field :session_expire_delay, class: 'form-control gl-form-input', title: _('Maximum duration of a session.'), data: { toggle: 'tooltip', container: 'body' } |       = f.number_field :session_expire_delay, class: 'form-control gl-form-input', title: _('Maximum duration of a session.'), data: { toggle: 'tooltip', container: 'body' } | ||||||
|  |  | ||||||
|  | @ -123,6 +123,7 @@ Sidekiq.configure_client do |config| | ||||||
|   config.client_middleware(&Gitlab::SidekiqMiddleware.client_configurator) |   config.client_middleware(&Gitlab::SidekiqMiddleware.client_configurator) | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | Sidekiq::Scheduled::Enq.prepend Gitlab::Patch::SidekiqScheduledEnq | ||||||
| Sidekiq::Scheduled::Poller.prepend Gitlab::Patch::SidekiqPoller | Sidekiq::Scheduled::Poller.prepend Gitlab::Patch::SidekiqPoller | ||||||
| Sidekiq::Cron::Poller.prepend Gitlab::Patch::SidekiqPoller | Sidekiq::Cron::Poller.prepend Gitlab::Patch::SidekiqPoller | ||||||
| Sidekiq::Cron::Poller.prepend Gitlab::Patch::SidekiqCronPoller | Sidekiq::Cron::Poller.prepend Gitlab::Patch::SidekiqCronPoller | ||||||
|  |  | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class AddDecompressArchiveFileTimeoutToApplicationSetting < Gitlab::Database::Migration[2.1] | ||||||
|  |   disable_ddl_transaction! | ||||||
|  | 
 | ||||||
|  |   def change | ||||||
|  |     add_column :application_settings, :decompress_archive_file_timeout, :integer, default: 210, null: false | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 2765c209b9347c0c76257a1af473edd6aebdc3f8d6dce3eed4d089e700c36808 | ||||||
|  | @ -11932,6 +11932,7 @@ CREATE TABLE application_settings ( | ||||||
|     max_decompressed_archive_size integer DEFAULT 25600 NOT NULL, |     max_decompressed_archive_size integer DEFAULT 25600 NOT NULL, | ||||||
|     ci_max_total_yaml_size_bytes integer DEFAULT 157286400 NOT NULL, |     ci_max_total_yaml_size_bytes integer DEFAULT 157286400 NOT NULL, | ||||||
|     prometheus_alert_db_indicators_settings jsonb, |     prometheus_alert_db_indicators_settings jsonb, | ||||||
|  |     decompress_archive_file_timeout integer DEFAULT 210 NOT NULL, | ||||||
|     CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)), |     CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)), | ||||||
|     CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)), |     CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)), | ||||||
|     CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)), |     CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)), | ||||||
|  |  | ||||||
|  | @ -17,7 +17,8 @@ their self-managed instance. | ||||||
| Use Credentials inventory to see for your GitLab instance all: | Use Credentials inventory to see for your GitLab instance all: | ||||||
| 
 | 
 | ||||||
| - Personal access tokens (PAT). | - Personal access tokens (PAT). | ||||||
| - Project access tokens (GitLab 14.8 and later). | - Project access tokens (introduced in GitLab 14.8). | ||||||
|  | - Group access tokens ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/102959) in GitLab 15.6). | ||||||
| - SSH keys. | - SSH keys. | ||||||
| - GPG keys. | - GPG keys. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -120,7 +120,7 @@ See [the available connection settings for different providers](object_storage.m | ||||||
| 
 | 
 | ||||||
|    ```ruby |    ```ruby | ||||||
|    gitlab_rails['ci_secure_files_object_store_enabled'] = true |    gitlab_rails['ci_secure_files_object_store_enabled'] = true | ||||||
|    gitlab_rails['ci_secure_files_object_store_remote_directory'] = "terraform" |    gitlab_rails['ci_secure_files_object_store_remote_directory'] = "ci_secure_files" | ||||||
|    gitlab_rails['ci_secure_files_object_store_connection'] = { |    gitlab_rails['ci_secure_files_object_store_connection'] = { | ||||||
|      'provider' => 'AWS', |      'provider' => 'AWS', | ||||||
|      'region' => 'eu-central-1', |      'region' => 'eu-central-1', | ||||||
|  |  | ||||||
|  | @ -155,6 +155,20 @@ To modify the maximum decompressed file size for imports in GitLab: | ||||||
| 1. Expand **Account and limit**. | 1. Expand **Account and limit**. | ||||||
| 1. Set another value for **Maximum decompressed size (MiB)**. | 1. Set another value for **Maximum decompressed size (MiB)**. | ||||||
| 
 | 
 | ||||||
|  | ## Timeout for decompressing archived files | ||||||
|  | 
 | ||||||
|  | > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128218) in GitLab 16.4. | ||||||
|  | 
 | ||||||
|  | When you [import a project](../../user/project/settings/import_export.md), you can specify the maximum time out for decompressing imported archives. The default value is 210 seconds. | ||||||
|  | 
 | ||||||
|  | To modify the maximum decompressed file size for imports in GitLab: | ||||||
|  | 
 | ||||||
|  | 1. On the left sidebar, expand the top-most chevron (**{chevron-down}**). | ||||||
|  | 1. Select **Admin Area**. | ||||||
|  | 1. Select **Settings > General**. | ||||||
|  | 1. Expand **Account and limit**. | ||||||
|  | 1. Set another value for **Timeout for decompressing archived files (seconds)**. | ||||||
|  | 
 | ||||||
| ## Personal access token prefix | ## Personal access token prefix | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20968) in GitLab 13.7. | > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20968) in GitLab 13.7. | ||||||
|  |  | ||||||
|  | @ -65,6 +65,7 @@ Example response: | ||||||
|   "container_registry_expiration_policies_caching": true, |   "container_registry_expiration_policies_caching": true, | ||||||
|   "container_registry_expiration_policies_worker_capacity": 4, |   "container_registry_expiration_policies_worker_capacity": 4, | ||||||
|   "container_registry_token_expire_delay": 5, |   "container_registry_token_expire_delay": 5, | ||||||
|  |   "decompress_archive_file_timeout": 210, | ||||||
|   "repository_storages_weighted": {"default": 100}, |   "repository_storages_weighted": {"default": 100}, | ||||||
|   "plantuml_enabled": false, |   "plantuml_enabled": false, | ||||||
|   "plantuml_url": null, |   "plantuml_url": null, | ||||||
|  | @ -208,6 +209,7 @@ Example response: | ||||||
|   "container_registry_expiration_policies_caching": true, |   "container_registry_expiration_policies_caching": true, | ||||||
|   "container_registry_expiration_policies_worker_capacity": 4, |   "container_registry_expiration_policies_worker_capacity": 4, | ||||||
|   "container_registry_token_expire_delay": 5, |   "container_registry_token_expire_delay": 5, | ||||||
|  |   "decompress_archive_file_timeout": 210, | ||||||
|   "package_registry_cleanup_policies_worker_capacity": 2, |   "package_registry_cleanup_policies_worker_capacity": 2, | ||||||
|   "repository_storages": ["default"], |   "repository_storages": ["default"], | ||||||
|   "plantuml_enabled": false, |   "plantuml_enabled": false, | ||||||
|  | @ -346,6 +348,7 @@ listed in the descriptions of the relevant settings. | ||||||
| | `allow_account_deletion`                 | boolean          | no                                   | Enable [users to delete their accounts](../administration/settings/account_and_limit_settings.md#prevent-users-from-deleting-their-accounts). | | | `allow_account_deletion`                 | boolean          | no                                   | Enable [users to delete their accounts](../administration/settings/account_and_limit_settings.md#prevent-users-from-deleting-their-accounts). | | ||||||
| | `deactivate_dormant_users`               | boolean          | no                                   | Enable [automatic deactivation of dormant users](../administration/moderate_users.md#automatically-deactivate-dormant-users). | | | `deactivate_dormant_users`               | boolean          | no                                   | Enable [automatic deactivation of dormant users](../administration/moderate_users.md#automatically-deactivate-dormant-users). | | ||||||
| | `deactivate_dormant_users_period`        | integer          | no                                   | Length of time (in days) after which a user is considered dormant. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/336747) in GitLab 15.3. | | | `deactivate_dormant_users_period`        | integer          | no                                   | Length of time (in days) after which a user is considered dormant. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/336747) in GitLab 15.3. | | ||||||
|  | | `decompress_archive_file_timeout`        | integer          | no                                   | Default timeout for decompressing archived files, in seconds. Set to 0 to disable timeouts. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/129161) in GitLab 16.4. | | ||||||
| | `default_artifacts_expire_in`            | string           | no                                   | Set the default expiration time for each job's artifacts. | | | `default_artifacts_expire_in`            | string           | no                                   | Set the default expiration time for each job's artifacts. | | ||||||
| | `default_branch_name`                    | string           | no                                   | [Instance-level custom initial branch name](../user/project/repository/branches/default.md#instance-level-custom-initial-branch-name). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225258) in GitLab 13.2. | | | `default_branch_name`                    | string           | no                                   | [Instance-level custom initial branch name](../user/project/repository/branches/default.md#instance-level-custom-initial-branch-name). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225258) in GitLab 13.2. | | ||||||
| | `default_branch_protection`              | integer          | no                                   | Determine if developers can push to the default branch. Can take: `0` _(not protected, both users with the Developer role or Maintainer role can push new commits and force push)_, `1` _(partially protected, users with the Developer role or Maintainer role can push new commits, but cannot force push)_ or `2` _(fully protected, users with the Developer or Maintainer role cannot push new commits, but users with the Developer or Maintainer role can; no one can force push)_ as a parameter. Default is `2`. | | | `default_branch_protection`              | integer          | no                                   | Determine if developers can push to the default branch. Can take: `0` _(not protected, both users with the Developer role or Maintainer role can push new commits and force push)_, `1` _(partially protected, users with the Developer role or Maintainer role can push new commits, but cannot force push)_ or `2` _(fully protected, users with the Developer or Maintainer role cannot push new commits, but users with the Developer or Maintainer role can; no one can force push)_ as a parameter. Default is `2`. | | ||||||
|  |  | ||||||
|  | @ -30,6 +30,10 @@ You can use Cosign to sign and verify container images and build artifacts. | ||||||
| 
 | 
 | ||||||
| - You must use a version of Cosign that is `>= 2.0.1`. | - You must use a version of Cosign that is `>= 2.0.1`. | ||||||
| 
 | 
 | ||||||
|  | **Limitations** | ||||||
|  | 
 | ||||||
|  | - The `id_tokens` portion of the CI/CD config file must be located in the project that is being built and signed. AutoDevOps, CI files included from another repository, and child pipelines are not supported. Work to remove this limitation is being tracked in [issue 411317](https://gitlab.com/gitlab-org/gitlab/-/issues/411317). | ||||||
|  | 
 | ||||||
| **Best practices**: | **Best practices**: | ||||||
| 
 | 
 | ||||||
| - Build and sign an image/artifact in the same job to prevent it from being tampered with before it is signed. | - Build and sign an image/artifact in the same job to prevent it from being tampered with before it is signed. | ||||||
|  |  | ||||||
|  | @ -53,59 +53,167 @@ For more information, view [Rouge Ruby Library](https://github.com/rouge-ruby/ro | ||||||
| 
 | 
 | ||||||
| ## Change the diff colors | ## Change the diff colors | ||||||
| 
 | 
 | ||||||
| Diffs use two different background colors to show changes between versions of code. By default, the original file in red and the changes made in green. | Diffs use two different background colors to show changes between versions of code. By default, the original file is in red, and the changes are in green. | ||||||
| 
 | 
 | ||||||
| To change the diff colors: | To change the diff colors: | ||||||
| 
 | 
 | ||||||
| 1. On the left sidebar, select your avatar. | 1. On the left sidebar, select your avatar. | ||||||
| 1. Select **Preferences**. | 1. Select **Preferences**. | ||||||
| 1. Go to the **Diff colors** section.  | 1. Go to the **Diff colors** section.  | ||||||
| 1. Complete the fields. | 1. Select a color or enter a color code. | ||||||
| 1. Select **Save changes**. | 1. Select **Save changes**. | ||||||
| 1. Optional. Type a color code in the fields. | 
 | ||||||
|  | To change back to the default colors, clear the **Color for removed lines** and **Color for added lines** text boxes and select **Save changes**. | ||||||
| 
 | 
 | ||||||
| ## Behavior | ## Behavior | ||||||
| 
 | 
 | ||||||
| The following settings allow you to customize the behavior of the GitLab layout | Use the **Behavior** section to customize the behavior and layout of your GitLab self-managed instance. You can change your layout width and choose the default content for your homepage, group and project overview pages. You have options to customize appearance and function, like whitespace rendering, file display, and text automation. | ||||||
| and default views of your dashboard and the projects' landing pages. |  | ||||||
| 
 | 
 | ||||||
| ### Layout width | ### Change the layout width on the UI | ||||||
| 
 | 
 | ||||||
| GitLab can be set up to use different widths depending on your liking. Choose | You can stretch content on the GitLab UI to fill the entire page. By default, page content is fixed at 1280 pixels wide. | ||||||
| between the fixed (max. `1280px`) and the fluid (`100%`) application layout. |  | ||||||
| 
 | 
 | ||||||
| NOTE: | To change the layout width of your UI: | ||||||
| While `1280px` is the standard max width when using fixed layout, some pages still use 100% width, depending on the content. |  | ||||||
| 
 | 
 | ||||||
| ### Homepage | 1. On the left sidebar, select your avatar. | ||||||
|  | 1. Select **Preferences**. | ||||||
|  | 1. Go to the **Behavior** section. | ||||||
|  | 1. Under **Layout width**, choose **Fixed** or **Fluid**. | ||||||
|  | 1. Select **Save changes**. | ||||||
| 
 | 
 | ||||||
| This setting changes the behavior of the tanuki icon in the upper-left corner of GitLab. | ### Choose your homepage | ||||||
| 
 | 
 | ||||||
| ### Group overview content | Control what page you view when you select the GitLab logo (**{tanuki}**). You can set your homepage to be Projects (default), Your Groups, Your Activity, and other content. | ||||||
| 
 | 
 | ||||||
| The **Group overview content** dropdown list allows you to choose what information is | 1. On the left sidebar, select your avatar. | ||||||
| displayed on a group's home page. | 1. Select **Preferences**. | ||||||
|  | 1. Go to the **Behavior** section. | ||||||
|  | 1. For **Homepage**, select a default. | ||||||
|  | 1. Select **Save changes**. | ||||||
| 
 | 
 | ||||||
| You can choose between 2 options: | ### Customize default content on your group overview page | ||||||
| 
 | 
 | ||||||
| - Details (default) | You can change the main content on your group overview page. Your group overview page is the page that shows when you select **Groups** on the left sidebar. You can customize the default content for your group overview page to the: | ||||||
| - [Security dashboard](../application_security/security_dashboard/index.md) |  | ||||||
| 
 | 
 | ||||||
| ### Project overview content | - Details Dashboard (default), which includes an overview of group activities and projects. | ||||||
|  | - Security Dashboard, which might include group security policies and other security topics. | ||||||
| 
 | 
 | ||||||
| The **Project overview content** setting allows you to choose what content you want to | For more information, view [Groups](../../user/group/index.md). | ||||||
| see on a project's home page. |  | ||||||
| 
 | 
 | ||||||
| If **Files and Readme** is selected, you can show or hide the shortcut buttons above the file list on the project overview with the **Show shortcut buttons above files on project overview** setting. | To change the default content on your group overview page: | ||||||
| 
 | 
 | ||||||
| ### Tab width | 1. On the left sidebar, select your avatar. | ||||||
|  | 1. Select **Preferences**. | ||||||
|  | 1. Go to the **Behavior** section. | ||||||
|  | 1. For **Group overivew content**, select an option. | ||||||
|  | 1. Select **Save changes**. | ||||||
| 
 | 
 | ||||||
| You can set the displayed width of tab characters across various parts of | ### Customize default content on your project overview page | ||||||
| GitLab, for example, blobs, diffs, and snippets. |  | ||||||
| 
 | 
 | ||||||
| NOTE: | Your project overview page is the page you view when you select **Project overview** on the left sidebar. You can set your main project overview page to the Activity page, the Readme file, and other content. | ||||||
| Some parts of GitLab do not respect this setting, including the WebIDE, file | 
 | ||||||
| editor and Markdown editor. | 1. On the left sidebar, select your avatar. | ||||||
|  | 1. Select **Preferences**. | ||||||
|  | 1. Go to the **Behavior** section. | ||||||
|  | 1. For **Project overivew content**, select an option. | ||||||
|  | 1. Select **Save changes**. | ||||||
|  | 
 | ||||||
|  | ### Hide shortcut buttons | ||||||
|  | 
 | ||||||
|  | Shortcut buttons precede the list of files on a project's overview page. These buttons provide links to parts of a project, such as the README file or license agreements. | ||||||
|  | 
 | ||||||
|  | To hide shortcut buttons on the project overview page: | ||||||
|  | 
 | ||||||
|  | 1. On the left sidebar, select your avatar. | ||||||
|  | 1. Select **Preferences**. | ||||||
|  | 1. Go to the **Behavior** section. | ||||||
|  | 1. Clear the **Show shortcut buttons above files on project overview** checkbox. | ||||||
|  | 1. Select **Save changes**. | ||||||
|  | 
 | ||||||
|  | ### Show whitespace characters in the Web IDE | ||||||
|  | 
 | ||||||
|  | Whitespace characters are any blank characters in a text, such as spaces and indentations. You might use whitespace to structure content in code. If your programming language is sensitive to whitespaces, the Web IDE can detect changes to them. | ||||||
|  | 
 | ||||||
|  | To render whitespace in the Web IDE: | ||||||
|  | 
 | ||||||
|  | 1. On the left sidebar, select your avatar. | ||||||
|  | 1. Select **Preferences**. | ||||||
|  | 1. Go to the **Behavior** section. | ||||||
|  | 1. Select the **Render whitespace characters in the Web IDE** checkbox. | ||||||
|  | 1. Select **Save changes**. | ||||||
|  | 
 | ||||||
|  | You can view changes to whitespace in diffs.  | ||||||
|  | 
 | ||||||
|  | To view diffs on the Web IDE, follow these steps: | ||||||
|  | 
 | ||||||
|  | 1. On the left sidebar, select **Source Control** (**{branch}**). | ||||||
|  | 1. Under the **Changes** tab, select your file. | ||||||
|  | 
 | ||||||
|  | ### Show whitespace changes in diffs | ||||||
|  | 
 | ||||||
|  | View changes to whitespace in diff files. For more information on whitespaces, view the previous task. | ||||||
|  | 
 | ||||||
|  | To view changes to whitespace in diffs: | ||||||
|  | 
 | ||||||
|  | 1. On the left sidebar, select your avatar. | ||||||
|  | 1. Select **Preferences**. | ||||||
|  | 1. Go to the **Behavior** section. | ||||||
|  | 1. Select the **Show whitespace changes in diffs** checkbox. | ||||||
|  | 1. Select **Save changes**. | ||||||
|  | 
 | ||||||
|  | For more information on diffs, view [Change the diff colors](#change-the-diff-colors). | ||||||
|  | 
 | ||||||
|  | ### Show one file per page in a merge request | ||||||
|  | 
 | ||||||
|  | The **Changes** tab lets you view all file changes in a merge request on one page. | ||||||
|  | Instead, you can choose to view one file at a time. | ||||||
|  | 
 | ||||||
|  | To show one file per page on the **Changes** tab: | ||||||
|  | 
 | ||||||
|  | 1. On the left sidebar, select your avatar. | ||||||
|  | 1. Select **Preferences**. | ||||||
|  | 1. Go to the **Behavior** section. | ||||||
|  | 1. Select the **Show one file at a time on merge request's Changes tab** checkbox. | ||||||
|  | 1. Select **Save changes**. | ||||||
|  | 
 | ||||||
|  | Then, to move between files on the **Changes** tab, below each file, select the **Previous** and **Next** buttons. | ||||||
|  | 
 | ||||||
|  | ### Autocomplete characters | ||||||
|  | 
 | ||||||
|  | When you type an opening character, like a bracket or quote mark, in a description or comment box, | ||||||
|  | GitLab can automatically insert the closing character as you type. For example, if you begin your text with an open bracket, GitLab can insert the closing bracket. | ||||||
|  | 
 | ||||||
|  | To autocomplete characters in description and comment boxes: | ||||||
|  | 
 | ||||||
|  | 1. On the left sidebar, select your avatar. | ||||||
|  | 1. Select **Preferences**. | ||||||
|  | 1. Go to the **Behavior** section. | ||||||
|  | 1. Select the **Surround text selection when typing quotes or brackets** checkbox. | ||||||
|  | 1. Select **Save changes**. | ||||||
|  | 
 | ||||||
|  | ### Automate new list items | ||||||
|  | 
 | ||||||
|  | Create a new list item when you press <kbd>Enter</kbd> within a list in description and comment boxes. | ||||||
|  | 
 | ||||||
|  | To add a new list item when you press the <kbd>Enter</kbd> key: | ||||||
|  | 
 | ||||||
|  | 1. On the left sidebar, select your avatar. | ||||||
|  | 1. Select **Preferences**. | ||||||
|  | 1. Go to the **Behavior** section. | ||||||
|  | 1. Select the **Automatically add new list items** checkbox. | ||||||
|  | 1. Select **Save changes**. | ||||||
|  | 
 | ||||||
|  | ### Change the tab width | ||||||
|  | 
 | ||||||
|  | Change the default size of tabs in diffs, blobs, and snippets. The WebIDE, file editor, and Markdown editor do not support this feature. | ||||||
|  | 
 | ||||||
|  | To adjust the default tab width: | ||||||
|  | 
 | ||||||
|  | 1. On the left sidebar, select your avatar. | ||||||
|  | 1. Select **Preferences**. | ||||||
|  | 1. Go to the **Behavior** section. | ||||||
|  | 1. For **Tab width**, enter a value. | ||||||
|  | 1. Select **Save changes**. | ||||||
| 
 | 
 | ||||||
| ## Localization | ## Localization | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -45,6 +45,7 @@ module API | ||||||
|       optional :asset_proxy_whitelist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Deprecated: Use :asset_proxy_allowlist instead. Assets that match these domain(s) will NOT be proxied. Wildcards allowed. Your GitLab installation URL is automatically whitelisted.' |       optional :asset_proxy_whitelist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Deprecated: Use :asset_proxy_allowlist instead. Assets that match these domain(s) will NOT be proxied. Wildcards allowed. Your GitLab installation URL is automatically whitelisted.' | ||||||
|       optional :asset_proxy_allowlist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Assets that match these domain(s) will NOT be proxied. Wildcards allowed. Your GitLab installation URL is automatically allowed.' |       optional :asset_proxy_allowlist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Assets that match these domain(s) will NOT be proxied. Wildcards allowed. Your GitLab installation URL is automatically allowed.' | ||||||
|       optional :container_registry_token_expire_delay, type: Integer, desc: 'Authorization token duration (minutes)' |       optional :container_registry_token_expire_delay, type: Integer, desc: 'Authorization token duration (minutes)' | ||||||
|  |       optional :decompress_archive_file_timeout, type: Integer, desc: 'Default timeout for decompressing archived files, in seconds. Set to 0 to disable timeouts.' | ||||||
|       optional :default_artifacts_expire_in, type: String, desc: "Set the default expiration time for each job's artifacts" |       optional :default_artifacts_expire_in, type: String, desc: "Set the default expiration time for each job's artifacts" | ||||||
|       optional :default_ci_config_path, type: String, desc: 'The instance default CI/CD configuration file and path for new projects' |       optional :default_ci_config_path, type: String, desc: 'The instance default CI/CD configuration file and path for new projects' | ||||||
|       optional :default_project_creation, type: Integer, values: ::Gitlab::Access.project_creation_values, desc: 'Determine if developers can create projects in the group' |       optional :default_project_creation, type: Integer, values: ::Gitlab::Access.project_creation_values, desc: 'Determine if developers can create projects in the group' | ||||||
|  |  | ||||||
|  | @ -4,6 +4,8 @@ module BulkImports | ||||||
|   module Groups |   module Groups | ||||||
|     module Loaders |     module Loaders | ||||||
|       class GroupLoader |       class GroupLoader | ||||||
|  |         TWO_FACTOR_KEY = 'require_two_factor_authentication' | ||||||
|  | 
 | ||||||
|         GroupCreationError = Class.new(StandardError) |         GroupCreationError = Class.new(StandardError) | ||||||
| 
 | 
 | ||||||
|         def load(context, data) |         def load(context, data) | ||||||
|  | @ -16,6 +18,10 @@ module BulkImports | ||||||
|           raise(GroupCreationError, 'User not allowed to create group') unless user_can_create_group?(current_user, data) |           raise(GroupCreationError, 'User not allowed to create group') unless user_can_create_group?(current_user, data) | ||||||
|           raise(GroupCreationError, 'Group exists') if group_exists?(destination_namespace, path) |           raise(GroupCreationError, 'Group exists') if group_exists?(destination_namespace, path) | ||||||
| 
 | 
 | ||||||
|  |           unless two_factor_requirements_met?(current_user, data) | ||||||
|  |             raise(GroupCreationError, 'User requires Two-Factor Authentication') | ||||||
|  |           end | ||||||
|  | 
 | ||||||
|           group = ::Groups::CreateService.new(current_user, data).execute |           group = ::Groups::CreateService.new(current_user, data).execute | ||||||
| 
 | 
 | ||||||
|           raise(GroupCreationError, group.errors.full_messages.to_sentence) if group.errors.any? |           raise(GroupCreationError, group.errors.full_messages.to_sentence) if group.errors.any? | ||||||
|  | @ -37,6 +43,12 @@ module BulkImports | ||||||
|           end |           end | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|  |         def two_factor_requirements_met?(current_user, data) | ||||||
|  |           return true unless data.has_key?(TWO_FACTOR_KEY) && data[TWO_FACTOR_KEY] | ||||||
|  | 
 | ||||||
|  |           current_user.two_factor_enabled? | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|         def group_exists?(destination_namespace, path) |         def group_exists?(destination_namespace, path) | ||||||
|           full_path = destination_namespace.present? ? File.join(destination_namespace, path) : path |           full_path = destination_namespace.present? ? File.join(destination_namespace, path) : path | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,13 +5,12 @@ module Gitlab | ||||||
|     class DecompressedArchiveSizeValidator |     class DecompressedArchiveSizeValidator | ||||||
|       include Gitlab::Utils::StrongMemoize |       include Gitlab::Utils::StrongMemoize | ||||||
| 
 | 
 | ||||||
|       TIMEOUT_LIMIT = 210.seconds |  | ||||||
| 
 |  | ||||||
|       ServiceError = Class.new(StandardError) |       ServiceError = Class.new(StandardError) | ||||||
| 
 | 
 | ||||||
|       def initialize(archive_path:, max_bytes: self.class.max_bytes) |       def initialize(archive_path:, max_bytes: self.class.max_bytes, timeout: self.class.timeout) | ||||||
|         @archive_path = archive_path |         @archive_path = archive_path | ||||||
|         @max_bytes = max_bytes |         @max_bytes = max_bytes | ||||||
|  |         @timeout = timeout | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       def valid? |       def valid? | ||||||
|  | @ -24,6 +23,10 @@ module Gitlab | ||||||
|         Gitlab::CurrentSettings.current_application_settings.max_decompressed_archive_size.megabytes |         Gitlab::CurrentSettings.current_application_settings.max_decompressed_archive_size.megabytes | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|  |       def self.timeout | ||||||
|  |         Gitlab::CurrentSettings.current_application_settings.decompress_archive_file_timeout | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|       private |       private | ||||||
| 
 | 
 | ||||||
|       def validate |       def validate | ||||||
|  | @ -32,7 +35,7 @@ module Gitlab | ||||||
| 
 | 
 | ||||||
|         validate_archive_path |         validate_archive_path | ||||||
| 
 | 
 | ||||||
|         Timeout.timeout(TIMEOUT_LIMIT) do |         Timeout.timeout(@timeout) do | ||||||
|           stderr_r, stderr_w = IO.pipe |           stderr_r, stderr_w = IO.pipe | ||||||
|           stdout, wait_threads = Open3.pipeline_r(*command, pgroup: true, err: stderr_w) |           stdout, wait_threads = Open3.pipeline_r(*command, pgroup: true, err: stderr_w) | ||||||
| 
 | 
 | ||||||
|  | @ -70,7 +73,7 @@ module Gitlab | ||||||
| 
 | 
 | ||||||
|         valid_archive |         valid_archive | ||||||
|       rescue Timeout::Error |       rescue Timeout::Error | ||||||
|         log_error('Timeout reached during archive decompression') |         log_error("Timeout of #{@timeout} seconds reached during archive decompression") | ||||||
| 
 | 
 | ||||||
|         pgrps.each { |pgrp| Process.kill(-1, pgrp) } if pgrps |         pgrps.each { |pgrp| Process.kill(-1, pgrp) } if pgrps | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,36 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | # Patch to address https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/2286 | ||||||
|  | # Using a dual-namespace poller eliminates the need for script based migration of | ||||||
|  | # schedule-related sets in Sidekiq. | ||||||
|  | module Gitlab | ||||||
|  |   module Patch | ||||||
|  |     module SidekiqScheduledEnq | ||||||
|  |       # The patched enqueue_jobs will poll non-namespaced scheduled sets before doing the same for | ||||||
|  |       # namespaced sets via super and vice-versa depending on how Sidekiq.redis was configured | ||||||
|  |       def enqueue_jobs(sorted_sets = Sidekiq::Scheduled::SETS) | ||||||
|  |         # checks the other namespace | ||||||
|  |         if Gitlab::Utils.to_boolean(ENV['SIDEKIQ_POLL_NON_NAMESPACED']) | ||||||
|  |           # Refer to https://github.com/sidekiq/sidekiq/blob/v6.5.7/lib/sidekiq/scheduled.rb#L25 | ||||||
|  |           # this portion swaps out Sidekiq.redis for Gitlab::Redis::Queues | ||||||
|  |           Gitlab::Redis::Queues.with do |conn| # rubocop:disable Cop/RedisQueueUsage | ||||||
|  |             sorted_sets.each do |sorted_set| | ||||||
|  |               # adds namespace if `super` polls with a non-namespaced Sidekiq.redis | ||||||
|  |               if Gitlab::Utils.to_boolean(ENV['SIDEKIQ_ENQUEUE_NON_NAMESPACED']) | ||||||
|  |                 sorted_set = "#{Gitlab::Redis::Queues::SIDEKIQ_NAMESPACE}:#{sorted_set}" # rubocop:disable Cop/RedisQueueUsage | ||||||
|  |               end | ||||||
|  | 
 | ||||||
|  |               while !@done && (job = zpopbyscore(conn, keys: [sorted_set], argv: [Time.now.to_f.to_s])) # rubocop:disable Gitlab/ModuleWithInstanceVariables, Lint/AssignmentInCondition | ||||||
|  |                 Sidekiq::Client.push(Sidekiq.load_json(job)) # rubocop:disable Cop/SidekiqApiUsage | ||||||
|  |                 Sidekiq.logger.debug { "enqueued #{sorted_set}: #{job}" } | ||||||
|  |               end | ||||||
|  |             end | ||||||
|  |           end | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         # calls original enqueue_jobs which may or may not be namespaced depending on SIDEKIQ_ENQUEUE_NON_NAMESPACED | ||||||
|  |         super | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -24238,6 +24238,12 @@ msgstr "" | ||||||
| msgid "Import|There is not a valid Git repository at this URL. If your HTTP repository is not publicly accessible, verify your credentials." | msgid "Import|There is not a valid Git repository at this URL. If your HTTP repository is not publicly accessible, verify your credentials." | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  | msgid "Import|Timeout for decompressing archived files (seconds)" | ||||||
|  | msgstr "" | ||||||
|  | 
 | ||||||
|  | msgid "Import|Timeout for decompressing archived files." | ||||||
|  | msgstr "" | ||||||
|  | 
 | ||||||
| msgid "Improve customer support with Service Desk" | msgid "Improve customer support with Service Desk" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  | @ -35722,9 +35728,6 @@ msgstr "" | ||||||
| msgid "ProductAnalytics|Click Events" | msgid "ProductAnalytics|Click Events" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "ProductAnalytics|Clickhouse URL" |  | ||||||
| msgstr "" |  | ||||||
| 
 |  | ||||||
| msgid "ProductAnalytics|Compares all events against each other" | msgid "ProductAnalytics|Compares all events against each other" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  | @ -35740,9 +35743,6 @@ msgstr "" | ||||||
| msgid "ProductAnalytics|Compares page views of all pages against each other" | msgid "ProductAnalytics|Compares page views of all pages against each other" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "ProductAnalytics|Connection string" |  | ||||||
| msgstr "" |  | ||||||
| 
 |  | ||||||
| msgid "ProductAnalytics|Create a visualization" | msgid "ProductAnalytics|Create a visualization" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  | @ -35842,6 +35842,9 @@ msgstr "" | ||||||
| msgid "ProductAnalytics|Set up to track how your product is performing and optimize your product and development processes." | msgid "ProductAnalytics|Set up to track how your product is performing and optimize your product and development processes." | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  | msgid "ProductAnalytics|Snowplow configurator connection string" | ||||||
|  | msgstr "" | ||||||
|  | 
 | ||||||
| msgid "ProductAnalytics|The connection string for your Snowplow configurator instance." | msgid "ProductAnalytics|The connection string for your Snowplow configurator instance." | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  | @ -35866,9 +35869,6 @@ msgstr "" | ||||||
| msgid "ProductAnalytics|Unique Users" | msgid "ProductAnalytics|Unique Users" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "ProductAnalytics|Used to connect Snowplow to the Clickhouse instance." |  | ||||||
| msgstr "" |  | ||||||
| 
 |  | ||||||
| msgid "ProductAnalytics|Used to retrieve dashboard data from the Cube instance." | msgid "ProductAnalytics|Used to retrieve dashboard data from the Cube instance." | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  | @ -41366,7 +41366,7 @@ msgstr "" | ||||||
| msgid "ScanExecutionPolicy|%{period} %{days} at %{time} %{timezoneLabel} %{timezone}" | msgid "ScanExecutionPolicy|%{period} %{days} at %{time} %{timezoneLabel} %{timezone}" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "ScanExecutionPolicy|%{rules} actions for %{scopes} %{branches} %{branchExceptions} %{agents} %{namespaces} %{period}" | msgid "ScanExecutionPolicy|%{rules} actions for %{scopes} %{branches} %{agents} %{branchExceptions} %{namespaces} %{period}" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "ScanExecutionPolicy|%{rules} every time a pipeline runs for %{scopes} %{branches} %{branchExceptions} %{agents} %{namespaces}" | msgid "ScanExecutionPolicy|%{rules} every time a pipeline runs for %{scopes} %{branches} %{branchExceptions} %{agents} %{namespaces}" | ||||||
|  | @ -42192,7 +42192,7 @@ msgstr "" | ||||||
| msgid "SecurityOrchestration|%{branchName} (in %{codeStart}%{fullPath}%{codeEnd})" | msgid "SecurityOrchestration|%{branchName} (in %{codeStart}%{fullPath}%{codeEnd})" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "SecurityOrchestration|%{cadence} on %{branches}" | msgid "SecurityOrchestration|%{cadence} on %{branches}%{branchExceptionsString}" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "SecurityOrchestration|%{licenses} and %{lastLicense}" | msgid "SecurityOrchestration|%{licenses} and %{lastLicense}" | ||||||
|  | @ -42321,7 +42321,7 @@ msgstr "" | ||||||
| msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}" | msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "SecurityOrchestration|Every time a pipeline runs for %{branches}" | msgid "SecurityOrchestration|Every time a pipeline runs for %{branches}%{branchExceptionsString}" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "SecurityOrchestration|Exceptions" | msgid "SecurityOrchestration|Exceptions" | ||||||
|  | @ -42677,7 +42677,7 @@ msgstr "" | ||||||
| msgid "SecurityOrchestration|branches" | msgid "SecurityOrchestration|branches" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "SecurityOrchestration|by the agent named %{agents} %{cadence}" | msgid "SecurityOrchestration|by the agent named %{agents} %{cadence}%{branchExceptionsString}" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "SecurityOrchestration|group level branch input" | msgid "SecurityOrchestration|group level branch input" | ||||||
|  | @ -43822,6 +43822,9 @@ msgstr "" | ||||||
| msgid "Set to 0 for no size limit." | msgid "Set to 0 for no size limit." | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  | msgid "Set to 0 to disable timeout." | ||||||
|  | msgstr "" | ||||||
|  | 
 | ||||||
| msgid "Set to auto-merge" | msgid "Set to auto-merge" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -32,6 +32,8 @@ module QA | ||||||
|             within_element :allowed_to_create_dropdown do |             within_element :allowed_to_create_dropdown do | ||||||
|               click_on role |               click_on role | ||||||
|             end |             end | ||||||
|  |             # confirm selection and remove dropdown | ||||||
|  |             click_element :allowed_to_create_dropdown | ||||||
|           end |           end | ||||||
| 
 | 
 | ||||||
|           def click_protect_tag_button |           def click_protect_tag_button | ||||||
|  |  | ||||||
|  | @ -84,6 +84,33 @@ RSpec.describe BulkImports::Groups::Loaders::GroupLoader, feature_category: :imp | ||||||
| 
 | 
 | ||||||
|         include_examples 'calls Group Create Service to create a new group' |         include_examples 'calls Group Create Service to create a new group' | ||||||
|       end |       end | ||||||
|  | 
 | ||||||
|  |       context 'when user does not have 2FA enabled' do | ||||||
|  |         before do | ||||||
|  |           allow(user).to receive(:two_factor_enabled?).and_return(false) | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         context 'when require_two_factor_authentication is not passed' do | ||||||
|  |           include_examples 'calls Group Create Service to create a new group' | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         context 'when require_two_factor_authentication is false' do | ||||||
|  |           let(:data) { { 'require_two_factor_authentication' => false, 'path' => 'test' } } | ||||||
|  | 
 | ||||||
|  |           include_examples 'calls Group Create Service to create a new group' | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         context 'when require_two_factor_authentication is true' do | ||||||
|  |           let(:data) { { 'require_two_factor_authentication' => true, 'path' => 'test' } } | ||||||
|  | 
 | ||||||
|  |           it 'does not create new group' do | ||||||
|  |             expect(::Groups::CreateService).not_to receive(:new) | ||||||
|  | 
 | ||||||
|  |             expect { subject.load(context, data) } | ||||||
|  |               .to raise_error(described_class::GroupCreationError, 'User requires Two-Factor Authentication') | ||||||
|  |           end | ||||||
|  |         end | ||||||
|  |       end | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     context 'when user cannot create group' do |     context 'when user cannot create group' do | ||||||
|  |  | ||||||
|  | @ -93,7 +93,7 @@ RSpec.describe Gitlab::ImportExport::DecompressedArchiveSizeValidator, feature_c | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       context 'when timeout occurs' do |       context 'when timeout occurs' do | ||||||
|         let(:error_message) { 'Timeout reached during archive decompression' } |         let(:error_message) { 'Timeout of 210 seconds reached during archive decompression' } | ||||||
|         let(:exception) { Timeout::Error } |         let(:exception) { Timeout::Error } | ||||||
| 
 | 
 | ||||||
|         include_examples 'logs raised exception and terminates validator process group' |         include_examples 'logs raised exception and terminates validator process group' | ||||||
|  |  | ||||||
|  | @ -0,0 +1,89 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | require 'spec_helper' | ||||||
|  | 
 | ||||||
|  | RSpec.describe Gitlab::Patch::SidekiqScheduledEnq, :clean_gitlab_redis_queues, feature_category: :scalability do | ||||||
|  |   describe '#enqueue_jobs' do | ||||||
|  |     let_it_be(:payload) { {} } | ||||||
|  | 
 | ||||||
|  |     before do | ||||||
|  |       allow(Sidekiq).to receive(:load_json).and_return(payload) | ||||||
|  | 
 | ||||||
|  |       # stub data in both namespaces | ||||||
|  |       Sidekiq.redis { |c| c.zadd('schedule', 100, 'dummy') } | ||||||
|  |       Gitlab::Redis::Queues.with { |c| c.zadd('schedule', 100, 'dummy') } | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     subject { Sidekiq::Scheduled::Enq.new.enqueue_jobs } | ||||||
|  | 
 | ||||||
|  |     it 'only polls with Sidekiq.redis' do | ||||||
|  |       expect(Sidekiq::Client).to receive(:push).with(payload).once | ||||||
|  | 
 | ||||||
|  |       subject | ||||||
|  | 
 | ||||||
|  |       Sidekiq.redis do |conn| | ||||||
|  |         expect(conn.zcard('schedule')).to eq(0) | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       Gitlab::Redis::Queues.with do |conn| | ||||||
|  |         expect(conn.zcard('schedule')).to eq(1) | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'when SIDEKIQ_POLL_NON_NAMESPACED is enabled' do | ||||||
|  |       before do | ||||||
|  |         stub_env('SIDEKIQ_POLL_NON_NAMESPACED', 'true') | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       it 'polls both sets' do | ||||||
|  |         expect(Sidekiq::Client).to receive(:push).with(payload).twice | ||||||
|  | 
 | ||||||
|  |         subject | ||||||
|  | 
 | ||||||
|  |         Sidekiq.redis do |conn| | ||||||
|  |           expect(conn.zcard('schedule')).to eq(0) | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         Gitlab::Redis::Queues.with do |conn| | ||||||
|  |           expect(conn.zcard('schedule')).to eq(0) | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'when both envvar are enabled' do | ||||||
|  |       around do |example| | ||||||
|  |         # runs the zadd to ensure it goes into namespaced set | ||||||
|  |         Sidekiq.redis { |c| c.zadd('schedule', 100, 'dummy') } | ||||||
|  | 
 | ||||||
|  |         holder = Sidekiq.redis_pool | ||||||
|  | 
 | ||||||
|  |         # forcibly replace Sidekiq.redis since this is set in config/initializer/sidekiq.rb | ||||||
|  |         Sidekiq.redis = Gitlab::Redis::Queues.pool | ||||||
|  | 
 | ||||||
|  |         example.run | ||||||
|  | 
 | ||||||
|  |       ensure | ||||||
|  |         Sidekiq.redis = holder | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       before do | ||||||
|  |         stub_env('SIDEKIQ_ENQUEUE_NON_NAMESPACED', 'true') | ||||||
|  |         stub_env('SIDEKIQ_POLL_NON_NAMESPACED', 'true') | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       it 'polls both sets' do | ||||||
|  |         expect(Sidekiq::Client).to receive(:push).with(payload).twice | ||||||
|  | 
 | ||||||
|  |         subject | ||||||
|  | 
 | ||||||
|  |         Sidekiq.redis do |conn| | ||||||
|  |           expect(conn.zcard('schedule')).to eq(0) | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         Gitlab::Redis::Queues.with do |conn| | ||||||
|  |           expect(conn.zcard('schedule')).to eq(0) | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -25,6 +25,7 @@ RSpec.describe ApplicationSetting, feature_category: :shared, type: :model do | ||||||
|     it { expect(setting.kroki_formats).to eq({}) } |     it { expect(setting.kroki_formats).to eq({}) } | ||||||
|     it { expect(setting.default_branch_protection_defaults).to eq({}) } |     it { expect(setting.default_branch_protection_defaults).to eq({}) } | ||||||
|     it { expect(setting.max_decompressed_archive_size).to eq(25600) } |     it { expect(setting.max_decompressed_archive_size).to eq(25600) } | ||||||
|  |     it { expect(setting.decompress_archive_file_timeout).to eq(210) } | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   describe 'validations' do |   describe 'validations' do | ||||||
|  | @ -134,6 +135,9 @@ RSpec.describe ApplicationSetting, feature_category: :shared, type: :model do | ||||||
|     it { is_expected.to validate_presence_of(:container_registry_import_target_plan) } |     it { is_expected.to validate_presence_of(:container_registry_import_target_plan) } | ||||||
|     it { is_expected.to validate_presence_of(:container_registry_import_created_before) } |     it { is_expected.to validate_presence_of(:container_registry_import_created_before) } | ||||||
| 
 | 
 | ||||||
|  |     it { is_expected.to validate_numericality_of(:decompress_archive_file_timeout).only_integer.is_greater_than_or_equal_to(0) } | ||||||
|  |     it { is_expected.not_to allow_value(nil).for(:decompress_archive_file_timeout) } | ||||||
|  | 
 | ||||||
|     it { is_expected.to validate_numericality_of(:dependency_proxy_ttl_group_policy_worker_capacity).only_integer.is_greater_than_or_equal_to(0) } |     it { is_expected.to validate_numericality_of(:dependency_proxy_ttl_group_policy_worker_capacity).only_integer.is_greater_than_or_equal_to(0) } | ||||||
|     it { is_expected.not_to allow_value(nil).for(:dependency_proxy_ttl_group_policy_worker_capacity) } |     it { is_expected.not_to allow_value(nil).for(:dependency_proxy_ttl_group_policy_worker_capacity) } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting, featu | ||||||
|       expect(json_response['secret_detection_token_revocation_url']).to be_nil |       expect(json_response['secret_detection_token_revocation_url']).to be_nil | ||||||
|       expect(json_response['secret_detection_revocation_token_types_url']).to be_nil |       expect(json_response['secret_detection_revocation_token_types_url']).to be_nil | ||||||
|       expect(json_response['sourcegraph_public_only']).to be_truthy |       expect(json_response['sourcegraph_public_only']).to be_truthy | ||||||
|  |       expect(json_response['decompress_archive_file_timeout']).to eq(210) | ||||||
|       expect(json_response['default_preferred_language']).to be_a String |       expect(json_response['default_preferred_language']).to be_a String | ||||||
|       expect(json_response['default_project_visibility']).to be_a String |       expect(json_response['default_project_visibility']).to be_a String | ||||||
|       expect(json_response['default_snippet_visibility']).to be_a String |       expect(json_response['default_snippet_visibility']).to be_a String | ||||||
|  | @ -153,6 +154,7 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting, featu | ||||||
|             enforce_terms: true, |             enforce_terms: true, | ||||||
|             terms: 'Hello world!', |             terms: 'Hello world!', | ||||||
|             performance_bar_allowed_group_path: group.full_path, |             performance_bar_allowed_group_path: group.full_path, | ||||||
|  |             decompress_archive_file_timeout: 60, | ||||||
|             diff_max_patch_bytes: 300_000, |             diff_max_patch_bytes: 300_000, | ||||||
|             diff_max_files: 2000, |             diff_max_files: 2000, | ||||||
|             diff_max_lines: 50000, |             diff_max_lines: 50000, | ||||||
|  | @ -234,6 +236,7 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting, featu | ||||||
|         expect(json_response['enforce_terms']).to be(true) |         expect(json_response['enforce_terms']).to be(true) | ||||||
|         expect(json_response['terms']).to eq('Hello world!') |         expect(json_response['terms']).to eq('Hello world!') | ||||||
|         expect(json_response['performance_bar_allowed_group_id']).to eq(group.id) |         expect(json_response['performance_bar_allowed_group_id']).to eq(group.id) | ||||||
|  |         expect(json_response['decompress_archive_file_timeout']).to eq(60) | ||||||
|         expect(json_response['diff_max_patch_bytes']).to eq(300_000) |         expect(json_response['diff_max_patch_bytes']).to eq(300_000) | ||||||
|         expect(json_response['diff_max_files']).to eq(2000) |         expect(json_response['diff_max_files']).to eq(2000) | ||||||
|         expect(json_response['diff_max_lines']).to eq(50000) |         expect(json_response['diff_max_lines']).to eq(50000) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue