Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-09-14 03:12:37 +00:00
parent 3521fa595b
commit 1a92cb5aaf
52 changed files with 246 additions and 129 deletions

View file

@ -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

View file

@ -251,6 +251,8 @@
- 1
- - integrations_irker
- 1
- - integrations_slack_event
- 1
- - invalid_gpg_signature_update
- 2
- - issuable_export_csv

View file

@ -80,6 +80,9 @@ swap:
neighbour: neighbor
normalise: normalize
offence: offense
optimise: optimize
optimised: optimized
optimising: optimizing
organise: organize
orientated: oriented
paralyse: paralyze

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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. |

View file

@ -1640,6 +1640,7 @@ these are all equivalent:
- `168 hours`
- `7 days`
- `one week`
- `never`
**Example of `environment:auto_stop_in`**:

View file

@ -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 |
|:--------------|:----------------------------|:---------|

View file

@ -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?

View file

@ -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:

View file

@ -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.

View file

@ -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`.

View file

@ -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.

View file

@ -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.

View file

@ -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`.

View file

@ -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.

View file

@ -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**.

View file

@ -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

View file

@ -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.
```

View file

@ -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.

View file

@ -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.

View file

@ -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**.

View file

@ -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.

View 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.

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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?

View file

@ -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 ""

View file

@ -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.',
);
});

View file

@ -1,4 +1,4 @@
const Sortablejs = jest.genMockFromModule('sortablejs');
const Sortablejs = jest.createMockFromModule('sortablejs');
export default Sortablejs;
export const Sortable = Sortablejs;

View file

@ -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);
});

View file

@ -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', () => {

View file

@ -139,7 +139,7 @@ describe('UsersChart', () => {
});
it('requests data twice', () => {
expect(queryHandler).toBeCalledTimes(2);
expect(queryHandler).toHaveBeenCalledTimes(2);
});
it('calls fetchMore', () => {

View file

@ -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,
);
});

View file

@ -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);
},
);

View file

@ -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);
},
);

View file

@ -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 });
});
});
});

View file

@ -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();
});
});

View file

@ -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?`,
);
});

View file

@ -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,
);
});

View file

@ -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);
});
});
});

View file

@ -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();
});
});
});

View file

@ -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 }));
});

View file

@ -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.',
});
});

View file

@ -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', () => {

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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