Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
bad127a0f6
commit
beeaef0da5
|
@ -8,9 +8,9 @@ import {
|
||||||
} from '@gitlab/ui';
|
} from '@gitlab/ui';
|
||||||
import { once } from 'lodash';
|
import { once } from 'lodash';
|
||||||
import * as Sentry from '@sentry/browser';
|
import * as Sentry from '@sentry/browser';
|
||||||
|
import { DynamicScroller, DynamicScrollerItem } from 'vendor/vue-virtual-scroller';
|
||||||
import api from '~/api';
|
import api from '~/api';
|
||||||
import { sprintf, s__, __ } from '~/locale';
|
import { sprintf, s__, __ } from '~/locale';
|
||||||
import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
|
|
||||||
import Poll from '~/lib/utils/poll';
|
import Poll from '~/lib/utils/poll';
|
||||||
import { EXTENSION_ICON_CLASS, EXTENSION_ICONS } from '../../constants';
|
import { EXTENSION_ICON_CLASS, EXTENSION_ICONS } from '../../constants';
|
||||||
import StatusIcon from './status_icon.vue';
|
import StatusIcon from './status_icon.vue';
|
||||||
|
@ -30,10 +30,11 @@ export default {
|
||||||
GlButton,
|
GlButton,
|
||||||
GlLoadingIcon,
|
GlLoadingIcon,
|
||||||
GlIntersectionObserver,
|
GlIntersectionObserver,
|
||||||
SmartVirtualList,
|
|
||||||
StatusIcon,
|
StatusIcon,
|
||||||
Actions,
|
Actions,
|
||||||
ChildContent,
|
ChildContent,
|
||||||
|
DynamicScroller,
|
||||||
|
DynamicScrollerItem,
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
SafeHtml: GlSafeHtmlDirective,
|
SafeHtml: GlSafeHtmlDirective,
|
||||||
|
@ -186,7 +187,7 @@ export default {
|
||||||
this.fetchFullData(this.$props)
|
this.fetchFullData(this.$props)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.loadingState = null;
|
this.loadingState = null;
|
||||||
this.fullData = data;
|
this.fullData = data.map((x, i) => ({ id: i, ...x }));
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
this.loadingState = LOADING_STATES.expandedError;
|
this.loadingState = LOADING_STATES.expandedError;
|
||||||
|
@ -276,34 +277,33 @@ export default {
|
||||||
<div v-if="isLoadingExpanded" class="report-block-container">
|
<div v-if="isLoadingExpanded" class="report-block-container">
|
||||||
<gl-loading-icon size="sm" inline /> {{ __('Loading...') }}
|
<gl-loading-icon size="sm" inline /> {{ __('Loading...') }}
|
||||||
</div>
|
</div>
|
||||||
<smart-virtual-list
|
<dynamic-scroller
|
||||||
v-else-if="hasFullData"
|
v-else-if="hasFullData"
|
||||||
:length="fullData.length"
|
:items="fullData"
|
||||||
:remain="20"
|
:min-item-size="32"
|
||||||
:size="32"
|
|
||||||
wtag="ul"
|
|
||||||
wclass="report-block-list"
|
|
||||||
class="report-block-container gl-px-5 gl-py-0"
|
class="report-block-container gl-px-5 gl-py-0"
|
||||||
>
|
>
|
||||||
<li
|
<template #default="{ item, index, active }">
|
||||||
v-for="(data, index) in fullData"
|
<dynamic-scroller-item :item="item" :active="active" :class="{ active }">
|
||||||
:key="data.id"
|
<div
|
||||||
:class="{
|
:class="{
|
||||||
'gl-border-b-solid gl-border-b-1 gl-border-gray-100': index !== fullData.length - 1,
|
'gl-border-b-solid gl-border-b-1 gl-border-gray-100': index !== fullData.length - 1,
|
||||||
}"
|
}"
|
||||||
class="gl-py-3 gl-pl-7"
|
class="gl-py-3 gl-pl-7"
|
||||||
data-testid="extension-list-item"
|
data-testid="extension-list-item"
|
||||||
>
|
>
|
||||||
<gl-intersection-observer
|
<gl-intersection-observer
|
||||||
:options="{ rootMargin: '100px', thresholds: 0.1 }"
|
:options="{ rootMargin: '100px', thresholds: 0.1 }"
|
||||||
class="gl-w-full"
|
class="gl-w-full"
|
||||||
@appear="appear(index)"
|
@appear="appear(index)"
|
||||||
@disappear="disappear(index)"
|
@disappear="disappear(index)"
|
||||||
>
|
>
|
||||||
<child-content :data="data" :widget-label="widgetLabel" :level="2" />
|
<child-content :data="item" :widget-label="widgetLabel" :level="2" />
|
||||||
</gl-intersection-observer>
|
</gl-intersection-observer>
|
||||||
</li>
|
</div>
|
||||||
</smart-virtual-list>
|
</dynamic-scroller-item>
|
||||||
|
</template>
|
||||||
|
</dynamic-scroller>
|
||||||
<div
|
<div
|
||||||
:class="{ show: showFade }"
|
:class="{ show: showFade }"
|
||||||
class="fade mr-extenson-scrim gl-absolute gl-left-0 gl-bottom-0 gl-w-full gl-h-7 gl-pointer-events-none"
|
class="fade mr-extenson-scrim gl-absolute gl-left-0 gl-bottom-0 gl-w-full gl-h-7 gl-pointer-events-none"
|
||||||
|
|
|
@ -745,6 +745,10 @@ $tabs-holder-z-index: 250;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mr-section-container .resize-observer > object {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Move to GitLab UI
|
// TODO: Move to GitLab UI
|
||||||
.mr-extenson-scrim {
|
.mr-extenson-scrim {
|
||||||
background: linear-gradient(to bottom, rgba($gray-light, 0), rgba($gray-light, 1));
|
background: linear-gradient(to bottom, rgba($gray-light, 0), rgba($gray-light, 1));
|
||||||
|
|
|
@ -370,6 +370,11 @@ You can only use the following rules with `include` (and only with [certain vari
|
||||||
|
|
||||||
`rules` keyword `changes` is not supported.
|
`rules` keyword `changes` is not supported.
|
||||||
|
|
||||||
|
You cannot use [`needs:`](index.md#needs) to create a job dependency that points to
|
||||||
|
a job added with `include:local:rules`. When the configuration is checked for validity,
|
||||||
|
GitLab returns `undefined need: <job-name>`. An [issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/345377)
|
||||||
|
to improve this behavior.
|
||||||
|
|
||||||
## Use `include:local` with wildcard file paths
|
## Use `include:local` with wildcard file paths
|
||||||
|
|
||||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25921) in GitLab 13.11.
|
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25921) in GitLab 13.11.
|
||||||
|
|
|
@ -145,7 +145,7 @@ For example, to scan an image from AWS Elastic Container Registry:
|
||||||
```yaml
|
```yaml
|
||||||
container_scanning:
|
container_scanning:
|
||||||
before_script:
|
before_script:
|
||||||
- curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" --output "awscliv2.zip"
|
- ruby -r open-uri -e "IO.copy_stream(URI.open('https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip'), 'awscliv2.zip')"
|
||||||
- unzip awscliv2.zip
|
- unzip awscliv2.zip
|
||||||
- ./aws/install
|
- ./aws/install
|
||||||
- aws --version
|
- aws --version
|
||||||
|
|
|
@ -628,7 +628,7 @@ These CI/CD variables are specific to DAST. They can be used to customize the be
|
||||||
| `DAST_AUTH_VERIFICATION_SELECTOR` <sup>2</sup> | selector | Verifies successful authentication by checking for presence of a selector once the login form has been submitted. Example: `css:.user-photo`. |
|
| `DAST_AUTH_VERIFICATION_SELECTOR` <sup>2</sup> | selector | Verifies successful authentication by checking for presence of a selector once the login form has been submitted. Example: `css:.user-photo`. |
|
||||||
| `DAST_AUTH_VERIFICATION_URL` <sup>1,2</sup> | URL | A URL only accessible to logged in users that DAST can use to confirm successful authentication. If provided, DAST exits if it cannot access the URL. Example: `"http://example.com/loggedin_page"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207335) in GitLab 13.8. |
|
| `DAST_AUTH_VERIFICATION_URL` <sup>1,2</sup> | URL | A URL only accessible to logged in users that DAST can use to confirm successful authentication. If provided, DAST exits if it cannot access the URL. Example: `"http://example.com/loggedin_page"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207335) in GitLab 13.8. |
|
||||||
| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP add-ons are pinned to specific versions in the DAST Docker image. Set to `true` to download the latest versions when the scan starts. Default: `false`. |
|
| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP add-ons are pinned to specific versions in the DAST Docker image. Set to `true` to download the latest versions when the scan starts. Default: `false`. |
|
||||||
| `DAST_BROWSER_PATH_TO_LOGIN_FORM` <sup>1,2</sup> | selector | Comma-separated list of selectors that will be clicked on prior to attempting to enter `DAST_USERNAME` and `DAST_PASSWORD` into the login form. Example: `"css:.navigation-menu,css:.login-menu-item"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326633) in GitLab 14.1. |
|
| `DAST_BROWSER_PATH_TO_LOGIN_FORM` <sup>1,2</sup> | selector | Comma-separated list of selectors that are clicked on prior to attempting to enter `DAST_USERNAME` and `DAST_PASSWORD` into the login form. Example: `"css:.navigation-menu,css:.login-menu-item"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326633) in GitLab 14.1. |
|
||||||
| `DAST_DEBUG` <sup>1</sup> | boolean | Enable debug message output. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
|
| `DAST_DEBUG` <sup>1</sup> | boolean | Enable debug message output. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
|
||||||
| `DAST_EXCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to exclude them from running during the scan. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://www.zaproxy.org/docs/alerts/). For example, `HTTP Parameter Override` has a rule ID of `10026`. Cannot be used when `DAST_ONLY_INCLUDE_RULES` is set. **Note:** In earlier versions of GitLab the excluded rules were executed but vulnerabilities they generated were suppressed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) in GitLab 12.10. |
|
| `DAST_EXCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to exclude them from running during the scan. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://www.zaproxy.org/docs/alerts/). For example, `HTTP Parameter Override` has a rule ID of `10026`. Cannot be used when `DAST_ONLY_INCLUDE_RULES` is set. **Note:** In earlier versions of GitLab the excluded rules were executed but vulnerabilities they generated were suppressed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) in GitLab 12.10. |
|
||||||
| `DAST_EXCLUDE_URLS` <sup>1,2</sup> | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. Example, `http://example.com/sign-out`. |
|
| `DAST_EXCLUDE_URLS` <sup>1,2</sup> | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. Example, `http://example.com/sign-out`. |
|
||||||
|
@ -737,7 +737,7 @@ Only run an authenticated scan against a test server.
|
||||||
|
|
||||||
### Log in using automatic detection of the login form
|
### Log in using automatic detection of the login form
|
||||||
|
|
||||||
By providing a `DAST_USERNAME`, `DAST_PASSWORD`, and `DAST_AUTH_URL`, DAST will attempt to authenticate to the
|
By providing a `DAST_USERNAME`, `DAST_PASSWORD`, and `DAST_AUTH_URL`, DAST attempts to authenticate to the
|
||||||
target application by locating the login form based on a determination about whether or not the form contains username or password fields.
|
target application by locating the login form based on a determination about whether or not the form contains username or password fields.
|
||||||
|
|
||||||
Automatic detection is "best-effort", and depending on the application being scanned may provide either a resilient login experience or one that fails to authenticate the user.
|
Automatic detection is "best-effort", and depending on the application being scanned may provide either a resilient login experience or one that fails to authenticate the user.
|
||||||
|
@ -753,8 +753,8 @@ Login process:
|
||||||
### Log in using explicit selection of the login form
|
### Log in using explicit selection of the login form
|
||||||
|
|
||||||
By providing a `DAST_USERNAME_FIELD`, `DAST_PASSWORD_FIELD`, and `DAST_SUBMIT_FIELD`, in addition to the fields required for automatic login,
|
By providing a `DAST_USERNAME_FIELD`, `DAST_PASSWORD_FIELD`, and `DAST_SUBMIT_FIELD`, in addition to the fields required for automatic login,
|
||||||
DAST will attempt to authenticate to the target application by locating the login form based on the selectors provided.
|
DAST attempts to authenticate to the target application by locating the login form based on the selectors provided.
|
||||||
Most applications will benefit from this approach to authentication.
|
Most applications benefit from this approach to authentication.
|
||||||
|
|
||||||
Login process:
|
Login process:
|
||||||
|
|
||||||
|
@ -885,7 +885,7 @@ dast:
|
||||||
### Selectors
|
### Selectors
|
||||||
|
|
||||||
Selectors are used by CI/CD variables to specify the location of an element displayed on a page in a browser.
|
Selectors are used by CI/CD variables to specify the location of an element displayed on a page in a browser.
|
||||||
Selectors have the format `type`:`search string`. The crawler will search for the selector using the search string based on the type.
|
Selectors have the format `type`:`search string`. The crawler searches for the selector using the search string based on the type.
|
||||||
|
|
||||||
| Selector type | Example | Description |
|
| Selector type | Example | Description |
|
||||||
| ------------- | ---------------------------------- | ----------- |
|
| ------------- | ---------------------------------- | ----------- |
|
||||||
|
|
|
@ -41,7 +41,7 @@ To protect a branch:
|
||||||
|
|
||||||
1. Go to your project and select **Settings > Repository**.
|
1. Go to your project and select **Settings > Repository**.
|
||||||
1. Expand **Protected branches**.
|
1. Expand **Protected branches**.
|
||||||
1. From the **Branch** dropdown menu, select the branch you want to protect.
|
1. From the **Branch** dropdown list, select the branch you want to protect.
|
||||||
1. From the **Allowed to merge** list, select a role, or group that can merge into this branch. In GitLab Premium, you can also add users.
|
1. From the **Allowed to merge** list, select a role, or group that can merge into this branch. In GitLab Premium, you can also add users.
|
||||||
1. From the **Allowed to push** list, select a role, group, or user that can push to this branch. In GitLab Premium, you can also add users.
|
1. From the **Allowed to push** list, select a role, group, or user that can push to this branch. In GitLab Premium, you can also add users.
|
||||||
1. Select **Protect**.
|
1. Select **Protect**.
|
||||||
|
@ -58,7 +58,7 @@ To protect multiple branches at the same time:
|
||||||
|
|
||||||
1. Go to your project and select **Settings > Repository**.
|
1. Go to your project and select **Settings > Repository**.
|
||||||
1. Expand **Protected branches**.
|
1. Expand **Protected branches**.
|
||||||
1. From the **Branch** dropdown menu, type the branch name and a wildcard.
|
1. From the **Branch** dropdown list, type the branch name and a wildcard.
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
| Wildcard protected branch | Matching branches |
|
| Wildcard protected branch | Matching branches |
|
||||||
|
@ -101,7 +101,7 @@ to a protected branch. This is compatible with workflows like the [GitLab workfl
|
||||||
|
|
||||||
1. Go to your project and select **Settings > Repository**.
|
1. Go to your project and select **Settings > Repository**.
|
||||||
1. Expand **Protected branches**.
|
1. Expand **Protected branches**.
|
||||||
1. From the **Branch** dropdown menu, select the branch you want to protect.
|
1. From the **Branch** dropdown list, select the branch you want to protect.
|
||||||
1. From the **Allowed to merge** list, select **Developers + Maintainers**.
|
1. From the **Allowed to merge** list, select **Developers + Maintainers**.
|
||||||
1. From the **Allowed to push** list, select **No one**.
|
1. From the **Allowed to push** list, select **No one**.
|
||||||
1. Select **Protect**.
|
1. Select **Protect**.
|
||||||
|
@ -112,7 +112,7 @@ You can allow everyone with write access to push to the protected branch.
|
||||||
|
|
||||||
1. Go to your project and select **Settings > Repository**.
|
1. Go to your project and select **Settings > Repository**.
|
||||||
1. Expand **Protected branches**.
|
1. Expand **Protected branches**.
|
||||||
1. From the **Branch** dropdown menu, select the branch you want to protect.
|
1. From the **Branch** dropdown list, select the branch you want to protect.
|
||||||
1. From the **Allowed to push** list, select **Developers + Maintainers**.
|
1. From the **Allowed to push** list, select **Developers + Maintainers**.
|
||||||
1. Select **Protect**.
|
1. Select **Protect**.
|
||||||
|
|
||||||
|
@ -135,11 +135,11 @@ To allow a deploy key to push to a protected branch:
|
||||||
|
|
||||||
1. Go to your project and select **Settings > Repository**.
|
1. Go to your project and select **Settings > Repository**.
|
||||||
1. Expand **Protected branches**.
|
1. Expand **Protected branches**.
|
||||||
1. From the **Branch** dropdown menu, select the branch you want to protect.
|
1. From the **Branch** dropdown list, select the branch you want to protect.
|
||||||
1. From the **Allowed to push** list, select the deploy key.
|
1. From the **Allowed to push** list, select the deploy key.
|
||||||
1. Select **Protect**.
|
1. Select **Protect**.
|
||||||
|
|
||||||
Deploy keys are not available in the **Allowed to merge** dropdown.
|
Deploy keys are not available in the **Allowed to merge** dropdown list.
|
||||||
|
|
||||||
## Allow force push on a protected branch
|
## Allow force push on a protected branch
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ To protect a new branch and enable force push:
|
||||||
|
|
||||||
1. Go to your project and select **Settings > Repository**.
|
1. Go to your project and select **Settings > Repository**.
|
||||||
1. Expand **Protected branches**.
|
1. Expand **Protected branches**.
|
||||||
1. From the **Branch** dropdown menu, select the branch you want to protect.
|
1. From the **Branch** dropdown list, select the branch you want to protect.
|
||||||
1. From the **Allowed to push** and **Allowed to merge** lists, select the settings you want.
|
1. From the **Allowed to push** and **Allowed to merge** lists, select the settings you want.
|
||||||
1. To allow all users with push access to force push, turn on the **Allowed to force push** toggle.
|
1. To allow all users with push access to force push, turn on the **Allowed to force push** toggle.
|
||||||
1. To reject code pushes that change files listed in the `CODEOWNERS` file, turn on the
|
1. To reject code pushes that change files listed in the `CODEOWNERS` file, turn on the
|
||||||
|
@ -182,7 +182,7 @@ To protect a new branch and enable Code Owner's approval:
|
||||||
|
|
||||||
1. Go to your project and select **Settings > Repository**.
|
1. Go to your project and select **Settings > Repository**.
|
||||||
1. Expand **Protected branches**.
|
1. Expand **Protected branches**.
|
||||||
1. From the **Branch** dropdown menu, select the branch you want to protect.
|
1. From the **Branch** dropdown list, select the branch you want to protect.
|
||||||
1. From the **Allowed to push** and **Allowed to merge** lists, select the settings you want.
|
1. From the **Allowed to push** and **Allowed to merge** lists, select the settings you want.
|
||||||
1. Turn on the **Require approval from code owners** toggle.
|
1. Turn on the **Require approval from code owners** toggle.
|
||||||
1. Select **Protect**.
|
1. Select **Protect**.
|
||||||
|
@ -221,7 +221,7 @@ Users with at least the Maintainer role can manually delete protected
|
||||||
branches by using the GitLab web interface:
|
branches by using the GitLab web interface:
|
||||||
|
|
||||||
1. Go to **Repository > Branches**.
|
1. Go to **Repository > Branches**.
|
||||||
1. Next to the branch you want to delete, select the **Delete** button (**{remove}**).
|
1. Next to the branch you want to delete, select **Delete** (**{remove}**).
|
||||||
1. On the confirmation dialog, type the branch name and select **Delete protected branch**.
|
1. On the confirmation dialog, type the branch name and select **Delete protected branch**.
|
||||||
|
|
||||||
Protected branches can only be deleted by using GitLab either from the UI or API.
|
Protected branches can only be deleted by using GitLab either from the UI or API.
|
||||||
|
|
|
@ -27,18 +27,18 @@ By default:
|
||||||
|
|
||||||
## Configuring protected tags
|
## Configuring protected tags
|
||||||
|
|
||||||
To protect a tag, you need to have at least the Maintainer role.
|
To protect a tag, you must have at least the Maintainer role.
|
||||||
|
|
||||||
1. Go to the project's **Settings > Repository**.
|
1. Go to the project's **Settings > Repository**.
|
||||||
|
|
||||||
1. From the **Tag** dropdown menu, select the tag you want to protect or type and click **Create wildcard**. In the screenshot below, we chose to protect all tags matching `v*`:
|
1. From the **Tag** dropdown list, select the tag you want to protect or type and click **Create wildcard**. In the screenshot below, we chose to protect all tags matching `v*`:
|
||||||
|
|
||||||
![Protected tags page](img/protected_tags_page_v12_3.png)
|
![Protected tags page](img/protected_tags_page_v12_3.png)
|
||||||
|
|
||||||
1. From the **Allowed to create** dropdown, select users with permission to create
|
1. From the **Allowed to create** dropdown list, select users with permission to create
|
||||||
matching tags, and click **Protect**:
|
matching tags, and select **Protect**:
|
||||||
|
|
||||||
![Allowed to create tags dropdown](img/protected_tags_permissions_dropdown_v12_3.png)
|
![Allowed to create tags dropdown list](img/protected_tags_permissions_dropdown_v12_3.png)
|
||||||
|
|
||||||
1. After done, the protected tag displays in the **Protected tags** list:
|
1. After done, the protected tag displays in the **Protected tags** list:
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ Two different wildcards can potentially match the same tag. For example,
|
||||||
In that case, if _any_ of these protected tags have a setting like
|
In that case, if _any_ of these protected tags have a setting like
|
||||||
**Allowed to create**, then `production-stable` also inherit this setting.
|
**Allowed to create**, then `production-stable` also inherit this setting.
|
||||||
|
|
||||||
If you click on a protected tag's name, GitLab displays a list of
|
If you select a protected tag's name, GitLab displays a list of
|
||||||
all matching tags:
|
all matching tags:
|
||||||
|
|
||||||
![Protected tag matches](img/protected_tag_matches.png)
|
![Protected tag matches](img/protected_tag_matches.png)
|
||||||
|
|
|
@ -25,11 +25,8 @@ GitLab.
|
||||||
|
|
||||||
## Cleaner diffs
|
## Cleaner diffs
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6589) in GitLab 14.5 [with a flag](../../../../administration/feature_flags.md) named `jupyter_clean_diffs`. Enabled by default.
|
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6589) in GitLab 14.5 [with a flag](../../../../administration/feature_flags.md) named `jupyter_clean_diffs`. Enabled by default.
|
||||||
|
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75500) in GitLab 14.9. Feature flag `jupyter_clean_diffs` removed.
|
||||||
FLAG:
|
|
||||||
On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to [disable the feature flag](../../../../administration/feature_flags.md) named `jupyter_clean_diffs`.
|
|
||||||
On GitLab.com, this feature is available.
|
|
||||||
|
|
||||||
When commits include changes to Jupyter Notebook files, GitLab:
|
When commits include changes to Jupyter Notebook files, GitLab:
|
||||||
|
|
||||||
|
|
|
@ -1461,7 +1461,7 @@ msgstr ""
|
||||||
msgid "1000+"
|
msgid "1000+"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "192.168.0.0/24"
|
msgid "192.168.0.0/24 or 2001:0DB8:1234::/48"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "1st contribution!"
|
msgid "1st contribution!"
|
||||||
|
|
|
@ -10,7 +10,11 @@ module QA
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :name do
|
attribute :name do
|
||||||
@name || path
|
@name || @path || Runtime::Namespace.name
|
||||||
|
end
|
||||||
|
|
||||||
|
attribute :path do
|
||||||
|
@path || @name || Runtime::Namespace.name
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :sandbox do
|
attribute :sandbox do
|
||||||
|
@ -20,7 +24,6 @@ module QA
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@path = Runtime::Namespace.name
|
|
||||||
@description = "QA test run at #{Runtime::Namespace.time}"
|
@description = "QA test run at #{Runtime::Namespace.time}"
|
||||||
@require_two_factor_authentication = false
|
@require_two_factor_authentication = false
|
||||||
end
|
end
|
||||||
|
@ -64,7 +67,7 @@ module QA
|
||||||
{
|
{
|
||||||
parent_id: sandbox.id,
|
parent_id: sandbox.id,
|
||||||
path: path,
|
path: path,
|
||||||
name: name || path,
|
name: name,
|
||||||
visibility: 'public',
|
visibility: 'public',
|
||||||
require_two_factor_authentication: @require_two_factor_authentication,
|
require_two_factor_authentication: @require_two_factor_authentication,
|
||||||
avatar: avatar
|
avatar: avatar
|
||||||
|
|
|
@ -10,13 +10,13 @@ module QA
|
||||||
|
|
||||||
let(:group) do
|
let(:group) do
|
||||||
Resource::Group.fabricate_via_api! do |group|
|
Resource::Group.fabricate_via_api! do |group|
|
||||||
group.name = 'group-to-test-milestones'
|
group.name = "group-to-test-milestones-#{SecureRandom.hex(4)}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:project) do
|
let(:project) do
|
||||||
Resource::Project.fabricate_via_api! do |project|
|
Resource::Project.fabricate_via_api! do |project|
|
||||||
project.name = 'project-to-test-milestones'
|
project.name = "project-to-test-milestones-#{SecureRandom.hex(4)}"
|
||||||
project.group = group
|
project.group = group
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -100,15 +100,15 @@ describe('Accessibility extension', () => {
|
||||||
await waitForPromises();
|
await waitForPromises();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('displays all report list items', async () => {
|
it('displays all report list items in viewport', async () => {
|
||||||
expect(findAllExtensionListItems()).toHaveLength(10);
|
expect(findAllExtensionListItems()).toHaveLength(7);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('displays report list item formatted', () => {
|
it('displays report list item formatted', () => {
|
||||||
const text = {
|
const text = {
|
||||||
newError: trimText(findAllExtensionListItems().at(0).text()),
|
newError: trimText(findAllExtensionListItems().at(0).text()),
|
||||||
resolvedError: findAllExtensionListItems().at(3).text(),
|
resolvedError: findAllExtensionListItems().at(3).text(),
|
||||||
existingError: trimText(findAllExtensionListItems().at(8).text()),
|
existingError: trimText(findAllExtensionListItems().at(6).text()),
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(text.newError).toBe(
|
expect(text.newError).toBe(
|
||||||
|
@ -118,7 +118,7 @@ describe('Accessibility extension', () => {
|
||||||
'The accessibility scanning found an error of the following type: WCAG2AA.Principle1.Guideline1_1.1_1_1.H30.2 Learn more Message: Img element is the only content of the link, but is missing alt text. The alt text should describe the purpose of the link.',
|
'The accessibility scanning found an error of the following type: WCAG2AA.Principle1.Guideline1_1.1_1_1.H30.2 Learn more Message: Img element is the only content of the link, but is missing alt text. The alt text should describe the purpose of the link.',
|
||||||
);
|
);
|
||||||
expect(text.existingError).toBe(
|
expect(text.existingError).toBe(
|
||||||
'The accessibility scanning found an error of the following type: WCAG2AA.Principle2.Guideline2_4.2_4_1.H64.1 Learn more Message: Iframe element requires a non-empty title attribute that identifies the frame.',
|
'The accessibility scanning found an error of the following type: WCAG2AA.Principle1.Guideline1_1.1_1_1.H37 Learn more Message: Img element missing an alt attribute. Use the alt attribute to specify a short text alternative.',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -947,6 +947,8 @@ describe('MrWidgetOptions', () => {
|
||||||
wrapper.find('[data-testid="widget-extension-top-level"]').find(GlDropdown).exists(),
|
wrapper.find('[data-testid="widget-extension-top-level"]').find(GlDropdown).exists(),
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
const collapsedSection = wrapper.find('[data-testid="widget-extension-collapsed-section"]');
|
const collapsedSection = wrapper.find('[data-testid="widget-extension-collapsed-section"]');
|
||||||
expect(collapsedSection.exists()).toBe(true);
|
expect(collapsedSection.exists()).toBe(true);
|
||||||
expect(collapsedSection.text()).toContain('Hello world');
|
expect(collapsedSection.text()).toContain('Hello world');
|
||||||
|
|
|
@ -102,8 +102,22 @@ RSpec.describe LooseForeignKeys::CleanupWorker do
|
||||||
loose_fk_parent_table_2.delete_all
|
loose_fk_parent_table_2.delete_all
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def perform_for(db:)
|
||||||
|
time = Time.current.midnight
|
||||||
|
|
||||||
|
if db == :main
|
||||||
|
time += 2.minutes
|
||||||
|
elsif db == :ci
|
||||||
|
time += 3.minutes
|
||||||
|
end
|
||||||
|
|
||||||
|
travel_to(time) do
|
||||||
|
described_class.new.perform
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it 'cleans up all rows' do
|
it 'cleans up all rows' do
|
||||||
described_class.new.perform
|
perform_for(db: :main)
|
||||||
|
|
||||||
expect(loose_fk_child_table_1_1.count).to eq(0)
|
expect(loose_fk_child_table_1_1.count).to eq(0)
|
||||||
expect(loose_fk_child_table_1_2.where(parent_id_with_different_column: nil).count).to eq(4)
|
expect(loose_fk_child_table_1_2.where(parent_id_with_different_column: nil).count).to eq(4)
|
||||||
|
@ -118,7 +132,7 @@ RSpec.describe LooseForeignKeys::CleanupWorker do
|
||||||
it 'cleans up all rows' do
|
it 'cleans up all rows' do
|
||||||
expect(LooseForeignKeys::BatchCleanerService).to receive(:new).exactly(:twice).and_call_original
|
expect(LooseForeignKeys::BatchCleanerService).to receive(:new).exactly(:twice).and_call_original
|
||||||
|
|
||||||
described_class.new.perform
|
perform_for(db: :main)
|
||||||
|
|
||||||
expect(loose_fk_child_table_1_1.count).to eq(0)
|
expect(loose_fk_child_table_1_1.count).to eq(0)
|
||||||
expect(loose_fk_child_table_1_2.where(parent_id_with_different_column: nil).count).to eq(4)
|
expect(loose_fk_child_table_1_2.where(parent_id_with_different_column: nil).count).to eq(4)
|
||||||
|
@ -137,25 +151,40 @@ RSpec.describe LooseForeignKeys::CleanupWorker do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'cleans up 2 rows' do
|
it 'cleans up 2 rows' do
|
||||||
expect { described_class.new.perform }.to change { count_deletable_rows }.by(-2)
|
expect { perform_for(db: :main) }.to change { count_deletable_rows }.by(-2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'multi-database support' do
|
describe 'multi-database support' do
|
||||||
where(:current_minute, :configured_base_models, :expected_connection) do
|
where(:current_minute, :configured_base_models, :expected_connection_model) do
|
||||||
2 | { main: ApplicationRecord, ci: Ci::ApplicationRecord } | ApplicationRecord.connection
|
2 | { main: 'ApplicationRecord', ci: 'Ci::ApplicationRecord' } | 'ApplicationRecord'
|
||||||
3 | { main: ApplicationRecord, ci: Ci::ApplicationRecord } | Ci::ApplicationRecord.connection
|
3 | { main: 'ApplicationRecord', ci: 'Ci::ApplicationRecord' } | 'Ci::ApplicationRecord'
|
||||||
2 | { main: ApplicationRecord } | ApplicationRecord.connection
|
2 | { main: 'ApplicationRecord' } | 'ApplicationRecord'
|
||||||
3 | { main: ApplicationRecord } | ApplicationRecord.connection
|
3 | { main: 'ApplicationRecord' } | 'ApplicationRecord'
|
||||||
end
|
end
|
||||||
|
|
||||||
with_them do
|
with_them do
|
||||||
|
let(:database_base_models) { configured_base_models.transform_values(&:constantize) }
|
||||||
|
|
||||||
|
let(:expected_connection) { expected_connection_model.constantize.connection }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(Gitlab::Database).to receive(:database_base_models).and_return(configured_base_models)
|
allow(Gitlab::Database).to receive(:database_base_models).and_return(database_base_models)
|
||||||
|
|
||||||
|
if database_base_models.has_key?(:ci)
|
||||||
|
Gitlab::Database::SharedModel.using_connection(database_base_models[:ci].connection) do
|
||||||
|
LooseForeignKeys::DeletedRecord.create!(fully_qualified_table_name: 'public._test_loose_fk_parent_table_1', primary_key_value: 999)
|
||||||
|
LooseForeignKeys::DeletedRecord.create!(fully_qualified_table_name: 'public._test_loose_fk_parent_table_1', primary_key_value: 9991)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'uses the correct connection' do
|
it 'uses the correct connection' do
|
||||||
LooseForeignKeys::DeletedRecord.count.times do
|
record_count = Gitlab::Database::SharedModel.using_connection(expected_connection) do
|
||||||
|
LooseForeignKeys::DeletedRecord.count
|
||||||
|
end
|
||||||
|
|
||||||
|
record_count.times do
|
||||||
expect_next_found_instance_of(LooseForeignKeys::DeletedRecord) do |instance|
|
expect_next_found_instance_of(LooseForeignKeys::DeletedRecord) do |instance|
|
||||||
expect(instance.class.connection).to eq(expected_connection)
|
expect(instance.class.connection).to eq(expected_connection)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue