diff options
52 files changed, 246 insertions, 129 deletions
diff --git a/config/feature_flags/development/update_legacy_slack_installations.yml b/config/feature_flags/development/update_legacy_slack_installations.yml deleted file mode 100644 index 0ec42b1859f..00000000000 --- a/config/feature_flags/development/update_legacy_slack_installations.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: update_legacy_slack_installations -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96208 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/371810 -milestone: '15.4' -type: development -group: group::integrations -default_enabled: false diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml index c8f9d78eb84..939872189f7 100644 --- a/config/sidekiq_queues.yml +++ b/config/sidekiq_queues.yml @@ -251,6 +251,8 @@ - 1 - - integrations_irker - 1 +- - integrations_slack_event + - 1 - - invalid_gpg_signature_update - 2 - - issuable_export_csv diff --git a/doc/.vale/gitlab/British.yml b/doc/.vale/gitlab/British.yml index f724eb19fa9..c63cbd917c7 100644 --- a/doc/.vale/gitlab/British.yml +++ b/doc/.vale/gitlab/British.yml @@ -80,6 +80,9 @@ swap: neighbour: neighbor normalise: normalize offence: offense + optimise: optimize + optimised: optimized + optimising: optimizing organise: organize orientated: oriented paralyse: paralyze diff --git a/doc/architecture/blueprints/database_scaling/size-limits.md b/doc/architecture/blueprints/database_scaling/size-limits.md index 284f6402d3c..0bb1ae9efb4 100644 --- a/doc/architecture/blueprints/database_scaling/size-limits.md +++ b/doc/architecture/blueprints/database_scaling/size-limits.md @@ -138,7 +138,7 @@ There is no standard solution to reduce table sizes - there are many! 1. **Retention**: Delete unnecessary data, for example expire old and unneeded records. 1. **Remove STI**: We still use [single-table inheritance](../../../development/database/single_table_inheritance.md) in a few places, which is considered an anti-pattern. Redesigning this, we can split data into multiple tables. 1. **Index optimization**: Drop unnecessary indexes and consolidate overlapping indexes if possible. -1. **Optimise data types**: Review data type decisions and optimise data types where possible (example: use integer instead of text for an enum column) +1. **Optimize data types**: Review data type decisions and optimize data types where possible (example: use integer instead of text for an enum column) 1. **Partitioning**: Apply a partitioning scheme if there is a common access dimension. 1. **Normalization**: Review relational modeling and apply normalization techniques to remove duplicate data 1. **Vertical table splits**: Review column usage and split table vertically. diff --git a/doc/architecture/blueprints/feature_flags_development/index.md b/doc/architecture/blueprints/feature_flags_development/index.md index 75238a7f422..08253ac883c 100644 --- a/doc/architecture/blueprints/feature_flags_development/index.md +++ b/doc/architecture/blueprints/feature_flags_development/index.md @@ -23,7 +23,7 @@ The extensive usage of feature flags poses a few challenges - Each feature flag that we add to codebase is a ~"technical debt" as it adds a matrix of configurations. - Testing each combination of feature flags is close to impossible, so we - instead try to optimise our testing of feature flags to the most common + instead try to optimize our testing of feature flags to the most common scenarios. - There's a growing challenge of maintaining a growing number of feature flags. We sometimes forget how our feature flags are configured or why we haven't diff --git a/doc/ci/cloud_services/index.md b/doc/ci/cloud_services/index.md index bde5e9dbb1b..93fedb0ffca 100644 --- a/doc/ci/cloud_services/index.md +++ b/doc/ci/cloud_services/index.md @@ -25,6 +25,10 @@ review for the pipeline, focusing on the additional access. You can use the [sof as a starting point, and for more information about supply chain attacks, see [How a DevOps Platform helps protect against supply chain attacks](https://about.gitlab.com/blog/2021/04/28/devops-platform-supply-chain-attacks/). +The `CI_JOB_JWT_V2` variable is available for testing, but the full feature is planned +to be generally available when [issue 360657](https://gitlab.com/gitlab-org/gitlab/-/issues/360657) +is complete. + ## Use cases - Removes the need to store secrets in your GitLab group or project. Temporary credentials can be retrieved from your cloud provider through OIDC. diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md index e0ec0728c71..6c1737f7c65 100644 --- a/doc/ci/variables/where_variables_can_be_used.md +++ b/doc/ci/variables/where_variables_can_be_used.md @@ -30,6 +30,7 @@ There are two places defined variables can be used. On the: | [`cache:key`](../yaml/index.md#cachekey) | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism). | | [`environment:name`](../yaml/index.md#environmentname) | yes | GitLab | Similar to `environment:url`, but the variables expansion doesn't support the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). | | [`environment:url`](../yaml/index.md#environmenturl) | yes | GitLab | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab.<br/><br/>Supported are all variables defined for a job (project/group variables, variables from `.gitlab-ci.yml`, variables from triggers, variables from pipeline schedules).<br/><br/>Not supported are variables defined in the GitLab Runner `config.toml` and variables created in the job's `script`. | +| [`environment:auto_stop_in`](../yaml/index.md#environmentauto_stop_in)| yes | GitLab | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab.<br/><br/> The value of the variable being substituted should be a period of time in a human readable natural language form. See [possible inputs](../yaml/index.md#environmentauto_stop_in) for more information.| | [`except:variables`](../yaml/index.md#onlyvariables--exceptvariables) | no | Not applicable | The variable must be in the form of `$variable`. Not supported are the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). | | [`image`](../yaml/index.md#image) | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism). | | [`include`](../yaml/index.md#include) | yes | GitLab | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab. <br/><br/>See [Use variables with include](../yaml/includes.md#use-variables-with-include) for more information on supported variables. | diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md index 2a05471fcf1..8aa3ebd4759 100644 --- a/doc/ci/yaml/index.md +++ b/doc/ci/yaml/index.md @@ -1640,6 +1640,7 @@ these are all equivalent: - `168 hours` - `7 days` - `one week` +- `never` **Example of `environment:auto_stop_in`**: diff --git a/doc/development/database/ordering_table_columns.md b/doc/development/database/ordering_table_columns.md index 7cd3d4fb208..a16df6a4499 100644 --- a/doc/development/database/ordering_table_columns.md +++ b/doc/development/database/ordering_table_columns.md @@ -117,7 +117,7 @@ divided into fixed size chunks as follows: This means that excluding the variable sized data and tuple header, we need at least 8 * 6 = 48 bytes per row. -We can optimise this by using the following column order instead: +We can optimize this by using the following column order instead: | Column | Type | Size | |:--------------|:----------------------------|:---------| diff --git a/doc/development/database/understanding_explain_plans.md b/doc/development/database/understanding_explain_plans.md index b3f99da5b26..c3cb408b35f 100644 --- a/doc/development/database/understanding_explain_plans.md +++ b/doc/development/database/understanding_explain_plans.md @@ -295,9 +295,9 @@ because the previous node produced 36 rows. This means that nested loops can quickly slow the query down if the various child nodes keep producing many rows. -## Optimising queries +## Optimizing queries -With that out of the way, let's see how we can optimise a query. Let's use the +With that out of the way, let's see how we can optimize a query. Let's use the following query as an example: ```sql @@ -453,7 +453,7 @@ this works is that now PostgreSQL no longer needs to apply a `Filter`, as the index only contains `twitter` values that are not empty. Keep in mind that you shouldn't just add partial indexes every time you want to -optimise a query. Every index has to be updated for every write, and they may +optimize a query. Every index has to be updated for every write, and they may require quite a bit of space, depending on the amount of indexed data. As a result, first check if there are any existing indexes you may be able to reuse. If there aren't any, check if you can perhaps slightly change an existing one to @@ -471,10 +471,10 @@ buffer numbers. [Database Lab Engine](#database-lab-engine) guarantees that the identical to production (and overall number of buffers is the same as on production), but difference in cache state and I/O speed may lead to different timings. -## Queries that can't be optimised +## Queries that can't be optimized -Now that we have seen how to optimise a query, let's look at another query that -we might not be able to optimise: +Now that we have seen how to optimize a query, let's look at another query that +we might not be able to optimize: ```sql EXPLAIN (ANALYZE, BUFFERS) @@ -546,7 +546,7 @@ improve this query, other than _not_ running it at all. What is important here is that while some may recommend to straight up add an index the moment you see a sequential scan, it is _much more important_ to first understand what your query does, how much data it retrieves, and so on. After -all, you can not optimise something you do not understand. +all, you can not optimize something you do not understand. ### Cardinality and selectivity @@ -567,7 +567,7 @@ using an index is not worth it, because it would produce almost no unique rows. ## Rewriting queries -So the above query can't really be optimised as-is, or at least not much. But +So the above query can't really be optimized as-is, or at least not much. But what if we slightly change the purpose of it? What if instead of retrieving all projects with `visibility_level` 0 or 20, we retrieve those that a user interacted with somehow? diff --git a/doc/development/sql.md b/doc/development/sql.md index e84c9747e32..029874011c4 100644 --- a/doc/development/sql.md +++ b/doc/development/sql.md @@ -397,7 +397,7 @@ default. While `WHERE IN` and `WHERE EXISTS` can be used to produce the same data it is recommended to use `WHERE EXISTS` whenever possible. While in many cases -PostgreSQL can optimise `WHERE IN` quite well there are also many cases where +PostgreSQL can optimize `WHERE IN` quite well there are also many cases where `WHERE EXISTS` performs (much) better. In Rails you have to use this by creating SQL fragments: diff --git a/doc/user/admin_area/settings/project_integration_management.md b/doc/user/admin_area/settings/project_integration_management.md index 010ba6a12fc..58afc6a104c 100644 --- a/doc/user/admin_area/settings/project_integration_management.md +++ b/doc/user/admin_area/settings/project_integration_management.md @@ -22,7 +22,7 @@ Only the complete settings for an integration can be inherited. Per-field inheri > - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2137) in GitLab 13.3 for project-level integrations. > - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2543) in GitLab 13.6 for group-level integrations. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Integrations**. 1. Select an integration. 1. Enter configuration details and select **Save changes**. @@ -54,7 +54,7 @@ integration on all non-configured groups and projects by default. ### Remove an instance-level default setting -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Integrations**. 1. Select an integration. 1. Select **Reset** and confirm. @@ -68,7 +68,7 @@ Resetting an instance-level default setting removes the integration from all pro You can view which projects in your instance use custom settings that [override the instance-level default settings](#use-custom-settings-for-a-group-or-project-integration) for an integration. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Integrations**. 1. Select an integration. 1. Select the **Projects using custom settings** tab. diff --git a/doc/user/admin_area/settings/push_event_activities_limit.md b/doc/user/admin_area/settings/push_event_activities_limit.md index 760ce96d987..cd982bb4aa3 100644 --- a/doc/user/admin_area/settings/push_event_activities_limit.md +++ b/doc/user/admin_area/settings/push_event_activities_limit.md @@ -26,7 +26,7 @@ the activity feed. To modify this setting: - In the Admin Area: - 1. On the top bar, select **Menu > Admin**. + 1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Network**, then expand **Performance optimization**. - Through the [Application settings API](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls) as `push_event_activities_limit`. diff --git a/doc/user/admin_area/settings/rate_limit_on_issues_creation.md b/doc/user/admin_area/settings/rate_limit_on_issues_creation.md index 6c0c15243da..8d08da8246a 100644 --- a/doc/user/admin_area/settings/rate_limit_on_issues_creation.md +++ b/doc/user/admin_area/settings/rate_limit_on_issues_creation.md @@ -12,7 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w This setting allows you to rate limit the requests to the issue and epic creation endpoints. To can change its value: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Network**. 1. Expand **Issues Rate Limits**. 1. Under **Max requests per minute**, enter the new value. diff --git a/doc/user/admin_area/settings/rate_limit_on_notes_creation.md b/doc/user/admin_area/settings/rate_limit_on_notes_creation.md index 0a07cf095ee..f55c2f3bd4a 100644 --- a/doc/user/admin_area/settings/rate_limit_on_notes_creation.md +++ b/doc/user/admin_area/settings/rate_limit_on_notes_creation.md @@ -13,7 +13,7 @@ You can configure the per-user rate limit for requests to the note creation endp To change the note creation rate limit: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Network**. 1. Expand **Notes rate limit**. 1. In the **Maximum requests per minute** box, enter the new value. diff --git a/doc/user/admin_area/settings/rate_limit_on_pipelines_creation.md b/doc/user/admin_area/settings/rate_limit_on_pipelines_creation.md index 5202a51de0f..ba383d74701 100644 --- a/doc/user/admin_area/settings/rate_limit_on_pipelines_creation.md +++ b/doc/user/admin_area/settings/rate_limit_on_pipelines_creation.md @@ -26,7 +26,7 @@ Requests that exceed the limit are logged in the `application_json.log` file. To limit the number of pipeline requests: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Network**. 1. Expand **Pipelines Rate Limits**. 1. Under **Max requests per minute**, enter a value greater than `0`. diff --git a/doc/user/admin_area/settings/rate_limit_on_users_api.md b/doc/user/admin_area/settings/rate_limit_on_users_api.md index 5eed989f73f..9792fd1000d 100644 --- a/doc/user/admin_area/settings/rate_limit_on_users_api.md +++ b/doc/user/admin_area/settings/rate_limit_on_users_api.md @@ -13,7 +13,7 @@ You can configure the per user rate limit for requests to [Users API](../../../a To change the rate limit: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Network**. 1. Expand **Users API rate limit**. 1. In the **Maximum requests per 10 minutes** text box, enter the new value. diff --git a/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md b/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md index 028d5e4c2f3..cb3ca0fe756 100644 --- a/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md +++ b/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md @@ -11,7 +11,7 @@ type: reference This setting defaults to `300` requests per minute, and allows you to rate limit the requests to raw endpoints: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Network**. 1. Expand **Performance optimization**. diff --git a/doc/user/admin_area/settings/sidekiq_job_limits.md b/doc/user/admin_area/settings/sidekiq_job_limits.md index 750665285b4..c1990572aee 100644 --- a/doc/user/admin_area/settings/sidekiq_job_limits.md +++ b/doc/user/admin_area/settings/sidekiq_job_limits.md @@ -17,7 +17,7 @@ Redis. To avoid excessive memory for Redis, we: To access Sidekiq job size limits: -1. On the top bar, select **Menu >** **{admin}** **Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Preferences**. 1. Expand **Sidekiq job size limits**. 1. Adjust the compression threshold or size limit. The compression can diff --git a/doc/user/admin_area/settings/sign_in_restrictions.md b/doc/user/admin_area/settings/sign_in_restrictions.md index e3fa8ba6df5..bdffe87b75c 100644 --- a/doc/user/admin_area/settings/sign_in_restrictions.md +++ b/doc/user/admin_area/settings/sign_in_restrictions.md @@ -12,7 +12,7 @@ You can use **Sign-in restrictions** to customize authentication restrictions fo To access sign-in restriction settings: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Sign-in restrictions** section. @@ -121,7 +121,7 @@ For example, if you include the following information in the noted text box: To access this text box: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**, and expand the **Sign-in restrictions** section. ``` diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md index 56abb3d4701..a0ec964e8db 100644 --- a/doc/user/admin_area/settings/sign_up_restrictions.md +++ b/doc/user/admin_area/settings/sign_up_restrictions.md @@ -22,7 +22,7 @@ you do not expect public users to sign up for an account. To disable sign ups: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**, and expand **Sign-up restrictions**. 1. Clear the **Sign-up enabled** checkbox, then select **Save changes**. @@ -38,7 +38,7 @@ enabled by default for new GitLab instances. It is only applicable if sign ups a To require administrator approval for new sign ups: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**, and expand **Sign-up restrictions**. 1. Select the **Require admin approval for new sign-ups** checkbox, then select **Save changes**. @@ -58,7 +58,7 @@ their email address before they are allowed to sign in. To enforce confirmation of the email address used for new sign ups: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**, and expand **Sign-up restrictions**. 1. Select the **Send confirmation email on sign-up** checkbox, then select **Save changes**. @@ -76,7 +76,7 @@ user cap, the users in pending approval state are automatically approved in a ba ### Set the user cap number -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand **Sign-up restrictions**. 1. Enter a number in **User cap**. @@ -86,7 +86,7 @@ New user sign ups are subject to the user cap restriction. ## Remove the user cap -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand **Sign-up restrictions**. 1. Remove the number from **User cap**. @@ -130,7 +130,7 @@ You can add additional complexity requirements. Changes to password complexity r Existing passwords are unaffected. To change password complexity requirements: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand **Sign-up restrictions**. 1. Under **Minimum password length (number of characters)**, select additional password complexity requirements. You can require numbers, uppercase letters, lowercase letters, @@ -159,7 +159,7 @@ reduce the risk of malicious users creating spam accounts with disposable email To create an email domain allowlist or denylist: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**, and expand **Sign-up restrictions**. 1. For the allowlist, you must enter the list manually. For the denylist, you can enter the list manually or upload a `.txt` file that contains list entries. diff --git a/doc/user/admin_area/settings/terms.md b/doc/user/admin_area/settings/terms.md index 870fa7ad18e..d26ace161bb 100644 --- a/doc/user/admin_area/settings/terms.md +++ b/doc/user/admin_area/settings/terms.md @@ -17,7 +17,7 @@ for example `https://gitlab.example.com/-/users/terms`. To enforce acceptance of a Terms of Service and Privacy Policy: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Terms of Service and Privacy Policy** section. 1. Check the **All users must accept the Terms of Service and Privacy Policy to access GitLab** checkbox. diff --git a/doc/user/admin_area/settings/third_party_offers.md b/doc/user/admin_area/settings/third_party_offers.md index 04ec9ed652f..59c100dc016 100644 --- a/doc/user/admin_area/settings/third_party_offers.md +++ b/doc/user/admin_area/settings/third_party_offers.md @@ -18,7 +18,7 @@ questions when creating a group. To toggle the display of customer experience improvement content and third-party offers: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings**, and expand **Customer experience improvement & third-party offers**. 1. Select **Do not display content for customer experience improvement and offers from third parties**. 1. Select **Save changes**. diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md index afb937494e0..ad018abf809 100644 --- a/doc/user/admin_area/settings/usage_statistics.md +++ b/doc/user/admin_area/settings/usage_statistics.md @@ -56,7 +56,7 @@ Registration is not yet required for participation, but may be added in a future ### Enable registration features 1. Sign in as a user with administrator access. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Metrics and profiling**. 1. Expand the **Usage statistics** section. 1. If not enabled, select the **Enable Service Ping** checkbox. @@ -113,7 +113,7 @@ If your GitLab instance is behind a proxy, set the appropriate To enable or disable Service Ping and version check: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Metrics and profiling**. 1. Expand **Usage statistics**. 1. Select or clear the **Enable version check** and **Enable Service Ping** checkboxes. @@ -165,7 +165,7 @@ the Admin Area: You can view the exact JSON payload sent to GitLab Inc. in the Admin Area. To view the payload: 1. Sign in as a user with administrator access. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Metrics and profiling**. 1. Expand the **Usage statistics** section. 1. Select **Preview payload**. @@ -183,7 +183,7 @@ or if the Service Ping [cron job](../../../development/service_ping/index.md#how To upload the payload manually: 1. Sign in as a user with administrator access. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Service** usage data. 1. Select **Download payload**. 1. Save the JSON file. diff --git a/doc/user/admin_area/settings/user_and_ip_rate_limits.md b/doc/user/admin_area/settings/user_and_ip_rate_limits.md index a35cbe5381a..86676e4a63e 100644 --- a/doc/user/admin_area/settings/user_and_ip_rate_limits.md +++ b/doc/user/admin_area/settings/user_and_ip_rate_limits.md @@ -31,7 +31,7 @@ counted as web traffic. To enable the unauthenticated request rate limit: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Network**, and expand **User and IP rate limits**. 1. Select **Enable unauthenticated API request rate limit**. @@ -44,7 +44,7 @@ To enable the unauthenticated request rate limit: To enable the unauthenticated request rate limit: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Network**, and expand **User and IP rate limits**. 1. Select **Enable unauthenticated web request rate limit**. @@ -57,7 +57,7 @@ To enable the unauthenticated request rate limit: To enable the authenticated API request rate limit: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Network**, and expand **User and IP rate limits**. 1. Select **Enable authenticated API request rate limit**. @@ -70,7 +70,7 @@ To enable the authenticated API request rate limit: To enable the unauthenticated request rate limit: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Network**, and expand **User and IP rate limits**. 1. Select **Enable authenticated web request rate limit**. @@ -88,7 +88,7 @@ plain-text body, which by default is `Retry later`. To use a custom response: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Network**, and expand **User and IP rate limits**. 1. In the **Plain-text response to send to clients that hit a rate limit** text box, add the plain-text response message. diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md index 551191433bd..87c24f04a1c 100644 --- a/doc/user/admin_area/settings/visibility_and_access_controls.md +++ b/doc/user/admin_area/settings/visibility_and_access_controls.md @@ -13,7 +13,7 @@ specific controls on branches, projects, snippets, groups, and more. To access the visibility and access control options: 1. Sign in to GitLab as a user with Administrator access level. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Visibility and access controls** section. @@ -24,7 +24,7 @@ Instance-level protections for project creation define which roles can on the instance. To alter which roles have permission to create projects: 1. Sign in to GitLab as a user with Administrator access level. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Visibility and access controls** section. 1. For **Default project creation protection**, select the desired roles: @@ -40,7 +40,7 @@ on the instance. To alter which roles have permission to create projects: By default both administrators and anyone with the **Owner** role can delete a project. To restrict project deletion to only administrators: 1. Sign in to GitLab as a user with administrator access. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Visibility and access controls** section. 1. Scroll to: @@ -78,7 +78,7 @@ deleted groups will remain restorable within a retention period. To configure delayed project deletion: 1. Sign in to GitLab as a user with administrator access. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Visibility and access controls** section. 1. Scroll to: @@ -112,7 +112,7 @@ Alternatively, projects that are marked for removal can be deleted immediately. To set the default [visibility levels for new projects](../../public_access.md): 1. Sign in to GitLab as a user with Administrator access level. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Visibility and access controls** section. 1. Select the desired default project visibility: @@ -127,7 +127,7 @@ To set the default [visibility levels for new projects](../../public_access.md): To set the default visibility levels for new [snippets](../../snippets.md): 1. Sign in to GitLab as a user with Administrator access level. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Visibility and access controls** section. 1. Select the desired default snippet visibility. @@ -141,7 +141,7 @@ For more details on snippet visibility, read To set the default visibility levels for new groups: 1. Sign in to GitLab as a user with Administrator access level. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Visibility and access controls** section. 1. Select the desired default group visibility: @@ -158,7 +158,7 @@ For more details on group visibility, see To restrict visibility levels for projects, snippets, and selected pages: 1. Sign in to GitLab as a user with Administrator access level. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Visibility and access controls** section. 1. In the **Restricted visibility levels** section, select the desired visibility levels to restrict. @@ -177,7 +177,7 @@ For more details on project visibility, see You can specify from which hosting sites users can [import their projects](../../project/import/index.md): 1. Sign in to GitLab as a user with Administrator access level. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Visibility and access controls** section. 1. Select each of **Import sources** to allow. @@ -189,7 +189,7 @@ To enable the export of [projects and their data](../../project/settings/import_export.md#export-a-project-and-its-data): 1. Sign in to GitLab as a user with Administrator access level. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Visibility and access controls** section. 1. Select **Project export enabled**. @@ -205,7 +205,7 @@ The GitLab restrictions apply at the application level. To specify the enabled Git access protocols: 1. Sign in to GitLab as a user with Administrator access level. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Visibility and access controls** section. 1. Select the desired Git access protocols: @@ -291,7 +291,7 @@ daemon to be unable to fetch artifacts from the pipeline runs. To add a IP address range to the group-level allowlist: 1. Sign in to GitLab as a user with Administrator access level. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Visibility and access controls** section. 1. In **Globally-allowed IP ranges**, provide a value. diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md index 5ac9c3f2e64..0f446ddee3e 100644 --- a/doc/user/application_security/dast/index.md +++ b/doc/user/application_security/dast/index.md @@ -357,13 +357,9 @@ variables: #### Import API specification from a file If your API specification file is in your repository, you can provide its filename as the target. -The API specification file must be in the `/zap/wrk` directory. ```yaml dast: - before_script: - - mkdir -p /zap/wrk - - cp api-specification.yml /zap/wrk/api-specification.yml variables: GIT_STRATEGY: fetch DAST_API_SPECIFICATION: api-specification.yml diff --git a/lib/api/admin/batched_background_migrations.rb b/lib/api/admin/batched_background_migrations.rb index 7d663b8e92a..675f3365bd3 100644 --- a/lib/api/admin/batched_background_migrations.rb +++ b/lib/api/admin/batched_background_migrations.rb @@ -66,6 +66,26 @@ module API end end end + + resources 'batched_background_migrations/:id/pause' do + desc 'Pause a batched background migration' + params do + optional :database, + type: String, + values: Gitlab::Database.all_database_names, + desc: 'The name of the database', + default: 'main' + requires :id, + type: Integer, + desc: 'The batched background migration id' + end + put do + Gitlab::Database::SharedModel.using_connection(base_model.connection) do + batched_background_migration.pause! + present_entity(batched_background_migration) + end + end + end end helpers do diff --git a/lib/gitlab/memory/jemalloc.rb b/lib/gitlab/memory/jemalloc.rb index 7163a70a5cb..e20e186cab9 100644 --- a/lib/gitlab/memory/jemalloc.rb +++ b/lib/gitlab/memory/jemalloc.rb @@ -27,21 +27,27 @@ module Gitlab # Write jemalloc stats to the given directory # @param [String] path Directory path the dump will be put into + # @param [String] tmp_dir Directory path the dump will be streaming to. It is moved to `path` when finished. # @param [String] format `json` or `txt` # @param [String] filename_label Optional custom string that will be injected into the file name, e.g. `worker_0` # @return [String] Full path to the resulting dump file - def dump_stats(path:, format: STATS_DEFAULT_FORMAT, filename_label: nil) + def dump_stats(path:, tmp_dir: Dir.tmpdir, format: STATS_DEFAULT_FORMAT, filename_label: nil) verify_format!(format) format_settings = STATS_FORMATS[format] + tmp_file_path = File.join(tmp_dir, file_name(format_settings[:extension], filename_label)) file_path = File.join(path, file_name(format_settings[:extension], filename_label)) with_malloc_stats_print do |stats_print| - File.open(file_path, 'wb') do |io| + File.open(tmp_file_path, 'wb') do |io| write_stats(stats_print, io, format_settings) end end + # On OSX, `with_malloc_stats_print` is no-op, and, as result, no file will be written + return unless File.exist?(tmp_file_path) + + FileUtils.mv(tmp_file_path, file_path) file_path end diff --git a/lib/gitlab/memory/reports/jemalloc_stats.rb b/lib/gitlab/memory/reports/jemalloc_stats.rb index b99bec4ac3e..05f0717d7c3 100644 --- a/lib/gitlab/memory/reports/jemalloc_stats.rb +++ b/lib/gitlab/memory/reports/jemalloc_stats.rb @@ -18,12 +18,19 @@ module Gitlab def initialize(reports_path:) @reports_path = reports_path + + # Store report in tmp subdir while it is still streaming. + # This will clearly separate finished reports from the files we are still writing to. + @tmp_dir = File.join(@reports_path, 'tmp') + FileUtils.mkdir_p(@tmp_dir) end def run return unless active? - Gitlab::Memory::Jemalloc.dump_stats(path: reports_path, filename_label: worker_id).tap { cleanup } + Gitlab::Memory::Jemalloc.dump_stats(path: reports_path, tmp_dir: @tmp_dir, filename_label: worker_id).tap do + cleanup + end end def active? diff --git a/locale/gitlab.pot b/locale/gitlab.pot index e5ddf3bbc3d..65281a6bc15 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -37061,6 +37061,39 @@ msgstr "" msgid "SlackService|Perform common operations in this project by entering slash commands in Slack." msgstr "" +msgid "Slack|%{asterisk}Step 1.%{asterisk} Connect your GitLab account to get started." +msgstr "" + +msgid "Slack|%{asterisk}Step 2.%{asterisk} Try it out!" +msgstr "" + +msgid "Slack|%{emoji}Connected to GitLab account %{account}" +msgstr "" + +msgid "Slack|%{emoji}Welcome to GitLab for Slack!" +msgstr "" + +msgid "Slack|Connect your GitLab account" +msgstr "" + +msgid "Slack|Create a new issue" +msgstr "" + +msgid "Slack|Create new issues from Slack: %{command}" +msgstr "" + +msgid "Slack|Run a CI/CD job" +msgstr "" + +msgid "Slack|See a list of available commands: %{command})" +msgstr "" + +msgid "Slack|Streamline your GitLab deployments with ChatOps. Once you've configured your %{startMarkup}CI/CD pipelines%{endMarkup}, try: %{command}" +msgstr "" + +msgid "Slack|View and control GitLab content while you're working in Slack. Type the command as a message in your chat client to activate it. %{startMarkup}Learn more%{endMarkup}." +msgstr "" + msgid "Slice multiplier" msgstr "" diff --git a/spec/frontend/__helpers__/matchers/to_validate_json_schema_spec.js b/spec/frontend/__helpers__/matchers/to_validate_json_schema_spec.js index fd42c710c65..e6096221528 100644 --- a/spec/frontend/__helpers__/matchers/to_validate_json_schema_spec.js +++ b/spec/frontend/__helpers__/matchers/to_validate_json_schema_spec.js @@ -38,7 +38,7 @@ describe('custom matcher toValidateJsonSchema', () => { }); it('throws if not matching', () => { - expect(() => expect(null).toValidateJsonSchema(schema)).toThrowError( + expect(() => expect(null).toValidateJsonSchema(schema)).toThrow( `Expected the given data to pass the schema validation, but found that it was considered invalid. Errors: Error with item : must be object`, ); @@ -57,7 +57,7 @@ Error with item : must be object`, }); it('throws if matching', () => { - expect(() => expect({ fruit: 'apple' }).not.toValidateJsonSchema(schema)).toThrowError( + expect(() => expect({ fruit: 'apple' }).not.toValidateJsonSchema(schema)).toThrow( 'Expected the given data not to pass the schema validation, but found that it was considered valid.', ); }); diff --git a/spec/frontend/__mocks__/sortablejs/index.js b/spec/frontend/__mocks__/sortablejs/index.js index 5039af54542..d8bc8ae9bda 100644 --- a/spec/frontend/__mocks__/sortablejs/index.js +++ b/spec/frontend/__mocks__/sortablejs/index.js @@ -1,4 +1,4 @@ -const Sortablejs = jest.genMockFromModule('sortablejs'); +const Sortablejs = jest.createMockFromModule('sortablejs'); export default Sortablejs; export const Sortable = Sortablejs; diff --git a/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js b/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js index a2dc3ac0a76..286a8b92282 100644 --- a/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js +++ b/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js @@ -75,7 +75,7 @@ describe('AddContextCommitsModal', () => { it('when user starts entering text in search box, it calls action "searchCommits" after waiting for 500s', () => { const searchText = 'abcd'; findSearch().vm.$emit('input', searchText); - expect(searchCommits).not.toBeCalled(); + expect(searchCommits).not.toHaveBeenCalled(); jest.advanceTimersByTime(500); expect(searchCommits).toHaveBeenCalledWith(expect.anything(), searchText); }); diff --git a/spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js b/spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js index 65ccca7334d..ad6089f74b5 100644 --- a/spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js +++ b/spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js @@ -61,7 +61,7 @@ describe('UsageTrendsCountChart', () => { }); it('requests data', () => { - expect(queryHandler).toBeCalledTimes(1); + expect(queryHandler).toHaveBeenCalledTimes(1); }); it('displays the skeleton loader', () => { @@ -105,7 +105,7 @@ describe('UsageTrendsCountChart', () => { }); it('requests data', () => { - expect(queryHandler).toBeCalledTimes(1); + expect(queryHandler).toHaveBeenCalledTimes(1); }); it('hides the skeleton loader', () => { @@ -141,7 +141,7 @@ describe('UsageTrendsCountChart', () => { }); it('requests data twice', () => { - expect(queryHandler).toBeCalledTimes(2); + expect(queryHandler).toHaveBeenCalledTimes(2); }); it('passes the data to the line chart', () => { diff --git a/spec/frontend/analytics/usage_trends/components/users_chart_spec.js b/spec/frontend/analytics/usage_trends/components/users_chart_spec.js index 6b9f09629e2..e7abd4d4323 100644 --- a/spec/frontend/analytics/usage_trends/components/users_chart_spec.js +++ b/spec/frontend/analytics/usage_trends/components/users_chart_spec.js @@ -139,7 +139,7 @@ describe('UsersChart', () => { }); it('requests data twice', () => { - expect(queryHandler).toBeCalledTimes(2); + expect(queryHandler).toHaveBeenCalledTimes(2); }); it('calls fetchMore', () => { diff --git a/spec/frontend/chronic_duration_spec.js b/spec/frontend/chronic_duration_spec.js index 32652e13dfc..b063110782a 100644 --- a/spec/frontend/chronic_duration_spec.js +++ b/spec/frontend/chronic_duration_spec.js @@ -86,7 +86,7 @@ describe('parseChronicDuration', () => { describe('when .raiseExceptions set to true', () => { it('raises with DurationParseError', () => { - expect(() => parseChronicDuration('23 gobblygoos', { raiseExceptions: true })).toThrowError( + expect(() => parseChronicDuration('23 gobblygoos', { raiseExceptions: true })).toThrow( DurationParseError, ); }); diff --git a/spec/frontend/editor/source_editor_extension_spec.js b/spec/frontend/editor/source_editor_extension_spec.js index 78453aaa491..3424e71d326 100644 --- a/spec/frontend/editor/source_editor_extension_spec.js +++ b/spec/frontend/editor/source_editor_extension_spec.js @@ -16,7 +16,7 @@ describe('Editor Extension', () => { 'throws when definition = $definition and setupOptions = $setupOptions', ({ definition, setupOptions }) => { const constructExtension = () => new EditorExtension({ definition, setupOptions }); - expect(constructExtension).toThrowError(EDITOR_EXTENSION_DEFINITION_ERROR); + expect(constructExtension).toThrow(EDITOR_EXTENSION_DEFINITION_ERROR); }, ); diff --git a/spec/frontend/editor/source_editor_instance_spec.js b/spec/frontend/editor/source_editor_instance_spec.js index 1223fee320e..3ac77da5729 100644 --- a/spec/frontend/editor/source_editor_instance_spec.js +++ b/spec/frontend/editor/source_editor_instance_spec.js @@ -248,7 +248,7 @@ describe('Source Editor Instance', () => { const useExtension = () => { seInstance.use(extensions); }; - expect(useExtension).toThrowError(thrownError); + expect(useExtension).toThrow(thrownError); }, ); @@ -336,7 +336,7 @@ describe('Source Editor Instance', () => { const unuse = () => { seInstance.unuse(unuseExtension); }; - expect(unuse).toThrowError(thrownError); + expect(unuse).toThrow(thrownError); }, ); diff --git a/spec/frontend/editor/source_editor_webide_ext_spec.js b/spec/frontend/editor/source_editor_webide_ext_spec.js index 096b6b1646f..f418eab668a 100644 --- a/spec/frontend/editor/source_editor_webide_ext_spec.js +++ b/spec/frontend/editor/source_editor_webide_ext_spec.js @@ -30,7 +30,7 @@ describe('Source Editor Web IDE Extension', () => { const sideBySideSpy = jest.spyOn(instance, 'updateOptions'); instance.use({ definition: EditorWebIdeExtension }); - expect(sideBySideSpy).toBeCalledWith({ renderSideBySide }); + expect(sideBySideSpy).toHaveBeenCalledWith({ renderSideBySide }); }, ); @@ -45,11 +45,11 @@ describe('Source Editor Web IDE Extension', () => { const sideBySideSpy = jest.spyOn(instance, 'updateOptions'); await emitter.fire(); - expect(sideBySideSpy).toBeCalledWith({ renderSideBySide: true }); + expect(sideBySideSpy).toHaveBeenCalledWith({ renderSideBySide: true }); editorEl.style.width = '0px'; await emitter.fire(); - expect(sideBySideSpy).toBeCalledWith({ renderSideBySide: false }); + expect(sideBySideSpy).toHaveBeenCalledWith({ renderSideBySide: false }); }); }); }); diff --git a/spec/frontend/header_search/init_spec.js b/spec/frontend/header_search/init_spec.js index 9515ca8c812..580798a6155 100644 --- a/spec/frontend/header_search/init_spec.js +++ b/spec/frontend/header_search/init_spec.js @@ -24,7 +24,7 @@ describe('Header Search EventListener', () => { const addEventListenerSpy = jest.spyOn(searchInputBox, 'addEventListener'); initHeaderSearch(); - expect(addEventListenerSpy).toBeCalledTimes(2); + expect(addEventListenerSpy).toHaveBeenCalledTimes(2); }); it('removes event listener ', async () => { @@ -39,7 +39,7 @@ describe('Header Search EventListener', () => { [cleanEventListeners], ); - expect(removeEventListenerSpy).toBeCalledTimes(2); + expect(removeEventListenerSpy).toHaveBeenCalledTimes(2); }); it('attaches new vue dropdown when feature flag is enabled', async () => { @@ -53,7 +53,7 @@ describe('Header Search EventListener', () => { () => {}, ); - expect(mockVueApp).toBeCalled(); + expect(mockVueApp).toHaveBeenCalled(); }); it('attaches old vue dropdown when feature flag is disabled', async () => { @@ -69,6 +69,6 @@ describe('Header Search EventListener', () => { () => {}, ); - expect(mockLegacyApp).toBeCalled(); + expect(mockLegacyApp).toHaveBeenCalled(); }); }); diff --git a/spec/frontend/lib/utils/finite_state_machine_spec.js b/spec/frontend/lib/utils/finite_state_machine_spec.js index 441dd24c758..cfde3b8596e 100644 --- a/spec/frontend/lib/utils/finite_state_machine_spec.js +++ b/spec/frontend/lib/utils/finite_state_machine_spec.js @@ -50,13 +50,13 @@ describe('Finite State Machine', () => { }); it('throws an error if the machine definition is invalid', () => { - expect(() => machine(badDefinition)).toThrowError( + expect(() => machine(badDefinition)).toThrow( 'A state machine must have an initial state (`.initial`) and a dictionary of possible states (`.states`)', ); }); it('throws an error if the initial state is invalid', () => { - expect(() => machine(unstartableDefinition)).toThrowError( + expect(() => machine(unstartableDefinition)).toThrow( `Cannot initialize the state machine to state '${STATE_IMPOSSIBLE}'. Is that one of the machine's defined states?`, ); }); diff --git a/spec/frontend/lib/utils/vuex_module_mappers_spec.js b/spec/frontend/lib/utils/vuex_module_mappers_spec.js index 1821a15f677..d25a692dfea 100644 --- a/spec/frontend/lib/utils/vuex_module_mappers_spec.js +++ b/spec/frontend/lib/utils/vuex_module_mappers_spec.js @@ -128,7 +128,7 @@ describe('~/lib/utils/vuex_module_mappers', () => { describe('with non-string object value', () => { it('throws helpful error', () => { - expect(() => mapVuexModuleActions((vm) => vm.bogus, { foo: () => {} })).toThrowError( + expect(() => mapVuexModuleActions((vm) => vm.bogus, { foo: () => {} })).toThrow( REQUIRE_STRING_ERROR_MESSAGE, ); }); diff --git a/spec/frontend/members/store/actions_spec.js b/spec/frontend/members/store/actions_spec.js index d37e6871387..20dce639177 100644 --- a/spec/frontend/members/store/actions_spec.js +++ b/spec/frontend/members/store/actions_spec.js @@ -69,7 +69,7 @@ describe('Vuex members actions', () => { payload: { error }, }, ]), - ).rejects.toThrowError(error); + ).rejects.toThrow(error); }); }); }); @@ -122,7 +122,7 @@ describe('Vuex members actions', () => { payload: { error }, }, ]), - ).rejects.toThrowError(error); + ).rejects.toThrow(error); }); }); }); diff --git a/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js b/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js index de78e6bb87b..6078657daf4 100644 --- a/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js @@ -328,8 +328,8 @@ describe('PackagesApp', () => { findPackageFiles().vm.$emit('delete-files', [fileToDelete]); - expect(showDeletePackageSpy).not.toBeCalled(); - expect(showDeleteFileSpy).toBeCalled(); + expect(showDeletePackageSpy).not.toHaveBeenCalled(); + expect(showDeleteFileSpy).toHaveBeenCalled(); }); it('when its the only file opens delete package confirmation modal', async () => { @@ -357,8 +357,8 @@ describe('PackagesApp', () => { findPackageFiles().vm.$emit('delete-files', [fileToDelete]); - expect(showDeletePackageSpy).toBeCalled(); - expect(showDeleteFileSpy).not.toBeCalled(); + expect(showDeletePackageSpy).toHaveBeenCalled(); + expect(showDeleteFileSpy).not.toHaveBeenCalled(); }); it('confirming on the modal sets the loading state', async () => { @@ -443,7 +443,7 @@ describe('PackagesApp', () => { findPackageFiles().vm.$emit('delete-files', packageFiles()); - expect(showDeleteFilesSpy).toBeCalled(); + expect(showDeleteFilesSpy).toHaveBeenCalled(); }); it('confirming on the modal sets the loading state', async () => { @@ -532,7 +532,7 @@ describe('PackagesApp', () => { findPackageFiles().vm.$emit('delete-files', packageFiles()); - expect(showDeletePackageSpy).toBeCalled(); + expect(showDeletePackageSpy).toHaveBeenCalled(); }); }); }); diff --git a/spec/frontend/persistent_user_callout_spec.js b/spec/frontend/persistent_user_callout_spec.js index bff8fcda9b9..9cd5bb9e9a1 100644 --- a/spec/frontend/persistent_user_callout_spec.js +++ b/spec/frontend/persistent_user_callout_spec.js @@ -201,7 +201,7 @@ describe('PersistentUserCallout', () => { await waitForPromises(); - expect(window.location.assign).toBeCalledWith(href); + expect(window.location.assign).toHaveBeenCalledWith(href); expect(persistentUserCallout.container.remove).not.toHaveBeenCalled(); expect(mockAxios.history.post[0].data).toBe(JSON.stringify({ feature_name: featureName })); }); diff --git a/spec/frontend/profile/account/components/update_username_spec.js b/spec/frontend/profile/account/components/update_username_spec.js index cdeeea12582..e331eed1863 100644 --- a/spec/frontend/profile/account/components/update_username_spec.js +++ b/spec/frontend/profile/account/components/update_username_spec.js @@ -149,7 +149,7 @@ describe('UpdateUsername component', () => { await expect(wrapper.vm.onConfirm()).rejects.toThrow(); - expect(createFlash).toBeCalledWith({ + expect(createFlash).toHaveBeenCalledWith({ message: 'Invalid username', }); }); @@ -161,7 +161,7 @@ describe('UpdateUsername component', () => { await expect(wrapper.vm.onConfirm()).rejects.toThrow(); - expect(createFlash).toBeCalledWith({ + expect(createFlash).toHaveBeenCalledWith({ message: 'An error occurred while updating your username, please try again.', }); }); diff --git a/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js b/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js index f2e3fa8d433..e020d9a557e 100644 --- a/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js +++ b/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js @@ -156,7 +156,7 @@ describe('Source Viewer component', () => { it('emits showBlobInteractionZones on the eventHub when chunk appears', () => { findChunks().at(0).vm.$emit('appear'); - expect(eventHub.$emit).toBeCalledWith('showBlobInteractionZones', path); + expect(eventHub.$emit).toHaveBeenCalledWith('showBlobInteractionZones', path); }); describe('LineHighlighter', () => { diff --git a/spec/frontend/vue_shared/components/user_callout_dismisser_spec.js b/spec/frontend/vue_shared/components/user_callout_dismisser_spec.js index 70dec42ab32..521744154ba 100644 --- a/spec/frontend/vue_shared/components/user_callout_dismisser_spec.js +++ b/spec/frontend/vue_shared/components/user_callout_dismisser_spec.js @@ -84,7 +84,7 @@ describe('UserCalloutDismisser', () => { }); it('passes expected slot props to child', () => { - expect(defaultScopedSlotSpy).lastCalledWith(initialSlotProps()); + expect(defaultScopedSlotSpy).toHaveBeenLastCalledWith(initialSlotProps()); }); }); @@ -98,7 +98,7 @@ describe('UserCalloutDismisser', () => { }); it('passes expected slot props to child', () => { - expect(defaultScopedSlotSpy).lastCalledWith( + expect(defaultScopedSlotSpy).toHaveBeenLastCalledWith( initialSlotProps({ isDismissed: true, isLoadingQuery: false, @@ -117,7 +117,7 @@ describe('UserCalloutDismisser', () => { }); it('passes expected slot props to child', () => { - expect(defaultScopedSlotSpy).lastCalledWith( + expect(defaultScopedSlotSpy).toHaveBeenLastCalledWith( initialSlotProps({ isLoadingQuery: false, shouldShowCallout: true, @@ -136,7 +136,7 @@ describe('UserCalloutDismisser', () => { }); it('passes expected slot props to child', () => { - expect(defaultScopedSlotSpy).lastCalledWith( + expect(defaultScopedSlotSpy).toHaveBeenLastCalledWith( initialSlotProps({ isLoadingQuery: false, queryError: expect.any(Error), @@ -155,7 +155,7 @@ describe('UserCalloutDismisser', () => { }); it('passes expected slot props to child', () => { - expect(defaultScopedSlotSpy).lastCalledWith( + expect(defaultScopedSlotSpy).toHaveBeenLastCalledWith( initialSlotProps({ isAnonUser: true, isLoadingQuery: false, @@ -186,7 +186,7 @@ describe('UserCalloutDismisser', () => { }); it('passes expected slot props to child', () => { - expect(defaultScopedSlotSpy).lastCalledWith( + expect(defaultScopedSlotSpy).toHaveBeenLastCalledWith( initialSlotProps({ isLoadingQuery: false, shouldShowCallout: true, @@ -217,7 +217,7 @@ describe('UserCalloutDismisser', () => { }); it('passes expected slot props to child', async () => { - expect(defaultScopedSlotSpy).lastCalledWith( + expect(defaultScopedSlotSpy).toHaveBeenLastCalledWith( initialSlotProps({ isLoadingQuery: false, shouldShowCallout: true, @@ -229,7 +229,7 @@ describe('UserCalloutDismisser', () => { // Wait for Vue re-render due to prop change await nextTick(); - expect(defaultScopedSlotSpy).lastCalledWith( + expect(defaultScopedSlotSpy).toHaveBeenLastCalledWith( initialSlotProps({ isDismissed: true, isLoadingMutation: true, @@ -240,7 +240,7 @@ describe('UserCalloutDismisser', () => { // Wait for mutation to resolve await waitForPromises(); - expect(defaultScopedSlotSpy).lastCalledWith( + expect(defaultScopedSlotSpy).toHaveBeenLastCalledWith( initialSlotProps({ isDismissed: true, isLoadingQuery: false, @@ -270,7 +270,7 @@ describe('UserCalloutDismisser', () => { }); it('passes expected slot props to child', async () => { - expect(defaultScopedSlotSpy).lastCalledWith( + expect(defaultScopedSlotSpy).toHaveBeenLastCalledWith( initialSlotProps({ isLoadingQuery: false, shouldShowCallout: true, @@ -282,7 +282,7 @@ describe('UserCalloutDismisser', () => { // Wait for Vue re-render due to prop change await nextTick(); - expect(defaultScopedSlotSpy).lastCalledWith( + expect(defaultScopedSlotSpy).toHaveBeenLastCalledWith( initialSlotProps({ isDismissed: true, isLoadingMutation: true, @@ -293,7 +293,7 @@ describe('UserCalloutDismisser', () => { // Wait for mutation to resolve await waitForPromises(); - expect(defaultScopedSlotSpy).lastCalledWith( + expect(defaultScopedSlotSpy).toHaveBeenLastCalledWith( initialSlotProps({ isDismissed: true, isLoadingQuery: false, diff --git a/spec/lib/gitlab/memory/jemalloc_spec.rb b/spec/lib/gitlab/memory/jemalloc_spec.rb index a6272a020ca..414d6017534 100644 --- a/spec/lib/gitlab/memory/jemalloc_spec.rb +++ b/spec/lib/gitlab/memory/jemalloc_spec.rb @@ -5,9 +5,11 @@ require 'tmpdir' RSpec.describe Gitlab::Memory::Jemalloc do let(:outdir) { Dir.mktmpdir } + let(:tmp_outdir) { Dir.mktmpdir } after do FileUtils.rm_f(outdir) + FileUtils.rm_f(tmp_outdir) end context 'when jemalloc is loaded' do @@ -29,7 +31,7 @@ RSpec.describe Gitlab::Memory::Jemalloc do describe '.dump_stats' do it 'writes stats JSON file' do - file_path = described_class.dump_stats(path: outdir, format: format) + file_path = described_class.dump_stats(path: outdir, tmp_dir: tmp_outdir, format: format) file = Dir.entries(outdir).find { |e| e.match(/jemalloc_stats\.#{$$}\.\d+\.json$/) } expect(file).not_to be_nil @@ -56,7 +58,8 @@ RSpec.describe Gitlab::Memory::Jemalloc do describe '.dump_stats' do shared_examples 'writes stats text file' do |filename_label, filename_pattern| it do - described_class.dump_stats(path: outdir, format: format, filename_label: filename_label) + described_class.dump_stats( + path: outdir, tmp_dir: tmp_outdir, format: format, filename_label: filename_label) file = Dir.entries(outdir).find { |e| e.match(filename_pattern) } expect(file).not_to be_nil @@ -88,7 +91,7 @@ RSpec.describe Gitlab::Memory::Jemalloc do describe '.dump_stats' do it 'raises an error' do expect do - described_class.dump_stats(path: outdir, format: format) + described_class.dump_stats(path: outdir, tmp_dir: tmp_outdir, format: format) end.to raise_error(/format must be one of/) end end @@ -110,7 +113,7 @@ RSpec.describe Gitlab::Memory::Jemalloc do it 'does nothing' do stub_env('LD_PRELOAD', nil) - described_class.dump_stats(path: outdir) + described_class.dump_stats(path: outdir, tmp_dir: tmp_outdir) expect(Dir.empty?(outdir)).to be(true) end diff --git a/spec/lib/gitlab/memory/reports/jemalloc_stats_spec.rb b/spec/lib/gitlab/memory/reports/jemalloc_stats_spec.rb index 53fae48776b..b327a40bc2c 100644 --- a/spec/lib/gitlab/memory/reports/jemalloc_stats_spec.rb +++ b/spec/lib/gitlab/memory/reports/jemalloc_stats_spec.rb @@ -3,14 +3,19 @@ require 'spec_helper' RSpec.describe Gitlab::Memory::Reports::JemallocStats do - let(:reports_dir) { '/empty-dir' } - let(:jemalloc_stats) { described_class.new(reports_path: reports_dir) } + let_it_be(:outdir) { Dir.mktmpdir } + + let(:jemalloc_stats) { described_class.new(reports_path: outdir) } + + after do + FileUtils.rm_f(outdir) + end describe '.run' do context 'when :report_jemalloc_stats ops FF is enabled' do let(:worker_id) { 'puma_1' } let(:report_name) { 'report.json' } - let(:report_path) { File.join(reports_dir, report_name) } + let(:report_path) { File.join(outdir, report_name) } before do allow(Prometheus::PidProvider).to receive(:worker_id).and_return(worker_id) @@ -18,14 +23,16 @@ RSpec.describe Gitlab::Memory::Reports::JemallocStats do it 'invokes Jemalloc.dump_stats and returns file path' do expect(Gitlab::Memory::Jemalloc) - .to receive(:dump_stats).with(path: reports_dir, filename_label: worker_id).and_return(report_path) + .to receive(:dump_stats) + .with(path: outdir, + tmp_dir: File.join(outdir, '/tmp'), + filename_label: worker_id) + .and_return(report_path) expect(jemalloc_stats.run).to eq(report_path) end describe 'reports cleanup' do - let_it_be(:outdir) { Dir.mktmpdir } - let(:jemalloc_stats) { described_class.new(reports_path: outdir) } before do @@ -33,10 +40,6 @@ RSpec.describe Gitlab::Memory::Reports::JemallocStats do allow(Gitlab::Memory::Jemalloc).to receive(:dump_stats) end - after do - FileUtils.rm_f(outdir) - end - context 'when number of reports exceeds `max_reports_stored`' do let_it_be(:reports) do now = Time.current diff --git a/spec/requests/api/admin/batched_background_migrations_spec.rb b/spec/requests/api/admin/batched_background_migrations_spec.rb index fb7b4246d64..c99b21c0c27 100644 --- a/spec/requests/api/admin/batched_background_migrations_spec.rb +++ b/spec/requests/api/admin/batched_background_migrations_spec.rb @@ -181,4 +181,50 @@ RSpec.describe API::Admin::BatchedBackgroundMigrations do end end end + + describe 'PUT /admin/batched_background_migrations/:id/pause' do + let!(:migration) { create(:batched_background_migration, :active) } + + it 'pauses the batched background migration' do + put api("/admin/batched_background_migrations/#{migration.id}/pause", admin), params: { database: :main } + + aggregate_failures "testing response" do + expect(response).to have_gitlab_http_status(:ok) + expect(json_response['id']).to eq(migration.id) + expect(json_response['status']).to eq('paused') + end + end + + context 'when the batched background migration does not exist' do + let(:params) { { database: :main } } + + it 'returns 404' do + put api("/admin/batched_background_migrations/#{non_existing_record_id}/pause", admin), params: params + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when multiple database is enabled' do + let(:ci_model) { Ci::ApplicationRecord } + + before do + skip_if_multiple_databases_not_setup + end + + it 'uses the correct connection' do + expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(ci_model.connection).and_yield + + put api("/admin/batched_background_migrations/#{migration.id}/pause", admin), params: { database: :ci } + end + end + + context 'when authenticated as a non-admin user' do + it 'returns 403' do + put api("/admin/batched_background_migrations/#{non_existing_record_id}/pause", unauthorized_user) + + expect(response).to have_gitlab_http_status(:forbidden) + end + end + end end |