Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
ba557e8fea
commit
7503415f61
|
|
@ -3160,7 +3160,6 @@ Layout/LineLength:
|
||||||
- 'lib/gitlab/database/reindexing/coordinator.rb'
|
- 'lib/gitlab/database/reindexing/coordinator.rb'
|
||||||
- 'lib/gitlab/database/reindexing/grafana_notifier.rb'
|
- 'lib/gitlab/database/reindexing/grafana_notifier.rb'
|
||||||
- 'lib/gitlab/database/reindexing/reindex_concurrently.rb'
|
- 'lib/gitlab/database/reindexing/reindex_concurrently.rb'
|
||||||
- 'lib/gitlab/database/schema_cleaner.rb'
|
|
||||||
- 'lib/gitlab/database/schema_migrations/context.rb'
|
- 'lib/gitlab/database/schema_migrations/context.rb'
|
||||||
- 'lib/gitlab/database/similarity_score.rb'
|
- 'lib/gitlab/database/similarity_score.rb'
|
||||||
- 'lib/gitlab/database/with_lock_retries.rb'
|
- 'lib/gitlab/database/with_lock_retries.rb'
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ import { getCookie, setCookie } from '~/lib/utils/common_utils';
|
||||||
import ValueStreamMetrics from '~/analytics/shared/components/value_stream_metrics.vue';
|
import ValueStreamMetrics from '~/analytics/shared/components/value_stream_metrics.vue';
|
||||||
import { VSA_METRICS_GROUPS } from '~/analytics/shared/constants';
|
import { VSA_METRICS_GROUPS } from '~/analytics/shared/constants';
|
||||||
import { toYmd } from '~/analytics/shared/utils';
|
import { toYmd } from '~/analytics/shared/utils';
|
||||||
import PathNavigation from '~/cycle_analytics/components/path_navigation.vue';
|
import PathNavigation from '~/analytics/cycle_analytics/components/path_navigation.vue';
|
||||||
import StageTable from '~/cycle_analytics/components/stage_table.vue';
|
import StageTable from '~/analytics/cycle_analytics/components/stage_table.vue';
|
||||||
import ValueStreamFilters from '~/cycle_analytics/components/value_stream_filters.vue';
|
import ValueStreamFilters from '~/analytics/cycle_analytics/components/value_stream_filters.vue';
|
||||||
import UrlSync from '~/vue_shared/components/url_sync.vue';
|
import UrlSync from '~/vue_shared/components/url_sync.vue';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import { SUMMARY_METRICS_REQUEST, METRICS_REQUESTS } from '../constants';
|
import { SUMMARY_METRICS_REQUEST, METRICS_REQUESTS } from '../constants';
|
||||||
|
|
@ -8,7 +8,7 @@ import {
|
||||||
GlTable,
|
GlTable,
|
||||||
GlBadge,
|
GlBadge,
|
||||||
} from '@gitlab/ui';
|
} from '@gitlab/ui';
|
||||||
import FormattedStageCount from '~/cycle_analytics/components/formatted_stage_count.vue';
|
import FormattedStageCount from '~/analytics/cycle_analytics/components/formatted_stage_count.vue';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import Tracking from '~/tracking';
|
import Tracking from '~/tracking';
|
||||||
import {
|
import {
|
||||||
|
|
@ -3,7 +3,7 @@ import {
|
||||||
extractFilterQueryParameters,
|
extractFilterQueryParameters,
|
||||||
extractPaginationQueryParameters,
|
extractPaginationQueryParameters,
|
||||||
} from '~/analytics/shared/utils';
|
} from '~/analytics/shared/utils';
|
||||||
import Translate from '../vue_shared/translate';
|
import Translate from '~/vue_shared/translate';
|
||||||
import CycleAnalytics from './components/base.vue';
|
import CycleAnalytics from './components/base.vue';
|
||||||
import createStore from './store';
|
import createStore from './store';
|
||||||
import { buildCycleAnalyticsInitialData } from './utils';
|
import { buildCycleAnalyticsInitialData } from './utils';
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import {
|
import {
|
||||||
PAGINATION_SORT_FIELD_END_EVENT,
|
PAGINATION_SORT_FIELD_END_EVENT,
|
||||||
PAGINATION_SORT_DIRECTION_DESC,
|
PAGINATION_SORT_DIRECTION_DESC,
|
||||||
} from '~/cycle_analytics/constants';
|
} from '~/analytics/cycle_analytics/constants';
|
||||||
|
|
||||||
export default () => ({
|
export default () => ({
|
||||||
id: null,
|
id: null,
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
import initCycleAnalytics from '~/cycle_analytics';
|
import initCycleAnalytics from '~/analytics/cycle_analytics';
|
||||||
|
|
||||||
initCycleAnalytics();
|
initCycleAnalytics();
|
||||||
|
|
|
||||||
|
|
@ -2334,9 +2334,7 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_password_weakness
|
def check_password_weakness
|
||||||
if Feature.enabled?(:block_weak_passwords) &&
|
if password.present? && Security::WeakPasswords.weak_for_user?(password, self)
|
||||||
password.present? &&
|
|
||||||
Security::WeakPasswords.weak_for_user?(password, self)
|
|
||||||
errors.add(:password, _('must not contain commonly used combinations of words and letters'))
|
errors.add(:password, _('must not contain commonly used combinations of words and letters'))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
---
|
|
||||||
name: block_weak_passwords
|
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86310
|
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/363445
|
|
||||||
milestone: '15.4'
|
|
||||||
type: development
|
|
||||||
group: group::authentication and authorization
|
|
||||||
default_enabled: false
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
---
|
|
||||||
name: dast_api_scanner
|
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73564
|
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345837
|
|
||||||
milestone: '14.7'
|
|
||||||
type: development
|
|
||||||
group: group::dynamic analysis
|
|
||||||
default_enabled: true
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
name: automatic_lock_writes_on_table
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99287
|
||||||
|
rollout_issue_url:
|
||||||
|
milestone: '15.7'
|
||||||
|
type: ops
|
||||||
|
group: group::pods
|
||||||
|
default_enabled: false
|
||||||
|
|
@ -14,7 +14,7 @@ A short downtime is expected for all methods.
|
||||||
|
|
||||||
## Omnibus installations
|
## Omnibus installations
|
||||||
|
|
||||||
If you have used the [Omnibus packages](https://about.gitlab.com/install/) to install GitLab, then
|
If you have used the [Omnibus packages](https://about.gitlab.com/install/) to install GitLab,
|
||||||
you should already have `gitlab-ctl` in your `PATH`.
|
you should already have `gitlab-ctl` in your `PATH`.
|
||||||
|
|
||||||
`gitlab-ctl` interacts with the Omnibus packages and can be used to restart the
|
`gitlab-ctl` interacts with the Omnibus packages and can be used to restart the
|
||||||
|
|
@ -88,16 +88,14 @@ sudo gitlab-ctl reconfigure
|
||||||
Reconfiguring GitLab should occur in the event that something in its
|
Reconfiguring GitLab should occur in the event that something in its
|
||||||
configuration (`/etc/gitlab/gitlab.rb`) has changed.
|
configuration (`/etc/gitlab/gitlab.rb`) has changed.
|
||||||
|
|
||||||
When you run this command, [Chef](https://www.chef.io/products/chef-infra), the underlying configuration management
|
When you run `gitlab-ctl reconfigure`, [Chef](https://www.chef.io/products/chef-infra),
|
||||||
application that powers Omnibus GitLab, makes sure that all things like directories,
|
the underlying configuration management application that powers Omnibus GitLab, runs some checks.
|
||||||
permissions, and services are in place and in the same shape that they were
|
Chef ensures directories, permissions, and services are in place and working.
|
||||||
initially shipped.
|
|
||||||
|
|
||||||
It also [restarts GitLab components](#how-to-restart-gitlab)
|
Chef also [restarts GitLab components](#how-to-restart-gitlab) if any of their configuration files have changed.
|
||||||
where needed, if any of their configuration files have changed.
|
|
||||||
|
|
||||||
If you manually edit any files in `/var/opt/gitlab` that are managed by Chef,
|
If you manually edit any files in `/var/opt/gitlab` that are managed by Chef,
|
||||||
running reconfigure reverts the changes and restarts the services that
|
running `reconfigure` reverts the changes and restarts the services that
|
||||||
depend on those files.
|
depend on those files.
|
||||||
|
|
||||||
## Installations from source
|
## Installations from source
|
||||||
|
|
@ -118,7 +116,7 @@ This should restart Puma, Sidekiq, GitLab Workhorse, and [Mailroom](reply_by_ema
|
||||||
|
|
||||||
## Helm chart installations
|
## Helm chart installations
|
||||||
|
|
||||||
There is no single command to restart the entire GitLab application installed via
|
There is no single command to restart the entire GitLab application installed through
|
||||||
the [cloud-native Helm chart](https://docs.gitlab.com/charts/). Usually, it should be
|
the [cloud-native Helm chart](https://docs.gitlab.com/charts/). Usually, it should be
|
||||||
enough to restart a specific component separately (for example, `gitaly`, `puma`,
|
enough to restart a specific component separately (for example, `gitaly`, `puma`,
|
||||||
`workhorse`, or `gitlab-shell`) by deleting all the pods related to it:
|
`workhorse`, or `gitlab-shell`) by deleting all the pods related to it:
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
||||||
|
|
||||||
# Uploads administration **(FREE SELF)**
|
# Uploads administration **(FREE SELF)**
|
||||||
|
|
||||||
Uploads represent all user data that may be sent to GitLab as a single file. As an example, avatars and notes' attachments are uploads. Uploads are integral to GitLab functionality, and therefore cannot be disabled.
|
Uploads represent all user data that may be sent to GitLab as a single file. For example, avatars and note attachments are uploads. Uploads are integral to GitLab functionality and therefore cannot be disabled.
|
||||||
|
|
||||||
## Using local storage
|
## Using local storage
|
||||||
|
|
||||||
|
|
@ -14,15 +14,15 @@ This is the default configuration. To change the location where the uploads are
|
||||||
stored locally, use the steps in this section based on your installation method:
|
stored locally, use the steps in this section based on your installation method:
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
For historical reasons, instance level uploads (for example the [favicon](../user/admin_area/appearance.md#favicon)) are stored into a base directory,
|
For historical reasons, uploads for the whole instance (for example the [favicon](../user/admin_area/appearance.md#favicon)) are stored in a base directory,
|
||||||
which by default is `uploads/-/system`. It is strongly discouraged to change the base
|
which by default is `uploads/-/system`. Changing the base
|
||||||
directory on an existing GitLab installation.
|
directory on an existing GitLab installation is strongly discouraged.
|
||||||
|
|
||||||
**In Omnibus GitLab installations:**
|
**In Omnibus GitLab installations:**
|
||||||
|
|
||||||
_The uploads are stored by default in `/var/opt/gitlab/gitlab-rails/uploads`._
|
_The uploads are stored by default in `/var/opt/gitlab/gitlab-rails/uploads`._
|
||||||
|
|
||||||
1. To change the storage path for example to `/mnt/storage/uploads`, edit
|
1. To change the storage path, for example to `/mnt/storage/uploads`, edit
|
||||||
`/etc/gitlab/gitlab.rb` and add the following line:
|
`/etc/gitlab/gitlab.rb` and add the following line:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
|
|
@ -38,7 +38,7 @@ _The uploads are stored by default in `/var/opt/gitlab/gitlab-rails/uploads`._
|
||||||
_The uploads are stored by default in
|
_The uploads are stored by default in
|
||||||
`/home/git/gitlab/public/uploads`._
|
`/home/git/gitlab/public/uploads`._
|
||||||
|
|
||||||
1. To change the storage path for example to `/mnt/storage/uploads`, edit
|
1. To change the storage path, for example to `/mnt/storage/uploads`, edit
|
||||||
`/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
|
`/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
|
@ -57,7 +57,7 @@ This configuration relies on valid AWS credentials to be configured already.
|
||||||
|
|
||||||
[Read more about using object storage with GitLab](object_storage.md).
|
[Read more about using object storage with GitLab](object_storage.md).
|
||||||
|
|
||||||
We recommend using the [consolidated object storage settings](object_storage.md#consolidated-object-storage-configuration). The following instructions apply to the original configuration format.
|
You should use the [consolidated object storage settings](object_storage.md#consolidated-object-storage-configuration). The following instructions apply to the original configuration format.
|
||||||
|
|
||||||
### Object Storage Settings
|
### Object Storage Settings
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2098,8 +2098,8 @@ Input type: `DastSiteProfileCreateInput`
|
||||||
| <a id="mutationdastsiteprofilecreatefullpath"></a>`fullPath` | [`ID!`](#id) | Project the site profile belongs to. |
|
| <a id="mutationdastsiteprofilecreatefullpath"></a>`fullPath` | [`ID!`](#id) | Project the site profile belongs to. |
|
||||||
| <a id="mutationdastsiteprofilecreateprofilename"></a>`profileName` | [`String!`](#string) | Name of the site profile. |
|
| <a id="mutationdastsiteprofilecreateprofilename"></a>`profileName` | [`String!`](#string) | Name of the site profile. |
|
||||||
| <a id="mutationdastsiteprofilecreaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
|
| <a id="mutationdastsiteprofilecreaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
|
||||||
| <a id="mutationdastsiteprofilecreatescanfilepath"></a>`scanFilePath` | [`String`](#string) | File Path or URL used as input for the scan method. Will not be saved or updated if `dast_api_scanner` feature flag is disabled. |
|
| <a id="mutationdastsiteprofilecreatescanfilepath"></a>`scanFilePath` | [`String`](#string) | File Path or URL used as input for the scan method. |
|
||||||
| <a id="mutationdastsiteprofilecreatescanmethod"></a>`scanMethod` | [`DastScanMethodType`](#dastscanmethodtype) | Scan method by the scanner. Is not saved or updated if `dast_api_scanner` feature flag is disabled. |
|
| <a id="mutationdastsiteprofilecreatescanmethod"></a>`scanMethod` | [`DastScanMethodType`](#dastscanmethodtype) | Scan method by the scanner. |
|
||||||
| <a id="mutationdastsiteprofilecreatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | Type of target to be scanned. |
|
| <a id="mutationdastsiteprofilecreatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | Type of target to be scanned. |
|
||||||
| <a id="mutationdastsiteprofilecreatetargeturl"></a>`targetUrl` | [`String`](#string) | URL of the target to be scanned. |
|
| <a id="mutationdastsiteprofilecreatetargeturl"></a>`targetUrl` | [`String`](#string) | URL of the target to be scanned. |
|
||||||
|
|
||||||
|
|
@ -2146,8 +2146,8 @@ Input type: `DastSiteProfileUpdateInput`
|
||||||
| <a id="mutationdastsiteprofileupdateid"></a>`id` | [`DastSiteProfileID!`](#dastsiteprofileid) | ID of the site profile to be updated. |
|
| <a id="mutationdastsiteprofileupdateid"></a>`id` | [`DastSiteProfileID!`](#dastsiteprofileid) | ID of the site profile to be updated. |
|
||||||
| <a id="mutationdastsiteprofileupdateprofilename"></a>`profileName` | [`String!`](#string) | Name of the site profile. |
|
| <a id="mutationdastsiteprofileupdateprofilename"></a>`profileName` | [`String!`](#string) | Name of the site profile. |
|
||||||
| <a id="mutationdastsiteprofileupdaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
|
| <a id="mutationdastsiteprofileupdaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
|
||||||
| <a id="mutationdastsiteprofileupdatescanfilepath"></a>`scanFilePath` | [`String`](#string) | File Path or URL used as input for the scan method. Will not be saved or updated if `dast_api_scanner` feature flag is disabled. |
|
| <a id="mutationdastsiteprofileupdatescanfilepath"></a>`scanFilePath` | [`String`](#string) | File Path or URL used as input for the scan method. |
|
||||||
| <a id="mutationdastsiteprofileupdatescanmethod"></a>`scanMethod` | [`DastScanMethodType`](#dastscanmethodtype) | Scan method by the scanner. Is not saved or updated if `dast_api_scanner` feature flag is disabled. |
|
| <a id="mutationdastsiteprofileupdatescanmethod"></a>`scanMethod` | [`DastScanMethodType`](#dastscanmethodtype) | Scan method by the scanner. |
|
||||||
| <a id="mutationdastsiteprofileupdatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | Type of target to be scanned. |
|
| <a id="mutationdastsiteprofileupdatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | Type of target to be scanned. |
|
||||||
| <a id="mutationdastsiteprofileupdatetargeturl"></a>`targetUrl` | [`String`](#string) | URL of the target to be scanned. |
|
| <a id="mutationdastsiteprofileupdatetargeturl"></a>`targetUrl` | [`String`](#string) | URL of the target to be scanned. |
|
||||||
|
|
||||||
|
|
@ -11708,8 +11708,8 @@ Represents a DAST Site Profile.
|
||||||
| <a id="dastsiteprofileprofilename"></a>`profileName` | [`String`](#string) | Name of the site profile. |
|
| <a id="dastsiteprofileprofilename"></a>`profileName` | [`String`](#string) | Name of the site profile. |
|
||||||
| <a id="dastsiteprofilereferencedinsecuritypolicies"></a>`referencedInSecurityPolicies` | [`[String!]`](#string) | List of security policy names that are referencing given project. |
|
| <a id="dastsiteprofilereferencedinsecuritypolicies"></a>`referencedInSecurityPolicies` | [`[String!]`](#string) | List of security policy names that are referencing given project. |
|
||||||
| <a id="dastsiteprofilerequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
|
| <a id="dastsiteprofilerequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
|
||||||
| <a id="dastsiteprofilescanfilepath"></a>`scanFilePath` | [`String`](#string) | Scan File Path used as input for the scanner. Will always return `null` if `dast_api_scanner` feature flag is disabled. |
|
| <a id="dastsiteprofilescanfilepath"></a>`scanFilePath` | [`String`](#string) | Scan File Path used as input for the scanner. |
|
||||||
| <a id="dastsiteprofilescanmethod"></a>`scanMethod` | [`DastScanMethodType`](#dastscanmethodtype) | Scan method used by the scanner. Always returns `null` if `dast_api_scanner` feature flag is disabled. |
|
| <a id="dastsiteprofilescanmethod"></a>`scanMethod` | [`DastScanMethodType`](#dastscanmethodtype) | Scan method used by the scanner. |
|
||||||
| <a id="dastsiteprofiletargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | Type of target to be scanned. |
|
| <a id="dastsiteprofiletargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | Type of target to be scanned. |
|
||||||
| <a id="dastsiteprofiletargeturl"></a>`targetUrl` | [`String`](#string) | URL of the target to be scanned. |
|
| <a id="dastsiteprofiletargeturl"></a>`targetUrl` | [`String`](#string) | URL of the target to be scanned. |
|
||||||
| <a id="dastsiteprofileuserpermissions"></a>`userPermissions` | [`DastSiteProfilePermissions!`](#dastsiteprofilepermissions) | Permissions for the current user on the resource. |
|
| <a id="dastsiteprofileuserpermissions"></a>`userPermissions` | [`DastSiteProfilePermissions!`](#dastsiteprofilepermissions) | Permissions for the current user on the resource. |
|
||||||
|
|
|
||||||
|
|
@ -61,12 +61,8 @@ Self-managed installations can configure the following additional password requi
|
||||||
## Block weak passwords
|
## Block weak passwords
|
||||||
|
|
||||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23610) in GitLab 15.4 [with a flag](../../administration/feature_flags.md) named `block_weak_passwords`, weak passwords aren't accepted. Disabled by default on self-managed.
|
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23610) in GitLab 15.4 [with a flag](../../administration/feature_flags.md) named `block_weak_passwords`, weak passwords aren't accepted. Disabled by default on self-managed.
|
||||||
> - [Enabled](https://gitlab.com/gitlab-org/gitlab/-/issues/363445) on GitLab.com.
|
> - [Enabled](https://gitlab.com/gitlab-org/gitlab/-/issues/363445) on GitLab.com in GitLab 15.6.
|
||||||
|
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/363445) and enabled on self-managed in GitLab 15.7. Feature flag `block_weak_passwords` removed.
|
||||||
FLAG:
|
|
||||||
On self-managed GitLab, by default blocking weak passwords is not available. To make it available, ask an administrator
|
|
||||||
to [enable the feature flag](../../administration/feature_flags.md) named `block_weak_passwords`. On GitLab.com, this
|
|
||||||
feature is available but can be configured by GitLab.com administrators only.
|
|
||||||
|
|
||||||
GitLab disallows weak passwords. Your password is considered weak when it:
|
GitLab disallows weak passwords. Your password is considered weak when it:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@
|
||||||
# Each table / view needs to have assigned gitlab_schema. Names supported today:
|
# Each table / view needs to have assigned gitlab_schema. Names supported today:
|
||||||
#
|
#
|
||||||
# - gitlab_shared - defines a set of tables that are found on all databases (data accessed is dependent on connection)
|
# - gitlab_shared - defines a set of tables that are found on all databases (data accessed is dependent on connection)
|
||||||
# - gitlab_main / gitlab_ci - defines a set of tables that can only exist on a given database
|
# - gitlab_main / gitlab_ci - defines a set of tables that can only exist on a given application database
|
||||||
|
# - gitlab_geo - defines a set of tables that can only exist on the geo database
|
||||||
|
# - gitlab_internal - defines all internal tables of Rails and PostgreSQL
|
||||||
#
|
#
|
||||||
# Tables for the purpose of tests should be prefixed with `_test_my_table_name`
|
# Tables for the purpose of tests should be prefixed with `_test_my_table_name`
|
||||||
|
|
||||||
|
|
@ -55,7 +57,7 @@ module Gitlab
|
||||||
tables.map { |table| table_schema(table) }.to_set
|
tables.map { |table| table_schema(table) }.to_set
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.table_schema(name)
|
def self.table_schema(name, undefined: true)
|
||||||
schema_name, table_name = name.split('.', 2) # Strip schema name like: `public.`
|
schema_name, table_name = name.split('.', 2) # Strip schema name like: `public.`
|
||||||
|
|
||||||
# Most of names do not have schemas, ensure that this is table
|
# Most of names do not have schemas, ensure that this is table
|
||||||
|
|
@ -84,6 +86,8 @@ module Gitlab
|
||||||
|
|
||||||
return :gitlab_ci if table_name.start_with?('_test_gitlab_ci_')
|
return :gitlab_ci if table_name.start_with?('_test_gitlab_ci_')
|
||||||
|
|
||||||
|
return :gitlab_geo if table_name.start_with?('_test_gitlab_geo_')
|
||||||
|
|
||||||
# All tables that start with `_test_` without a following schema are shared and ignored
|
# All tables that start with `_test_` without a following schema are shared and ignored
|
||||||
return :gitlab_shared if table_name.start_with?('_test_')
|
return :gitlab_shared if table_name.start_with?('_test_')
|
||||||
|
|
||||||
|
|
@ -91,7 +95,7 @@ module Gitlab
|
||||||
return :gitlab_internal if table_name.start_with?('pg_')
|
return :gitlab_internal if table_name.start_with?('pg_')
|
||||||
|
|
||||||
# When undefined it's best to return a unique name so that we don't incorrectly assume that 2 undefined schemas belong on the same database
|
# When undefined it's best to return a unique name so that we don't incorrectly assume that 2 undefined schemas belong on the same database
|
||||||
:"undefined_#{table_name}"
|
undefined ? :"undefined_#{table_name}" : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.tables_to_schema
|
def self.tables_to_schema
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,10 @@ module Gitlab
|
||||||
include Gitlab::Database::MigrationHelpers::RestrictGitlabSchema
|
include Gitlab::Database::MigrationHelpers::RestrictGitlabSchema
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class V2_1 < V2_0 # rubocop:disable Naming/ClassAndModuleCamelCase
|
||||||
|
include Gitlab::Database::MigrationHelpers::AutomaticLockWritesOnTables
|
||||||
|
end
|
||||||
|
|
||||||
def self.[](version)
|
def self.[](version)
|
||||||
version = version.to_s
|
version = version.to_s
|
||||||
name = "V#{version.tr('.', '_')}"
|
name = "V#{version.tr('.', '_')}"
|
||||||
|
|
@ -61,7 +65,7 @@ module Gitlab
|
||||||
|
|
||||||
# The current version to be used in new migrations
|
# The current version to be used in new migrations
|
||||||
def self.current_version
|
def self.current_version
|
||||||
2.0
|
2.1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Gitlab
|
||||||
|
module Database
|
||||||
|
module MigrationHelpers
|
||||||
|
module AutomaticLockWritesOnTables
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
class_attribute :skip_automatic_lock_on_writes
|
||||||
|
end
|
||||||
|
|
||||||
|
def exec_migration(connection, direction)
|
||||||
|
return super if %w[main ci].exclude?(Gitlab::Database.db_config_name(connection))
|
||||||
|
return super if automatic_lock_on_writes_disabled?
|
||||||
|
|
||||||
|
# This compares the tables only on the `public` schema. Partitions are not affected
|
||||||
|
tables = connection.tables
|
||||||
|
super
|
||||||
|
new_tables = connection.tables - tables
|
||||||
|
|
||||||
|
new_tables.each do |table_name|
|
||||||
|
lock_writes_on_table(connection, table_name) if should_lock_writes_on_table?(table_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def automatic_lock_on_writes_disabled?
|
||||||
|
# Feature flags are set on the main database, see tables features/feature_gates.
|
||||||
|
# That is why we switch the ActiveRecord::Base.connection temporarily here back to the 'main' database
|
||||||
|
# for the cases when the migration is targeting another database, like the 'ci' database.
|
||||||
|
with_restored_connection_stack do |_|
|
||||||
|
Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.with_suppressed do
|
||||||
|
skip_automatic_lock_on_writes ||
|
||||||
|
Gitlab::Utils.to_boolean(ENV['SKIP_AUTOMATIC_LOCK_ON_WRITES']) ||
|
||||||
|
Feature.disabled?(:automatic_lock_writes_on_table, type: :ops)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def should_lock_writes_on_table?(table_name)
|
||||||
|
# currently gitlab_schema represents only present existing tables, this is workaround for deleted tables
|
||||||
|
# that should be skipped as they will be removed in a future migration.
|
||||||
|
return false if Gitlab::Database::GitlabSchema::DELETED_TABLES[table_name]
|
||||||
|
|
||||||
|
table_schema = Gitlab::Database::GitlabSchema.table_schema(table_name.to_s, undefined: false)
|
||||||
|
|
||||||
|
if table_schema.nil?
|
||||||
|
error_message = <<~ERROR
|
||||||
|
No gitlab_schema is defined for the table #{table_name}. Please consider
|
||||||
|
adding it to the file config 'lib/gitlab/database/gitlab_schemas.yml'
|
||||||
|
ERROR
|
||||||
|
raise error_message
|
||||||
|
end
|
||||||
|
|
||||||
|
return false unless %i[gitlab_main gitlab_ci].include?(table_schema)
|
||||||
|
|
||||||
|
Gitlab::Database.gitlab_schemas_for_connection(connection).exclude?(table_schema)
|
||||||
|
end
|
||||||
|
|
||||||
|
def lock_writes_on_table(connection, table_name)
|
||||||
|
database_name = Gitlab::Database.db_config_name(connection)
|
||||||
|
LockWritesManager.new(
|
||||||
|
table_name: table_name,
|
||||||
|
connection: connection,
|
||||||
|
database_name: database_name,
|
||||||
|
logger: Logger.new($stdout)
|
||||||
|
).lock_writes
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -25,7 +25,23 @@ module Gitlab
|
||||||
# The intention here is to not introduce an assumption about the standard schema,
|
# The intention here is to not introduce an assumption about the standard schema,
|
||||||
# unless we have a good reason to do so.
|
# unless we have a good reason to do so.
|
||||||
structure.gsub!(/public\.(\w+)/, '\1')
|
structure.gsub!(/public\.(\w+)/, '\1')
|
||||||
structure.gsub!(/CREATE EXTENSION IF NOT EXISTS (\w+) WITH SCHEMA public;/, 'CREATE EXTENSION IF NOT EXISTS \1;')
|
structure.gsub!(
|
||||||
|
/CREATE EXTENSION IF NOT EXISTS (\w+) WITH SCHEMA public;/,
|
||||||
|
'CREATE EXTENSION IF NOT EXISTS \1;'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Table lock-writes triggers should not be added to the schema
|
||||||
|
# These triggers are added by the rake task gitlab:db:lock_writes for a decomposed database.
|
||||||
|
structure.gsub!(
|
||||||
|
%r{
|
||||||
|
^CREATE.TRIGGER.gitlab_schema_write_trigger_\w+
|
||||||
|
\s
|
||||||
|
BEFORE.INSERT.OR.DELETE.OR.UPDATE.OR.TRUNCATE.ON.\w+
|
||||||
|
\s
|
||||||
|
FOR.EACH.STATEMENT.EXECUTE.FUNCTION.gitlab_schema_prevent_write\(\);$
|
||||||
|
}x,
|
||||||
|
''
|
||||||
|
)
|
||||||
|
|
||||||
structure.gsub!(/\n{3,}/, "\n\n")
|
structure.gsub!(/\n{3,}/, "\n\n")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
"@gitlab/at.js": "1.5.7",
|
"@gitlab/at.js": "1.5.7",
|
||||||
"@gitlab/favicon-overlay": "2.0.0",
|
"@gitlab/favicon-overlay": "2.0.0",
|
||||||
"@gitlab/svgs": "3.11.0",
|
"@gitlab/svgs": "3.11.0",
|
||||||
"@gitlab/ui": "49.11.2",
|
"@gitlab/ui": "50.1.2",
|
||||||
"@gitlab/visual-review-tools": "1.7.3",
|
"@gitlab/visual-review-tools": "1.7.3",
|
||||||
"@gitlab/web-ide": "0.0.1-dev-20221114183058",
|
"@gitlab/web-ide": "0.0.1-dev-20221114183058",
|
||||||
"@rails/actioncable": "6.1.4-7",
|
"@rails/actioncable": "6.1.4-7",
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,10 @@ module RuboCop
|
||||||
include MigrationHelpers
|
include MigrationHelpers
|
||||||
|
|
||||||
ENFORCED_SINCE = 2021_09_02_00_00_00
|
ENFORCED_SINCE = 2021_09_02_00_00_00
|
||||||
|
CURRENT_DATABASE_MIGRATION_CLASS = 'Gitlab::Database::Migration[2.1]'
|
||||||
|
|
||||||
MSG_INHERIT = 'Don\'t inherit from ActiveRecord::Migration but use Gitlab::Database::Migration[1.0] instead. See https://docs.gitlab.com/ee/development/migration_style_guide.html#migration-helpers-and-versioning.'
|
MSG_INHERIT = 'Don\'t inherit from ActiveRecord::Migration but use Gitlab::Database::Migration[2.1] instead. See https://docs.gitlab.com/ee/development/migration_style_guide.html#migration-helpers-and-versioning.'
|
||||||
MSG_INCLUDE = 'Don\'t include migration helper modules directly. Inherit from Gitlab::Database::Migration[1.0] instead. See https://docs.gitlab.com/ee/development/migration_style_guide.html#migration-helpers-and-versioning.'
|
MSG_INCLUDE = 'Don\'t include migration helper modules directly. Inherit from Gitlab::Database::Migration[2.1] instead. See https://docs.gitlab.com/ee/development/migration_style_guide.html#migration-helpers-and-versioning.'
|
||||||
|
|
||||||
ACTIVERECORD_MIGRATION_CLASS = 'ActiveRecord::Migration'
|
ACTIVERECORD_MIGRATION_CLASS = 'ActiveRecord::Migration'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -486,7 +486,6 @@ RSpec.describe RegistrationsController do
|
||||||
|
|
||||||
subject { post(:create, params: new_user_params) }
|
subject { post(:create, params: new_user_params) }
|
||||||
|
|
||||||
context 'when block_weak_passwords is enabled (default)' do
|
|
||||||
it 'renders the form with errors' do
|
it 'renders the form with errors' do
|
||||||
expect { subject }.not_to change(User, :count)
|
expect { subject }.not_to change(User, :count)
|
||||||
|
|
||||||
|
|
@ -506,17 +505,6 @@ RSpec.describe RegistrationsController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when block_weak_passwords is disabled' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(block_weak_passwords: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'permits weak passwords' do
|
|
||||||
expect { subject }.to change(User, :count).by(1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when the password is not weak' do
|
context 'when the password is not weak' do
|
||||||
it 'does not track a weak password error' do
|
it 'does not track a weak password error' do
|
||||||
subject
|
subject
|
||||||
|
|
|
||||||
|
|
@ -77,3 +77,17 @@ ALTER TABLE ONLY public.abuse_reports
|
||||||
|
|
||||||
CREATE INDEX index_abuse_reports_on_user_id ON public.abuse_reports USING btree (user_id);
|
CREATE INDEX index_abuse_reports_on_user_id ON public.abuse_reports USING btree (user_id);
|
||||||
|
|
||||||
|
CREATE TRIGGER gitlab_schema_write_trigger_for_users BEFORE INSERT OR DELETE OR UPDATE OR TRUNCATE ON users FOR EACH STATEMENT EXECUTE FUNCTION gitlab_schema_prevent_write();
|
||||||
|
|
||||||
|
CREATE FUNCTION gitlab_schema_prevent_write() RETURNS trigger
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS $$
|
||||||
|
BEGIN
|
||||||
|
IF COALESCE(NULLIF(current_setting(CONCAT('lock_writes.', TG_TABLE_NAME), true), ''), 'true') THEN
|
||||||
|
RAISE EXCEPTION 'Table: "%" is write protected within this Gitlab database.', TG_TABLE_NAME
|
||||||
|
USING ERRCODE = 'modifying_sql_data_not_permitted',
|
||||||
|
HINT = 'Make sure you are using the right database connection';
|
||||||
|
END IF;
|
||||||
|
RETURN NEW;
|
||||||
|
END
|
||||||
|
$$;
|
||||||
|
|
|
||||||
|
|
@ -24,3 +24,16 @@ ALTER TABLE ONLY abuse_reports
|
||||||
ADD CONSTRAINT abuse_reports_pkey PRIMARY KEY (id);
|
ADD CONSTRAINT abuse_reports_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
CREATE INDEX index_abuse_reports_on_user_id ON abuse_reports USING btree (user_id);
|
CREATE INDEX index_abuse_reports_on_user_id ON abuse_reports USING btree (user_id);
|
||||||
|
|
||||||
|
CREATE FUNCTION gitlab_schema_prevent_write() RETURNS trigger
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS $$
|
||||||
|
BEGIN
|
||||||
|
IF COALESCE(NULLIF(current_setting(CONCAT('lock_writes.', TG_TABLE_NAME), true), ''), 'true') THEN
|
||||||
|
RAISE EXCEPTION 'Table: "%" is write protected within this Gitlab database.', TG_TABLE_NAME
|
||||||
|
USING ERRCODE = 'modifying_sql_data_not_permitted',
|
||||||
|
HINT = 'Make sure you are using the right database connection';
|
||||||
|
END IF;
|
||||||
|
RETURN NEW;
|
||||||
|
END
|
||||||
|
$$;
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ import Vue from 'vue';
|
||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||||
import ValueStreamMetrics from '~/analytics/shared/components/value_stream_metrics.vue';
|
import ValueStreamMetrics from '~/analytics/shared/components/value_stream_metrics.vue';
|
||||||
import BaseComponent from '~/cycle_analytics/components/base.vue';
|
import BaseComponent from '~/analytics/cycle_analytics/components/base.vue';
|
||||||
import PathNavigation from '~/cycle_analytics/components/path_navigation.vue';
|
import PathNavigation from '~/analytics/cycle_analytics/components/path_navigation.vue';
|
||||||
import StageTable from '~/cycle_analytics/components/stage_table.vue';
|
import StageTable from '~/analytics/cycle_analytics/components/stage_table.vue';
|
||||||
import ValueStreamFilters from '~/cycle_analytics/components/value_stream_filters.vue';
|
import ValueStreamFilters from '~/analytics/cycle_analytics/components/value_stream_filters.vue';
|
||||||
import { NOT_ENOUGH_DATA_ERROR } from '~/cycle_analytics/constants';
|
import { NOT_ENOUGH_DATA_ERROR } from '~/analytics/cycle_analytics/constants';
|
||||||
import initState from '~/cycle_analytics/store/state';
|
import initState from '~/analytics/cycle_analytics/store/state';
|
||||||
import {
|
import {
|
||||||
transformedProjectStagePathData,
|
transformedProjectStagePathData,
|
||||||
selectedStage,
|
selectedStage,
|
||||||
|
|
@ -7,8 +7,8 @@ import {
|
||||||
filterMilestones,
|
filterMilestones,
|
||||||
filterLabels,
|
filterLabels,
|
||||||
} from 'jest/vue_shared/components/filtered_search_bar/store/modules/filters/mock_data';
|
} from 'jest/vue_shared/components/filtered_search_bar/store/modules/filters/mock_data';
|
||||||
import FilterBar from '~/cycle_analytics/components/filter_bar.vue';
|
import FilterBar from '~/analytics/cycle_analytics/components/filter_bar.vue';
|
||||||
import storeConfig from '~/cycle_analytics/store';
|
import storeConfig from '~/analytics/cycle_analytics/store';
|
||||||
import * as commonUtils from '~/lib/utils/common_utils';
|
import * as commonUtils from '~/lib/utils/common_utils';
|
||||||
import * as urlUtils from '~/lib/utils/url_utility';
|
import * as urlUtils from '~/lib/utils/url_utility';
|
||||||
import {
|
import {
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { shallowMount } from '@vue/test-utils';
|
import { shallowMount } from '@vue/test-utils';
|
||||||
import Component from '~/cycle_analytics/components/formatted_stage_count.vue';
|
import Component from '~/analytics/cycle_analytics/components/formatted_stage_count.vue';
|
||||||
|
|
||||||
describe('Formatted Stage Count', () => {
|
describe('Formatted Stage Count', () => {
|
||||||
let wrapper = null;
|
let wrapper = null;
|
||||||
|
|
@ -12,7 +12,7 @@ import {
|
||||||
PAGINATION_TYPE,
|
PAGINATION_TYPE,
|
||||||
PAGINATION_SORT_DIRECTION_DESC,
|
PAGINATION_SORT_DIRECTION_DESC,
|
||||||
PAGINATION_SORT_FIELD_END_EVENT,
|
PAGINATION_SORT_FIELD_END_EVENT,
|
||||||
} from '~/cycle_analytics/constants';
|
} from '~/analytics/cycle_analytics/constants';
|
||||||
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
|
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
|
||||||
import { getDateInPast } from '~/lib/utils/datetime_utility';
|
import { getDateInPast } from '~/lib/utils/datetime_utility';
|
||||||
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { GlPath, GlSkeletonLoader } from '@gitlab/ui';
|
||||||
import { mount } from '@vue/test-utils';
|
import { mount } from '@vue/test-utils';
|
||||||
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
|
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
|
||||||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||||
import Component from '~/cycle_analytics/components/path_navigation.vue';
|
import Component from '~/analytics/cycle_analytics/components/path_navigation.vue';
|
||||||
import { transformedProjectStagePathData, selectedStage } from './mock_data';
|
import { transformedProjectStagePathData, selectedStage } from './mock_data';
|
||||||
|
|
||||||
describe('Project PathNavigation', () => {
|
describe('Project PathNavigation', () => {
|
||||||
|
|
@ -3,8 +3,8 @@ import { shallowMount, mount } from '@vue/test-utils';
|
||||||
import { nextTick } from 'vue';
|
import { nextTick } from 'vue';
|
||||||
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
|
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
|
||||||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||||
import StageTable from '~/cycle_analytics/components/stage_table.vue';
|
import StageTable from '~/analytics/cycle_analytics/components/stage_table.vue';
|
||||||
import { PAGINATION_SORT_FIELD_DURATION } from '~/cycle_analytics/constants';
|
import { PAGINATION_SORT_FIELD_DURATION } from '~/analytics/cycle_analytics/constants';
|
||||||
import { issueEvents, issueStage, reviewStage, reviewEvents } from './mock_data';
|
import { issueEvents, issueStage, reviewStage, reviewEvents } from './mock_data';
|
||||||
|
|
||||||
let wrapper = null;
|
let wrapper = null;
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import MockAdapter from 'axios-mock-adapter';
|
import MockAdapter from 'axios-mock-adapter';
|
||||||
import testAction from 'helpers/vuex_action_helper';
|
import testAction from 'helpers/vuex_action_helper';
|
||||||
import * as actions from '~/cycle_analytics/store/actions';
|
import * as actions from '~/analytics/cycle_analytics/store/actions';
|
||||||
import * as getters from '~/cycle_analytics/store/getters';
|
import * as getters from '~/analytics/cycle_analytics/store/getters';
|
||||||
import httpStatusCodes from '~/lib/utils/http_status';
|
import httpStatusCodes from '~/lib/utils/http_status';
|
||||||
import {
|
import {
|
||||||
allowedStages,
|
allowedStages,
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import * as getters from '~/cycle_analytics/store/getters';
|
import * as getters from '~/analytics/cycle_analytics/store/getters';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
allowedStages,
|
allowedStages,
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { useFakeDate } from 'helpers/fake_date';
|
import { useFakeDate } from 'helpers/fake_date';
|
||||||
import * as types from '~/cycle_analytics/store/mutation_types';
|
import * as types from '~/analytics/cycle_analytics/store/mutation_types';
|
||||||
import mutations from '~/cycle_analytics/store/mutations';
|
import mutations from '~/analytics/cycle_analytics/store/mutations';
|
||||||
import {
|
import {
|
||||||
PAGINATION_SORT_FIELD_END_EVENT,
|
PAGINATION_SORT_FIELD_END_EVENT,
|
||||||
PAGINATION_SORT_DIRECTION_DESC,
|
PAGINATION_SORT_DIRECTION_DESC,
|
||||||
} from '~/cycle_analytics/constants';
|
} from '~/analytics/cycle_analytics/constants';
|
||||||
import {
|
import {
|
||||||
selectedStage,
|
selectedStage,
|
||||||
rawIssueEvents,
|
rawIssueEvents,
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { mount } from '@vue/test-utils';
|
import { mount } from '@vue/test-utils';
|
||||||
import TotalTime from '~/cycle_analytics/components/total_time.vue';
|
import TotalTime from '~/analytics/cycle_analytics/components/total_time.vue';
|
||||||
|
|
||||||
describe('TotalTime', () => {
|
describe('TotalTime', () => {
|
||||||
let wrapper = null;
|
let wrapper = null;
|
||||||
|
|
@ -4,7 +4,7 @@ import {
|
||||||
formatMedianValues,
|
formatMedianValues,
|
||||||
filterStagesByHiddenStatus,
|
filterStagesByHiddenStatus,
|
||||||
buildCycleAnalyticsInitialData,
|
buildCycleAnalyticsInitialData,
|
||||||
} from '~/cycle_analytics/utils';
|
} from '~/analytics/cycle_analytics/utils';
|
||||||
import {
|
import {
|
||||||
selectedStage,
|
selectedStage,
|
||||||
allowedStages,
|
allowedStages,
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { shallowMount } from '@vue/test-utils';
|
import { shallowMount } from '@vue/test-utils';
|
||||||
import Daterange from '~/analytics/shared/components/daterange.vue';
|
import Daterange from '~/analytics/shared/components/daterange.vue';
|
||||||
import ProjectsDropdownFilter from '~/analytics/shared/components/projects_dropdown_filter.vue';
|
import ProjectsDropdownFilter from '~/analytics/shared/components/projects_dropdown_filter.vue';
|
||||||
import FilterBar from '~/cycle_analytics/components/filter_bar.vue';
|
import FilterBar from '~/analytics/cycle_analytics/components/filter_bar.vue';
|
||||||
import ValueStreamFilters from '~/cycle_analytics/components/value_stream_filters.vue';
|
import ValueStreamFilters from '~/analytics/cycle_analytics/components/value_stream_filters.vue';
|
||||||
import {
|
import {
|
||||||
createdAfter as startDate,
|
createdAfter as startDate,
|
||||||
createdBefore as endDate,
|
createdBefore as endDate,
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
|
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
|
||||||
# for more information on how to write migrations for GitLab.
|
# for more information on how to write migrations for GitLab.
|
||||||
|
|
||||||
class CreateModelGeneratorTestFoos < Gitlab::Database::Migration[2.0]
|
class CreateModelGeneratorTestFoos < Gitlab::Database::Migration[2.1]
|
||||||
# When using the methods "add_concurrent_index" or "remove_concurrent_index"
|
# When using the methods "add_concurrent_index" or "remove_concurrent_index"
|
||||||
# you must disable the use of transactions
|
# you must disable the use of transactions
|
||||||
# as these methods can not run in an existing transaction.
|
# as these methods can not run in an existing transaction.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,333 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe Gitlab::Database::MigrationHelpers::AutomaticLockWritesOnTables,
|
||||||
|
:reestablished_active_record_base, query_analyzers: false do
|
||||||
|
using RSpec::Parameterized::TableSyntax
|
||||||
|
|
||||||
|
let(:schema_class) { Class.new(Gitlab::Database::Migration[2.1]) }
|
||||||
|
let(:gitlab_main_table_name) { :_test_gitlab_main_table }
|
||||||
|
let(:gitlab_ci_table_name) { :_test_gitlab_ci_table }
|
||||||
|
let(:gitlab_geo_table_name) { :_test_gitlab_geo_table }
|
||||||
|
let(:gitlab_shared_table_name) { :_test_table }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_feature_flags(automatic_lock_writes_on_table: true)
|
||||||
|
reconfigure_db_connection(model: ActiveRecord::Base, config_model: config_model)
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'does not lock writes on table' do |config_model|
|
||||||
|
let(:config_model) { config_model }
|
||||||
|
|
||||||
|
it 'allows deleting records from the table' do
|
||||||
|
allow_next_instance_of(Gitlab::Database::LockWritesManager) do |instance|
|
||||||
|
expect(instance).not_to receive(:lock_writes)
|
||||||
|
end
|
||||||
|
|
||||||
|
run_migration
|
||||||
|
|
||||||
|
expect do
|
||||||
|
migration_class.connection.execute("DELETE FROM #{table_name}")
|
||||||
|
end.not_to raise_error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'locks writes on table' do |config_model|
|
||||||
|
let(:config_model) { config_model }
|
||||||
|
|
||||||
|
it 'errors on deleting' do
|
||||||
|
allow_next_instance_of(Gitlab::Database::LockWritesManager) do |instance|
|
||||||
|
expect(instance).to receive(:lock_writes).and_call_original
|
||||||
|
end
|
||||||
|
|
||||||
|
run_migration
|
||||||
|
|
||||||
|
expect do
|
||||||
|
migration_class.connection.execute("DELETE FROM #{table_name}")
|
||||||
|
end.to raise_error(ActiveRecord::StatementInvalid, /is write protected/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when executing create_table migrations' do
|
||||||
|
let(:create_gitlab_main_table_migration_class) { create_table_migration(gitlab_main_table_name) }
|
||||||
|
let(:create_gitlab_ci_table_migration_class) { create_table_migration(gitlab_ci_table_name) }
|
||||||
|
let(:create_gitlab_shared_table_migration_class) { create_table_migration(gitlab_shared_table_name) }
|
||||||
|
|
||||||
|
context 'when single database' do
|
||||||
|
let(:config_model) { Gitlab::Database.database_base_models[:main] }
|
||||||
|
|
||||||
|
before do
|
||||||
|
skip_if_multiple_databases_are_setup
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not lock any newly created tables' do
|
||||||
|
allow_next_instance_of(Gitlab::Database::LockWritesManager) do |instance|
|
||||||
|
expect(instance).not_to receive(:lock_writes)
|
||||||
|
end
|
||||||
|
|
||||||
|
create_gitlab_main_table_migration_class.migrate(:up)
|
||||||
|
create_gitlab_ci_table_migration_class.migrate(:up)
|
||||||
|
create_gitlab_shared_table_migration_class.migrate(:up)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
create_gitlab_main_table_migration_class.connection.execute("DELETE FROM #{gitlab_main_table_name}")
|
||||||
|
create_gitlab_ci_table_migration_class.connection.execute("DELETE FROM #{gitlab_ci_table_name}")
|
||||||
|
create_gitlab_shared_table_migration_class.connection.execute("DELETE FROM #{gitlab_shared_table_name}")
|
||||||
|
end.not_to raise_error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when multiple databases' do
|
||||||
|
before do
|
||||||
|
skip_if_multiple_databases_not_setup
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:skip_automatic_lock_on_writes) { false }
|
||||||
|
let(:migration_class) { create_table_migration(table_name, skip_automatic_lock_on_writes) }
|
||||||
|
let(:run_migration) { migration_class.migrate(:up) }
|
||||||
|
|
||||||
|
context 'for creating a gitlab_main table' do
|
||||||
|
let(:table_name) { gitlab_main_table_name }
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:main]
|
||||||
|
it_behaves_like 'locks writes on table', Gitlab::Database.database_base_models[:ci]
|
||||||
|
|
||||||
|
context 'when table listed as a deleted table' do
|
||||||
|
before do
|
||||||
|
stub_const("Gitlab::Database::GitlabSchema::DELETED_TABLES", { table_name.to_s => :gitlab_main })
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:ci]
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the migration skips automatic locking of tables' do
|
||||||
|
let(:skip_automatic_lock_on_writes) { true }
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:ci]
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the SKIP_AUTOMATIC_LOCK_ON_WRITES feature flag is set' do
|
||||||
|
before do
|
||||||
|
stub_env('SKIP_AUTOMATIC_LOCK_ON_WRITES' => 'true')
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:ci]
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the automatic_lock_writes_on_table feature flag is disabled' do
|
||||||
|
before do
|
||||||
|
stub_feature_flags(automatic_lock_writes_on_table: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:ci]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for creating a gitlab_ci table' do
|
||||||
|
let(:table_name) { gitlab_ci_table_name }
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:ci]
|
||||||
|
it_behaves_like 'locks writes on table', Gitlab::Database.database_base_models[:main]
|
||||||
|
|
||||||
|
context 'when table listed as a deleted table' do
|
||||||
|
before do
|
||||||
|
stub_const("Gitlab::Database::GitlabSchema::DELETED_TABLES", { table_name.to_s => :gitlab_ci })
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:main]
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the migration skips automatic locking of tables' do
|
||||||
|
let(:skip_automatic_lock_on_writes) { true }
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:main]
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the SKIP_AUTOMATIC_LOCK_ON_WRITES feature flag is set' do
|
||||||
|
before do
|
||||||
|
stub_env('SKIP_AUTOMATIC_LOCK_ON_WRITES' => 'true')
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:main]
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the automatic_lock_writes_on_table feature flag is disabled' do
|
||||||
|
before do
|
||||||
|
stub_feature_flags(automatic_lock_writes_on_table: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:main]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for creating gitlab_shared table' do
|
||||||
|
let(:table_name) { gitlab_shared_table_name }
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:main]
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:ci]
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for creating a gitlab_geo table' do
|
||||||
|
before do
|
||||||
|
skip unless geo_configured?
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:table_name) { gitlab_geo_table_name }
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:geo]
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for creating an unknown gitlab_schema table' do
|
||||||
|
let(:table_name) { :foobar } # no gitlab_schema defined
|
||||||
|
let(:config_model) { Gitlab::Database.database_base_models[:main] }
|
||||||
|
|
||||||
|
it "raises an error about undefined gitlab_schema" do
|
||||||
|
expected_error_message = <<~ERROR
|
||||||
|
No gitlab_schema is defined for the table #{table_name}. Please consider
|
||||||
|
adding it to the file config 'lib/gitlab/database/gitlab_schemas.yml'
|
||||||
|
ERROR
|
||||||
|
|
||||||
|
expect { run_migration }.to raise_error(expected_error_message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when renaming a table' do
|
||||||
|
before do
|
||||||
|
skip_if_multiple_databases_not_setup
|
||||||
|
create_table_migration(old_table_name).migrate(:up) # create the table first before renaming it
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:migration_class) { rename_table_migration(old_table_name, table_name) }
|
||||||
|
let(:run_migration) { migration_class.migrate(:up) }
|
||||||
|
|
||||||
|
context 'when a gitlab_main table' do
|
||||||
|
let(:old_table_name) { gitlab_main_table_name }
|
||||||
|
let(:table_name) { :_test_gitlab_main_new_table }
|
||||||
|
let(:database_base_model) { Gitlab::Database.database_base_models[:main] }
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:main]
|
||||||
|
it_behaves_like 'locks writes on table', Gitlab::Database.database_base_models[:ci]
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a gitlab_ci table' do
|
||||||
|
let(:old_table_name) { gitlab_ci_table_name }
|
||||||
|
let(:table_name) { :_test_gitlab_ci_new_table }
|
||||||
|
let(:database_base_model) { Gitlab::Database.database_base_models[:ci] }
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:ci]
|
||||||
|
it_behaves_like 'locks writes on table', Gitlab::Database.database_base_models[:main]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when reversing drop_table migrations' do
|
||||||
|
let(:drop_gitlab_main_table_migration_class) { drop_table_migration(gitlab_main_table_name) }
|
||||||
|
let(:drop_gitlab_ci_table_migration_class) { drop_table_migration(gitlab_ci_table_name) }
|
||||||
|
let(:drop_gitlab_shared_table_migration_class) { drop_table_migration(gitlab_shared_table_name) }
|
||||||
|
|
||||||
|
context 'when single database' do
|
||||||
|
let(:config_model) { Gitlab::Database.database_base_models[:main] }
|
||||||
|
|
||||||
|
before do
|
||||||
|
skip_if_multiple_databases_are_setup
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not lock any newly created tables' do
|
||||||
|
allow_next_instance_of(Gitlab::Database::LockWritesManager) do |instance|
|
||||||
|
expect(instance).not_to receive(:lock_writes)
|
||||||
|
end
|
||||||
|
|
||||||
|
drop_gitlab_main_table_migration_class.connection.execute("CREATE TABLE #{gitlab_main_table_name}()")
|
||||||
|
drop_gitlab_ci_table_migration_class.connection.execute("CREATE TABLE #{gitlab_ci_table_name}()")
|
||||||
|
drop_gitlab_shared_table_migration_class.connection.execute("CREATE TABLE #{gitlab_shared_table_name}()")
|
||||||
|
|
||||||
|
drop_gitlab_main_table_migration_class.migrate(:up)
|
||||||
|
drop_gitlab_ci_table_migration_class.migrate(:up)
|
||||||
|
drop_gitlab_shared_table_migration_class.migrate(:up)
|
||||||
|
|
||||||
|
drop_gitlab_main_table_migration_class.migrate(:down)
|
||||||
|
drop_gitlab_ci_table_migration_class.migrate(:down)
|
||||||
|
drop_gitlab_shared_table_migration_class.migrate(:down)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
drop_gitlab_main_table_migration_class.connection.execute("DELETE FROM #{gitlab_main_table_name}")
|
||||||
|
drop_gitlab_ci_table_migration_class.connection.execute("DELETE FROM #{gitlab_ci_table_name}")
|
||||||
|
drop_gitlab_shared_table_migration_class.connection.execute("DELETE FROM #{gitlab_shared_table_name}")
|
||||||
|
end.not_to raise_error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when multiple databases' do
|
||||||
|
before do
|
||||||
|
skip_if_multiple_databases_not_setup
|
||||||
|
migration_class.connection.execute("CREATE TABLE #{table_name}()")
|
||||||
|
migration_class.migrate(:up)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:migration_class) { drop_table_migration(table_name) }
|
||||||
|
let(:run_migration) { migration_class.migrate(:down) }
|
||||||
|
|
||||||
|
context 'for re-creating a gitlab_main table' do
|
||||||
|
let(:table_name) { gitlab_main_table_name }
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:main]
|
||||||
|
it_behaves_like 'locks writes on table', Gitlab::Database.database_base_models[:ci]
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for re-creating a gitlab_ci table' do
|
||||||
|
let(:table_name) { gitlab_ci_table_name }
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:ci]
|
||||||
|
it_behaves_like 'locks writes on table', Gitlab::Database.database_base_models[:main]
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for re-creating a gitlab_shared table' do
|
||||||
|
let(:table_name) { gitlab_shared_table_name }
|
||||||
|
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:main]
|
||||||
|
it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:ci]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_table_migration(table_name, skip_lock_on_writes = false)
|
||||||
|
migration_class = Class.new(schema_class) do
|
||||||
|
class << self; attr_accessor :table_name; end
|
||||||
|
def change
|
||||||
|
create_table self.class.table_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
migration_class.skip_automatic_lock_on_writes = skip_lock_on_writes
|
||||||
|
migration_class.tap { |klass| klass.table_name = table_name }
|
||||||
|
end
|
||||||
|
|
||||||
|
def rename_table_migration(old_table_name, new_table_name)
|
||||||
|
migration_class = Class.new(schema_class) do
|
||||||
|
class << self; attr_accessor :old_table_name, :new_table_name; end
|
||||||
|
def change
|
||||||
|
rename_table self.class.old_table_name, self.class.new_table_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
migration_class.tap do |klass|
|
||||||
|
klass.old_table_name = old_table_name
|
||||||
|
klass.new_table_name = new_table_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def drop_table_migration(table_name)
|
||||||
|
migration_class = Class.new(schema_class) do
|
||||||
|
class << self; attr_accessor :table_name; end
|
||||||
|
def change
|
||||||
|
drop_table(self.class.table_name) {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
migration_class.tap { |klass| klass.table_name = table_name }
|
||||||
|
end
|
||||||
|
|
||||||
|
def geo_configured?
|
||||||
|
!!ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: 'geo')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -14,7 +14,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::RestrictGitlabSchema, query_a
|
||||||
|
|
||||||
describe '#restrict_gitlab_migration' do
|
describe '#restrict_gitlab_migration' do
|
||||||
it 'invalid schema raises exception' do
|
it 'invalid schema raises exception' do
|
||||||
expect { schema_class.restrict_gitlab_migration gitlab_schema: :gitlab_non_exisiting }
|
expect { schema_class.restrict_gitlab_migration gitlab_schema: :gitlab_non_existing }
|
||||||
.to raise_error /Unknown 'gitlab_schema:/
|
.to raise_error /Unknown 'gitlab_schema:/
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -102,7 +102,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::RestrictGitlabSchema, query_a
|
||||||
"does add index to projects in gitlab_main and gitlab_ci" => {
|
"does add index to projects in gitlab_main and gitlab_ci" => {
|
||||||
migration: ->(klass) do
|
migration: ->(klass) do
|
||||||
def change
|
def change
|
||||||
# Due to running in transactin we cannot use `add_concurrent_index`
|
# Due to running in transaction we cannot use `add_concurrent_index`
|
||||||
add_index :projects, :hidden
|
add_index :projects, :hidden
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,15 @@ RSpec.describe Gitlab::Database::SchemaCleaner do
|
||||||
expect(subject).not_to match(/public\.\w+/)
|
expect(subject).not_to match(/public\.\w+/)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'cleans up all the gitlab_schema_prevent_write table triggers' do
|
||||||
|
expect(subject).not_to match(/CREATE TRIGGER gitlab_schema_write_trigger_for_\w+/)
|
||||||
|
expect(subject).not_to match(/FOR EACH STATEMENT EXECUTE FUNCTION gitlab_schema_prevent_write/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'keeps the lock_writes trigger functions' do
|
||||||
|
expect(subject).to match(/CREATE FUNCTION gitlab_schema_prevent_write/)
|
||||||
|
end
|
||||||
|
|
||||||
it 'cleans up the full schema as expected (blackbox test with example)' do
|
it 'cleans up the full schema as expected (blackbox test with example)' do
|
||||||
expected_schema = fixture_file(File.join('gitlab', 'database', 'structure_example_cleaned.sql'))
|
expected_schema = fixture_file(File.join('gitlab', 'database', 'structure_example_cleaned.sql'))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -345,24 +345,6 @@ RSpec.describe User do
|
||||||
context 'check_password_weakness' do
|
context 'check_password_weakness' do
|
||||||
let(:weak_password) { "qwertyuiop" }
|
let(:weak_password) { "qwertyuiop" }
|
||||||
|
|
||||||
context 'when feature flag is disabled' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(block_weak_passwords: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not add an error when password is weak' do
|
|
||||||
expect(Security::WeakPasswords).not_to receive(:weak_for_user?)
|
|
||||||
|
|
||||||
user.password = weak_password
|
|
||||||
expect(user).to be_valid
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when feature flag is enabled' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(block_weak_passwords: true)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'checks for password weakness when password changes' do
|
it 'checks for password weakness when password changes' do
|
||||||
expect(Security::WeakPasswords).to receive(:weak_for_user?)
|
expect(Security::WeakPasswords).to receive(:weak_for_user?)
|
||||||
.with(weak_password, user).and_call_original
|
.with(weak_password, user).and_call_original
|
||||||
|
|
@ -393,7 +375,6 @@ RSpec.describe User do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
describe 'name' do
|
describe 'name' do
|
||||||
it { is_expected.to validate_presence_of(:name) }
|
it { is_expected.to validate_presence_of(:name) }
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ require_relative '../../../../rubocop/cop/migration/versioned_migration_class'
|
||||||
RSpec.describe RuboCop::Cop::Migration::VersionedMigrationClass do
|
RSpec.describe RuboCop::Cop::Migration::VersionedMigrationClass do
|
||||||
let(:migration) do
|
let(:migration) do
|
||||||
<<~SOURCE
|
<<~SOURCE
|
||||||
class TestMigration < Gitlab::Database::Migration[1.0]
|
class TestMigration < Gitlab::Database::Migration[2.1]
|
||||||
def up
|
def up
|
||||||
execute 'select 1'
|
execute 'select 1'
|
||||||
end
|
end
|
||||||
|
|
@ -49,23 +49,23 @@ RSpec.describe RuboCop::Cop::Migration::VersionedMigrationClass do
|
||||||
it 'adds an offence if inheriting from ActiveRecord::Migration' do
|
it 'adds an offence if inheriting from ActiveRecord::Migration' do
|
||||||
expect_offense(<<~RUBY)
|
expect_offense(<<~RUBY)
|
||||||
class MyMigration < ActiveRecord::Migration[6.1]
|
class MyMigration < ActiveRecord::Migration[6.1]
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't inherit from ActiveRecord::Migration but use Gitlab::Database::Migration[1.0] instead. See https://docs.gitlab.com/ee/development/migration_style_guide.html#migration-helpers-and-versioning.
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't inherit from ActiveRecord::Migration but use Gitlab::Database::Migration[2.1] instead. See https://docs.gitlab.com/ee/development/migration_style_guide.html#migration-helpers-and-versioning.
|
||||||
end
|
end
|
||||||
RUBY
|
RUBY
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'adds an offence if including Gitlab::Database::MigrationHelpers directly' do
|
it 'adds an offence if including Gitlab::Database::MigrationHelpers directly' do
|
||||||
expect_offense(<<~RUBY)
|
expect_offense(<<~RUBY)
|
||||||
class MyMigration < Gitlab::Database::Migration[1.0]
|
class MyMigration < Gitlab::Database::Migration[2.1]
|
||||||
include Gitlab::Database::MigrationHelpers
|
include Gitlab::Database::MigrationHelpers
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't include migration helper modules directly. Inherit from Gitlab::Database::Migration[1.0] instead. See https://docs.gitlab.com/ee/development/migration_style_guide.html#migration-helpers-and-versioning.
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't include migration helper modules directly. Inherit from Gitlab::Database::Migration[2.1] instead. See https://docs.gitlab.com/ee/development/migration_style_guide.html#migration-helpers-and-versioning.
|
||||||
end
|
end
|
||||||
RUBY
|
RUBY
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'excludes ActiveRecord classes defined inside the migration' do
|
it 'excludes ActiveRecord classes defined inside the migration' do
|
||||||
expect_no_offenses(<<~RUBY)
|
expect_no_offenses(<<~RUBY)
|
||||||
class TestMigration < Gitlab::Database::Migration[1.0]
|
class TestMigration < Gitlab::Database::Migration[2.1]
|
||||||
class TestModel < ApplicationRecord
|
class TestModel < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1125,10 +1125,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.11.0.tgz#91e8e25583cddef48c0c79175203e5b0a4eaa519"
|
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.11.0.tgz#91e8e25583cddef48c0c79175203e5b0a4eaa519"
|
||||||
integrity sha512-1cJu1WXPoOHfGgv5fT3nmA9cgAQ3U1Fm/oMSVYUgBxU35R0I8W704GMLsIZwBuQ/S/Ow7WLwIkoOhLb/spNKPg==
|
integrity sha512-1cJu1WXPoOHfGgv5fT3nmA9cgAQ3U1Fm/oMSVYUgBxU35R0I8W704GMLsIZwBuQ/S/Ow7WLwIkoOhLb/spNKPg==
|
||||||
|
|
||||||
"@gitlab/ui@49.11.2":
|
"@gitlab/ui@50.1.2":
|
||||||
version "49.11.2"
|
version "50.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-49.11.2.tgz#290bba7a3d4682365ad81747cf54a2f9927526c1"
|
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-50.1.2.tgz#d24100b6d6fc77c7708d9139f09e2142b1292d31"
|
||||||
integrity sha512-qu5qcl+4niYBCPIZS9ZU0i1h/IGL4ZOp4hDsEAIUFGJg9Sp0TBmwdjwKJQbvnexDS3xs1eSBzi+kQ57H+c9wQQ==
|
integrity sha512-bRzF9SkDGY2WrmIuFriFLyRMym2ydAeJB71FCXfHvhei3EWAeaiZv5oEB/a4oMN8nmt0rt4GrPQ5PpGiQKoKfQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@popperjs/core" "^2.11.2"
|
"@popperjs/core" "^2.11.2"
|
||||||
bootstrap-vue "2.20.1"
|
bootstrap-vue "2.20.1"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue