Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
3521fa595b
commit
1a92cb5aaf
52 changed files with 246 additions and 129 deletions
|
@ -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
|
|
@ -251,6 +251,8 @@
|
|||
- 1
|
||||
- - integrations_irker
|
||||
- 1
|
||||
- - integrations_slack_event
|
||||
- 1
|
||||
- - invalid_gpg_signature_update
|
||||
- 2
|
||||
- - issuable_export_csv
|
||||
|
|
|
@ -80,6 +80,9 @@ swap:
|
|||
neighbour: neighbor
|
||||
normalise: normalize
|
||||
offence: offense
|
||||
optimise: optimize
|
||||
optimised: optimized
|
||||
optimising: optimizing
|
||||
organise: organize
|
||||
orientated: oriented
|
||||
paralyse: paralyze
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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. |
|
||||
|
|
|
@ -1640,6 +1640,7 @@ these are all equivalent:
|
|||
- `168 hours`
|
||||
- `7 days`
|
||||
- `one week`
|
||||
- `never`
|
||||
|
||||
**Example of `environment:auto_stop_in`**:
|
||||
|
||||
|
|
|
@ -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 |
|
||||
|:--------------|:----------------------------|:---------|
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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**.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
```
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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**.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -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.',
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const Sortablejs = jest.genMockFromModule('sortablejs');
|
||||
const Sortablejs = jest.createMockFromModule('sortablejs');
|
||||
|
||||
export default Sortablejs;
|
||||
export const Sortable = Sortablejs;
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
|
@ -139,7 +139,7 @@ describe('UsersChart', () => {
|
|||
});
|
||||
|
||||
it('requests data twice', () => {
|
||||
expect(queryHandler).toBeCalledTimes(2);
|
||||
expect(queryHandler).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('calls fetchMore', () => {
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
@ -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 });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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?`,
|
||||
);
|
||||
});
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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 }));
|
||||
});
|
||||
|
|
|
@ -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.',
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue