Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
18ffa5e881
commit
f9cda7671c
25 changed files with 277 additions and 113 deletions
|
@ -109,8 +109,10 @@ class GfmAutoComplete {
|
||||||
tpl += ' <small class="params"><%- params.join(" ") %></small>';
|
tpl += ' <small class="params"><%- params.join(" ") %></small>';
|
||||||
}
|
}
|
||||||
if (value.warning && value.icon && value.icon === 'confidential') {
|
if (value.warning && value.icon && value.icon === 'confidential') {
|
||||||
tpl +=
|
tpl += `<small class="description gl-display-flex gl-align-items-center">${spriteIcon(
|
||||||
'<small class="description"><em><i class="fa fa-eye-slash" aria-hidden="true"/><%- warning %></em></small>';
|
'eye-slash',
|
||||||
|
's16 gl-mr-2',
|
||||||
|
)}<em><%- warning %></em></small>`;
|
||||||
} else if (value.warning) {
|
} else if (value.warning) {
|
||||||
tpl += '<small class="description"><em><%- warning %></em></small>';
|
tpl += '<small class="description"><em><%- warning %></em></small>';
|
||||||
} else if (value.description !== '') {
|
} else if (value.description !== '') {
|
||||||
|
|
|
@ -119,10 +119,12 @@ export default {
|
||||||
<template v-if="showJiraIssuesIntegration">
|
<template v-if="showJiraIssuesIntegration">
|
||||||
<gl-form-group
|
<gl-form-group
|
||||||
:label="s__('JiraService|Jira project key')"
|
:label="s__('JiraService|Jira project key')"
|
||||||
|
label-for="service_project_key"
|
||||||
:invalid-feedback="__('This field is required.')"
|
:invalid-feedback="__('This field is required.')"
|
||||||
:state="validProjectKey"
|
:state="validProjectKey"
|
||||||
>
|
>
|
||||||
<gl-form-input
|
<gl-form-input
|
||||||
|
id="service_project_key"
|
||||||
v-model="projectKey"
|
v-model="projectKey"
|
||||||
name="service[project_key]"
|
name="service[project_key]"
|
||||||
:placeholder="s__('JiraService|e.g. AB')"
|
:placeholder="s__('JiraService|e.g. AB')"
|
||||||
|
|
|
@ -230,13 +230,15 @@ export default {
|
||||||
<div class="flex-grow-1">
|
<div class="flex-grow-1">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<span class="issue-title-text">
|
<span class="issue-title-text">
|
||||||
<i
|
<gl-icon
|
||||||
v-if="issuable.confidential"
|
v-if="issuable.confidential"
|
||||||
v-gl-tooltip
|
v-gl-tooltip
|
||||||
class="fa fa-eye-slash"
|
name="eye-slash"
|
||||||
|
class="gl-vertical-align-text-bottom"
|
||||||
|
:size="16"
|
||||||
:title="$options.confidentialTooltipText"
|
:title="$options.confidentialTooltipText"
|
||||||
:aria-label="$options.confidentialTooltipText"
|
:aria-label="$options.confidentialTooltipText"
|
||||||
></i>
|
/>
|
||||||
<gl-link
|
<gl-link
|
||||||
:href="issuable.web_url"
|
:href="issuable.web_url"
|
||||||
:target="isJiraIssue ? '_blank' : null"
|
:target="isJiraIssue ? '_blank' : null"
|
||||||
|
|
|
@ -41,7 +41,7 @@ module IssuesHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def confidential_icon(issue)
|
def confidential_icon(issue)
|
||||||
icon('eye-slash') if issue.confidential?
|
sprite_icon('eye-slash', size: 16, css_class: 'gl-vertical-align-text-bottom') if issue.confidential?
|
||||||
end
|
end
|
||||||
|
|
||||||
def award_user_list(awards, current_user, limit: 10)
|
def award_user_list(awards, current_user, limit: 10)
|
||||||
|
|
|
@ -15,7 +15,7 @@ class SnippetInputAction
|
||||||
|
|
||||||
validates :action, inclusion: { in: ACTIONS, message: "%{value} is not a valid action" }
|
validates :action, inclusion: { in: ACTIONS, message: "%{value} is not a valid action" }
|
||||||
validates :previous_path, presence: true, if: :move_action?
|
validates :previous_path, presence: true, if: :move_action?
|
||||||
validates :file_path, presence: true
|
validates :file_path, presence: true, unless: :create_action?
|
||||||
validates :content, presence: true, if: -> (action) { action.create_action? || action.update_action? }
|
validates :content, presence: true, if: -> (action) { action.create_action? || action.update_action? }
|
||||||
validate :ensure_same_file_path_and_previous_path, if: :update_action?
|
validate :ensure_same_file_path_and_previous_path, if: :update_action?
|
||||||
validate :ensure_different_file_path_and_previous_path, if: :move_action?
|
validate :ensure_different_file_path_and_previous_path, if: :move_action?
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
= _('Admin Area')
|
= _('Admin Area')
|
||||||
%ul.sidebar-top-level-items{ data: { qa_selector: 'admin_sidebar_overview_submenu_content' } }
|
%ul.sidebar-top-level-items{ data: { qa_selector: 'admin_sidebar_overview_submenu_content' } }
|
||||||
= nav_link(controller: %w(dashboard admin admin/projects users groups jobs runners gitaly_servers), html_options: {class: 'home'}) do
|
= nav_link(controller: %w(dashboard admin admin/projects users groups jobs runners gitaly_servers), html_options: {class: 'home'}) do
|
||||||
= link_to admin_root_path, class: 'shortcuts-tree' do
|
= link_to admin_root_path do
|
||||||
.nav-icon-container
|
.nav-icon-container
|
||||||
= sprite_icon('overview')
|
= sprite_icon('overview')
|
||||||
%span.nav-item-name
|
%span.nav-item-name
|
||||||
|
|
|
@ -362,7 +362,7 @@
|
||||||
|
|
||||||
- if project_nav_tab? :settings
|
- if project_nav_tab? :settings
|
||||||
= nav_link(path: sidebar_settings_paths) do
|
= nav_link(path: sidebar_settings_paths) do
|
||||||
= link_to edit_project_path(@project), class: 'shortcuts-tree' do
|
= link_to edit_project_path(@project) do
|
||||||
.nav-icon-container
|
.nav-icon-container
|
||||||
= sprite_icon('settings')
|
= sprite_icon('settings')
|
||||||
%span.nav-item-name.qa-settings-item#js-onboarding-settings-link
|
%span.nav-item-name.qa-settings-item#js-onboarding-settings-link
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Replace fa-eyes-slash icons with GitLab SVG eye-slash icon
|
||||||
|
merge_request: 36602
|
||||||
|
author:
|
||||||
|
type: performance
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Remove file_path validation in snippet create action
|
||||||
|
merge_request: 36809
|
||||||
|
author:
|
||||||
|
type: changed
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Parameterize PG deprecation notice
|
||||||
|
merge_request: 35271
|
||||||
|
author:
|
||||||
|
type: changed
|
|
@ -2831,7 +2831,12 @@ be available for download in the GitLab UI.
|
||||||
|
|
||||||
Paths are relative to the project directory (`$CI_PROJECT_DIR`) and can't directly
|
Paths are relative to the project directory (`$CI_PROJECT_DIR`) and can't directly
|
||||||
link outside it. Wildcards can be used that follow the [glob](https://en.wikipedia.org/wiki/Glob_(programming))
|
link outside it. Wildcards can be used that follow the [glob](https://en.wikipedia.org/wiki/Glob_(programming))
|
||||||
patterns and [`filepath.Match`](https://golang.org/pkg/path/filepath/#Match).
|
patterns and:
|
||||||
|
|
||||||
|
- In [GitLab Runner 13.0](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620) and later,
|
||||||
|
[`doublestar.Glob`](https://pkg.go.dev/github.com/bmatcuk/doublestar@v1.2.2?tab=doc#Match).
|
||||||
|
- In GitLab Runner 12.10 and earlier,
|
||||||
|
[`filepath.Match`](https://pkg.go.dev/path/filepath/#Match).
|
||||||
|
|
||||||
To restrict which jobs a specific job will fetch artifacts from, see [dependencies](#dependencies).
|
To restrict which jobs a specific job will fetch artifacts from, see [dependencies](#dependencies).
|
||||||
|
|
||||||
|
|
|
@ -201,6 +201,72 @@ By following this pattern we guarantee:
|
||||||
1. All data in the application follows the same lifecycle pattern
|
1. All data in the application follows the same lifecycle pattern
|
||||||
1. Unit tests are easier
|
1. Unit tests are easier
|
||||||
|
|
||||||
|
#### Updating complex state
|
||||||
|
|
||||||
|
Sometimes, especially when the state is complex, is really hard to traverse the state to precisely update what the mutation needs to update.
|
||||||
|
Ideally a `vuex` state should be as normalized/decoupled as possible but this is not always the case.
|
||||||
|
|
||||||
|
It's important to remember that the code is much easier to read and maintain when the `portion of the mutated state` is selected and mutated in the mutation itself.
|
||||||
|
|
||||||
|
Given this state:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export default () => ({
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'my_issue',
|
||||||
|
closed: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'another_issue',
|
||||||
|
closed: false,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
It may be tempting to write a mutation like so:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Bad
|
||||||
|
export default {
|
||||||
|
[types.MARK_AS_CLOSED](state, item) {
|
||||||
|
Object.assign(item, {closed: true})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
While this approach works it has several dependencies:
|
||||||
|
|
||||||
|
- Correct selection of `item` in the component/action.
|
||||||
|
- The `item` property is already declared in the `closed` state.
|
||||||
|
- A new `confidential` property would not be reactive.
|
||||||
|
- Noting that `item` is referenced by `items`
|
||||||
|
|
||||||
|
A mutation written like this is harder to maintain and more error prone. We should rather write a mutation like this:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Good
|
||||||
|
export default {
|
||||||
|
[types.MARK_AS_CLOSED](state, itemId) {
|
||||||
|
const item = state.items.find(i => i.id == itemId);
|
||||||
|
Vue.set(item, 'closed', true)
|
||||||
|
|
||||||
|
state.items.splice(index, 1, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This approach is better because:
|
||||||
|
|
||||||
|
- It selects and updates the state in the mutation, which is more maintainable.
|
||||||
|
- It has no external dependencies, if the correct `itemId` is passed the state is correctly updated.
|
||||||
|
- It does not have reactivity caveats, as we generate a new `item` to avoid coupling to the initial state.
|
||||||
|
|
||||||
|
A mutation written like this is easier to maintain. In addition, we avoid errors due to the limitation of the reactivity system.
|
||||||
|
|
||||||
### `getters.js`
|
### `getters.js`
|
||||||
|
|
||||||
Sometimes we may need to get derived state based on store state, like filtering for a specific prop.
|
Sometimes we may need to get derived state based on store state, like filtering for a specific prop.
|
||||||
|
|
|
@ -12,7 +12,7 @@ what environments to run tests against using the `only` metadata.
|
||||||
| `domain` | Set the domain matcher | `String` |
|
| `domain` | Set the domain matcher | `String` |
|
||||||
| `production` | Match against production | `Static` |
|
| `production` | Match against production | `Static` |
|
||||||
|
|
||||||
WARNING: **Be advised:**
|
CAUTION: **Caution:**
|
||||||
You cannot specify `:production` and `{ <switch>: 'value' }` simultaneously.
|
You cannot specify `:production` and `{ <switch>: 'value' }` simultaneously.
|
||||||
These options are mutually exclusive. If you want to specify production, you
|
These options are mutually exclusive. If you want to specify production, you
|
||||||
can control the `tld` and `domain` independently.
|
can control the `tld` and `domain` independently.
|
||||||
|
|
|
@ -61,7 +61,7 @@ for. The rollout strategy will have no effect if the environment spec is disable
|
||||||
It can be set to:
|
It can be set to:
|
||||||
|
|
||||||
- All users
|
- All users
|
||||||
- [Percent rollout (logged in users)](#percent-rollout-logged-in-users)
|
- [Percent of users](#percent-of-users)
|
||||||
- Optionally, you can click the **Include additional user IDs** checkbox and add a list
|
- Optionally, you can click the **Include additional user IDs** checkbox and add a list
|
||||||
of specific users IDs to enable the feature for.
|
of specific users IDs to enable the feature for.
|
||||||
- [User IDs](#user-ids)
|
- [User IDs](#user-ids)
|
||||||
|
@ -82,9 +82,9 @@ for granular feature flag controls. GitLab Feature Flags can have multiple strat
|
||||||
and the supported strategies are:
|
and the supported strategies are:
|
||||||
|
|
||||||
- [All users](#all-users)
|
- [All users](#all-users)
|
||||||
- [Percent rollout (logged in users)](#percent-rollout-logged-in-users)
|
- [Percent of Users](#percent-of-users)
|
||||||
- [User IDs](#user-ids)
|
- [User IDs](#user-ids)
|
||||||
- [List](#list)
|
- [User List](#user-list)
|
||||||
|
|
||||||
Strategies can be added to feature flags when [creating a feature flag](#create-a-feature-flag),
|
Strategies can be added to feature flags when [creating a feature flag](#create-a-feature-flag),
|
||||||
or by editing an existing feature flag after creation by navigating to **Operations > Feature Flags**
|
or by editing an existing feature flag after creation by navigating to **Operations > Feature Flags**
|
||||||
|
@ -95,7 +95,7 @@ and clicking **{pencil}** (edit).
|
||||||
Enables the feature for all users. It uses the [`default`](https://unleash.github.io/docs/activation_strategy#default)
|
Enables the feature for all users. It uses the [`default`](https://unleash.github.io/docs/activation_strategy#default)
|
||||||
Unleash activation strategy.
|
Unleash activation strategy.
|
||||||
|
|
||||||
### Percent rollout (logged in users)
|
### Percent of Users
|
||||||
|
|
||||||
Enables the feature for a percentage of authenticated users. It uses the
|
Enables the feature for a percentage of authenticated users. It uses the
|
||||||
[`gradualRolloutUserId`](https://unleash.github.io/docs/activation_strategy#gradualrolloutuserid)
|
[`gradualRolloutUserId`](https://unleash.github.io/docs/activation_strategy#gradualrolloutuserid)
|
||||||
|
@ -130,7 +130,7 @@ CAUTION: **Caution:**
|
||||||
The Unleash client **must** be given a user ID for the feature to be enabled for
|
The Unleash client **must** be given a user ID for the feature to be enabled for
|
||||||
target users. See the [Ruby example](#ruby-application-example) below.
|
target users. See the [Ruby example](#ruby-application-example) below.
|
||||||
|
|
||||||
### List
|
### User List
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35930) in GitLab 13.1.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35930) in GitLab 13.1.
|
||||||
|
|
||||||
|
@ -165,6 +165,7 @@ to disable a feature flag for a specific environment:
|
||||||
1. Navigate to your project's **Operations > Feature Flags**.
|
1. Navigate to your project's **Operations > Feature Flags**.
|
||||||
1. For the feature flag you want to disable, click the Pencil icon.
|
1. For the feature flag you want to disable, click the Pencil icon.
|
||||||
1. To disable the flag:
|
1. To disable the flag:
|
||||||
|
|
||||||
- In GitLab 13.0 and earlier: Slide the Status toggle for the environment. Or, to delete the
|
- In GitLab 13.0 and earlier: Slide the Status toggle for the environment. Or, to delete the
|
||||||
environment spec, on the right, click the **Remove (X)** icon.
|
environment spec, on the right, click the **Remove (X)** icon.
|
||||||
- In GitLab 13.1 and later: For each strategy it applies to, under **Environments**, delete the environment.
|
- In GitLab 13.1 and later: For each strategy it applies to, under **Environments**, delete the environment.
|
||||||
|
|
|
@ -584,9 +584,9 @@ is used to forward logs to an [Elastic cluster](https://gitlab.com/gitlab-com/ru
|
||||||
|
|
||||||
You can view more information in our runbooks such as:
|
You can view more information in our runbooks such as:
|
||||||
|
|
||||||
- A [detailed list of what we're logging](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#what-are-we-logging)
|
- A [detailed list of what we're logging](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging#what-are-we-logging)
|
||||||
- Our [current log retention policies](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#retention)
|
- Our [current log retention policies](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging#retention)
|
||||||
- A [diagram of our logging infrastructure](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#logging-infrastructure-overview)
|
- A [diagram of our logging infrastructure](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging#logging-infrastructure-overview)
|
||||||
|
|
||||||
## GitLab.com at scale
|
## GitLab.com at scale
|
||||||
|
|
||||||
|
|
|
@ -5,22 +5,43 @@ module Gitlab
|
||||||
module ExternalDatabaseChecker
|
module ExternalDatabaseChecker
|
||||||
extend self
|
extend self
|
||||||
|
|
||||||
# DB is considered deprecated if it is below version 11
|
|
||||||
def db_version_deprecated?
|
|
||||||
Gitlab::Database.version.to_f < 11
|
|
||||||
end
|
|
||||||
|
|
||||||
def check
|
def check
|
||||||
return [] unless db_version_deprecated?
|
notices = []
|
||||||
|
|
||||||
[
|
unless Gitlab::Database.postgresql_minimum_supported_version?
|
||||||
{
|
notices <<
|
||||||
type: 'warning',
|
{
|
||||||
message: _('Note that PostgreSQL 11 will become the minimum required PostgreSQL version in GitLab 13.0 (May 2020). '\
|
type: 'warning',
|
||||||
'PostgreSQL 9.6 and PostgreSQL 10 will no longer be supported in GitLab 13.0. '\
|
message: _('You are using PostgreSQL %{pg_version_current}, but PostgreSQL ' \
|
||||||
'Please consider upgrading your PostgreSQL version (%{db_version}) soon.') % { db_version: Gitlab::Database.version.to_s }
|
'%{pg_version_minimum} is required for this version of GitLab. ' \
|
||||||
}
|
'Please upgrade your environment to a supported PostgreSQL version, ' \
|
||||||
]
|
'see %{pg_requirements_url} for details.') % {
|
||||||
|
pg_version_current: Gitlab::Database.version,
|
||||||
|
pg_version_minimum: Gitlab::Database::MINIMUM_POSTGRES_VERSION,
|
||||||
|
pg_requirements_url: '<a href="https://docs.gitlab.com/ee/install/requirements.html#database">database requirements</a>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
if Gitlab::Database.postgresql_upcoming_deprecation?
|
||||||
|
upcoming_deprecation = Gitlab::Database::UPCOMING_POSTGRES_VERSION_DETAILS
|
||||||
|
|
||||||
|
notices <<
|
||||||
|
{
|
||||||
|
type: 'warning',
|
||||||
|
message: _('Note that PostgreSQL %{pg_version_upcoming} will become the minimum required ' \
|
||||||
|
'version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please ' \
|
||||||
|
'consider upgrading your environment to a supported PostgreSQL version soon, ' \
|
||||||
|
'see <a href="%{pg_version_upcoming_url}">the related epic</a> for details.') % {
|
||||||
|
pg_version_upcoming: upcoming_deprecation[:pg_version_minimum],
|
||||||
|
gl_version_upcoming: upcoming_deprecation[:gl_version],
|
||||||
|
gl_version_upcoming_date: upcoming_deprecation[:gl_version_date],
|
||||||
|
pg_version_upcoming_url: upcoming_deprecation[:url]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
notices
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,8 +4,20 @@ module Gitlab
|
||||||
module Database
|
module Database
|
||||||
include Gitlab::Metrics::Methods
|
include Gitlab::Metrics::Methods
|
||||||
|
|
||||||
|
# Minimum PostgreSQL version requirement per documentation:
|
||||||
|
# https://docs.gitlab.com/ee/install/requirements.html#postgresql-requirements
|
||||||
MINIMUM_POSTGRES_VERSION = 11
|
MINIMUM_POSTGRES_VERSION = 11
|
||||||
|
|
||||||
|
# Upcoming PostgreSQL version requirements
|
||||||
|
# Allows a soft warning about an upcoming minimum version requirement
|
||||||
|
# so administrators can prepare to upgrade
|
||||||
|
UPCOMING_POSTGRES_VERSION_DETAILS = {
|
||||||
|
gl_version: '13.6.0',
|
||||||
|
gl_version_date: 'November 2020',
|
||||||
|
pg_version_minimum: 12,
|
||||||
|
url: 'https://gitlab.com/groups/gitlab-org/-/epics/2374'
|
||||||
|
}.freeze
|
||||||
|
|
||||||
# https://www.postgresql.org/docs/9.2/static/datatype-numeric.html
|
# https://www.postgresql.org/docs/9.2/static/datatype-numeric.html
|
||||||
MAX_INT_VALUE = 2147483647
|
MAX_INT_VALUE = 2147483647
|
||||||
|
|
||||||
|
@ -103,6 +115,10 @@ module Gitlab
|
||||||
version.to_f >= MINIMUM_POSTGRES_VERSION
|
version.to_f >= MINIMUM_POSTGRES_VERSION
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.postgresql_upcoming_deprecation?
|
||||||
|
version.to_f < UPCOMING_POSTGRES_VERSION_DETAILS[:pg_version_minimum]
|
||||||
|
end
|
||||||
|
|
||||||
def self.check_postgres_version_and_print_warning
|
def self.check_postgres_version_and_print_warning
|
||||||
return if Gitlab::Database.postgresql_minimum_supported_version?
|
return if Gitlab::Database.postgresql_minimum_supported_version?
|
||||||
return if Gitlab::Runtime.rails_runner?
|
return if Gitlab::Runtime.rails_runner?
|
||||||
|
|
|
@ -15820,7 +15820,7 @@ msgstr ""
|
||||||
msgid "Note parameters are invalid: %{errors}"
|
msgid "Note parameters are invalid: %{errors}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Note that PostgreSQL 11 will become the minimum required PostgreSQL version in GitLab 13.0 (May 2020). PostgreSQL 9.6 and PostgreSQL 10 will no longer be supported in GitLab 13.0. Please consider upgrading your PostgreSQL version (%{db_version}) soon."
|
msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
|
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
|
||||||
|
@ -16707,7 +16707,7 @@ msgstr ""
|
||||||
msgid "People without permission will never get a notification."
|
msgid "People without permission will never get a notification."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Percent rollout (logged in users)"
|
msgid "Percent of users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Percentage"
|
msgid "Percentage"
|
||||||
|
@ -25502,6 +25502,9 @@ msgstr ""
|
||||||
msgid "User IDs"
|
msgid "User IDs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "User List"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "User Lists can only be created and modified with %{linkStart}the API%{linkEnd}"
|
msgid "User Lists can only be created and modified with %{linkStart}the API%{linkEnd}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -26648,6 +26651,9 @@ msgstr ""
|
||||||
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
|
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "You are using PostgreSQL %{pg_version_current}, but PostgreSQL %{pg_version_minimum} is required for this version of GitLab. Please upgrade your environment to a supported PostgreSQL version, see %{pg_requirements_url} for details."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
|
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'securerandom'
|
||||||
|
|
||||||
module QA
|
module QA
|
||||||
module Page
|
module Page
|
||||||
module Project
|
module Project
|
||||||
|
@ -60,7 +62,7 @@ module QA
|
||||||
def duplicate_dashboard(save_as = 'test_duplication.yml', commit_option = 'Commit to master branch')
|
def duplicate_dashboard(save_as = 'test_duplication.yml', commit_option = 'Commit to master branch')
|
||||||
click_element :dashboards_filter_dropdown
|
click_element :dashboards_filter_dropdown
|
||||||
click_on 'Duplicate dashboard'
|
click_on 'Duplicate dashboard'
|
||||||
fill_element :duplicate_dashboard_filename_field, save_as
|
fill_element :duplicate_dashboard_filename_field, "#{SecureRandom.hex(8)}-#{save_as}"
|
||||||
choose commit_option
|
choose commit_option
|
||||||
within('.modal-content') { click_button(class: 'btn-success') }
|
within('.modal-content') { click_button(class: 'btn-success') }
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { shallowMount } from '@vue/test-utils';
|
import { shallowMount } from '@vue/test-utils';
|
||||||
import { GlSprintf, GlLabel } from '@gitlab/ui';
|
import { GlSprintf, GlLabel, GlIcon } from '@gitlab/ui';
|
||||||
import { TEST_HOST } from 'helpers/test_constants';
|
import { TEST_HOST } from 'helpers/test_constants';
|
||||||
import { trimText } from 'helpers/text_helper';
|
import { trimText } from 'helpers/text_helper';
|
||||||
import initUserPopovers from '~/user_popovers';
|
import initUserPopovers from '~/user_popovers';
|
||||||
|
@ -75,7 +75,9 @@ describe('Issuable component', () => {
|
||||||
window.Date = DateOrig;
|
window.Date = DateOrig;
|
||||||
});
|
});
|
||||||
|
|
||||||
const findConfidentialIcon = () => wrapper.find('.fa-eye-slash');
|
const checkExists = findFn => () => findFn().exists();
|
||||||
|
const hasConfidentialIcon = () =>
|
||||||
|
wrapper.findAll(GlIcon).wrappers.some(iconWrapper => iconWrapper.props('name') === 'eye-slash');
|
||||||
const findTaskStatus = () => wrapper.find('.task-status');
|
const findTaskStatus = () => wrapper.find('.task-status');
|
||||||
const findOpenedAgoContainer = () => wrapper.find('[data-testid="openedByMessage"]');
|
const findOpenedAgoContainer = () => wrapper.find('[data-testid="openedByMessage"]');
|
||||||
const findMilestone = () => wrapper.find('.js-milestone');
|
const findMilestone = () => wrapper.find('.js-milestone');
|
||||||
|
@ -169,19 +171,19 @@ describe('Issuable component', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each`
|
it.each`
|
||||||
desc | finder
|
desc | check
|
||||||
${'bulk editing checkbox'} | ${findBulkCheckbox}
|
${'bulk editing checkbox'} | ${checkExists(findBulkCheckbox)}
|
||||||
${'confidential icon'} | ${findConfidentialIcon}
|
${'confidential icon'} | ${hasConfidentialIcon}
|
||||||
${'task status'} | ${findTaskStatus}
|
${'task status'} | ${checkExists(findTaskStatus)}
|
||||||
${'milestone'} | ${findMilestone}
|
${'milestone'} | ${checkExists(findMilestone)}
|
||||||
${'due date'} | ${findDueDate}
|
${'due date'} | ${checkExists(findDueDate)}
|
||||||
${'labels'} | ${findLabels}
|
${'labels'} | ${checkExists(findLabels)}
|
||||||
${'weight'} | ${findWeight}
|
${'weight'} | ${checkExists(findWeight)}
|
||||||
${'merge request count'} | ${findMergeRequestsCount}
|
${'merge request count'} | ${checkExists(findMergeRequestsCount)}
|
||||||
${'upvotes'} | ${findUpvotes}
|
${'upvotes'} | ${checkExists(findUpvotes)}
|
||||||
${'downvotes'} | ${findDownvotes}
|
${'downvotes'} | ${checkExists(findDownvotes)}
|
||||||
`('does not render $desc', ({ finder }) => {
|
`('does not render $desc', ({ check }) => {
|
||||||
expect(finder().exists()).toBe(false);
|
expect(check()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('show relative reference path', () => {
|
it('show relative reference path', () => {
|
||||||
|
@ -215,7 +217,7 @@ describe('Issuable component', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders the confidential icon', () => {
|
it('renders the confidential icon', () => {
|
||||||
expect(findConfidentialIcon().exists()).toBe(true);
|
expect(hasConfidentialIcon()).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,51 +6,54 @@ RSpec.describe Gitlab::ConfigChecker::ExternalDatabaseChecker do
|
||||||
describe '#check' do
|
describe '#check' do
|
||||||
subject { described_class.check }
|
subject { described_class.check }
|
||||||
|
|
||||||
context 'database version is not deprecated' do
|
let_it_be(:deprecation_warning) { "Please upgrade" }
|
||||||
|
let_it_be(:upcoming_deprecation_warning) { "Please consider upgrading" }
|
||||||
|
|
||||||
|
context 'when database meets minimum version and there is no upcoming deprecation' do
|
||||||
before do
|
before do
|
||||||
allow(described_class).to receive(:db_version_deprecated?).and_return(false)
|
allow(Gitlab::Database).to receive(:postgresql_minimum_supported_version?).and_return(true)
|
||||||
|
allow(Gitlab::Database).to receive(:postgresql_upcoming_deprecation?).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to be_empty }
|
it { is_expected.to be_empty }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'database version is deprecated' do
|
context 'when database does not meet minimum version and there is no upcoming deprecation' do
|
||||||
before do
|
before do
|
||||||
allow(described_class).to receive(:db_version_deprecated?).and_return(true)
|
allow(Gitlab::Database).to receive(:postgresql_minimum_supported_version?).and_return(false)
|
||||||
|
allow(Gitlab::Database).to receive(:postgresql_upcoming_deprecation?).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:notice_deprecated_database) do
|
it 'only returns notice about deprecated database version' do
|
||||||
{
|
is_expected.to include(a_hash_including(message: include(deprecation_warning)))
|
||||||
type: 'warning',
|
is_expected.not_to include(a_hash_including(message: include(upcoming_deprecation_warning)))
|
||||||
message: _('Note that PostgreSQL 11 will become the minimum required PostgreSQL version in GitLab 13.0 (May 2020). '\
|
|
||||||
'PostgreSQL 9.6 and PostgreSQL 10 will no longer be supported in GitLab 13.0. '\
|
|
||||||
'Please consider upgrading your PostgreSQL version (%{db_version}) soon.') % { db_version: Gitlab::Database.version.to_s }
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'reports deprecated database notices' do
|
|
||||||
is_expected.to contain_exactly(notice_deprecated_database)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
describe '#db_version_deprecated' do
|
context 'when database meets minimum version and there is an upcoming deprecation' do
|
||||||
subject { described_class.db_version_deprecated? }
|
|
||||||
|
|
||||||
context 'database version is not deprecated' do
|
|
||||||
before do
|
before do
|
||||||
allow(Gitlab::Database).to receive(:version).and_return(11)
|
allow(Gitlab::Database).to receive(:postgresql_minimum_supported_version?).and_return(true)
|
||||||
|
allow(Gitlab::Database).to receive(:postgresql_upcoming_deprecation?).and_return(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to be false }
|
it 'only returns notice about an upcoming deprecation' do
|
||||||
|
is_expected.to include(a_hash_including(message: include(upcoming_deprecation_warning)))
|
||||||
|
is_expected.not_to include(a_hash_including(message: include(deprecation_warning)))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'database version is deprecated' do
|
context 'when database does not meet minimum version and there is an upcoming deprecation' do
|
||||||
before do
|
before do
|
||||||
allow(Gitlab::Database).to receive(:version).and_return(10)
|
allow(Gitlab::Database).to receive(:postgresql_minimum_supported_version?).and_return(false)
|
||||||
|
allow(Gitlab::Database).to receive(:postgresql_upcoming_deprecation?).and_return(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to be true }
|
it 'returns notice about deprecated database version and an upcoming deprecation' do
|
||||||
|
is_expected.to include(
|
||||||
|
a_hash_including(message: include(deprecation_warning)),
|
||||||
|
a_hash_including(message: include(upcoming_deprecation_warning))
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -90,29 +90,43 @@ RSpec.describe Gitlab::Database do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.postgresql_minimum_supported_version?' do
|
describe '.postgresql_minimum_supported_version?' do
|
||||||
it 'returns false when using PostgreSQL 9.5' do
|
|
||||||
allow(described_class).to receive(:version).and_return('9.5')
|
|
||||||
|
|
||||||
expect(described_class.postgresql_minimum_supported_version?).to eq(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns false when using PostgreSQL 9.6' do
|
|
||||||
allow(described_class).to receive(:version).and_return('9.6')
|
|
||||||
|
|
||||||
expect(described_class.postgresql_minimum_supported_version?).to eq(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns false when using PostgreSQL 10' do
|
it 'returns false when using PostgreSQL 10' do
|
||||||
allow(described_class).to receive(:version).and_return('10')
|
allow(described_class).to receive(:version).and_return('10')
|
||||||
|
|
||||||
expect(described_class.postgresql_minimum_supported_version?).to eq(false)
|
expect(described_class.postgresql_minimum_supported_version?).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns true when using PostgreSQL 11 or newer' do
|
it 'returns true when using PostgreSQL 11' do
|
||||||
allow(described_class).to receive(:version).and_return('11.0')
|
allow(described_class).to receive(:version).and_return('11')
|
||||||
|
|
||||||
expect(described_class.postgresql_minimum_supported_version?).to eq(true)
|
expect(described_class.postgresql_minimum_supported_version?).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns true when using PostgreSQL 12' do
|
||||||
|
allow(described_class).to receive(:version).and_return('12')
|
||||||
|
|
||||||
|
expect(described_class.postgresql_minimum_supported_version?).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.postgresql_upcoming_deprecation?' do
|
||||||
|
it 'returns true when database version is lower than the upcoming minimum' do
|
||||||
|
allow(described_class).to receive(:version).and_return('11')
|
||||||
|
|
||||||
|
expect(described_class.postgresql_upcoming_deprecation?).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false when database version equals the upcoming minimum' do
|
||||||
|
allow(described_class).to receive(:version).and_return('12')
|
||||||
|
|
||||||
|
expect(described_class.postgresql_upcoming_deprecation?).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false when database version is greater the upcoming minimum' do
|
||||||
|
allow(described_class).to receive(:version).and_return('13')
|
||||||
|
|
||||||
|
expect(described_class.postgresql_upcoming_deprecation?).to eq(false)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.check_postgres_version_and_print_warning' do
|
describe '.check_postgres_version_and_print_warning' do
|
||||||
|
|
|
@ -29,8 +29,8 @@ RSpec.describe SnippetInputAction do
|
||||||
:move | 'foobar' | '' | 'foo1' | nil | true | nil
|
:move | 'foobar' | '' | 'foo1' | nil | true | nil
|
||||||
:create | 'foobar' | nil | 'foobar' | nil | false | :content
|
:create | 'foobar' | nil | 'foobar' | nil | false | :content
|
||||||
:create | 'foobar' | '' | 'foobar' | nil | false | :content
|
:create | 'foobar' | '' | 'foobar' | nil | false | :content
|
||||||
:create | nil | 'foobar' | 'foobar' | nil | false | :file_path
|
:create | nil | 'foobar' | 'foobar' | nil | true | nil
|
||||||
:create | '' | 'foobar' | 'foobar' | nil | false | :file_path
|
:create | '' | 'foobar' | 'foobar' | nil | true | nil
|
||||||
:update | 'foobar' | nil | 'foobar' | nil | false | :content
|
:update | 'foobar' | nil | 'foobar' | nil | false | :content
|
||||||
:update | 'foobar' | '' | 'foobar' | nil | false | :content
|
:update | 'foobar' | '' | 'foobar' | nil | false | :content
|
||||||
:update | 'other' | 'foobar' | 'foobar' | nil | false | :file_path
|
:update | 'other' | 'foobar' | 'foobar' | nil | false | :file_path
|
||||||
|
|
|
@ -177,10 +177,8 @@ RSpec.describe Snippets::CreateService do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns a generic error' do
|
it 'returns a generic error' do
|
||||||
response = subject
|
expect(subject).to be_error
|
||||||
|
expect(snippet.errors[:repository]).to eq ['Error creating the snippet']
|
||||||
expect(response).to be_error
|
|
||||||
expect(response.payload[:snippet].errors[:repository]).to eq ['Error creating the snippet']
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -250,7 +248,7 @@ RSpec.describe Snippets::CreateService do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'commit the files to the repository' do
|
it 'commit the files to the repository' do
|
||||||
subject
|
expect(subject).to be_success
|
||||||
|
|
||||||
blob = snippet.repository.blob_at('master', file_path)
|
blob = snippet.repository.blob_at('master', file_path)
|
||||||
|
|
||||||
|
@ -261,10 +259,7 @@ RSpec.describe Snippets::CreateService do
|
||||||
let(:extra_opts) { { content: 'foo', file_name: 'path' } }
|
let(:extra_opts) { { content: 'foo', file_name: 'path' } }
|
||||||
|
|
||||||
it 'a validation error is raised' do
|
it 'a validation error is raised' do
|
||||||
response = subject
|
expect(subject).to be_error
|
||||||
snippet = response.payload[:snippet]
|
|
||||||
|
|
||||||
expect(response).to be_error
|
|
||||||
expect(snippet.errors.full_messages_for(:content)).to eq ['Content and snippet files cannot be used together']
|
expect(snippet.errors.full_messages_for(:content)).to eq ['Content and snippet files cannot be used together']
|
||||||
expect(snippet.errors.full_messages_for(:file_name)).to eq ['File name and snippet files cannot be used together']
|
expect(snippet.errors.full_messages_for(:file_name)).to eq ['File name and snippet files cannot be used together']
|
||||||
expect(snippet.repository.exists?).to be_falsey
|
expect(snippet.repository.exists?).to be_falsey
|
||||||
|
@ -275,10 +270,7 @@ RSpec.describe Snippets::CreateService do
|
||||||
let(:snippet_files) { [{ action: 'invalid_action', file_path: 'snippet_file_path.rb', content: 'snippet_content' }] }
|
let(:snippet_files) { [{ action: 'invalid_action', file_path: 'snippet_file_path.rb', content: 'snippet_content' }] }
|
||||||
|
|
||||||
it 'a validation error is raised' do
|
it 'a validation error is raised' do
|
||||||
response = subject
|
expect(subject).to be_error
|
||||||
snippet = response.payload[:snippet]
|
|
||||||
|
|
||||||
expect(response).to be_error
|
|
||||||
expect(snippet.errors.full_messages_for(:snippet_files)).to eq ['Snippet files have invalid data']
|
expect(snippet.errors.full_messages_for(:snippet_files)).to eq ['Snippet files have invalid data']
|
||||||
expect(snippet.repository.exists?).to be_falsey
|
expect(snippet.repository.exists?).to be_falsey
|
||||||
end
|
end
|
||||||
|
@ -288,14 +280,21 @@ RSpec.describe Snippets::CreateService do
|
||||||
let(:snippet_files) { [{ action: 'delete', file_path: 'snippet_file_path.rb' }] }
|
let(:snippet_files) { [{ action: 'delete', file_path: 'snippet_file_path.rb' }] }
|
||||||
|
|
||||||
it 'a validation error is raised' do
|
it 'a validation error is raised' do
|
||||||
response = subject
|
expect(subject).to be_error
|
||||||
snippet = response.payload[:snippet]
|
|
||||||
|
|
||||||
expect(response).to be_error
|
|
||||||
expect(snippet.errors.full_messages_for(:snippet_files)).to eq ['Snippet files have invalid data']
|
expect(snippet.errors.full_messages_for(:snippet_files)).to eq ['Snippet files have invalid data']
|
||||||
expect(snippet.repository.exists?).to be_falsey
|
expect(snippet.repository.exists?).to be_falsey
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when "create" operation does not have file_path or is empty' do
|
||||||
|
let(:snippet_files) { [{ action: 'create', content: content }, { action: 'create', content: content, file_path: '' }] }
|
||||||
|
|
||||||
|
it 'generates the file path for the files' do
|
||||||
|
expect(subject).to be_success
|
||||||
|
expect(snippet.repository.blob_at('master', 'snippetfile1.txt').data).to eq content
|
||||||
|
expect(snippet.repository.blob_at('master', 'snippetfile2.txt').data).to eq content
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when ProjectSnippet' do
|
context 'when ProjectSnippet' do
|
||||||
|
|
|
@ -537,10 +537,18 @@ RSpec.describe Snippets::UpdateService do
|
||||||
it_behaves_like 'returns an error', 'Snippet files have invalid data'
|
it_behaves_like 'returns an error', 'Snippet files have invalid data'
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when file_path is not present' do
|
context 'when file_path is not present or empty' do
|
||||||
let(:snippet_files) { [{ action: :create, content: content }] }
|
let(:snippet_files) { [{ action: :create, content: content }, { action: :create, file_path: '', content: content }] }
|
||||||
|
|
||||||
it_behaves_like 'returns an error', 'Snippet files have invalid data'
|
it 'generates the file path for the files' do
|
||||||
|
expect(blob('snippetfile1.txt')).to be_nil
|
||||||
|
expect(blob('snippetfile2.txt')).to be_nil
|
||||||
|
|
||||||
|
expect(subject).to be_success
|
||||||
|
|
||||||
|
expect(blob('snippetfile1.txt').data).to eq content
|
||||||
|
expect(blob('snippetfile2.txt').data).to eq content
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when file_path already exists in the repository' do
|
context 'when file_path already exists in the repository' do
|
||||||
|
|
Loading…
Reference in a new issue