+
diff --git a/app/assets/javascripts/design_management_legacy/components/upload/design_version_dropdown.vue b/app/assets/javascripts/design_management_legacy/components/upload/design_version_dropdown.vue
index 993eac6f37f..8d90ae4af6d 100644
--- a/app/assets/javascripts/design_management_legacy/components/upload/design_version_dropdown.vue
+++ b/app/assets/javascripts/design_management_legacy/components/upload/design_version_dropdown.vue
@@ -68,7 +68,7 @@ export default {
diff --git a/app/assets/javascripts/diffs/components/hidden_files_warning.vue b/app/assets/javascripts/diffs/components/hidden_files_warning.vue
index ad0ca4fa402..baf7471582a 100644
--- a/app/assets/javascripts/diffs/components/hidden_files_warning.vue
+++ b/app/assets/javascripts/diffs/components/hidden_files_warning.vue
@@ -26,7 +26,7 @@ export default {
{{ __('Too many changes to show.') }}
-
+
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index 108cc8d3a78..b728b2eee62 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -743,7 +743,7 @@ export default class FilteredSearchManager {
let tokenPath = '';
if (condition) {
- tokenPath = condition.url;
+ tokenPath = condition.replacementUrl || condition.url;
} else {
let tokenValue = token.value;
diff --git a/app/assets/javascripts/incidents/components/incidents_list.vue b/app/assets/javascripts/incidents/components/incidents_list.vue
index 4cd86c4b8b9..2731b49c4cc 100644
--- a/app/assets/javascripts/incidents/components/incidents_list.vue
+++ b/app/assets/javascripts/incidents/components/incidents_list.vue
@@ -10,13 +10,14 @@ import {
GlButton,
GlSearchBoxByType,
GlIcon,
+ GlPagination,
} from '@gitlab/ui';
import { debounce } from 'lodash';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { s__ } from '~/locale';
import { mergeUrlParams, joinPaths, visitUrl } from '~/lib/utils/url_utility';
import getIncidents from '../graphql/queries/get_incidents.query.graphql';
-import { I18N, INCIDENT_SEARCH_DELAY } from '../constants';
+import { I18N, DEFAULT_PAGE_SIZE, INCIDENT_SEARCH_DELAY } from '../constants';
const tdClass =
'table-col gl-display-flex d-md-table-cell gl-align-items-center gl-white-space-nowrap';
@@ -24,6 +25,14 @@ const thClass = 'gl-hover-bg-blue-50';
const bodyTrClass =
'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-cursor-pointer gl-hover-bg-blue-50 gl-hover-border-b-solid gl-hover-border-blue-200';
+const initialPaginationState = {
+ currentPage: 1,
+ prevPageCursor: '',
+ nextPageCursor: '',
+ firstPageSize: DEFAULT_PAGE_SIZE,
+ lastPageSize: null,
+};
+
export default {
i18n: I18N,
fields: [
@@ -57,6 +66,7 @@ export default {
TimeAgoTooltip,
GlSearchBoxByType,
GlIcon,
+ GlPagination,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -70,9 +80,18 @@ export default {
searchTerm: this.searchTerm,
projectPath: this.projectPath,
labelNames: ['incident'],
+ firstPageSize: this.pagination.firstPageSize,
+ lastPageSize: this.pagination.lastPageSize,
+ prevPageCursor: this.pagination.prevPageCursor,
+ nextPageCursor: this.pagination.nextPageCursor,
+ };
+ },
+ update({ project: { issues: { nodes = [], pageInfo = {} } = {} } = {} }) {
+ return {
+ list: nodes,
+ pageInfo,
};
},
- update: ({ project: { issues: { nodes = [] } = {} } = {} }) => nodes,
error() {
this.errored = true;
},
@@ -84,6 +103,8 @@ export default {
isErrorAlertDismissed: false,
redirecting: false,
searchTerm: '',
+ pagination: initialPaginationState,
+ incidents: {},
};
},
computed: {
@@ -94,7 +115,19 @@ export default {
return this.$apollo.queries.incidents.loading;
},
hasIncidents() {
- return this.incidents?.length;
+ return this.incidents?.list?.length;
+ },
+ showPaginationControls() {
+ return Boolean(
+ this.incidents?.pageInfo?.hasNextPage || this.incidents?.pageInfo?.hasPreviousPage,
+ );
+ },
+ prevPage() {
+ return Math.max(this.pagination.currentPage - 1, 0);
+ },
+ nextPage() {
+ const nextPage = this.pagination.currentPage + 1;
+ return this.incidents?.list?.length < DEFAULT_PAGE_SIZE ? null : nextPage;
},
tbodyTrClass() {
return {
@@ -119,6 +152,28 @@ export default {
navigateToIncidentDetails({ iid }) {
return visitUrl(joinPaths(this.issuePath, iid));
},
+ handlePageChange(page) {
+ const { startCursor, endCursor } = this.incidents.pageInfo;
+
+ if (page > this.pagination.currentPage) {
+ this.pagination = {
+ ...initialPaginationState,
+ nextPageCursor: endCursor,
+ currentPage: page,
+ };
+ } else {
+ this.pagination = {
+ lastPageSize: DEFAULT_PAGE_SIZE,
+ firstPageSize: null,
+ prevPageCursor: startCursor,
+ nextPageCursor: '',
+ currentPage: page,
+ };
+ }
+ },
+ resetPagination() {
+ this.pagination = initialPaginationState;
+ },
},
};
@@ -155,7 +210,7 @@ export default {
{{ s__('IncidentManagement|Incidents') }}
+
+
diff --git a/app/assets/javascripts/incidents/constants.js b/app/assets/javascripts/incidents/constants.js
index a0064c44a6e..4246c3e914f 100644
--- a/app/assets/javascripts/incidents/constants.js
+++ b/app/assets/javascripts/incidents/constants.js
@@ -9,3 +9,4 @@ export const I18N = {
};
export const INCIDENT_SEARCH_DELAY = 300;
+export const DEFAULT_PAGE_SIZE = 10;
diff --git a/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql b/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
index eeba60139ca..d717d898ef0 100644
--- a/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
+++ b/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
@@ -1,11 +1,23 @@
query getIncidents(
- $searchTerm: String
$projectPath: ID!
$labelNames: [String]
$state: IssuableState
+ $firstPageSize: Int
+ $lastPageSize: Int
+ $prevPageCursor: String = ""
+ $nextPageCursor: String = ""
+ $searchTerm: String
) {
project(fullPath: $projectPath) {
- issues(search: $searchTerm, state: $state, labelName: $labelNames) {
+ issues(
+ search: $searchTerm
+ state: $state
+ labelName: $labelNames
+ first: $firstPageSize
+ last: $lastPageSize
+ after: $nextPageCursor
+ before: $prevPageCursor
+ ) {
nodes {
iid
title
@@ -26,6 +38,12 @@ query getIncidents(
}
}
}
+ pageInfo {
+ hasNextPage
+ endCursor
+ hasPreviousPage
+ startCursor
+ }
}
}
}
diff --git a/app/assets/javascripts/packages/details/components/information.vue b/app/assets/javascripts/packages/details/components/information.vue
index 60bf1d40ff0..d787e0898ca 100644
--- a/app/assets/javascripts/packages/details/components/information.vue
+++ b/app/assets/javascripts/packages/details/components/information.vue
@@ -40,7 +40,7 @@ export default {
-
{{ item.label }}
-
+
{{ dropdownButtonText }}
-
+
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue
index 94671f8a109..55e2fb68275 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue
@@ -105,13 +105,13 @@ export default {
:disabled="disableCreate"
category="primary"
variant="success"
- class="pull-left d-flex align-items-center"
+ class="float-left d-flex align-items-center"
@click="handleCreateClick"
>
{{ __('Create') }}
-
+
{{ __('Cancel') }}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue
index ec6ba4b97f4..2d6a4a9758c 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue
@@ -29,7 +29,7 @@ export default {
not verified to belong to the same user.').html_safe
+ = html_escape(_('This commit was signed with a verified signature, but the committer email is %{strong_open}not verified%{strong_close} to belong to the same user.')) % { strong_open: '
'.html_safe, strong_close: ''.html_safe }
- locals = { signature: signature, title: title, label: _('Unverified'), css_class: ['invalid'], icon: 'status_notfound_borderless', show_user: true }
diff --git a/app/views/projects/commit/_unverified_signature_badge.html.haml b/app/views/projects/commit/_unverified_signature_badge.html.haml
index 294f916d18f..0ce8e06382b 100644
--- a/app/views/projects/commit/_unverified_signature_badge.html.haml
+++ b/app/views/projects/commit/_unverified_signature_badge.html.haml
@@ -1,5 +1,5 @@
- title = capture do
- = _('This commit was signed with an
unverified signature.').html_safe
+ = html_escape(_('This commit was signed with an %{strong_open}unverified%{strong_close} signature.')) % { strong_open: '
'.html_safe, strong_close: ''.html_safe }
- locals = { signature: signature, title: title, label: _('Unverified'), css_class: 'invalid', icon: 'status_notfound_borderless' }
diff --git a/app/views/projects/commit/x509/_verified_signature_badge.html.haml b/app/views/projects/commit/x509/_verified_signature_badge.html.haml
index 4964b1b8ee7..357ad467539 100644
--- a/app/views/projects/commit/x509/_verified_signature_badge.html.haml
+++ b/app/views/projects/commit/x509/_verified_signature_badge.html.haml
@@ -1,5 +1,5 @@
- title = capture do
- = _('This commit was signed with a
verified signature and the committer email is verified to belong to the same user.').html_safe
+ = html_escape(_('This commit was signed with a %{strong_open}verified%{strong_close} signature and the committer email is verified to belong to the same user.')) % { strong_open: '
'.html_safe, strong_close: ''.html_safe }
- locals = { signature: signature, title: title, label: _('Verified'), css_class: 'valid', icon: 'status_success_borderless', show_user: true }
diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml
index 93ee1bed809..e45ea209e8c 100644
--- a/app/views/projects/compare/index.html.haml
+++ b/app/views/projects/compare/index.html.haml
@@ -8,9 +8,9 @@
%code.ref-name master
- example_sha = capture do
%code.ref-name 4eedf23
- = (_("Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request.") % { master: example_master, sha: example_sha }).html_safe
+ = html_escape(_("Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request.")) % { master: example_master.html_safe, sha: example_sha.html_safe }
%br
- = (_("Changes are shown as if the
source revision was being merged into the
target revision.")).html_safe
+ = html_escape(_("Changes are shown as if the %{b_open}source%{b_close} revision was being merged into the %{b_open}target%{b_close} revision.")) % { b_open: '
'.html_safe, b_close: ''.html_safe }
.prepend-top-20
= render "form"
diff --git a/app/views/projects/diffs/_warning.html.haml b/app/views/projects/diffs/_warning.html.haml
index 2cc3d921abc..643d111fedd 100644
--- a/app/views/projects/diffs/_warning.html.haml
+++ b/app/views/projects/diffs/_warning.html.haml
@@ -9,4 +9,4 @@
= link_to _("Plain diff"), merge_request_path(@merge_request, format: :diff), class: "btn btn-sm"
= link_to _("Email patch"), merge_request_path(@merge_request, format: :patch), class: "btn btn-sm"
%p
- = _("To preserve performance only
%{display_size} of %{real_size} files are displayed.").html_safe % { display_size: diff_files.size, real_size: diff_files.real_size }
+ = html_escape(_("To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed.")) % { display_size: diff_files.size, real_size: diff_files.real_size, strong_open: '
'.html_safe, strong_close: ''.html_safe }
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index d5249662dde..2e665a12a0a 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -65,7 +65,7 @@
%h4.state-title
= _("You don't have any deployments right now.")
%p.blank-state-text
- = _("Define environments in the deploy stage(s) in
.gitlab-ci.yml
to track deployments here.").html_safe
+ = html_escape(_("Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here.")) % { code_open: '
'.html_safe, code_close: '
'.html_safe }
.text-center
= link_to _("Read more"), help_page_path("ci/environments"), class: "btn btn-success"
- else
diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml
index daac118d88e..45d314a1088 100644
--- a/app/views/projects/forks/new.html.haml
+++ b/app/views/projects/forks/new.html.haml
@@ -5,7 +5,9 @@
%h4.gl-mt-0
= _("Fork project")
%p
- = _("A fork is a copy of a project.
Forking a repository allows you to make changes without affecting the original project.").html_safe
+ = _("A fork is a copy of a project.")
+ %br
+ = _('Forking a repository allows you to make changes without affecting the original project.')
.col-lg-9
- if @own_namespace.present?
.fork-thumbnail-container.js-fork-content
diff --git a/app/views/projects/mirrors/_instructions.html.haml b/app/views/projects/mirrors/_instructions.html.haml
index 15c9076c1ab..97b04acea31 100644
--- a/app/views/projects/mirrors/_instructions.html.haml
+++ b/app/views/projects/mirrors/_instructions.html.haml
@@ -1,10 +1,10 @@
.account-well.gl-mt-3.gl-mb-3
%ul
%li
- = _('The repository must be accessible over
http://
,
-
https://
,
ssh://
or
git://
.').html_safe
- %li= _('When using the
http://
or
https://
protocols, please provide the exact URL to the repository. HTTP redirects will not be followed.').html_safe
- %li= _('Include the username in the URL if required:
https://username@gitlab.company.com/group/project.git
.').html_safe
+ = html_escape(_('The repository must be accessible over %{code_open}http://%{code_close},
+ %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} or %{code_open}git://%{code_close}.')) % { code_open: '
'.html_safe, code_close: '
'.html_safe }
+ %li= html_escape(_('When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed.')) % { code_open: '
'.html_safe, code_close: '
'.html_safe }
+ %li= html_escape(_('Include the username in the URL if required: %{code_open}https://username@gitlab.company.com/group/project.git%{code_close}.')) % { code_open: '
'.html_safe, code_close: '
'.html_safe }
%li
- minutes = Gitlab.config.gitlab_shell.git_timeout / 60
= _("The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination.") % { number_of_minutes: minutes }
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index 77f1f4c6a77..5c67d3d4373 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -70,7 +70,7 @@
.badge.mirror-error-badge{ data: { toggle: 'tooltip', html: 'true', qa_selector: 'mirror_error_badge' }, title: html_escape(mirror.last_error.try(:strip)) }= _('Error')
%td
- if mirror_settings_enabled
- .btn-group.mirror-actions-group.pull-right{ role: 'group' }
+ .btn-group.mirror-actions-group.float-right{ role: 'group' }
- if mirror.ssh_key_auth?
= clipboard_button(text: mirror.ssh_public_key, class: 'btn btn-default', title: _('Copy SSH public key'), qa_selector: 'copy_public_key_button')
= render 'shared/remote_mirror_update_button', remote_mirror: mirror
diff --git a/app/views/projects/packages/packages/_legacy_package_list.html.haml b/app/views/projects/packages/packages/_legacy_package_list.html.haml
index afce5b6b992..43dbb5c3eee 100644
--- a/app/views/projects/packages/packages/_legacy_package_list.html.haml
+++ b/app/views/projects/packages/packages/_legacy_package_list.html.haml
@@ -50,7 +50,7 @@
.table-mobile-header{ role: "rowheader" }
.table-mobile-content
- if can_destroy_package
- .pull-right
+ .float-right
= link_to project_package_path(@project, package), method: :delete, data: { confirm: _("Are you sure?") }, class: "btn btn-grouped btn-remove", title: _('Delete Package') do
= icon('trash')
= paginate @packages, theme: "gitlab"
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
index 7c1930a4fc6..9ca76708557 100644
--- a/app/views/projects/pipelines/_info.html.haml
+++ b/app/views/projects/pipelines/_info.html.haml
@@ -35,7 +35,7 @@
%span.js-pipeline-url-failure.badge.badge-danger.has-tooltip{ title: @pipeline.failure_reason }
error
- if @pipeline.auto_devops_source?
- - popover_title_text = _('This pipeline makes use of a predefined CI/CD configuration enabled by
Auto DevOps.').html_safe
+ - popover_title_text = html_escape(_('This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}')) % { b_open: '
'.html_safe, b_close: ''.html_safe }
- popover_content_url = help_page_path('topics/autodevops/index.md')
- popover_content_text = _('Learn more about Auto DevOps')
%a.js-pipeline-url-autodevops.badge.badge-info.autodevops-badge{ href: "#", tabindex: "0", role: "button", data: { container: "body",
diff --git a/app/views/projects/project_members/_groups.html.haml b/app/views/projects/project_members/_groups.html.haml
index 353c36d0fed..39ef1e52a0d 100644
--- a/app/views/projects/project_members/_groups.html.haml
+++ b/app/views/projects/project_members/_groups.html.haml
@@ -1,6 +1,6 @@
.card.project-members-groups
.card-header
- = _("Groups with access to
%{project_name}").html_safe % { project_name: sanitize(@project.name, tags: []) }
+ = html_escape(_("Groups with access to %{strong_open}%{project_name}%{strong_close}")) % { project_name: sanitize(@project.name, tags: []), strong_open: '
'.html_safe, strong_close: ''.html_safe }
%span.badge.badge-pill= group_links.size
%ul.content-list.members-list
- can_admin_member = can?(current_user, :admin_project_member, @project)
diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml
index 5d8005b2e2a..655984397e3 100644
--- a/app/views/projects/project_members/_team.html.haml
+++ b/app/views/projects/project_members/_team.html.haml
@@ -4,7 +4,7 @@
.card
.card-header.flex-project-members-panel
%span.flex-project-title
- = _("Members of
%{project_name}").html_safe % { project_name: sanitize(project.name, tags: []) }
+ = html_escape(_("Members of %{strong_open}%{project_name}%{strong_close}")) % { project_name: sanitize(project.name, tags: []), strong_open: '
'.html_safe, strong_close: ''.html_safe }
%span.badge.badge-pill= members.total_count
= form_tag project_project_members_path(project), method: :get, class: 'form-inline user-search-form flex-users-form' do
.form-group
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index ba964e5cd37..9a1e997fce7 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -11,7 +11,7 @@
%p= share_project_description(@project)
- else
%p
- = _("Members can be added by project
Maintainers or
Owners").html_safe
+ = html_escape(_("Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}")) % { i_open: '
'.html_safe, i_close: ''.html_safe }
.light
- if can_admin_project_members && project_can_be_shared?
diff --git a/app/views/projects/services/slack/_help.haml b/app/views/projects/services/slack/_help.haml
index d7ea1b270f5..3cf28bddf88 100644
--- a/app/views/projects/services/slack/_help.haml
+++ b/app/views/projects/services/slack/_help.haml
@@ -6,11 +6,11 @@
%p= s_('SlackIntegration|This service send notifications about projects\' events to Slack channels. To set up this service:')
%ol
%li
- = s_('SlackIntegration|%{webhooks_link_start}Add an incoming webhook%{webhooks_link_end} in your Slack team. The default channel can be overridden for each event.').html_safe % { webhooks_link_start: webhooks_link_start, webhooks_link_end: ''.html_safe }
+ = html_escape(s_('SlackIntegration|%{webhooks_link_start}Add an incoming webhook%{webhooks_link_end} in your Slack team. The default channel can be overridden for each event.')) % { webhooks_link_start: webhooks_link_start.html_safe, webhooks_link_end: ''.html_safe }
%li
- = s_('SlackIntegration|Paste the
Webhook URL into the field below.').html_safe
+ = html_escape(s_('SlackIntegration|Paste the %{strong_open}Webhook URL%{strong_close} into the field below.')) % { strong_open: '
'.html_safe, strong_close: ''.html_safe }
%li
- = s_('SlackIntegration|Select events below to enable notifications. The
Slack channel names and
Slack username fields are optional.').html_safe
+ = html_escape(s_('SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional.')) % { strong_open: '
'.html_safe, strong_close: ''.html_safe }
%p.mt-3.mb-0
- = s_('SlackIntegration|
Note: Usernames and private channels are not supported.').html_safe
+ = html_escape(s_('SlackIntegration|%{strong_open}Note:%{strong_close} Usernames and private channels are not supported.')) % { strong_open: '
'.html_safe, strong_close: ''.html_safe }
= link_to _('Learn more'), help_page_path('user/project/integrations/slack')
diff --git a/app/views/projects/services/slack_slash_commands/_help.html.haml b/app/views/projects/services/slack_slash_commands/_help.html.haml
index 05ffaebdb9a..96fef9101d2 100644
--- a/app/views/projects/services/slack_slash_commands/_help.html.haml
+++ b/app/views/projects/services/slack_slash_commands/_help.html.haml
@@ -89,6 +89,6 @@
%ul.list-unstyled.indent-list
%li
- = s_("SlackService|2. Paste the
Token into the field below").html_safe
+ = html_escape(s_("SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below")) % { strong_open: '
'.html_safe, strong_close: ''.html_safe }
%li
- = s_("SlackService|3. Select the
Active checkbox, press
Save changes and start using GitLab inside Slack!").html_safe
+ = html_escape(s_("SlackService|3. Select the %{strong_open}Active%{strong_close} checkbox, press %{strong_open}Save changes%{strong_close} and start using GitLab inside Slack!")) % { strong_open: '
'.html_safe, strong_close: ''.html_safe }
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index e8e5a5f0256..a0dd06e3304 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -7,7 +7,7 @@
%h5.gl-mt-0
= _("Git strategy for pipelines")
%p
- = _("Choose between
clone
or
fetch
to get the recent application code").html_safe
+ = html_escape(_("Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code")) % { code_open: '
'.html_safe, code_close: '
'.html_safe }
= link_to icon('question-circle'), help_page_path('ci/pipelines/settings', anchor: 'git-strategy'), target: '_blank'
.form-check
= f.radio_button :build_allow_git_fetch, 'false', { class: 'form-check-input' }
@@ -54,7 +54,7 @@
= f.label :ci_config_path, _('Custom CI configuration path'), class: 'label-bold'
= f.text_field :ci_config_path, class: 'form-control', placeholder: '.gitlab-ci.yml'
%p.form-text.text-muted
- = _("The path to the CI configuration file. Defaults to
.gitlab-ci.yml
").html_safe
+ = html_escape(_("The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}")) % { code_open: '
'.html_safe, code_close: '
'.html_safe }
= link_to icon('question-circle'), help_page_path('ci/pipelines/settings', anchor: 'custom-ci-configuration-path'), target: '_blank'
%hr
diff --git a/app/views/shared/issuable/form/_branch_chooser.html.haml b/app/views/shared/issuable/form/_branch_chooser.html.haml
index 1823c5279e5..3801bbd6512 100644
--- a/app/views/shared/issuable/form/_branch_chooser.html.haml
+++ b/app/views/shared/issuable/form/_branch_chooser.html.haml
@@ -9,7 +9,7 @@
.form-group.row.d-flex.gl-pl-3-deprecated-no-really-do-not-use-me.gl-pr-3-deprecated-no-really-do-not-use-me.branch-selector
.align-self-center
%span
- = _('From
%{source_title}
into').html_safe % { source_title: source_title }
+ = html_escape(_('From %{code_open}%{source_title}%{code_close} into')) % { source_title: source_title, code_open: '
'.html_safe, code_close: '
'.html_safe }
- if issuable.new_record?
%code#js-target-branch-title= target_title
diff --git a/app/views/users/terms/index.html.haml b/app/views/users/terms/index.html.haml
index bc4861d6ae8..175fde1c862 100644
--- a/app/views/users/terms/index.html.haml
+++ b/app/views/users/terms/index.html.haml
@@ -9,7 +9,7 @@
= button_to accept_term_path(@term, redirect_params), class: 'btn btn-success gl-ml-3', data: { qa_selector: 'accept_terms_button' } do
= _('Accept terms')
- else
- .pull-right
+ .float-right
= link_to root_path, class: 'btn btn-success gl-ml-3' do
= _('Continue')
- if can?(current_user, :decline_terms, @term)
diff --git a/changelogs/unreleased/208782-graphql-api-mutation-for-changing-labels-of-an-issue.yml b/changelogs/unreleased/208782-graphql-api-mutation-for-changing-labels-of-an-issue.yml
new file mode 100644
index 00000000000..0aef6971dec
--- /dev/null
+++ b/changelogs/unreleased/208782-graphql-api-mutation-for-changing-labels-of-an-issue.yml
@@ -0,0 +1,5 @@
+---
+title: Allow user to update issue labels via GraphQL
+merge_request: 37728
+author:
+type: added
diff --git a/changelogs/unreleased/220338-remove-newlines-in-prom-queries.yml b/changelogs/unreleased/220338-remove-newlines-in-prom-queries.yml
new file mode 100644
index 00000000000..50d861a6b7e
--- /dev/null
+++ b/changelogs/unreleased/220338-remove-newlines-in-prom-queries.yml
@@ -0,0 +1,5 @@
+---
+title: Allow multiline Prometheus queries in metrics dashboards yaml
+merge_request: 34508
+author:
+type: changed
diff --git a/changelogs/unreleased/229406-incident-pagination.yml b/changelogs/unreleased/229406-incident-pagination.yml
new file mode 100644
index 00000000000..0b98163c59b
--- /dev/null
+++ b/changelogs/unreleased/229406-incident-pagination.yml
@@ -0,0 +1,5 @@
+---
+title: Add pagination to the incident list
+merge_request: 37993
+author:
+type: changed
diff --git a/changelogs/unreleased/231269-monaco-yaml.yml b/changelogs/unreleased/231269-monaco-yaml.yml
new file mode 100644
index 00000000000..4ba76eb18b8
--- /dev/null
+++ b/changelogs/unreleased/231269-monaco-yaml.yml
@@ -0,0 +1,5 @@
+---
+title: Fix console errors due to monaco-yaml's outdated use of monaco.Promise
+merge_request: 38135
+author:
+type: fixed
diff --git a/changelogs/unreleased/232468-prometheus-conn-timeout.yml b/changelogs/unreleased/232468-prometheus-conn-timeout.yml
new file mode 100644
index 00000000000..c2b25346925
--- /dev/null
+++ b/changelogs/unreleased/232468-prometheus-conn-timeout.yml
@@ -0,0 +1,5 @@
+---
+title: Set appropriate timeouts for PrometheusClient
+merge_request: 37924
+author:
+type: other
diff --git a/changelogs/unreleased/allow-query-jira-projects-by-key-and-name.yml b/changelogs/unreleased/allow-query-jira-projects-by-key-and-name.yml
new file mode 100644
index 00000000000..cb0e3cd4b0f
--- /dev/null
+++ b/changelogs/unreleased/allow-query-jira-projects-by-key-and-name.yml
@@ -0,0 +1,5 @@
+---
+title: Query Jira projects by key or name and return all Jira projects in one query
+merge_request: 37799
+author:
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-6.yml b/changelogs/unreleased/rails-save-bang-6.yml
new file mode 100644
index 00000000000..d0731fd34a9
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-6.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor spec/policies and ee/spec/policies to fix SaveBang Cop
+merge_request: 37956
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/weimeng-master-patch-35379.yml b/changelogs/unreleased/weimeng-master-patch-35379.yml
new file mode 100644
index 00000000000..7c17c6c8f05
--- /dev/null
+++ b/changelogs/unreleased/weimeng-master-patch-35379.yml
@@ -0,0 +1,5 @@
+---
+title: Fix error when blob has no auxiliary viewer
+merge_request: 38018
+author:
+type: fixed
diff --git a/config/plugins/monaco_webpack.js b/config/plugins/monaco_webpack.js
index 7d283782453..698d1b9b1fa 100644
--- a/config/plugins/monaco_webpack.js
+++ b/config/plugins/monaco_webpack.js
@@ -8,10 +8,10 @@ const { languagesArr } = require('monaco-editor-webpack-plugin/out/languages');
const yamlLang = languagesArr.find(t => t.label === 'yaml');
-yamlLang.entry = [yamlLang.entry, '../../monaco-yaml/esm/monaco.contribution'];
+yamlLang.entry = [yamlLang.entry, '../../monaco-yaml/lib/esm/monaco.contribution'];
yamlLang.worker = {
id: 'vs/language/yaml/yamlWorker',
- entry: '../../monaco-yaml/esm/yaml.worker.js',
+ entry: '../../monaco-yaml/lib/esm/yaml.worker.js',
};
module.exports = require('monaco-editor-webpack-plugin');
diff --git a/doc/administration/issue_closing_pattern.md b/doc/administration/issue_closing_pattern.md
index 7b85ba77f50..7abe0f725f2 100644
--- a/doc/administration/issue_closing_pattern.md
+++ b/doc/administration/issue_closing_pattern.md
@@ -1,3 +1,10 @@
+---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
+type: reference
+---
+
# Issue closing pattern **(CORE ONLY)**
NOTE: **Note:**
diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md
index 8fde71a66bf..876dcf1fae4 100644
--- a/doc/administration/reference_architectures/index.md
+++ b/doc/administration/reference_architectures/index.md
@@ -115,7 +115,8 @@ to the default installation:
> - Supported tiers: [GitLab Starter, Premium, and Ultimate](https://about.gitlab.com/pricing/)
GitLab supports [zero-downtime updates](https://docs.gitlab.com/omnibus/update/#zero-downtime-updates).
-Although you can perform zero-downtime updates with a single GitLab node, the recommendation is to separate GitLab into several application nodes.
+Single GitLab nodes can be updated with only a [few minutes of downtime](https://docs.gitlab.com/omnibus/update/README.html#single-node-deployment).
+To avoid this, we recommend to separate GitLab into several application nodes.
As long as at least one of each component is online and capable of handling the instance's usage load, your team's productivity will not be interrupted during the update.
### Automated database failover **(PREMIUM ONLY)**
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index cd0f32b728d..ec602222f3b 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -2152,6 +2152,46 @@ type CreateSnippetPayload {
snippet: Snippet
}
+"""
+Autogenerated input type of DastOnDemandScanCreate
+"""
+input DastOnDemandScanCreateInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ ID of the site profile to be used for the scan.
+ """
+ dastSiteProfileId: ID!
+
+ """
+ The project the site profile belongs to.
+ """
+ fullPath: ID!
+}
+
+"""
+Autogenerated return type of DastOnDemandScanCreate
+"""
+type DastOnDemandScanCreatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ URL of the pipeline that was created.
+ """
+ pipelineUrl: String
+}
+
enum DastScanTypeEnum {
"""
Passive DAST scan. This scan will not make active attacks against the target site.
@@ -8275,6 +8315,7 @@ type Mutation {
createNote(input: CreateNoteInput!): CreateNotePayload
createRequirement(input: CreateRequirementInput!): CreateRequirementPayload
createSnippet(input: CreateSnippetInput!): CreateSnippetPayload
+ dastOnDemandScanCreate(input: DastOnDemandScanCreateInput!): DastOnDemandScanCreatePayload
dastScannerProfileCreate(input: DastScannerProfileCreateInput!): DastScannerProfileCreatePayload
dastSiteProfileCreate(input: DastSiteProfileCreateInput!): DastSiteProfileCreatePayload
deleteAnnotation(input: DeleteAnnotationInput!): DeleteAnnotationPayload
@@ -14128,6 +14169,11 @@ type UpdateImageDiffNotePayload {
Autogenerated input type of UpdateIssue
"""
input UpdateIssueInput {
+ """
+ The IDs of labels to be added to the issue.
+ """
+ addLabelIds: [ID!]
+
"""
A unique identifier for the client performing the mutation.
"""
@@ -14168,6 +14214,11 @@ input UpdateIssueInput {
"""
projectPath: ID!
+ """
+ The IDs of labels to be removed from the issue.
+ """
+ removeLabelIds: [ID!]
+
"""
Title of the issue
"""
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index b5fff06982d..838bd1cc0a2 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -5768,6 +5768,122 @@
"enumValues": null,
"possibleTypes": null
},
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "DastOnDemandScanCreateInput",
+ "description": "Autogenerated input type of DastOnDemandScanCreate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "fullPath",
+ "description": "The project the site profile belongs to.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "dastSiteProfileId",
+ "description": "ID of the site profile to be used for the scan.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "DastOnDemandScanCreatePayload",
+ "description": "Autogenerated return type of DastOnDemandScanCreate",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pipelineUrl",
+ "description": "URL of the pipeline that was created.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
{
"kind": "ENUM",
"name": "DastScanTypeEnum",
@@ -23712,6 +23828,33 @@
"isDeprecated": false,
"deprecationReason": null
},
+ {
+ "name": "dastOnDemandScanCreate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "DastOnDemandScanCreateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastOnDemandScanCreatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
{
"name": "dastScannerProfileCreate",
"description": null,
@@ -41855,6 +41998,42 @@
},
"defaultValue": null
},
+ {
+ "name": "addLabelIds",
+ "description": "The IDs of labels to be added to the issue.",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "removeLabelIds",
+ "description": "The IDs of labels to be removed from the issue.",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
{
"name": "healthStatus",
"description": "The desired health status",
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 708c2c578e9..73df0156fe6 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -382,6 +382,16 @@ Autogenerated return type of CreateSnippet
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `snippet` | Snippet | The snippet after mutation |
+## DastOnDemandScanCreatePayload
+
+Autogenerated return type of DastOnDemandScanCreate
+
+| Name | Type | Description |
+| --- | ---- | ---------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `pipelineUrl` | String | URL of the pipeline that was created. |
+
## DastScannerProfileCreatePayload
Autogenerated return type of DastScannerProfileCreate
@@ -1041,7 +1051,6 @@ Autogenerated return type of JiraImportUsers
| Name | Type | Description |
| --- | ---- | ---------- |
| `active` | Boolean | Indicates if the service is active |
-| `projects` | JiraProjectConnection | List of all Jira projects fetched through Jira REST API |
| `type` | String | Class name of the service |
## JiraUser
diff --git a/doc/api/notification_settings.md b/doc/api/notification_settings.md
index ae9e9ec7dee..8442e371a56 100644
--- a/doc/api/notification_settings.md
+++ b/doc/api/notification_settings.md
@@ -87,8 +87,8 @@ curl --request PUT --header "PRIVATE-TOKEN:
" "https://gitlab
| `failed_pipeline` | boolean | no | Enable/disable this notification |
| `fixed_pipeline` | boolean | no | Enable/disable this notification |
| `success_pipeline` | boolean | no | Enable/disable this notification |
-| `moved_project` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37269) in 13.3)|
-| `new_epic` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6626) in 11.3) **(ULTIMATE)** |
+| `moved_project` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30371) in GitLab 13.3) |
+| `new_epic` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5863) in GitLab 11.3) **(ULTIMATE)** |
Example response:
@@ -158,8 +158,8 @@ curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab
| `failed_pipeline` | boolean | no | Enable/disable this notification |
| `fixed_pipeline` | boolean | no | Enable/disable this notification |
| `success_pipeline` | boolean | no | Enable/disable this notification |
-| `moved_project` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37269) in 13.3)|
-| `new_epic` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6626) in 11.3) **(ULTIMATE)** |
+| `moved_project` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30371) in GitLab 13.3) |
+| `new_epic` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5863) in GitLab 11.3) **(ULTIMATE)** |
Example responses:
@@ -190,8 +190,8 @@ Example responses:
}
```
-Users on GitLab [Ultimate or Gold](https://about.gitlab.com/pricing/) will also see
-the `new_epic` parameter:
+Users on GitLab [Ultimate or Gold](https://about.gitlab.com/pricing/) also see the `new_epic`
+parameter:
```json
{
diff --git a/doc/development/reference_processing.md b/doc/development/reference_processing.md
index 79377533966..527fb94f228 100644
--- a/doc/development/reference_processing.md
+++ b/doc/development/reference_processing.md
@@ -18,6 +18,16 @@ and link the same type of objects (as specified by the `data-reference-type`
attribute), then we only need one reference parser for that type of domain
object.
+## Banzai pipeline
+
+`Banzai` pipeline returns the `result` Hash after being filtered by the Pipeline.
+
+The `result` Hash is passed to each filter for modification. This is where Filters store extracted information from the content.
+It contains:
+
+- An `:output` key with the DocumentFragment or String HTML markup based on the output of the last filter in the pipeline.
+- A `:reference_filter_nodes` key with the list of DocumentFragment `nodes` that are ready for processing, updated by each filter in the pipeline.
+
## Reference filters
The first way that references are handled is by reference filters. These are
@@ -69,6 +79,8 @@ a minimum implementation of `AbstractReferenceFilter` should define:
### Performance
+#### Find object optimization
+
This default implementation is not very efficient, because we need to call
`#find_object` for each reference, which may require issuing a DB query every
time. For this reason, most reference filter implementations will instead use an
@@ -96,6 +108,22 @@ This makes the number of queries linear in the number of projects. We only need
to implement `parent_records` method when we call `records_per_parent` in our
reference filter.
+#### Filtering nodes optimization
+
+Each `ReferenceFilter` would iterate over all `` and `text()` nodes in a document.
+
+Not all nodes are processed, document is filtered only for nodes that we want to process.
+We are skipping:
+
+- Link tags already processed by some previous filter (if they have a `gfm` class).
+- Nodes with the ancestor node that we want to ignore (`ignore_ancestor_query`).
+- Empty line.
+- Link tags with the empty `href` attribute.
+
+To avoid filtering such nodes for each `ReferenceFilter`, we do it only once and store the result in the result Hash of the pipeline as `result[:reference_filter_nodes]`.
+
+Pipeline `result` is passed to each filter for modification, so every time when `ReferenceFilter` replaces text or link tag, filtered list (`reference_filter_nodes`) will be updated for the next filter to use.
+
## Reference parsers
In a number of cases, as a performance optimization, we render Markdown to HTML
diff --git a/doc/development/telemetry/index.md b/doc/development/telemetry/index.md
index fbd81aca914..2af0614da54 100644
--- a/doc/development/telemetry/index.md
+++ b/doc/development/telemetry/index.md
@@ -133,6 +133,22 @@ Our reporting levels of aggregate or individual reporting varies by segment. For
| Aggregate | ✅ | 📅 | ✅ | ✅ | ✅ | 📅 | ✅ | ✅ |
| Individual | ✅ | 📅 | ✅ | 🔄 | ✅ | ✖️ | ✖️ | ✖️ |
+## Event types by segment
+
+The availability of event types and their tracking tools varies by segment. For example, on Self-Managed Users, we only have reporting using Database records via Usage Ping.
+
+| Event Types | SaaS Instance | SaaS Group | SaaS Session | SaaS User | Self-Managed Instance | Self-Managed Group | Self-Managed Session | Self-Managed User |
+|-------------------------------------|---------------|------------|--------------|-----------|-----------------------|--------------------|----------------------|-------------------|
+| Pageview events (Snowplow JS) | ✅ | 📅 | ✅ | 🔄 | 🔄 | 📅 | 🔄 | 🔄 |
+| Pageview events (Snowplow Ruby) | ✅ | 📅 | ✅ | 🔄 | 🔄 | 📅 | 🔄 | 🔄 |
+| UI events (Snowplow JS) | ✅ | 📅 | ✅ | 🔄 | 🔄 | 📅 | 🔄 | 🔄 |
+| CRUD and API events (Snowplow Ruby) | ✅ | 📅 | ✅ | 🔄 | 🔄 | 📅 | 🔄 | 🔄 |
+| Database records (Usage Ping) | ✅ | 📅 | ✖️ | ✅ | ✅ | 📅 | ✖️ | ✅ |
+| Database records (Database import) | ✅ | ✅ | ✖️ | ✅ | ✖️ | ✖️ | ✖️ | ✖️ |
+| Instance logs (Log system) | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ |
+| Instance settings (Usage Ping) | ✅ | 📅 | ✖️ | ✅ | ✅ | 📅 | ✖️ | ✅ |
+| Instance integrations (Usage Ping) | ✅ | 📅 | ✖️ | ✅ | ✅ | 📅 | ✖️ | ✅ |
+
**Legend**
✅ Available, 🔄 In Progress, 📅 Planned, ✖️ Not Possible
diff --git a/doc/gitlab-basics/README.md b/doc/gitlab-basics/README.md
index 0f95c9e0cb6..a7f18e13f74 100644
--- a/doc/gitlab-basics/README.md
+++ b/doc/gitlab-basics/README.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
comments: false
type: index
---
diff --git a/doc/gitlab-basics/add-file.md b/doc/gitlab-basics/add-file.md
index 13a1591fb76..c5b57d4623d 100644
--- a/doc/gitlab-basics/add-file.md
+++ b/doc/gitlab-basics/add-file.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: howto
---
diff --git a/doc/gitlab-basics/command-line-commands.md b/doc/gitlab-basics/command-line-commands.md
index b9426ec0849..e259aeef37b 100644
--- a/doc/gitlab-basics/command-line-commands.md
+++ b/doc/gitlab-basics/command-line-commands.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: howto, reference
---
diff --git a/doc/gitlab-basics/create-branch.md b/doc/gitlab-basics/create-branch.md
index e2a2fb52af8..0ad5cb53e97 100644
--- a/doc/gitlab-basics/create-branch.md
+++ b/doc/gitlab-basics/create-branch.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: howto
---
diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md
index def14cfce6d..929062102bb 100644
--- a/doc/gitlab-basics/create-project.md
+++ b/doc/gitlab-basics/create-project.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: howto
---
diff --git a/doc/gitlab-basics/create-your-ssh-keys.md b/doc/gitlab-basics/create-your-ssh-keys.md
index 248f39b842c..fba0408e26b 100644
--- a/doc/gitlab-basics/create-your-ssh-keys.md
+++ b/doc/gitlab-basics/create-your-ssh-keys.md
@@ -1,6 +1,10 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: howto
---
+
# Create and add your SSH key pair
It is best practice to use [Git over SSH instead of Git over HTTP](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols).
diff --git a/doc/gitlab-basics/feature_branch_workflow.md b/doc/gitlab-basics/feature_branch_workflow.md
index dd7eed89ea1..0fe04e62f22 100644
--- a/doc/gitlab-basics/feature_branch_workflow.md
+++ b/doc/gitlab-basics/feature_branch_workflow.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/workflow.html'
---
diff --git a/doc/gitlab-basics/fork-project.md b/doc/gitlab-basics/fork-project.md
index e92491a0821..76685db8d7d 100644
--- a/doc/gitlab-basics/fork-project.md
+++ b/doc/gitlab-basics/fork-project.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: howto
---
diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md
index d767bee4cf1..95b3a59ef6e 100644
--- a/doc/gitlab-basics/start-using-git.md
+++ b/doc/gitlab-basics/start-using-git.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: howto, tutorial
description: "Introduction to using Git through the command line."
last_updated: 2020-06-30
diff --git a/doc/integration/sourcegraph.md b/doc/integration/sourcegraph.md
index 90e9c7b9534..c366dab49b1 100644
--- a/doc/integration/sourcegraph.md
+++ b/doc/integration/sourcegraph.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: reference, how-to
---
diff --git a/doc/intro/README.md b/doc/intro/README.md
index 879d406d144..4bf9c766fc4 100644
--- a/doc/intro/README.md
+++ b/doc/intro/README.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
comments: false
---
diff --git a/doc/push_rules/push_rules.md b/doc/push_rules/push_rules.md
index e0ca914b67b..12c5bb3ba1b 100644
--- a/doc/push_rules/push_rules.md
+++ b/doc/push_rules/push_rules.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: reference, howto
---
diff --git a/doc/ssh/README.md b/doc/ssh/README.md
index 980a20ade3e..25913c6fa7c 100644
--- a/doc/ssh/README.md
+++ b/doc/ssh/README.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: howto, reference
---
diff --git a/doc/topics/git/feature_branch_development.md b/doc/topics/git/feature_branch_development.md
index ab3adf54dd7..762eddbc130 100644
--- a/doc/topics/git/feature_branch_development.md
+++ b/doc/topics/git/feature_branch_development.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: how-tos
---
diff --git a/doc/topics/git/how_to_install_git/index.md b/doc/topics/git/how_to_install_git/index.md
index 75ea6183a32..7b842b6a409 100644
--- a/doc/topics/git/how_to_install_git/index.md
+++ b/doc/topics/git/how_to_install_git/index.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
author: Sean Packham
author_gitlab: SeanPackham
level: beginner
diff --git a/doc/topics/git/index.md b/doc/topics/git/index.md
index 89da3dfdbd0..92181fb7bb0 100644
--- a/doc/topics/git/index.md
+++ b/doc/topics/git/index.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: index
---
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index 1e2f45fd67b..5875cdd4ca1 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -1,4 +1,8 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
+type: reference, howto
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/lfs/lfs/index.html'
---
diff --git a/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md b/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md
index 759da295d58..c62b7e1cc12 100644
--- a/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md
+++ b/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md
@@ -1,3 +1,10 @@
+---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
+type: reference, howto
+---
+
# Migration guide from Git Annex to Git LFS
NOTE: **Note:**
diff --git a/doc/topics/git/numerous_undo_possibilities_in_git/index.md b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
index fdf86d8f646..285ab133196 100644
--- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md
+++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
author: Crt Mori
author_gitlab: Letme
level: intermediary
diff --git a/doc/topics/git/partial_clone.md b/doc/topics/git/partial_clone.md
index 528cb44d90a..c976eda688a 100644
--- a/doc/topics/git/partial_clone.md
+++ b/doc/topics/git/partial_clone.md
@@ -1,3 +1,10 @@
+---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
+type: reference, howto
+---
+
# Partial Clone
As Git repositories grow in size, they can become cumbersome to work with
diff --git a/doc/topics/git/troubleshooting_git.md b/doc/topics/git/troubleshooting_git.md
index 010a811bd33..523718e4133 100644
--- a/doc/topics/git/troubleshooting_git.md
+++ b/doc/topics/git/troubleshooting_git.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: howto
---
diff --git a/doc/topics/git/useful_git_commands.md b/doc/topics/git/useful_git_commands.md
index 711567dbd06..0bf6075a1ea 100644
--- a/doc/topics/git/useful_git_commands.md
+++ b/doc/topics/git/useful_git_commands.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
type: reference
---
diff --git a/doc/topics/gitlab_flow.md b/doc/topics/gitlab_flow.md
index 221f6853891..339da40b29d 100644
--- a/doc/topics/gitlab_flow.md
+++ b/doc/topics/gitlab_flow.md
@@ -1,4 +1,7 @@
---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/gitlab_flow.html'
---
diff --git a/doc/update/README.md b/doc/update/README.md
index 2c681d6cec8..a82563bfefe 100644
--- a/doc/update/README.md
+++ b/doc/update/README.md
@@ -50,7 +50,8 @@ However, for this to work there are the following requirements:
migrations](../development/post_deployment_migrations.md) (included in
zero downtime update steps below).
- You are using PostgreSQL. Starting from GitLab 12.1, MySQL is not supported.
-- Multi-node GitLab instance. Single-node instances may experience brief interruptions as services restart.
+- Multi-node GitLab instance. Single-node instances may experience brief interruptions
+ [as services restart (Puma in particular)](https://docs.gitlab.com/omnibus/update/README.html#single-node-deployment).
Most of the time you can safely upgrade from a patch release to the next minor
release if the patch release is not the latest. For example, upgrading from
diff --git a/doc/user/asciidoc.md b/doc/user/asciidoc.md
index 6ed2cc1fe28..f1e881bddea 100644
--- a/doc/user/asciidoc.md
+++ b/doc/user/asciidoc.md
@@ -1,3 +1,10 @@
+---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
+type: reference, howto
+---
+
# AsciiDoc
GitLab uses the [Asciidoctor](https://asciidoctor.org) gem to convert AsciiDoc content to HTML5.
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index c116ee3e084..1332992b348 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -1,7 +1,8 @@
---
-stage: Plan
-group: Project Management
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
+type: reference, howto
---
# Threads
diff --git a/doc/user/index.md b/doc/user/index.md
index f50b712e2c3..1ab3541575c 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -1,4 +1,5 @@
---
+type: reference, index
description: 'Read through the GitLab User documentation to learn how to use, configure, and customize GitLab and GitLab.com to your own needs.'
---
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index 32e220522fb..895f89ac23f 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -1,7 +1,8 @@
---
-stage: Plan
-group: Project Management
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
+type: reference, howto
---
# GitLab Markdown
diff --git a/doc/user/search/advanced_global_search.md b/doc/user/search/advanced_global_search.md
index 0613e9b8e34..c8ef1d9e5af 100644
--- a/doc/user/search/advanced_global_search.md
+++ b/doc/user/search/advanced_global_search.md
@@ -1,3 +1,10 @@
+---
+stage: Create
+group: Editor
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
+type: reference
+---
+
# Advanced Global Search **(STARTER)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109) in GitLab [Starter](https://about.gitlab.com/pricing/) 8.4.
diff --git a/doc/user/search/advanced_search_syntax.md b/doc/user/search/advanced_search_syntax.md
index 5dc1f8fe779..c325c7e5e92 100644
--- a/doc/user/search/advanced_search_syntax.md
+++ b/doc/user/search/advanced_search_syntax.md
@@ -1,3 +1,10 @@
+---
+stage: Create
+group: Editor
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
+type: reference
+---
+
# Advanced Syntax Search **(STARTER)**
> - Introduced in [GitLab Enterprise Starter](https://about.gitlab.com/pricing/) 9.2
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index b616b606b64..98b34fe8383 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -1,3 +1,10 @@
+---
+stage: Create
+group: Editor
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
+type: index, reference, howto
+---
+
# Search through GitLab
## Issues and merge requests
diff --git a/doc/user/snippets.md b/doc/user/snippets.md
index 4d8f47ee3be..15391f034a8 100644
--- a/doc/user/snippets.md
+++ b/doc/user/snippets.md
@@ -1,3 +1,10 @@
+---
+stage: Create
+group: Editor
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
+type: reference
+---
+
# Snippets
With GitLab Snippets you can store and share bits of code and text with other users.
diff --git a/lib/api/entities/job_request/response.rb b/lib/api/entities/job_request/response.rb
index fdacd3af2da..8db9aff3dc9 100644
--- a/lib/api/entities/job_request/response.rb
+++ b/lib/api/entities/job_request/response.rb
@@ -33,3 +33,5 @@ module API
end
end
end
+
+API::Entities::JobRequest::Response.prepend_if_ee('EE::API::Entities::JobRequest::Response')
diff --git a/lib/gitlab/i18n/html_todo.yml b/lib/gitlab/i18n/html_todo.yml
index 19780991e54..b54a722eae8 100644
--- a/lib/gitlab/i18n/html_todo.yml
+++ b/lib/gitlab/i18n/html_todo.yml
@@ -93,19 +93,6 @@
- "Supprime la branche source"
- "elimina la rama origen"
- "Kaynak dalı siler"
-"A fork is a copy of a project.
Forking a repository allows you to make changes without affecting the original project.":
- plural_id:
- translations:
- - "Um fork é uma cópia de um projeto.
Fork de um repositório permite que você faça alterações sem afetar o projeto original."
- - "フォークはプロジェクトのコピーです。
リポジトリをフォークすると、元のプロジェクトに影響を与えずに変更することができます。"
- - "分叉是專案的複本。
分叉版本庫讓您在不影響原始專案的情況下,進行變更。"
- - "Um fork é uma cópia de um projeto.
Bifurcação de um repositório permite que faças alterações sem afetar o projeto original."
- - "Ответвление - это копия проекта.
Ответвление репозитория позволяет вносить изменения, не влияя на исходный проект."
- - "派生是项目的副本。
仓库的派生允许您在不影响原始项目的情况下进行更改。"
- - "Форк - це копія проєкту.
Форк репозиторію дозволяє вносити зміни без впливу на оригінальний проєкт."
- - "Ein Fork ist eine Kopie eines Projekts.
Wenn du ein Repository forkst, kannst du, ohne Auswirkungen auf das ursprüngliche Projekt, Änderungen vornehmen."
- - "포크는 프로젝트의 사본입니다.
저장소를 포크하면 원래 프로젝트에 영향을주지 않고 변경할 수 있습니다."
- - "Un fork es una copia de un proyecto.
Realizar un fork de un repositorio le permite realizar cambios sin afectar al proyecto original."
"Badges|You are going to delete this badge. Deleted badges cannot be restored.":
plural_id:
translations:
@@ -144,32 +131,6 @@
- "La branĉo %{branch_name} estis kreita. Por agordi aŭtomatan disponigadon, bonvolu elekti Yaml-ŝablonon por GitLab CI kaj enmeti viajn ŝanĝojn. %{link_to_autodeploy_doc}"
- "La branche %{branch_name} a été créée. Pour mettre en place le déploiement automatisé, sélectionnez un modèle de fichier YAML pour l’intégration continue (CI) de GitLab, et validez les modifications. %{link_to_autodeploy_doc}"
- "La rama %{branch_name} fue creada. Para configurar el auto despliegue, escoge una plantilla Yaml para GitLab CI y envía tus cambios. %{link_to_autodeploy_doc}"
-"Changes are shown as if the source revision was being merged into the target revision.":
- plural_id:
- translations:
- - "Mudanças serão mostradas se revisão de origem tiver sofrido merge na revisão alvo."
- - "sourceリビジョンがtargetリビジョン内に取り込まれているような変更として表示されます"
- - "As alterações são mostradas como se a revisão de origem estivesse a ser mesclada na revisão de destino."
- - "Показаны изменения как будто произошло слияние ревизии кода источника с целевой ревизией кода."
- - "差异显示方式依源版本合并到目标版本的形式。"
- - "Зміни відображаються так, ніби редакція-джерело була злита в цільову редакцію."
- - "Änderungen werden angezeigt, als ob die Quell-Revision in die Ziel-Revision gemerged wurde."
- - "변경 사항은 source 리비전이 target 리비전에 머지된 것처럼 표시됩니다."
- - "Les modifications sont affichées comme si la révision source était fusionnée dans la révisioncible."
- - "Los cambios se muestran como si la revisión del origen se ha fusionado con la revisión del objetivo."
-"Choose between clone
or fetch
to get the recent application code":
- plural_id:
- translations:
- - "Escolha entre clone
ou fetch
para obter o código do aplicativo recente"
- - "clone
または fetch
を選択して最新のアプリケーションコードを取得してください"
- - "Escolhe entre clone
ou fetch
para obter o código da aplicação recente"
- - "选择 克隆
或 拉取
以获取最近的应用程序代码"
- - "Оберіть між clone
таfetch
щоб отримати найновіший код програми"
- - "Wähle zwischen clone
oder fetch
, um den aktuellen Anwendungscode zu erhalten"
- - "최근 응용 프로그램 코드를 얻으려면 클론
또는 fetch
를 선택하십시오."
- - "Choisissez entre clone
ou fetch
pour obtenir les dernières modifications du code de l’application"
- - "Elija entre clone
o fetch
para obtener el código de la aplicación más reciente"
- - "Wybierz pomiędzy klonem
lub pobierz
aby uzyskać najnowszy kod aplikacji"
"ClusterIntegration| This will permanently delete the following resources: - All installed applications and related resources
- The
gitlab-managed-apps
namespace - Any project namespaces
clusterroles
clusterrolebindings
":
plural_id:
translations:
@@ -222,14 +183,6 @@
- "Contributions du %{calendar_date}"
- "Contribuciones para %{calendar_date}"
- "%{calendar_date} için katkılar"
-"Define environments in the deploy stage(s) in .gitlab-ci.yml
to track deployments here.":
- plural_id:
- translations:
- - "デプロイステージの環境を .gitlab-ci.yml
で定義して、デプロイを追跡します。"
- - "Обозначьте окружения на этапе(ах) развёртывания в .gitlab-ci.yml
для отслеживания развёртывания здесь."
- - "在.githab-ci.yml
的 deploy 阶段中定义 environment 来跟踪部署。"
- - "Визначте середовища на стадії розгортання у .gitlab-ci.yml
щоб відстежувати розгортання тут."
- - "Defina entornos en las distintas etapas de despliegue en el fichero .gitlab-ci.yml
para llevar un registro de las implementaciones desde aquí."
"Depends on %d closed merge request.":
plural_id: "Depends on %d closed merge requests."
translations:
@@ -274,11 +227,6 @@
- "完成您的%{group_name}专用帐户设置。"
- "Завершіть налаштування вашого виділеного облікового запису для %{group_name}."
- "Finalizar la configuración de su cuenta dedicada para %{group_name}."
-"From %{source_title}
into":
- plural_id:
- translations:
- - "%{source_title}
から"
- - "Від %{source_title}
до"
"Geo|You are on a secondary, read-only Geo node. If you want to make changes, you must visit this page on the %{primary_node}.":
plural_id:
translations:
@@ -326,14 +274,6 @@
"Go to Issues > Boards to access your personalized learning issue board.":
plural_id:
translations:
-"Groups with access to %{project_name}":
- plural_id:
- translations:
- - "Grupos com acesso a %{project_name}"
- - "%{project_name}へのアクセス権を持つグループ"
- - "可以访问 %{project_name}"
- - "Групи з доступом до %{project_name}"
- - "Los grupos con acceso a %{project_name}"
"In order to personalize your experience with GitLab
we would like to know a bit more about you.":
plural_id:
translations:
@@ -439,32 +379,6 @@
- "회원과 %{sso_label} 항목을 공유해 신원 제공 업체를 통해 그룹에 로그인할 수 있도록 합니다."
- "Partager le %{sso_label} avec les membres afin qu’ils puissent se connecter à votre groupe via votre fournisseur d’identité"
- "Comparta %{sso_label} con los diferentes miembros para que puedan iniciar sesión en su grupo a través de su proveedor de identidad"
-"SlackIntegration|Note: Usernames and private channels are not supported.":
- plural_id:
- translations:
- - " 注: ユーザー名とプライベートチャネルはサポートしていません。"
- - "Примечание: Имена пользователей и частные каналы не поддерживаются."
-"SlackIntegration|Paste the Webhook URL into the field below.":
- plural_id:
- translations:
- - "Вставьте URL веб-обработчика в поле ниже."
-"SlackIntegration|Select events below to enable notifications. The Slack channel names and Slack username fields are optional.":
- plural_id:
- translations:
-"SlackService|2. Paste the Token into the field below":
- plural_id:
- translations:
- - "2. トークン を下のフィールドに貼り付けます"
- - "2. 将Token粘贴到下面的字段中"
- - "2. Вставте Токен у поле нижче"
- - "2. Pegue el Token en el campo que se muestra a continuación"
-"SlackService|3. Select the Active checkbox, press Save changes and start using GitLab inside Slack!":
- plural_id:
- translations:
- - "3. アクティブな チェックボックスを選択し、 変更を保存 を押して、Slack内でGitLabの使用を開始します!"
- - "Выберите флажок Активный, нажмите на Сохранить изменения и начните использовать GitLab внутри Slack!"
- - "3. 选择Active复选框,点击Save change后开始在Slack中使用GitLab!"
- - "3. Встановіть прапорець в пункті Активний, натисніть Зберегти зміни та починайте використовувати GitLab в Slack!"
"Speed up your DevOps
with GitLab":
plural_id:
translations:
@@ -480,14 +394,6 @@
- "Les objets Git LFS ne sont pas synchronisés."
- "Los objetos Git LFS no serán sincronizados."
- "Obiekty Git LFS nie będą zsynchronizowane."
-"The path to the CI configuration file. Defaults to .gitlab-ci.yml
":
- plural_id:
- translations:
- - "CI 設定ファイルへのパス。デフォルトは .gitlab-ci.yml
"
- - "Путь к файлу конфигурации CI. По умолчанию это .gitlab-ci.yml
"
- - "CI配置文件的路径。默认为.gitlab-ci.yml
"
- - "Шлях до кофігураційного файлу CI. За замовчуванням .gitlab-ci.yml
"
- - "La ruta al archivo de configuración CI. Por defecto .gitlab-ci.yml
"
"The repository must be accessible over http://
, https://
, ssh://
or git://
.":
plural_id:
translations:
@@ -504,30 +410,6 @@
- "此%{issuable}已被锁定。只有项目成员可以发表评论。"
- "Ця %{issuable} заблокована. Лише учасники проекту можуть коментувати."
- "Este %{issuable} está bloqueado. Solo los miembros del proyecto pueden comentar."
-"This commit was signed with a verified signature and the committer email is verified to belong to the same user.":
- plural_id:
- translations:
- - "このコミットは 検証済み の署名でサインされており、このコミッターのメールは同じユーザーのものであることが検証されています。"
- - "Это коммит был подписан верифицированной подписью и коммитер подтвердил, что адрес почты принадлежит ему."
- - "此提交使用 已验证 的签名进行签名,并且已验证提交者的电子邮件属于同一用户。"
- - "Цей коміт підписано перевіреним підписом і адреса електронної пошти комітера гарантовано належить тому самому користувачу."
- - "Este commit fue firmado con una firma verificada, y se ha verificado que la dirección de correo electrónico del committer y la firma pertenecen al mismo usuario."
-"This commit was signed with a verified signature, but the committer email is not verified to belong to the same user.":
- plural_id:
- translations:
- - "このコミットは検証済みの署名でサインされています。しかしコミッターのメールは、 同じユーザーのものと検証されていません。"
- - "Этот коммит был подписан верифицированной подписью, но не подтверждена принадлежность электронной почты коммитеру."
- - "此提交已使用经过验证的签名进行签名,但未验证的提交者电子邮件属于同一用户。"
- - "Цей коміт підписано перевіреним підписом але адреса електронної пошти комітера не гарантовано належить тому самому користувачу."
- - "Este commit fue firmado con una firma verificada, pero no se ha verificado si la dirección de correo electrónico del commiter y la firma pertenecen al mismo usuario."
-"This commit was signed with an unverified signature.":
- plural_id:
- translations:
- - "このコミットは検証されていない 署名でサインされています。"
- - "Этот коммит был подписан непроверенной подписью."
- - "此提交使用 未经验证的 签名进行签名。"
- - "Цей коміт підписано неперевіреним підписом."
- - "Esta commit fue firmado con una firma no verificada."
"This group, including all subgroups, projects and git repositories, will only be reachable from the specified IP address range. Multiple addresses are supported with comma delimiters.
Example: 192.168.0.0/24,192.168.1.0/24
. %{read_more_link}.":
plural_id:
translations:
@@ -536,13 +418,6 @@
- "此群组,包括所有子群组、项目和git仓库,只能从指定的IP地址范围中访问。支持用逗号分隔符分隔的多个地址列表。例如: 192.168.0.0/24,168.1.0/24
. %{read_more_link}。"
- "Ця група разом із усіма її підгрупами, проектами та репозиторями Git буде доступна тільки із вказаного діапазону IP-адрес. Підтримується декілька адрес, розділених комами.
Наприклад: 192.168.0.0/24
.%{read_more_link}."
- "Este grupo, incluyendo todos los subgrupos, proyectos y repositorios git, sólo será accesible desde el rango de direcciones IP especificado. Se admiten múltiples direcciones delimitadas con comas.
Ejemplo: 192.168.0.0/24,192.168.1.0/24
. %{read_more_link}."
-"This pipeline makes use of a predefined CI/CD configuration enabled by Auto DevOps.":
- plural_id:
- translations:
- - "このパイプラインは、Auto DevOpsによって有効化された定義済みのCI/CD構成を利用します。"
- - "此流水线使用了 Auto DevOps 预先定义的并已启用的 CI/CD 配置。"
- - "Цей конвеєр використовує попередньо визначену конфігурацію CI / CD, увімкнену за допомогою Auto DevOps"
- - "Este pipeline utiliza una configuración de CI/CD predefinida habilitada por Auto DevOps."
"This project does not have billing enabled. To create a cluster, enable billing and try again.":
plural_id:
translations:
@@ -553,28 +428,6 @@
- "Für dieses Projekt ist keine Abrechnung aktiviert. Um ein Cluster zu erstellen, aktiviere die Abrechnung und versuche es erneut."
- "Ce projet n’a pas de facturation activée. Afin de créer une grappe de serveurs, veuillez activer la facturation et réessayer."
- "Este proyecto no tiene la facturación habilitada. Para crear un clúster, habilite la facturación e inténtelo de nuevo."
-"This project will live in your group %{namespace}. A project is where you house your files (repository), plan your work (issues), publish your documentation (wiki), and so much more.":
- plural_id:
- translations:
-"To only use CI/CD features for an external repository, choose CI/CD for external repo.":
- plural_id:
- translations:
- - "Para usar apenas recursos CI/CD para um repositório externo, escolha CI/CD para repo externo."
- - "外部リポジトリにのみ CI/CD の機能を使用するには、外部リポジトリ用 CI/CDを選択してください。"
- - "要仅为外部仓库使用CI / CD功能时,请选择使用外部仓库运行CI/CD。"
- - "Щоб використовувати лише функції CI/CD для зовнішнього репозиторію, виберіть CI/CD для зовнішнього репозиторію."
- - "Um die CI/CD-Funktionen nur für ein externes Repository zu verwenden, wähle CI/CD für externes Repo aus."
- - "CI/CD 기능만 외부 저장소를 위해 사용할 수 있습니다, 외부 저장소용 CI/CD 저장소를 선택하십시오."
- - "Pour n’utiliser uniquement que les fonctionnalités d’intégration et livraison continues (CI / CD) pour un dépôt externe, choisissez Intégration et livraison continues (CI / CD) pour dépôt externe."
- - "Para utilizar únicamente las funciones de CI/CD en un repositorio externo, seleccione CI/CD para un repositorio externo."
- - "Harici bir depoda yalnızca CI/CD özelliklerini kullanmak için Harici depo için CI/CD'yi seçin."
-"To preserve performance only %{display_size} of %{real_size} files are displayed.":
- plural_id:
- translations:
- - "パフォーマンス維持のため、 %{real_size} 個中 %{display_size} 個 のファイルのみが表示されています。"
- - "为了保持性能,仅显示文件中的 %{display_size}/%{real_size}。"
- - "Для збереження швидкодії відображаються лише %{display_size} із %{real_size} файлів."
- - "Para mantener el rendimiento, solo se muestran %{display_size} de %{real_size} archivos."
"Unlock this %{issuableDisplayName}? Everyone will be able to comment.":
plural_id:
translations:
@@ -1053,3 +906,150 @@
- "CSV导出将在后台创建。完成后,它将以附件形式发送到%{email}。"
- "Експорт CSV буде створено у фоновому режимі. Після завершення його буде надіслано на %{email} у вкладенні."
- "La exportación CSV se creará en segundo plano. Una vez finalizada, será enviada a %{email} como un fichero adjunto al correo electrónico."
+"A fork is a copy of a project.
Forking a repository allows you to make changes without affecting the original project.":
+ plural_id:
+ translations:
+ - "Um fork é uma cópia de um projeto.
Fork de um repositório permite que você faça alterações sem afetar o projeto original."
+ - "フォークはプロジェクトのコピーです。
リポジトリをフォークすると、元のプロジェクトに影響を与えずに変更することができます。"
+ - "分叉是專案的複本。
分叉版本庫讓您在不影響原始專案的情況下,進行變更。"
+ - "Um fork é uma cópia de um projeto.
Bifurcação de um repositório permite que faças alterações sem afetar o projeto original."
+ - "Ответвление - это копия проекта.
Ответвление репозитория позволяет вносить изменения, не влияя на исходный проект."
+ - "派生是项目的副本。
仓库的派生允许您在不影响原始项目的情况下进行更改。"
+ - "Форк - це копія проєкту.
Форк репозиторію дозволяє вносити зміни без впливу на оригінальний проєкт."
+ - "Ein Fork ist eine Kopie eines Projekts.
Wenn du ein Repository forkst, kannst du, ohne Auswirkungen auf das ursprüngliche Projekt, Änderungen vornehmen."
+ - "포크는 프로젝트의 사본입니다.
저장소를 포크하면 원래 프로젝트에 영향을주지 않고 변경할 수 있습니다."
+ - "Un fork es una copia de un proyecto.
Realizar un fork de un repositorio le permite realizar cambios sin afectar al proyecto original."
+"Changes are shown as if the source revision was being merged into the target revision.":
+ plural_id:
+ translations:
+ - "Mudanças serão mostradas se revisão de origem tiver sofrido merge na revisão alvo."
+ - "sourceリビジョンがtargetリビジョン内に取り込まれているような変更として表示されます"
+ - "As alterações são mostradas como se a revisão de origem estivesse a ser mesclada na revisão de destino."
+ - "Показаны изменения как будто произошло слияние ревизии кода источника с целевой ревизией кода."
+ - "差异显示方式依源版本合并到目标版本的形式。"
+ - "Зміни відображаються так, ніби редакція-джерело була злита в цільову редакцію."
+ - "Änderungen werden angezeigt, als ob die Quell-Revision in die Ziel-Revision gemerged wurde."
+ - "변경 사항은 source 리비전이 target 리비전에 머지된 것처럼 표시됩니다."
+ - "Les modifications sont affichées comme si la révision source était fusionnée dans la révisioncible."
+ - "Los cambios se muestran como si la revisión del origen se ha fusionado con la revisión del objetivo."
+"From %{source_title}
into":
+ plural_id:
+ translations:
+ - "%{source_title}
から"
+ - "Від %{source_title}
до"
+"Choose between clone
or fetch
to get the recent application code":
+ plural_id:
+ translations:
+ - "Escolha entre clone
ou fetch
para obter o código do aplicativo recente"
+ - "clone
または fetch
を選択して最新のアプリケーションコードを取得してください"
+ - "Escolhe entre clone
ou fetch
para obter o código da aplicação recente"
+ - "选择 克隆
或 拉取
以获取最近的应用程序代码"
+ - "Оберіть між clone
таfetch
щоб отримати найновіший код програми"
+ - "Wähle zwischen clone
oder fetch
, um den aktuellen Anwendungscode zu erhalten"
+ - "최근 응용 프로그램 코드를 얻으려면 클론
또는 fetch
를 선택하십시오."
+ - "Choisissez entre clone
ou fetch
pour obtenir les dernières modifications du code de l’application"
+ - "Elija entre clone
o fetch
para obtener el código de la aplicación más reciente"
+ - "Wybierz pomiędzy klonem
lub pobierz
aby uzyskać najnowszy kod aplikacji"
+"The path to the CI configuration file. Defaults to .gitlab-ci.yml
":
+ plural_id:
+ translations:
+ - "CI 設定ファイルへのパス。デフォルトは .gitlab-ci.yml
"
+ - "Путь к файлу конфигурации CI. По умолчанию это .gitlab-ci.yml
"
+ - "CI配置文件的路径。默认为.gitlab-ci.yml
"
+ - "Шлях до кофігураційного файлу CI. За замовчуванням .gitlab-ci.yml
"
+ - "La ruta al archivo de configuración CI. Por defecto .gitlab-ci.yml
"
+"Define environments in the deploy stage(s) in .gitlab-ci.yml
to track deployments here.":
+ plural_id:
+ translations:
+ - "デプロイステージの環境を .gitlab-ci.yml
で定義して、デプロイを追跡します。"
+ - "Обозначьте окружения на этапе(ах) развёртывания в .gitlab-ci.yml
для отслеживания развёртывания здесь."
+ - "在.githab-ci.yml
的 deploy 阶段中定义 environment 来跟踪部署。"
+ - "Визначте середовища на стадії розгортання у .gitlab-ci.yml
щоб відстежувати розгортання тут."
+ - "Defina entornos en las distintas etapas de despliegue en el fichero .gitlab-ci.yml
para llevar un registro de las implementaciones desde aquí."
+"Groups with access to %{project_name}":
+ plural_id:
+ translations:
+ - "Grupos com acesso a %{project_name}"
+ - "%{project_name}へのアクセス権を持つグループ"
+ - "可以访问 %{project_name}"
+ - "Групи з доступом до %{project_name}"
+ - "Los grupos con acceso a %{project_name}"
+"This commit was signed with a verified signature, but the committer email is not verified to belong to the same user.":
+ plural_id:
+ translations:
+ - "このコミットは検証済みの署名でサインされています。しかしコミッターのメールは、 同じユーザーのものと検証されていません。"
+ - "Этот коммит был подписан верифицированной подписью, но не подтверждена принадлежность электронной почты коммитеру."
+ - "此提交已使用经过验证的签名进行签名,但未验证的提交者电子邮件属于同一用户。"
+ - "Цей коміт підписано перевіреним підписом але адреса електронної пошти комітера не гарантовано належить тому самому користувачу."
+ - "Este commit fue firmado con una firma verificada, pero no se ha verificado si la dirección de correo electrónico del commiter y la firma pertenecen al mismo usuario."
+"This commit was signed with an unverified signature.":
+ plural_id:
+ translations:
+ - "このコミットは検証されていない 署名でサインされています。"
+ - "Этот коммит был подписан непроверенной подписью."
+ - "此提交使用 未经验证的 签名进行签名。"
+ - "Цей коміт підписано неперевіреним підписом."
+ - "Esta commit fue firmado con una firma no verificada."
+"This commit was signed with a verified signature and the committer email is verified to belong to the same user.":
+ plural_id:
+ translations:
+ - "このコミットは 検証済み の署名でサインされており、このコミッターのメールは同じユーザーのものであることが検証されています。"
+ - "Это коммит был подписан верифицированной подписью и коммитер подтвердил, что адрес почты принадлежит ему."
+ - "此提交使用 已验证 的签名进行签名,并且已验证提交者的电子邮件属于同一用户。"
+ - "Цей коміт підписано перевіреним підписом і адреса електронної пошти комітера гарантовано належить тому самому користувачу."
+ - "Este commit fue firmado con una firma verificada, y se ha verificado que la dirección de correo electrónico del committer y la firma pertenecen al mismo usuario."
+"To preserve performance only %{display_size} of %{real_size} files are displayed.":
+ plural_id:
+ translations:
+ - "パフォーマンス維持のため、 %{real_size} 個中 %{display_size} 個 のファイルのみが表示されています。"
+ - "为了保持性能,仅显示文件中的 %{display_size}/%{real_size}。"
+ - "Для збереження швидкодії відображаються лише %{display_size} із %{real_size} файлів."
+ - "Para mantener el rendimiento, solo se muestran %{display_size} de %{real_size} archivos."
+"This pipeline makes use of a predefined CI/CD configuration enabled by Auto DevOps.":
+ plural_id:
+ translations:
+ - "このパイプラインは、Auto DevOpsによって有効化された定義済みのCI/CD構成を利用します。"
+ - "此流水线使用了 Auto DevOps 预先定义的并已启用的 CI/CD 配置。"
+ - "Цей конвеєр використовує попередньо визначену конфігурацію CI / CD, увімкнену за допомогою Auto DevOps"
+ - "Este pipeline utiliza una configuración de CI/CD predefinida habilitada por Auto DevOps."
+"This project will live in your group %{namespace}. A project is where you house your files (repository), plan your work (issues), publish your documentation (wiki), and so much more.":
+ plural_id:
+ translations:
+"To only use CI/CD features for an external repository, choose CI/CD for external repo.":
+ plural_id:
+ translations:
+ - "Para usar apenas recursos CI/CD para um repositório externo, escolha CI/CD para repo externo."
+ - "外部リポジトリにのみ CI/CD の機能を使用するには、外部リポジトリ用 CI/CDを選択してください。"
+ - "要仅为外部仓库使用CI / CD功能时,请选择使用外部仓库运行CI/CD。"
+ - "Щоб використовувати лише функції CI/CD для зовнішнього репозиторію, виберіть CI/CD для зовнішнього репозиторію."
+ - "Um die CI/CD-Funktionen nur für ein externes Repository zu verwenden, wähle CI/CD für externes Repo aus."
+ - "CI/CD 기능만 외부 저장소를 위해 사용할 수 있습니다, 외부 저장소용 CI/CD 저장소를 선택하십시오."
+ - "Pour n’utiliser uniquement que les fonctionnalités d’intégration et livraison continues (CI / CD) pour un dépôt externe, choisissez Intégration et livraison continues (CI / CD) pour dépôt externe."
+ - "Para utilizar únicamente las funciones de CI/CD en un repositorio externo, seleccione CI/CD para un repositorio externo."
+ - "Harici bir depoda yalnızca CI/CD özelliklerini kullanmak için Harici depo için CI/CD'yi seçin."
+"SlackIntegration|Paste the Webhook URL into the field below.":
+ plural_id:
+ translations:
+ - "Вставьте URL веб-обработчика в поле ниже."
+"SlackIntegration|Select events below to enable notifications. The Slack channel names and Slack username fields are optional.":
+ plural_id:
+ translations:
+"SlackIntegration|Note: Usernames and private channels are not supported.":
+ plural_id:
+ translations:
+ - " 注: ユーザー名とプライベートチャネルはサポートしていません。"
+ - "Примечание: Имена пользователей и частные каналы не поддерживаются."
+"SlackService|2. Paste the Token into the field below":
+ plural_id:
+ translations:
+ - "2. トークン を下のフィールドに貼り付けます"
+ - "2. 将Token粘贴到下面的字段中"
+ - "2. Вставте Токен у поле нижче"
+ - "2. Pegue el Token en el campo que se muestra a continuación"
+"SlackService|3. Select the Active checkbox, press Save changes and start using GitLab inside Slack!":
+ plural_id:
+ translations:
+ - "3. アクティブな チェックボックスを選択し、 変更を保存 を押して、Slack内でGitLabの使用を開始します!"
+ - "Выберите флажок Активный, нажмите на Сохранить изменения и начните использовать GitLab внутри Slack!"
+ - "3. 选择Active复选框,点击Save change后开始在Slack中使用GitLab!"
+ - "3. Встановіть прапорець в пункті Активний, натисніть Зберегти зміни та починайте використовувати GitLab в Slack!"
diff --git a/lib/gitlab/metrics/dashboard/stages/metric_endpoint_inserter.rb b/lib/gitlab/metrics/dashboard/stages/metric_endpoint_inserter.rb
index c48a7ff25a5..944977a4bc8 100644
--- a/lib/gitlab/metrics/dashboard/stages/metric_endpoint_inserter.rb
+++ b/lib/gitlab/metrics/dashboard/stages/metric_endpoint_inserter.rb
@@ -45,7 +45,9 @@ module Gitlab
raise Errors::MissingQueryError.new('Each "metric" must define one of :query or :query_range') unless query
- query
+ # We need to remove any newlines since our UrlBlocker does not allow
+ # multiline URLs.
+ query.squish
end
end
end
diff --git a/lib/gitlab/prometheus_client.rb b/lib/gitlab/prometheus_client.rb
index 69499b5494e..cf1abb3d2ec 100644
--- a/lib/gitlab/prometheus_client.rb
+++ b/lib/gitlab/prometheus_client.rb
@@ -132,7 +132,7 @@ module Gitlab
def http_options
strong_memoize(:http_options) do
- { follow_redirects: false }.merge(mapped_options)
+ { follow_redirects: false, open_timeout: 5, read_timeout: 10 }.merge(mapped_options)
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index a90510b842e..a7c3d2f45a4 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1091,7 +1091,7 @@ msgstr ""
msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr ""
-msgid "A fork is a copy of a project.
Forking a repository allows you to make changes without affecting the original project."
+msgid "A fork is a copy of a project."
msgstr ""
msgid "A group is a collection of several projects"
@@ -4386,7 +4386,7 @@ msgstr ""
msgid "Changes affect new repositories only. If not specified, Git's default name %{branch_name_default} will be used."
msgstr ""
-msgid "Changes are shown as if the source revision was being merged into the target revision."
+msgid "Changes are shown as if the %{b_open}source%{b_close} revision was being merged into the %{b_open}target%{b_close} revision."
msgstr ""
msgid "Changes are still tracked. Useful for cluster/index migrations."
@@ -4683,7 +4683,7 @@ msgstr ""
msgid "Choose any color."
msgstr ""
-msgid "Choose between clone
or fetch
to get the recent application code"
+msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
msgstr ""
msgid "Choose file…"
@@ -7651,7 +7651,7 @@ msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
-msgid "Define environments in the deploy stage(s) in .gitlab-ci.yml
to track deployments here."
+msgid "Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here."
msgstr ""
msgid "Definition"
@@ -10669,6 +10669,9 @@ msgstr ""
msgid "ForkedFromProjectPath|Forked from an inaccessible project"
msgstr ""
+msgid "Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "Forking in progress"
msgstr ""
@@ -10708,10 +10711,10 @@ msgstr ""
msgid "From"
msgstr ""
-msgid "From %{providerTitle}"
+msgid "From %{code_open}%{source_title}%{code_close} into"
msgstr ""
-msgid "From %{source_title}
into"
+msgid "From %{providerTitle}"
msgstr ""
msgid "From Google Code"
@@ -11188,7 +11191,7 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
-msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will not be synced in push mirrors."
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will %{strong_open}not%{strong_close} be synced in push mirrors."
msgstr ""
msgid "Git LFS status:"
@@ -12070,10 +12073,10 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
+msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{project_name}"
+msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
msgid "GroupsDropdown|Frequently visited"
@@ -12767,7 +12770,7 @@ msgstr ""
msgid "Include merge request description"
msgstr ""
-msgid "Include the username in the URL if required: https://username@gitlab.company.com/group/project.git
."
+msgid "Include the username in the URL if required: %{code_open}https://username@gitlab.company.com/group/project.git%{code_close}."
msgstr ""
msgid "Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited."
@@ -14651,10 +14654,10 @@ msgstr ""
msgid "Members"
msgstr ""
-msgid "Members can be added by project Maintainers or Owners"
+msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members of %{project_name}"
+msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
msgid "Members of a group may only view projects they have permission to access"
@@ -22108,25 +22111,25 @@ msgstr ""
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
+msgid "SlackIntegration|%{strong_open}Note:%{strong_close} Usernames and private channels are not supported."
+msgstr ""
+
msgid "SlackIntegration|%{webhooks_link_start}Add an incoming webhook%{webhooks_link_end} in your Slack team. The default channel can be overridden for each event."
msgstr ""
-msgid "SlackIntegration|Note: Usernames and private channels are not supported."
+msgid "SlackIntegration|Paste the %{strong_open}Webhook URL%{strong_close} into the field below."
msgstr ""
-msgid "SlackIntegration|Paste the Webhook URL into the field below."
-msgstr ""
-
-msgid "SlackIntegration|Select events below to enable notifications. The Slack channel names and Slack username fields are optional."
+msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
msgstr ""
-msgid "SlackService|2. Paste the Token into the field below"
+msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
msgstr ""
-msgid "SlackService|3. Select the Active checkbox, press Save changes and start using GitLab inside Slack!"
+msgid "SlackService|3. Select the %{strong_open}Active%{strong_close} checkbox, press %{strong_open}Save changes%{strong_close} and start using GitLab inside Slack!"
msgstr ""
msgid "SlackService|Fill in the word that works best for your team."
@@ -23843,7 +23846,7 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to .gitlab-ci.yml
"
+msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
msgstr ""
msgid "The phase of the development lifecycle."
@@ -23912,7 +23915,7 @@ msgstr ""
msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close} or %{code_open}git://%{code_close}."
msgstr ""
-msgid "The repository must be accessible over http://
, https://
, ssh://
or git://
."
+msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} or %{code_open}git://%{code_close}."
msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
@@ -24326,13 +24329,19 @@ msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
+msgid "This commit was signed with a %{strong_open}verified%{strong_close} signature and the committer email is verified to belong to the same user."
+msgstr ""
+
msgid "This commit was signed with a verified signature and the committer email is verified to belong to the same user."
msgstr ""
msgid "This commit was signed with a different user's verified signature."
msgstr ""
-msgid "This commit was signed with a verified signature, but the committer email is not verified to belong to the same user."
+msgid "This commit was signed with a verified signature, but the committer email is %{strong_open}not verified%{strong_close} to belong to the same user."
+msgstr ""
+
+msgid "This commit was signed with an %{strong_open}unverified%{strong_close} signature."
msgstr ""
msgid "This commit was signed with an unverified signature."
@@ -24605,10 +24614,10 @@ msgstr ""
msgid "This pipeline does not use the %{codeStart}needs%{codeEnd} keyword and can't be represented as a directed acyclic graph."
msgstr ""
-msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}"
msgstr ""
-msgid "This pipeline makes use of a predefined CI/CD configuration enabled by Auto DevOps."
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
msgstr ""
msgid "This pipeline was triggered by a schedule."
@@ -24644,7 +24653,7 @@ msgstr ""
msgid "This project will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
-msgid "This project will live in your group %{namespace}. A project is where you house your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
+msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you house your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
msgstr ""
msgid "This repository"
@@ -25104,13 +25113,13 @@ msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
-msgid "To only use CI/CD features for an external repository, choose CI/CD for external repo."
+msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
-msgid "To preserve performance only %{display_size} of %{real_size} files are displayed."
+msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
msgid "To protect this issue's confidentiality, %{forkLink} and set the fork's visibility to private."
@@ -26958,9 +26967,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the http://
or https://
protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
diff --git a/package.json b/package.json
index 8b9f3d8005e..cc5bb07a5f5 100644
--- a/package.json
+++ b/package.json
@@ -111,7 +111,7 @@
"minimatch": "^3.0.4",
"monaco-editor": "^0.20.0",
"monaco-editor-webpack-plugin": "^1.9.0",
- "monaco-yaml": "^2.4.0",
+ "monaco-yaml": "^2.4.1",
"mousetrap": "^1.4.6",
"pdfjs-dist": "^2.0.943",
"pikaday": "^1.8.0",
diff --git a/spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml b/spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml
index 1e41ef669d1..287e78c9405 100644
--- a/spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml
+++ b/spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml
@@ -41,7 +41,17 @@ panel_groups:
max_value: 1
metrics:
- id: metric_a1
- query_range: 'query'
+ query_range: |+
+ avg(
+ sum(
+ container_memory_usage_bytes{
+ container_name!="POD",
+ pod_name=~"^{{ci_environment_slug}}-(.*)",
+ namespace="{{kube_namespace}}"
+ }
+ ) by (job)
+ ) without (job)
+ /1024/1024/1024
unit: unit
label: Legend Label
- title: "Super Chart A2"
diff --git a/spec/frontend/__mocks__/monaco-editor/index.js b/spec/frontend/__mocks__/monaco-editor/index.js
index b9602d69b74..18b7df32f9b 100644
--- a/spec/frontend/__mocks__/monaco-editor/index.js
+++ b/spec/frontend/__mocks__/monaco-editor/index.js
@@ -8,11 +8,11 @@ import 'monaco-editor/esm/vs/language/css/monaco.contribution';
import 'monaco-editor/esm/vs/language/json/monaco.contribution';
import 'monaco-editor/esm/vs/language/html/monaco.contribution';
import 'monaco-editor/esm/vs/basic-languages/monaco.contribution';
-import 'monaco-yaml/esm/monaco.contribution';
+import 'monaco-yaml/lib/esm/monaco.contribution';
// This language starts trying to spin up web workers which obviously breaks in Jest environment
jest.mock('monaco-editor/esm/vs/language/typescript/tsMode');
-jest.mock('monaco-yaml/esm/yamlMode');
+jest.mock('monaco-yaml/lib/esm/yamlMode');
export * from 'monaco-editor/esm/vs/editor/editor.api';
export default global.monaco;
diff --git a/spec/frontend/branches/components/__snapshots__/divergence_graph_spec.js.snap b/spec/frontend/branches/components/__snapshots__/divergence_graph_spec.js.snap
index c9948db95f8..261c406171e 100644
--- a/spec/frontend/branches/components/__snapshots__/divergence_graph_spec.js.snap
+++ b/spec/frontend/branches/components/__snapshots__/divergence_graph_spec.js.snap
@@ -12,7 +12,7 @@ exports[`Branch divergence graph component renders ahead and behind count 1`] =
/>
@@ -107,7 +107,7 @@ exports[`Design management design version dropdown component renders design vers
diff --git a/spec/frontend/design_management_legacy/components/upload/__snapshots__/design_version_dropdown_spec.js.snap b/spec/frontend/design_management_legacy/components/upload/__snapshots__/design_version_dropdown_spec.js.snap
index 00f1a40dfb2..a6b30d57c0d 100644
--- a/spec/frontend/design_management_legacy/components/upload/__snapshots__/design_version_dropdown_spec.js.snap
+++ b/spec/frontend/design_management_legacy/components/upload/__snapshots__/design_version_dropdown_spec.js.snap
@@ -28,7 +28,7 @@ exports[`Design management design version dropdown component renders design vers
@@ -83,7 +83,7 @@ exports[`Design management design version dropdown component renders design vers
diff --git a/spec/frontend/filtered_search/filtered_search_manager_spec.js b/spec/frontend/filtered_search/filtered_search_manager_spec.js
index 70e8b339d4b..37a5e294f7a 100644
--- a/spec/frontend/filtered_search/filtered_search_manager_spec.js
+++ b/spec/frontend/filtered_search/filtered_search_manager_spec.js
@@ -225,6 +225,26 @@ describe('Filtered Search Manager', () => {
manager.search();
});
+ it('should use replacement URL for condition', done => {
+ tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
+ FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', '13', true),
+ );
+
+ visitUrl.mockImplementation(url => {
+ expect(url).toEqual(`${defaultParams}&milestone_title=replaced`);
+ done();
+ });
+
+ manager.filteredSearchTokenKeys.conditions.push({
+ url: 'milestone_title=13',
+ replacementUrl: 'milestone_title=replaced',
+ tokenKey: 'milestone',
+ value: '13',
+ operator: '=',
+ });
+ manager.search();
+ });
+
it('removes duplicated tokens', done => {
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug')}
diff --git a/spec/frontend/incidents/components/incidents_list_spec.js b/spec/frontend/incidents/components/incidents_list_spec.js
index 0d7daf08272..e067ef744fd 100644
--- a/spec/frontend/incidents/components/incidents_list_spec.js
+++ b/spec/frontend/incidents/components/incidents_list_spec.js
@@ -1,5 +1,12 @@
import { mount } from '@vue/test-utils';
-import { GlAlert, GlLoadingIcon, GlTable, GlAvatar, GlSearchBoxByType } from '@gitlab/ui';
+import {
+ GlAlert,
+ GlLoadingIcon,
+ GlTable,
+ GlAvatar,
+ GlPagination,
+ GlSearchBoxByType,
+} from '@gitlab/ui';
import { visitUrl, joinPaths } from '~/lib/utils/url_utility';
import IncidentsList from '~/incidents/components/incidents_list.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
@@ -26,6 +33,7 @@ describe('Incidents List', () => {
const findCreateIncidentBtn = () => wrapper.find('[data-testid="createIncidentBtn"]');
const findSearch = () => wrapper.find(GlSearchBoxByType);
const findClosedIcon = () => wrapper.findAll("[data-testid='incident-closed']");
+ const findPagination = () => wrapper.find(GlPagination);
function mountComponent({ data = { incidents: [] }, loading = false }) {
wrapper = mount(IncidentsList, {
@@ -70,7 +78,7 @@ describe('Incidents List', () => {
it('shows empty state', () => {
mountComponent({
- data: { incidents: [] },
+ data: { incidents: { list: [] } },
loading: false,
});
expect(findTable().text()).toContain(I18N.noIncidents);
@@ -78,7 +86,7 @@ describe('Incidents List', () => {
it('shows error state', () => {
mountComponent({
- data: { incidents: [], errored: true },
+ data: { incidents: { list: [] }, errored: true },
loading: false,
});
expect(findTable().text()).toContain(I18N.noIncidents);
@@ -88,7 +96,7 @@ describe('Incidents List', () => {
describe('Incident Management list', () => {
beforeEach(() => {
mountComponent({
- data: { incidents: mockIncidents },
+ data: { incidents: { list: mockIncidents } },
loading: false,
});
});
@@ -140,7 +148,7 @@ describe('Incidents List', () => {
describe('Create Incident', () => {
beforeEach(() => {
mountComponent({
- data: { incidents: [] },
+ data: { incidents: { list: [] } },
loading: false,
});
});
@@ -157,24 +165,120 @@ describe('Incidents List', () => {
});
});
- describe('Search', () => {
+ describe('Pagination', () => {
beforeEach(() => {
mountComponent({
- data: { incidents: mockIncidents },
+ data: {
+ incidents: {
+ list: mockIncidents,
+ pageInfo: { hasNextPage: true, hasPreviousPage: true },
+ },
+ errored: false,
+ },
loading: false,
});
});
- it('renders the search component for incidents', () => {
- expect(findSearch().exists()).toBe(true);
+ it('should render pagination', () => {
+ expect(wrapper.find(GlPagination).exists()).toBe(true);
});
- it('sets the `searchTerm` graphql variable', () => {
- const SEARCH_TERM = 'Simple Incident';
+ describe('prevPage', () => {
+ it('returns prevPage button', () => {
+ findPagination().vm.$emit('input', 3);
- findSearch().vm.$emit('input', SEARCH_TERM);
+ return wrapper.vm.$nextTick(() => {
+ expect(
+ findPagination()
+ .findAll('.page-item')
+ .at(0)
+ .text(),
+ ).toBe('Prev');
+ });
+ });
- expect(wrapper.vm.$data.searchTerm).toBe(SEARCH_TERM);
+ it('returns prevPage number', () => {
+ findPagination().vm.$emit('input', 3);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.prevPage).toBe(2);
+ });
+ });
+
+ it('returns 0 when it is the first page', () => {
+ findPagination().vm.$emit('input', 1);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.prevPage).toBe(0);
+ });
+ });
+ });
+
+ describe('nextPage', () => {
+ it('returns nextPage button', () => {
+ findPagination().vm.$emit('input', 3);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(
+ findPagination()
+ .findAll('.page-item')
+ .at(1)
+ .text(),
+ ).toBe('Next');
+ });
+ });
+
+ it('returns nextPage number', () => {
+ mountComponent({
+ data: {
+ incidents: {
+ list: [...mockIncidents, ...mockIncidents, ...mockIncidents],
+ pageInfo: { hasNextPage: true, hasPreviousPage: true },
+ },
+ errored: false,
+ },
+ loading: false,
+ });
+ findPagination().vm.$emit('input', 1);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.nextPage).toBe(2);
+ });
+ });
+
+ it('returns `null` when currentPage is already last page', () => {
+ findPagination().vm.$emit('input', 1);
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.nextPage).toBeNull();
+ });
+ });
+ });
+
+ describe('Search', () => {
+ beforeEach(() => {
+ mountComponent({
+ data: {
+ incidents: {
+ list: mockIncidents,
+ pageInfo: { hasNextPage: true, hasPreviousPage: true },
+ },
+ errored: false,
+ },
+ loading: false,
+ });
+ });
+
+ it('renders the search component for incidents', () => {
+ expect(findSearch().exists()).toBe(true);
+ });
+
+ it('sets the `searchTerm` graphql variable', () => {
+ const SEARCH_TERM = 'Simple Incident';
+
+ findSearch().vm.$emit('input', SEARCH_TERM);
+
+ expect(wrapper.vm.$data.searchTerm).toBe(SEARCH_TERM);
+ });
});
});
});
diff --git a/spec/graphql/mutations/issues/update_spec.rb b/spec/graphql/mutations/issues/update_spec.rb
index 4d3ee79d0b0..5e8dfe31e83 100644
--- a/spec/graphql/mutations/issues/update_spec.rb
+++ b/spec/graphql/mutations/issues/update_spec.rb
@@ -3,8 +3,11 @@
require 'spec_helper'
RSpec.describe Mutations::Issues::Update do
- let_it_be(:issue) { create(:issue) }
+ let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
+ let_it_be(:project_label) { create(:label, project: project) }
+ let_it_be(:issue) { create(:issue, project: project, labels: [project_label]) }
+
let(:expected_attributes) do
{
title: 'new title',
@@ -22,7 +25,7 @@ RSpec.describe Mutations::Issues::Update do
describe '#resolve' do
let(:mutation_params) do
{
- project_path: issue.project.full_path,
+ project_path: project.full_path,
iid: issue.iid
}.merge(expected_attributes)
end
@@ -37,7 +40,7 @@ RSpec.describe Mutations::Issues::Update do
context 'when the user can update the issue' do
before do
- issue.project.add_developer(user)
+ project.add_developer(user)
end
it 'updates issue with correct values' do
@@ -53,6 +56,52 @@ RSpec.describe Mutations::Issues::Update do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
+
+ context 'when changing labels' do
+ let_it_be(:label_1) { create(:label, project: project) }
+ let_it_be(:label_2) { create(:label, project: project) }
+ let_it_be(:external_label) { create(:label, project: create(:project)) }
+
+ it 'adds and removes labels correctly' do
+ mutation_params[:add_label_ids] = [label_1.id, label_2.id]
+ mutation_params[:remove_label_ids] = [project_label.id]
+
+ subject
+
+ expect(issue.reload.labels).to match_array([label_1, label_2])
+ end
+
+ it 'does not add label if label id is nil' do
+ mutation_params[:add_label_ids] = [nil, label_2.id]
+
+ subject
+
+ expect(issue.reload.labels).to match_array([project_label, label_2])
+ end
+
+ it 'does not add label if label is not found' do
+ mutation_params[:add_label_ids] = [external_label.id, label_2.id]
+
+ subject
+
+ expect(issue.reload.labels).to match_array([project_label, label_2])
+ end
+
+ it 'does not modify labels if label is already present' do
+ mutation_params[:add_label_ids] = [project_label.id]
+
+ expect(issue.reload.labels).to match_array([project_label])
+ end
+
+ it 'does not modify labels if label is addded and removed in the same request' do
+ mutation_params[:add_label_ids] = [label_1.id, label_2.id]
+ mutation_params[:remove_label_ids] = [label_1.id]
+
+ subject
+
+ expect(issue.reload.labels).to match_array([project_label, label_2])
+ end
+ end
end
end
end
diff --git a/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb b/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb
index 4038bcb3e5d..840aea8b8c4 100644
--- a/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do
end
end
- context 'when project has no jira service' do
+ context 'when project has no Jira service' do
let_it_be(:jira_service) { nil }
context 'when user is a maintainer' do
@@ -29,7 +29,7 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do
end
end
- context 'when project has jira service' do
+ context 'when project has Jira service' do
let(:jira_service) { create(:jira_service, project: project) }
context 'when user is a developer' do
@@ -46,10 +46,11 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do
end
context 'when Jira connection is valid' do
- include_context 'jira projects request context'
+ include_context 'Jira projects request context'
- it 'returns jira projects' do
- jira_projects = resolve_jira_projects
+ it 'returns Jira projects', :aggregate_failures do
+ resolver = resolve_jira_projects
+ jira_projects = resolver.items
project_keys = jira_projects.map(&:key)
project_names = jira_projects.map(&:name)
project_ids = jira_projects.map(&:id)
@@ -58,6 +59,23 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do
expect(project_keys).to eq(%w(EX ABC))
expect(project_names).to eq(%w(Example Alphabetical))
expect(project_ids).to eq(%w(10000 10001))
+ expect(resolver.max_page_size).to eq(2)
+ end
+
+ context 'when filtering projects by name' do
+ it 'returns Jira projects', :aggregate_failures do
+ resolver = resolve_jira_projects({ name: 'ABC' })
+ jira_projects = resolver.items
+ project_keys = jira_projects.map(&:key)
+ project_names = jira_projects.map(&:name)
+ project_ids = jira_projects.map(&:id)
+
+ expect(jira_projects.size).to eq 1
+ expect(project_keys).to eq(%w(ABC))
+ expect(project_names).to eq(%w(Alphabetical))
+ expect(project_ids).to eq(%w(10001))
+ expect(resolver.max_page_size).to eq(1)
+ end
end
end
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index 74ee7a152b3..3ba9f39d21a 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -282,6 +282,16 @@ RSpec.describe BlobHelper do
expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
end
end
+
+ context 'blob does not have auxiliary view' do
+ before do
+ allow(blob).to receive(:auxiliary_viewer).and_return(nil)
+ end
+
+ it 'is false' do
+ expect(helper.show_suggest_pipeline_creation_celebration?).to be_falsey
+ end
+ end
end
context 'experiment disabled' do
diff --git a/spec/lib/gitlab/metrics/dashboard/processor_spec.rb b/spec/lib/gitlab/metrics/dashboard/processor_spec.rb
index 7f7070dfafb..e794e28a279 100644
--- a/spec/lib/gitlab/metrics/dashboard/processor_spec.rb
+++ b/spec/lib/gitlab/metrics/dashboard/processor_spec.rb
@@ -26,12 +26,6 @@ RSpec.describe Gitlab::Metrics::Dashboard::Processor do
let(:process_params) { [project, dashboard_yml, sequence, { environment: environment }] }
let(:dashboard) { described_class.new(*process_params).process }
- it 'includes a path for the prometheus endpoint with each metric' do
- expect(all_metrics).to satisfy_all do |metric|
- metric[:prometheus_endpoint_path] == prometheus_path(metric[:query_range])
- end
- end
-
it 'includes an id for each dashboard panel' do
expect(all_panels).to satisfy_all do |panel|
panel[:id].present?
diff --git a/spec/lib/gitlab/metrics/dashboard/stages/metric_endpoint_inserter_spec.rb b/spec/lib/gitlab/metrics/dashboard/stages/metric_endpoint_inserter_spec.rb
new file mode 100644
index 00000000000..d268f215ec7
--- /dev/null
+++ b/spec/lib/gitlab/metrics/dashboard/stages/metric_endpoint_inserter_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Metrics::Dashboard::Stages::MetricEndpointInserter do
+ include MetricsDashboardHelpers
+
+ let(:project) { build_stubbed(:project) }
+ let(:environment) { build_stubbed(:environment, project: project) }
+
+ describe '#transform!' do
+ subject(:transform!) { described_class.new(project, dashboard, environment: environment).transform! }
+
+ let(:dashboard) { load_sample_dashboard.deep_symbolize_keys }
+
+ it 'generates prometheus_endpoint_path without newlines' do
+ query = 'avg( sum( container_memory_usage_bytes{ container_name!="POD", '\
+ 'pod_name=~"^{{ci_environment_slug}}-(.*)", namespace="{{kube_namespace}}" } ) '\
+ 'by (job) ) without (job) /1024/1024/1024'
+
+ transform!
+
+ expect(all_metrics[0][:prometheus_endpoint_path]).to eq(prometheus_path(query))
+ end
+
+ it 'includes a path for the prometheus endpoint with each metric' do
+ transform!
+
+ expect(all_metrics).to satisfy_all do |metric|
+ metric[:prometheus_endpoint_path] == prometheus_path(metric[:query_range].squish)
+ end
+ end
+ end
+
+ private
+
+ def all_metrics
+ dashboard[:panel_groups].flat_map do |group|
+ group[:panels].flat_map { |panel| panel[:metrics] }
+ end
+ end
+
+ def prometheus_path(query)
+ Gitlab::Routing.url_helpers.prometheus_api_project_environment_path(
+ project,
+ environment,
+ proxy_path: :query_range,
+ query: query
+ )
+ end
+end
diff --git a/spec/policies/ci/build_policy_spec.rb b/spec/policies/ci/build_policy_spec.rb
index d2547338855..7ea180af9d0 100644
--- a/spec/policies/ci/build_policy_spec.rb
+++ b/spec/policies/ci/build_policy_spec.rb
@@ -146,7 +146,7 @@ RSpec.describe Ci::BuildPolicy do
create(:protected_tag, :no_one_can_create,
name: build.ref, project: project)
- build.update(tag: true)
+ build.update!(tag: true)
end
it 'does not include ability to update build' do
diff --git a/spec/policies/ci/pipeline_policy_spec.rb b/spec/policies/ci/pipeline_policy_spec.rb
index fcd96bc6653..9a65823c950 100644
--- a/spec/policies/ci/pipeline_policy_spec.rb
+++ b/spec/policies/ci/pipeline_policy_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe Ci::PipelinePolicy, :models do
create(:protected_tag, :no_one_can_create,
name: pipeline.ref, project: project)
- pipeline.update(tag: true)
+ pipeline.update!(tag: true)
end
it 'does not include ability to update pipeline' do
diff --git a/spec/policies/ci/pipeline_schedule_policy_spec.rb b/spec/policies/ci/pipeline_schedule_policy_spec.rb
index b455384d17a..1e36f455f6f 100644
--- a/spec/policies/ci/pipeline_schedule_policy_spec.rb
+++ b/spec/policies/ci/pipeline_schedule_policy_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe Ci::PipelineSchedulePolicy, :models do
let(:tag) { 'v1.0.0' }
before do
- pipeline_schedule.update(ref: tag)
+ pipeline_schedule.update!(ref: tag)
create(:protected_tag, :no_one_can_create,
name: pipeline_schedule.ref, project: project)
@@ -69,7 +69,7 @@ RSpec.describe Ci::PipelineSchedulePolicy, :models do
describe 'rules for owner of schedule' do
before do
project.add_developer(user)
- pipeline_schedule.update(owner: user)
+ pipeline_schedule.update!(owner: user)
end
it 'includes abilities to do all operations on pipeline schedule' do
@@ -97,7 +97,7 @@ RSpec.describe Ci::PipelineSchedulePolicy, :models do
before do
project.add_maintainer(owner)
project.add_maintainer(user)
- pipeline_schedule.update(owner: owner)
+ pipeline_schedule.update!(owner: owner)
end
it 'includes abilities to take ownership' do
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index 733cc9bd9cb..4debaf59eb9 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -107,7 +107,7 @@ RSpec.describe GroupPolicy do
context 'with subgroup_creation level set to maintainer' do
before_all do
- group.update(subgroup_creation_level: ::Gitlab::Access::MAINTAINER_SUBGROUP_ACCESS)
+ group.update!(subgroup_creation_level: ::Gitlab::Access::MAINTAINER_SUBGROUP_ACCESS)
end
it 'allows every maintainer permission plus creating subgroups' do
@@ -363,7 +363,7 @@ RSpec.describe GroupPolicy do
context 'transfer_projects' do
shared_examples_for 'allowed to transfer projects' do
before do
- group.update(project_creation_level: project_creation_level)
+ group.update!(project_creation_level: project_creation_level)
end
it { is_expected.to be_allowed(:transfer_projects) }
@@ -371,7 +371,7 @@ RSpec.describe GroupPolicy do
shared_examples_for 'not allowed to transfer projects' do
before do
- group.update(project_creation_level: project_creation_level)
+ group.update!(project_creation_level: project_creation_level)
end
it { is_expected.to be_disallowed(:transfer_projects) }
@@ -445,7 +445,7 @@ RSpec.describe GroupPolicy do
context 'create_projects' do
context 'when group has no project creation level set' do
before_all do
- group.update(project_creation_level: nil)
+ group.update!(project_creation_level: nil)
end
context 'reporter' do
@@ -475,7 +475,7 @@ RSpec.describe GroupPolicy do
context 'when group has project creation level set to no one' do
before_all do
- group.update(project_creation_level: ::Gitlab::Access::NO_ONE_PROJECT_ACCESS)
+ group.update!(project_creation_level: ::Gitlab::Access::NO_ONE_PROJECT_ACCESS)
end
context 'reporter' do
@@ -505,7 +505,7 @@ RSpec.describe GroupPolicy do
context 'when group has project creation level set to maintainer only' do
before_all do
- group.update(project_creation_level: ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS)
+ group.update!(project_creation_level: ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS)
end
context 'reporter' do
@@ -535,7 +535,7 @@ RSpec.describe GroupPolicy do
context 'when group has project creation level set to developers + maintainer' do
before_all do
- group.update(project_creation_level: ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS)
+ group.update!(project_creation_level: ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS)
end
context 'reporter' do
@@ -567,7 +567,7 @@ RSpec.describe GroupPolicy do
context 'create_subgroup' do
context 'when group has subgroup creation level set to owner' do
before_all do
- group.update(subgroup_creation_level: ::Gitlab::Access::OWNER_SUBGROUP_ACCESS)
+ group.update!(subgroup_creation_level: ::Gitlab::Access::OWNER_SUBGROUP_ACCESS)
end
context 'reporter' do
@@ -597,7 +597,7 @@ RSpec.describe GroupPolicy do
context 'when group has subgroup creation level set to maintainer' do
before_all do
- group.update(subgroup_creation_level: ::Gitlab::Access::MAINTAINER_SUBGROUP_ACCESS)
+ group.update!(subgroup_creation_level: ::Gitlab::Access::MAINTAINER_SUBGROUP_ACCESS)
end
context 'reporter' do
@@ -706,7 +706,7 @@ RSpec.describe GroupPolicy do
context 'which does not have design management enabled' do
before do
- project.update(lfs_enabled: false)
+ project.update!(lfs_enabled: false)
end
it { is_expected.not_to be_allowed(:read_design_activity) }
diff --git a/spec/policies/issue_policy_spec.rb b/spec/policies/issue_policy_spec.rb
index b917def66aa..e352b990159 100644
--- a/spec/policies/issue_policy_spec.rb
+++ b/spec/policies/issue_policy_spec.rb
@@ -188,7 +188,7 @@ RSpec.describe IssuePolicy do
context 'when issues are private' do
before do
- project.project_feature.update(issues_access_level: ProjectFeature::PRIVATE)
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
end
let(:issue) { create(:issue, project: project, author: author) }
let(:visitor) { create(:user) }
diff --git a/spec/policies/merge_request_policy_spec.rb b/spec/policies/merge_request_policy_spec.rb
index 2f3cb2e998a..3a46d5b9226 100644
--- a/spec/policies/merge_request_policy_spec.rb
+++ b/spec/policies/merge_request_policy_spec.rb
@@ -51,7 +51,7 @@ RSpec.describe MergeRequestPolicy do
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: author) }
before do
- project.project_feature.update(merge_requests_access_level: ProjectFeature::DISABLED)
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
end
describe 'the author' do
@@ -83,8 +83,8 @@ RSpec.describe MergeRequestPolicy do
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: author) }
before do
- project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
- project.project_feature.update(merge_requests_access_level: ProjectFeature::PRIVATE)
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
end
describe 'a non-team-member' do
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index dc6ed94309b..2c246bd475b 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -105,7 +105,7 @@ RSpec.describe ProjectPolicy do
subject { described_class.new(owner, project) }
before do
- project.project_feature.destroy
+ project.project_feature.destroy!
project.reload
end
@@ -953,7 +953,12 @@ RSpec.describe ProjectPolicy do
context 'when repository is disabled' do
before do
- project.project_feature.update(repository_access_level: ProjectFeature::DISABLED)
+ project.project_feature.update!(
+ # Disable merge_requests and builds as well, since merge_requests and
+ # builds cannot have higher visibility than repository.
+ merge_requests_access_level: ProjectFeature::DISABLED,
+ builds_access_level: ProjectFeature::DISABLED,
+ repository_access_level: ProjectFeature::DISABLED)
end
it { is_expected.to be_disallowed(:read_package) }
diff --git a/spec/requests/api/graphql/project/jira_projects_spec.rb b/spec/requests/api/graphql/project/jira_projects_spec.rb
index d5f59711ab1..410d5b21505 100644
--- a/spec/requests/api/graphql/project/jira_projects_spec.rb
+++ b/spec/requests/api/graphql/project/jira_projects_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'query Jira projects' do
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
- include_context 'jira projects request context'
+ include_context 'Jira projects request context'
let(:services) { graphql_data_at(:project, :services, :edges) }
let(:jira_projects) { services.first.dig('node', 'projects', 'nodes') }
diff --git a/spec/services/jira/requests/projects/list_service_spec.rb b/spec/services/jira/requests/projects/list_service_spec.rb
index 51e67dd821d..b4db77f8104 100644
--- a/spec/services/jira/requests/projects/list_service_spec.rb
+++ b/spec/services/jira/requests/projects/list_service_spec.rb
@@ -66,16 +66,28 @@ RSpec.describe Jira::Requests::Projects::ListService do
context 'when the request returns values' do
before do
- expect(client).to receive(:get).and_return([{ "key" => 'project1' }, { "key" => 'project2' }])
+ expect(client).to receive(:get).and_return([{ 'key' => 'pr1', 'name' => 'First Project' }, { 'key' => 'pr2', 'name' => 'Second Project' }])
end
- it 'returns a paylod with jira projets' do
+ it 'returns a paylod with Jira projets' do
payload = subject.payload
expect(subject.success?).to be_truthy
- expect(payload[:projects].map(&:key)).to eq(%w(project1 project2))
+ expect(payload[:projects].map(&:key)).to eq(%w(pr1 pr2))
expect(payload[:is_last]).to be_truthy
end
+
+ context 'when filtering projects by name' do
+ let(:params) { { query: 'first' } }
+
+ it 'returns a paylod with Jira projets' do
+ payload = subject.payload
+
+ expect(subject.success?).to be_truthy
+ expect(payload[:projects].map(&:key)).to eq(%w(pr1))
+ expect(payload[:is_last]).to be_truthy
+ end
+ end
end
end
end
diff --git a/spec/support/shared_contexts/requests/api/graphql/jira_import/jira_projects_context.rb b/spec/support/shared_contexts/requests/api/graphql/jira_import/jira_projects_context.rb
index 7f150bed43d..edc5b313220 100644
--- a/spec/support/shared_contexts/requests/api/graphql/jira_import/jira_projects_context.rb
+++ b/spec/support/shared_contexts/requests/api/graphql/jira_import/jira_projects_context.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_context 'jira projects request context' do
+RSpec.shared_context 'Jira projects request context' do
let(:url) { 'https://jira.example.com' }
let(:username) { 'jira-username' }
let(:password) { 'jira-password' }
diff --git a/spec/support/shared_examples/finders/snippet_visibility_shared_examples.rb b/spec/support/shared_examples/finders/snippet_visibility_shared_examples.rb
index c802038c9da..a2c34cdd4a1 100644
--- a/spec/support/shared_examples/finders/snippet_visibility_shared_examples.rb
+++ b/spec/support/shared_examples/finders/snippet_visibility_shared_examples.rb
@@ -9,13 +9,28 @@ RSpec.shared_examples 'snippet visibility' do
let_it_be(:non_member) { create(:user) }
let_it_be(:project, reload: true) do
- create(:project).tap do |project|
+ create(:project, :public).tap do |project|
project.add_developer(author)
project.add_developer(member)
end
end
+ let(:snippets) do
+ {
+ private: private_snippet,
+ public: public_snippet,
+ internal: internal_snippet
+ }
+ end
+
+ let(:user) { users[user_type] }
+ let(:snippet) { snippets[snippet_visibility] }
+
context "For project snippets" do
+ let_it_be(:private_snippet) { create(:project_snippet, :private, project: project, author: author) }
+ let_it_be(:public_snippet) { create(:project_snippet, :public, project: project, author: author) }
+ let_it_be(:internal_snippet) { create(:project_snippet, :internal, project: project, author: author) }
+
let!(:users) do
{
unauthenticated: nil,
@@ -26,214 +41,212 @@ RSpec.shared_examples 'snippet visibility' do
}
end
- where(:project_type, :feature_visibility, :user_type, :snippet_type, :outcome) do
+ where(:project_visibility, :feature_visibility, :user_type, :snippet_visibility, :outcome) do
[
# Public projects
- [:public, ProjectFeature::ENABLED, :unauthenticated, Snippet::PUBLIC, true],
- [:public, ProjectFeature::ENABLED, :unauthenticated, Snippet::INTERNAL, false],
- [:public, ProjectFeature::ENABLED, :unauthenticated, Snippet::PRIVATE, false],
+ [:public, :enabled, :unauthenticated, :public, true],
+ [:public, :enabled, :unauthenticated, :internal, false],
+ [:public, :enabled, :unauthenticated, :private, false],
- [:public, ProjectFeature::ENABLED, :external, Snippet::PUBLIC, true],
- [:public, ProjectFeature::ENABLED, :external, Snippet::INTERNAL, false],
- [:public, ProjectFeature::ENABLED, :external, Snippet::PRIVATE, false],
+ [:public, :enabled, :external, :public, true],
+ [:public, :enabled, :external, :internal, false],
+ [:public, :enabled, :external, :private, false],
- [:public, ProjectFeature::ENABLED, :non_member, Snippet::PUBLIC, true],
- [:public, ProjectFeature::ENABLED, :non_member, Snippet::INTERNAL, true],
- [:public, ProjectFeature::ENABLED, :non_member, Snippet::PRIVATE, false],
+ [:public, :enabled, :non_member, :public, true],
+ [:public, :enabled, :non_member, :internal, true],
+ [:public, :enabled, :non_member, :private, false],
- [:public, ProjectFeature::ENABLED, :member, Snippet::PUBLIC, true],
- [:public, ProjectFeature::ENABLED, :member, Snippet::INTERNAL, true],
- [:public, ProjectFeature::ENABLED, :member, Snippet::PRIVATE, true],
+ [:public, :enabled, :member, :public, true],
+ [:public, :enabled, :member, :internal, true],
+ [:public, :enabled, :member, :private, true],
- [:public, ProjectFeature::ENABLED, :author, Snippet::PUBLIC, true],
- [:public, ProjectFeature::ENABLED, :author, Snippet::INTERNAL, true],
- [:public, ProjectFeature::ENABLED, :author, Snippet::PRIVATE, true],
+ [:public, :enabled, :author, :public, true],
+ [:public, :enabled, :author, :internal, true],
+ [:public, :enabled, :author, :private, true],
- [:public, ProjectFeature::PRIVATE, :unauthenticated, Snippet::PUBLIC, false],
- [:public, ProjectFeature::PRIVATE, :unauthenticated, Snippet::INTERNAL, false],
- [:public, ProjectFeature::PRIVATE, :unauthenticated, Snippet::PRIVATE, false],
+ [:public, :private, :unauthenticated, :public, false],
+ [:public, :private, :unauthenticated, :internal, false],
+ [:public, :private, :unauthenticated, :private, false],
- [:public, ProjectFeature::PRIVATE, :external, Snippet::PUBLIC, false],
- [:public, ProjectFeature::PRIVATE, :external, Snippet::INTERNAL, false],
- [:public, ProjectFeature::PRIVATE, :external, Snippet::PRIVATE, false],
+ [:public, :private, :external, :public, false],
+ [:public, :private, :external, :internal, false],
+ [:public, :private, :external, :private, false],
- [:public, ProjectFeature::PRIVATE, :non_member, Snippet::PUBLIC, false],
- [:public, ProjectFeature::PRIVATE, :non_member, Snippet::INTERNAL, false],
- [:public, ProjectFeature::PRIVATE, :non_member, Snippet::PRIVATE, false],
+ [:public, :private, :non_member, :public, false],
+ [:public, :private, :non_member, :internal, false],
+ [:public, :private, :non_member, :private, false],
- [:public, ProjectFeature::PRIVATE, :member, Snippet::PUBLIC, true],
- [:public, ProjectFeature::PRIVATE, :member, Snippet::INTERNAL, true],
- [:public, ProjectFeature::PRIVATE, :member, Snippet::PRIVATE, true],
+ [:public, :private, :member, :public, true],
+ [:public, :private, :member, :internal, true],
+ [:public, :private, :member, :private, true],
- [:public, ProjectFeature::PRIVATE, :author, Snippet::PUBLIC, true],
- [:public, ProjectFeature::PRIVATE, :author, Snippet::INTERNAL, true],
- [:public, ProjectFeature::PRIVATE, :author, Snippet::PRIVATE, true],
+ [:public, :private, :author, :public, true],
+ [:public, :private, :author, :internal, true],
+ [:public, :private, :author, :private, true],
- [:public, ProjectFeature::DISABLED, :unauthenticated, Snippet::PUBLIC, false],
- [:public, ProjectFeature::DISABLED, :unauthenticated, Snippet::INTERNAL, false],
- [:public, ProjectFeature::DISABLED, :unauthenticated, Snippet::PRIVATE, false],
+ [:public, :disabled, :unauthenticated, :public, false],
+ [:public, :disabled, :unauthenticated, :internal, false],
+ [:public, :disabled, :unauthenticated, :private, false],
- [:public, ProjectFeature::DISABLED, :external, Snippet::PUBLIC, false],
- [:public, ProjectFeature::DISABLED, :external, Snippet::INTERNAL, false],
- [:public, ProjectFeature::DISABLED, :external, Snippet::PRIVATE, false],
+ [:public, :disabled, :external, :public, false],
+ [:public, :disabled, :external, :internal, false],
+ [:public, :disabled, :external, :private, false],
- [:public, ProjectFeature::DISABLED, :non_member, Snippet::PUBLIC, false],
- [:public, ProjectFeature::DISABLED, :non_member, Snippet::INTERNAL, false],
- [:public, ProjectFeature::DISABLED, :non_member, Snippet::PRIVATE, false],
+ [:public, :disabled, :non_member, :public, false],
+ [:public, :disabled, :non_member, :internal, false],
+ [:public, :disabled, :non_member, :private, false],
- [:public, ProjectFeature::DISABLED, :member, Snippet::PUBLIC, false],
- [:public, ProjectFeature::DISABLED, :member, Snippet::INTERNAL, false],
- [:public, ProjectFeature::DISABLED, :member, Snippet::PRIVATE, false],
+ [:public, :disabled, :member, :public, false],
+ [:public, :disabled, :member, :internal, false],
+ [:public, :disabled, :member, :private, false],
- [:public, ProjectFeature::DISABLED, :author, Snippet::PUBLIC, false],
- [:public, ProjectFeature::DISABLED, :author, Snippet::INTERNAL, false],
- [:public, ProjectFeature::DISABLED, :author, Snippet::PRIVATE, false],
+ [:public, :disabled, :author, :public, false],
+ [:public, :disabled, :author, :internal, false],
+ [:public, :disabled, :author, :private, false],
# Internal projects
- [:internal, ProjectFeature::ENABLED, :unauthenticated, Snippet::PUBLIC, false],
- [:internal, ProjectFeature::ENABLED, :unauthenticated, Snippet::INTERNAL, false],
- [:internal, ProjectFeature::ENABLED, :unauthenticated, Snippet::PRIVATE, false],
+ [:internal, :enabled, :unauthenticated, :public, false],
+ [:internal, :enabled, :unauthenticated, :internal, false],
+ [:internal, :enabled, :unauthenticated, :private, false],
- [:internal, ProjectFeature::ENABLED, :external, Snippet::PUBLIC, false],
- [:internal, ProjectFeature::ENABLED, :external, Snippet::INTERNAL, false],
- [:internal, ProjectFeature::ENABLED, :external, Snippet::PRIVATE, false],
+ [:internal, :enabled, :external, :public, false],
+ [:internal, :enabled, :external, :internal, false],
+ [:internal, :enabled, :external, :private, false],
- [:internal, ProjectFeature::ENABLED, :non_member, Snippet::PUBLIC, true],
- [:internal, ProjectFeature::ENABLED, :non_member, Snippet::INTERNAL, true],
- [:internal, ProjectFeature::ENABLED, :non_member, Snippet::PRIVATE, false],
+ [:internal, :enabled, :non_member, :public, true],
+ [:internal, :enabled, :non_member, :internal, true],
+ [:internal, :enabled, :non_member, :private, false],
- [:internal, ProjectFeature::ENABLED, :member, Snippet::PUBLIC, true],
- [:internal, ProjectFeature::ENABLED, :member, Snippet::INTERNAL, true],
- [:internal, ProjectFeature::ENABLED, :member, Snippet::PRIVATE, true],
+ [:internal, :enabled, :member, :public, true],
+ [:internal, :enabled, :member, :internal, true],
+ [:internal, :enabled, :member, :private, true],
- [:internal, ProjectFeature::ENABLED, :author, Snippet::PUBLIC, true],
- [:internal, ProjectFeature::ENABLED, :author, Snippet::INTERNAL, true],
- [:internal, ProjectFeature::ENABLED, :author, Snippet::PRIVATE, true],
+ [:internal, :enabled, :author, :public, true],
+ [:internal, :enabled, :author, :internal, true],
+ [:internal, :enabled, :author, :private, true],
- [:internal, ProjectFeature::PRIVATE, :unauthenticated, Snippet::PUBLIC, false],
- [:internal, ProjectFeature::PRIVATE, :unauthenticated, Snippet::INTERNAL, false],
- [:internal, ProjectFeature::PRIVATE, :unauthenticated, Snippet::PRIVATE, false],
+ [:internal, :private, :unauthenticated, :public, false],
+ [:internal, :private, :unauthenticated, :internal, false],
+ [:internal, :private, :unauthenticated, :private, false],
- [:internal, ProjectFeature::PRIVATE, :external, Snippet::PUBLIC, false],
- [:internal, ProjectFeature::PRIVATE, :external, Snippet::INTERNAL, false],
- [:internal, ProjectFeature::PRIVATE, :external, Snippet::PRIVATE, false],
+ [:internal, :private, :external, :public, false],
+ [:internal, :private, :external, :internal, false],
+ [:internal, :private, :external, :private, false],
- [:internal, ProjectFeature::PRIVATE, :non_member, Snippet::PUBLIC, false],
- [:internal, ProjectFeature::PRIVATE, :non_member, Snippet::INTERNAL, false],
- [:internal, ProjectFeature::PRIVATE, :non_member, Snippet::PRIVATE, false],
+ [:internal, :private, :non_member, :public, false],
+ [:internal, :private, :non_member, :internal, false],
+ [:internal, :private, :non_member, :private, false],
- [:internal, ProjectFeature::PRIVATE, :member, Snippet::PUBLIC, true],
- [:internal, ProjectFeature::PRIVATE, :member, Snippet::INTERNAL, true],
- [:internal, ProjectFeature::PRIVATE, :member, Snippet::PRIVATE, true],
+ [:internal, :private, :member, :public, true],
+ [:internal, :private, :member, :internal, true],
+ [:internal, :private, :member, :private, true],
- [:internal, ProjectFeature::PRIVATE, :author, Snippet::PUBLIC, true],
- [:internal, ProjectFeature::PRIVATE, :author, Snippet::INTERNAL, true],
- [:internal, ProjectFeature::PRIVATE, :author, Snippet::PRIVATE, true],
+ [:internal, :private, :author, :public, true],
+ [:internal, :private, :author, :internal, true],
+ [:internal, :private, :author, :private, true],
- [:internal, ProjectFeature::DISABLED, :unauthenticated, Snippet::PUBLIC, false],
- [:internal, ProjectFeature::DISABLED, :unauthenticated, Snippet::INTERNAL, false],
- [:internal, ProjectFeature::DISABLED, :unauthenticated, Snippet::PRIVATE, false],
+ [:internal, :disabled, :unauthenticated, :public, false],
+ [:internal, :disabled, :unauthenticated, :internal, false],
+ [:internal, :disabled, :unauthenticated, :private, false],
- [:internal, ProjectFeature::DISABLED, :external, Snippet::PUBLIC, false],
- [:internal, ProjectFeature::DISABLED, :external, Snippet::INTERNAL, false],
- [:internal, ProjectFeature::DISABLED, :external, Snippet::PRIVATE, false],
+ [:internal, :disabled, :external, :public, false],
+ [:internal, :disabled, :external, :internal, false],
+ [:internal, :disabled, :external, :private, false],
- [:internal, ProjectFeature::DISABLED, :non_member, Snippet::PUBLIC, false],
- [:internal, ProjectFeature::DISABLED, :non_member, Snippet::INTERNAL, false],
- [:internal, ProjectFeature::DISABLED, :non_member, Snippet::PRIVATE, false],
+ [:internal, :disabled, :non_member, :public, false],
+ [:internal, :disabled, :non_member, :internal, false],
+ [:internal, :disabled, :non_member, :private, false],
- [:internal, ProjectFeature::DISABLED, :member, Snippet::PUBLIC, false],
- [:internal, ProjectFeature::DISABLED, :member, Snippet::INTERNAL, false],
- [:internal, ProjectFeature::DISABLED, :member, Snippet::PRIVATE, false],
+ [:internal, :disabled, :member, :public, false],
+ [:internal, :disabled, :member, :internal, false],
+ [:internal, :disabled, :member, :private, false],
- [:internal, ProjectFeature::DISABLED, :author, Snippet::PUBLIC, false],
- [:internal, ProjectFeature::DISABLED, :author, Snippet::INTERNAL, false],
- [:internal, ProjectFeature::DISABLED, :author, Snippet::PRIVATE, false],
+ [:internal, :disabled, :author, :public, false],
+ [:internal, :disabled, :author, :internal, false],
+ [:internal, :disabled, :author, :private, false],
# Private projects
- [:private, ProjectFeature::ENABLED, :unauthenticated, Snippet::PUBLIC, false],
- [:private, ProjectFeature::ENABLED, :unauthenticated, Snippet::INTERNAL, false],
- [:private, ProjectFeature::ENABLED, :unauthenticated, Snippet::PRIVATE, false],
+ [:private, :enabled, :unauthenticated, :public, false],
+ [:private, :enabled, :unauthenticated, :internal, false],
+ [:private, :enabled, :unauthenticated, :private, false],
- [:private, ProjectFeature::ENABLED, :external, Snippet::PUBLIC, true],
- [:private, ProjectFeature::ENABLED, :external, Snippet::INTERNAL, true],
- [:private, ProjectFeature::ENABLED, :external, Snippet::PRIVATE, true],
+ [:private, :enabled, :external, :public, true],
+ [:private, :enabled, :external, :internal, true],
+ [:private, :enabled, :external, :private, true],
- [:private, ProjectFeature::ENABLED, :non_member, Snippet::PUBLIC, false],
- [:private, ProjectFeature::ENABLED, :non_member, Snippet::INTERNAL, false],
- [:private, ProjectFeature::ENABLED, :non_member, Snippet::PRIVATE, false],
+ [:private, :enabled, :non_member, :public, false],
+ [:private, :enabled, :non_member, :internal, false],
+ [:private, :enabled, :non_member, :private, false],
- [:private, ProjectFeature::ENABLED, :member, Snippet::PUBLIC, true],
- [:private, ProjectFeature::ENABLED, :member, Snippet::INTERNAL, true],
- [:private, ProjectFeature::ENABLED, :member, Snippet::PRIVATE, true],
+ [:private, :enabled, :member, :public, true],
+ [:private, :enabled, :member, :internal, true],
+ [:private, :enabled, :member, :private, true],
- [:private, ProjectFeature::ENABLED, :author, Snippet::PUBLIC, true],
- [:private, ProjectFeature::ENABLED, :author, Snippet::INTERNAL, true],
- [:private, ProjectFeature::ENABLED, :author, Snippet::PRIVATE, true],
+ [:private, :enabled, :author, :public, true],
+ [:private, :enabled, :author, :internal, true],
+ [:private, :enabled, :author, :private, true],
- [:private, ProjectFeature::PRIVATE, :unauthenticated, Snippet::PUBLIC, false],
- [:private, ProjectFeature::PRIVATE, :unauthenticated, Snippet::INTERNAL, false],
- [:private, ProjectFeature::PRIVATE, :unauthenticated, Snippet::PRIVATE, false],
+ [:private, :private, :unauthenticated, :public, false],
+ [:private, :private, :unauthenticated, :internal, false],
+ [:private, :private, :unauthenticated, :private, false],
- [:private, ProjectFeature::PRIVATE, :external, Snippet::PUBLIC, true],
- [:private, ProjectFeature::PRIVATE, :external, Snippet::INTERNAL, true],
- [:private, ProjectFeature::PRIVATE, :external, Snippet::PRIVATE, true],
+ [:private, :private, :external, :public, true],
+ [:private, :private, :external, :internal, true],
+ [:private, :private, :external, :private, true],
- [:private, ProjectFeature::PRIVATE, :non_member, Snippet::PUBLIC, false],
- [:private, ProjectFeature::PRIVATE, :non_member, Snippet::INTERNAL, false],
- [:private, ProjectFeature::PRIVATE, :non_member, Snippet::PRIVATE, false],
+ [:private, :private, :non_member, :public, false],
+ [:private, :private, :non_member, :internal, false],
+ [:private, :private, :non_member, :private, false],
- [:private, ProjectFeature::PRIVATE, :member, Snippet::PUBLIC, true],
- [:private, ProjectFeature::PRIVATE, :member, Snippet::INTERNAL, true],
- [:private, ProjectFeature::PRIVATE, :member, Snippet::PRIVATE, true],
+ [:private, :private, :member, :public, true],
+ [:private, :private, :member, :internal, true],
+ [:private, :private, :member, :private, true],
- [:private, ProjectFeature::PRIVATE, :author, Snippet::PUBLIC, true],
- [:private, ProjectFeature::PRIVATE, :author, Snippet::INTERNAL, true],
- [:private, ProjectFeature::PRIVATE, :author, Snippet::PRIVATE, true],
+ [:private, :private, :author, :public, true],
+ [:private, :private, :author, :internal, true],
+ [:private, :private, :author, :private, true],
- [:private, ProjectFeature::DISABLED, :unauthenticated, Snippet::PUBLIC, false],
- [:private, ProjectFeature::DISABLED, :unauthenticated, Snippet::INTERNAL, false],
- [:private, ProjectFeature::DISABLED, :unauthenticated, Snippet::PRIVATE, false],
+ [:private, :disabled, :unauthenticated, :public, false],
+ [:private, :disabled, :unauthenticated, :internal, false],
+ [:private, :disabled, :unauthenticated, :private, false],
- [:private, ProjectFeature::DISABLED, :external, Snippet::PUBLIC, false],
- [:private, ProjectFeature::DISABLED, :external, Snippet::INTERNAL, false],
- [:private, ProjectFeature::DISABLED, :external, Snippet::PRIVATE, false],
+ [:private, :disabled, :external, :public, false],
+ [:private, :disabled, :external, :internal, false],
+ [:private, :disabled, :external, :private, false],
- [:private, ProjectFeature::DISABLED, :non_member, Snippet::PUBLIC, false],
- [:private, ProjectFeature::DISABLED, :non_member, Snippet::INTERNAL, false],
- [:private, ProjectFeature::DISABLED, :non_member, Snippet::PRIVATE, false],
+ [:private, :disabled, :non_member, :public, false],
+ [:private, :disabled, :non_member, :internal, false],
+ [:private, :disabled, :non_member, :private, false],
- [:private, ProjectFeature::DISABLED, :member, Snippet::PUBLIC, false],
- [:private, ProjectFeature::DISABLED, :member, Snippet::INTERNAL, false],
- [:private, ProjectFeature::DISABLED, :member, Snippet::PRIVATE, false],
+ [:private, :disabled, :member, :public, false],
+ [:private, :disabled, :member, :internal, false],
+ [:private, :disabled, :member, :private, false],
- [:private, ProjectFeature::DISABLED, :author, Snippet::PUBLIC, false],
- [:private, ProjectFeature::DISABLED, :author, Snippet::INTERNAL, false],
- [:private, ProjectFeature::DISABLED, :author, Snippet::PRIVATE, false]
+ [:private, :disabled, :author, :public, false],
+ [:private, :disabled, :author, :internal, false],
+ [:private, :disabled, :author, :private, false]
]
end
with_them do
- let!(:project_visibility) { project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value(project_type.to_s)) }
- let!(:project_feature) { project.project_feature.update_column(:snippets_access_level, feature_visibility) }
- let!(:user) { users[user_type] }
- let!(:snippet) { create(:project_snippet, visibility_level: snippet_type, project: project, author: author) }
- let!(:external_member) do
- member = project.project_member(external)
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel.level_value(project_visibility.to_s), snippets_access_level: feature_visibility)
- if project.private?
- project.add_developer(external) unless member
- else
- member.delete if member
+ if user_type == :external
+ member = project.project_member(external)
+
+ if project.private?
+ project.add_developer(external) unless member
+ else
+ member.delete if member
+ end
end
end
context "For #{params[:project_type]} project and #{params[:user_type]} users" do
- it 'agrees with the read_snippet policy' do
- expect(can?(user, :read_snippet, snippet)).to eq(outcome)
- end
-
it 'returns proper outcome' do
+ expect(can?(user, :read_snippet, snippet)).to eq(outcome)
+
results = described_class.new(user, project: project).execute
expect(results.include?(snippet)).to eq(outcome)
@@ -243,17 +256,9 @@ RSpec.shared_examples 'snippet visibility' do
context "Without a given project and #{params[:user_type]} users" do
it 'returns proper outcome' do
results = described_class.new(user).execute
+
expect(results.include?(snippet)).to eq(outcome)
end
-
- it 'returns no snippets when the user cannot read cross project' do
- allow(Ability).to receive(:allowed?).and_call_original
- allow(Ability).to receive(:allowed?).with(user, :read_cross_project) { false }
-
- snippets = described_class.new(user).execute
-
- expect(snippets).to be_empty
- end
end
end
end
@@ -270,40 +275,31 @@ RSpec.shared_examples 'snippet visibility' do
where(:snippet_visibility, :user_type, :outcome) do
[
- [Snippet::PUBLIC, :unauthenticated, true],
- [Snippet::PUBLIC, :external, true],
- [Snippet::PUBLIC, :non_member, true],
- [Snippet::PUBLIC, :author, true],
+ [:public, :unauthenticated, true],
+ [:public, :external, true],
+ [:public, :non_member, true],
+ [:public, :author, true],
- [Snippet::INTERNAL, :unauthenticated, false],
- [Snippet::INTERNAL, :external, false],
- [Snippet::INTERNAL, :non_member, true],
- [Snippet::INTERNAL, :author, true],
+ [:internal, :unauthenticated, false],
+ [:internal, :external, false],
+ [:internal, :non_member, true],
+ [:internal, :author, true],
- [Snippet::PRIVATE, :unauthenticated, false],
- [Snippet::PRIVATE, :external, false],
- [Snippet::PRIVATE, :non_member, false],
- [Snippet::PRIVATE, :author, true]
+ [:private, :unauthenticated, false],
+ [:private, :external, false],
+ [:private, :non_member, false],
+ [:private, :author, true]
]
end
with_them do
- let!(:user) { users[user_type] }
- let!(:snippet) { create(:personal_snippet, visibility_level: snippet_visibility, author: author) }
+ let_it_be(:private_snippet) { create(:personal_snippet, :private, author: author) }
+ let_it_be(:public_snippet) { create(:personal_snippet, :public, author: author) }
+ let_it_be(:internal_snippet) { create(:personal_snippet, :internal, author: author) }
context "For personal and #{params[:snippet_visibility]} snippets with #{params[:user_type]} user" do
- it 'agrees with read_snippet policy' do
- expect(can?(user, :read_snippet, snippet)).to eq(outcome)
- end
-
it 'returns proper outcome' do
- results = described_class.new(user).execute
- expect(results.include?(snippet)).to eq(outcome)
- end
-
- it 'returns personal snippets when the user cannot read cross project' do
- allow(Ability).to receive(:allowed?).and_call_original
- allow(Ability).to receive(:allowed?).with(user, :read_cross_project) { false }
+ expect(can?(user, :read_snippet, snippet)).to eq(outcome)
results = described_class.new(user).execute
@@ -312,4 +308,22 @@ RSpec.shared_examples 'snippet visibility' do
end
end
end
+
+ context 'when the user cannot read cross project' do
+ it 'returns only personal snippets' do
+ personal_snippet = create(:personal_snippet, :public, author: author)
+ create(:project_snippet, :public, project: project, author: author)
+
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(author, :read_cross_project) { false }
+
+ service = described_class.new(author)
+
+ expect(service).to receive(:personal_snippets).and_call_original
+ expect(service).not_to receive(:snippets_of_visible_projects)
+ expect(service).not_to receive(:snippets_of_authorized_projects)
+
+ expect(service.execute).to match_array([personal_snippet])
+ end
+ end
end
diff --git a/yarn.lock b/yarn.lock
index 122a78d65a2..dd65f0a9537 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7101,10 +7101,10 @@ js-cookie@^2.2.1:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-js-yaml@^3.13.1:
- version "3.13.1"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
- integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
+js-yaml@^3.12.0, js-yaml@^3.13.1:
+ version "3.14.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482"
+ integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
@@ -7267,6 +7267,11 @@ json5@^1.0.1:
dependencies:
minimist "^1.2.0"
+jsonc-parser@^2.2.1:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.0.tgz#7c7fc988ee1486d35734faaaa866fadb00fa91ee"
+ integrity sha512-b0EBt8SWFNnixVdvoR2ZtEGa9ZqLhbJnOjezn+WP+8kspFm+PFYDN8Z4Bc7pRlDjvuVcADSUkroIuTWWn/YiIA==
+
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
@@ -8233,10 +8238,15 @@ monaco-editor@0.20.0, monaco-editor@^0.20.0:
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea"
integrity sha512-hkvf4EtPJRMQlPC3UbMoRs0vTAFAYdzFQ+gpMb8A+9znae1c43q8Mab9iVsgTcg/4PNiLGGn3SlDIa8uvK1FIQ==
-monaco-yaml@^2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/monaco-yaml/-/monaco-yaml-2.4.0.tgz#027307a231d809c416babf1cf89b4c1bb940e55d"
- integrity sha512-ElUS6uBqEjA2/o2gLuNdnqWSAAQXh8ISr1kwlFErm3t5IXO74TNfS3gnjO6Kv9TXS7LImjGfgPAZei7o8zNTHw==
+monaco-yaml@^2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/monaco-yaml/-/monaco-yaml-2.4.1.tgz#f0d3384b1f10cc7af2b60e3a30b0adc6683b728a"
+ integrity sha512-Q0Yj6FNok97AslptS1OVfyX07rJ5uhOYsHKaVoU0usiUqeL7gzl6l8TL8W3QGdwCKm4WhfKpJ9bqPDtiQvCirg==
+ dependencies:
+ js-yaml "^3.12.0"
+ vscode-json-languageservice "^3.4.11"
+ vscode-languageserver "^5.2.1"
+ vscode-uri "^2.1.1"
optionalDependencies:
prettier "^1.19.1"
@@ -12053,6 +12063,68 @@ void-elements@^2.0.0:
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
+vscode-json-languageservice@^3.4.11:
+ version "3.7.0"
+ resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.7.0.tgz#0174417f139cf41dd60c84538fd052385bfb46f6"
+ integrity sha512-nGLqcBhTjdfkl8Dz9sYGK/ZCTjscYFoIjYw+qqkWB+vyNfM0k/AyIoT73DQvB/PArteCKjEVfQUF72GRZEDSbQ==
+ dependencies:
+ jsonc-parser "^2.2.1"
+ vscode-languageserver-textdocument "^1.0.1"
+ vscode-languageserver-types "^3.15.1"
+ vscode-nls "^4.1.2"
+ vscode-uri "^2.1.2"
+
+vscode-jsonrpc@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9"
+ integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg==
+
+vscode-languageserver-protocol@3.14.1:
+ version "3.14.1"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz#b8aab6afae2849c84a8983d39a1cf742417afe2f"
+ integrity sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g==
+ dependencies:
+ vscode-jsonrpc "^4.0.0"
+ vscode-languageserver-types "3.14.0"
+
+vscode-languageserver-textdocument@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz#178168e87efad6171b372add1dea34f53e5d330f"
+ integrity sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==
+
+vscode-languageserver-types@3.14.0:
+ version "3.14.0"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743"
+ integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A==
+
+vscode-languageserver-types@^3.15.1:
+ version "3.15.1"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz#17be71d78d2f6236d414f0001ce1ef4d23e6b6de"
+ integrity sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==
+
+vscode-languageserver@^5.2.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.2.1.tgz#0d2feddd33f92aadf5da32450df498d52f6f14eb"
+ integrity sha512-GuayqdKZqAwwaCUjDvMTAVRPJOp/SLON3mJ07eGsx/Iq9HjRymhKWztX41rISqDKhHVVyFM+IywICyZDla6U3A==
+ dependencies:
+ vscode-languageserver-protocol "3.14.1"
+ vscode-uri "^1.0.6"
+
+vscode-nls@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167"
+ integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==
+
+vscode-uri@^1.0.6:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.8.tgz#9769aaececae4026fb6e22359cb38946580ded59"
+ integrity sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==
+
+vscode-uri@^2.1.1, vscode-uri@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c"
+ integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==
+
vue-apollo@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/vue-apollo/-/vue-apollo-3.0.3.tgz#7f29558df76eec0f03251847eef153816a261827"