Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml36
-rw-r--r--.haml-lint_todo.yml1
-rw-r--r--app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue4
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/inline_html.js4
-rw-r--r--app/assets/javascripts/ci_variable_list/ajax_variable_list.js4
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue22
-rw-r--r--app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue4
-rw-r--r--app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue4
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue6
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue6
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue4
-rw-r--r--app/assets/javascripts/create_item_dropdown.js8
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue4
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue6
-rw-r--r--app/assets/javascripts/diffs/components/no_changes.vue6
-rw-r--r--app/assets/javascripts/dropzone_input.js4
-rw-r--r--app/assets/javascripts/environments/components/confirm_rollback_modal.vue10
-rw-r--r--app/assets/javascripts/error_tracking/components/stacktrace_entry.vue4
-rw-r--r--app/assets/javascripts/filtered_search/visual_token_value.js4
-rw-r--r--app/assets/javascripts/flash.js6
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js14
-rw-r--r--app/assets/javascripts/gl_dropdown.js4
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/actions.vue4
-rw-r--r--app/assets/javascripts/ide/components/pipelines/list.vue4
-rw-r--r--app/assets/javascripts/ide/stores/actions.js4
-rw-r--r--app/assets/javascripts/ide/stores/actions/project.js6
-rw-r--r--app/assets/javascripts/importer_status.js6
-rw-r--r--app/assets/javascripts/jobs/components/environments_block.vue8
-rw-r--r--app/assets/javascripts/labels_select.js6
-rw-r--r--app/assets/javascripts/milestone_select.js12
-rw-r--r--app/assets/javascripts/mirrors/ssh_mirror.js4
-rw-r--r--app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue8
-rw-r--r--app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue6
-rw-r--r--app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue4
-rw-r--r--app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component.vue4
-rw-r--r--app/assets/javascripts/profile/account/components/update_username.vue10
-rw-r--r--app/assets/javascripts/releases/components/app_edit.vue4
-rw-r--r--app/assets/javascripts/search_autocomplete.js4
-rw-r--r--app/assets/javascripts/sidebar/lib/sidebar_move_issue.js4
-rw-r--r--app/assets/javascripts/users_select.js14
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/issue_warning.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue4
-rw-r--r--app/helpers/export_helper.rb10
-rw-r--r--app/models/deploy_token.rb5
-rw-r--r--app/services/snippets/update_service.rb2
-rw-r--r--app/services/spam/spam_action_service.rb2
-rw-r--r--app/views/groups/edit.html.haml4
-rw-r--r--app/views/groups/settings/_advanced.html.haml2
-rw-r--r--app/views/groups/settings/_export.html.haml28
-rw-r--r--app/views/layouts/nav/sidebar/_profile.html.haml4
-rw-r--r--changelogs/unreleased/213566-package-deploy-tokens.yml5
-rw-r--r--changelogs/unreleased/jh-group_export_ui_frontend.yml5
-rw-r--r--db/migrate/20200411125656_add_package_scopes_to_deploy_tokens.rb19
-rw-r--r--db/structure.sql5
-rw-r--r--doc/administration/auditor_users.md10
-rw-r--r--doc/administration/auth/crowd.md5
-rw-r--r--doc/administration/auth/google_secure_ldap.md7
-rw-r--r--doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md5
-rw-r--r--doc/administration/auth/jwt.md5
-rw-r--r--doc/administration/file_hooks.md12
-rw-r--r--doc/administration/geo/replication/using_a_geo_server.md2
-rw-r--r--doc/administration/git_annex.md25
-rw-r--r--doc/administration/gitaly/praefect.md26
-rw-r--r--doc/administration/lfs/index.md11
-rw-r--r--doc/administration/logs.md13
-rw-r--r--doc/administration/pages/index.md4
-rw-r--r--doc/administration/pages/source.md4
-rw-r--r--doc/administration/terraform_state.md11
-rw-r--r--doc/api/group_import_export.md2
-rw-r--r--doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_MR_v12_09.pngbin0 -> 29650 bytes
-rw-r--r--doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_branch_v12_09.pngbin0 -> 29680 bytes
-rw-r--r--doc/ci/merge_request_pipelines/index.md72
-rw-r--r--doc/development/application_limits.md2
-rw-r--r--doc/development/creating_enums.md89
-rw-r--r--doc/user/admin_area/license.md7
-rw-r--r--doc/user/admin_area/monitoring/health_check.md10
-rw-r--r--doc/user/admin_area/settings/email.md5
-rw-r--r--doc/user/admin_area/settings/external_authorization.md7
-rw-r--r--doc/user/admin_area/settings/sign_up_restrictions.md7
-rw-r--r--doc/user/admin_area/settings/usage_statistics.md13
-rw-r--r--doc/user/group/settings/img/export_panel.pngbin0 -> 200162 bytes
-rw-r--r--doc/user/group/settings/import_export.md76
-rw-r--r--doc/user/permissions.md2
-rw-r--r--doc/user/project/integrations/prometheus.md10
-rw-r--r--doc/user/project/integrations/prometheus_units.md71
-rw-r--r--doc/user/project/members/index.md2
-rw-r--r--doc/user/project/settings/import_export.md1
-rw-r--r--lib/quality/helm3_client.rb6
-rw-r--r--lib/quality/helm_client.rb114
-rw-r--r--locale/gitlab.pot32
-rwxr-xr-xscripts/review_apps/automated_cleanup.rb21
-rwxr-xr-xscripts/review_apps/gcp_cleanup.sh7
-rwxr-xr-xscripts/review_apps/review-apps.sh33
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb8
-rw-r--r--spec/controllers/projects/snippets_controller_spec.rb24
-rw-r--r--spec/controllers/registrations_controller_spec.rb2
-rw-r--r--spec/controllers/snippets_controller_spec.rb22
-rw-r--r--spec/factories/deploy_tokens.rb8
-rw-r--r--spec/features/groups/import_export/export_file_spec.rb59
-rw-r--r--spec/features/issues/spam_issues_spec.rb4
-rw-r--r--spec/features/snippets/spam_snippets_spec.rb10
-rw-r--r--spec/javascripts/filtered_search/visual_token_value_spec.js4
-rw-r--r--spec/javascripts/issue_show/components/app_spec.js2
-rw-r--r--spec/javascripts/issue_show/components/description_spec.js2
-rw-r--r--spec/lib/quality/helm_client_spec.rb132
-rw-r--r--spec/models/deploy_token_spec.rb4
-rw-r--r--spec/services/issues/create_service_spec.rb4
-rw-r--r--spec/services/spam/spam_action_service_spec.rb4
112 files changed, 741 insertions, 669 deletions
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index 99867eb3cdc..256952098d6 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -19,49 +19,24 @@ build-qa-image:
- export QA_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-${GITLAB_EDITION}-qa:${CI_COMMIT_REF_SLUG}"
- /kaniko/executor --context=${CI_PROJECT_DIR} --dockerfile=${CI_PROJECT_DIR}/qa/Dockerfile --destination=${QA_IMAGE} --cache=true
-.review-cleanup-base:
+review-cleanup:
extends:
- .default-retry
- .review:rules:review-cleanup
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-helm3-kubectl1.14
stage: prepare
- allow_failure: true
environment:
name: review/auto-cleanup
action: stop
before_script:
- source scripts/utils.sh
+ - source scripts/review_apps/gcp_cleanup.sh
- install_gitlab_gem
+ - setup_gcp_dependencies
script:
- ruby -rrubygems scripts/review_apps/automated_cleanup.rb
-
-review-cleanup:
- extends:
- - .review-cleanup-base
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base
-
-review-cleanup-helm3:
- extends:
- - .review-cleanup-base
- variables:
- HELM_3: 1
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-helm3-kubectl1.14
-
-review-gcp-cleanup:
- extends:
- - .review:rules:review-gcp-cleanup
- stage: prepare
- image: gcr.io/google.com/cloudsdktool/cloud-sdk:latest
- allow_failure: true
- environment:
- name: review/auto-gcp-cleanup
- action: stop
- before_script:
- - gcloud auth activate-service-account --key-file=$REVIEW_APPS_GCP_CREDENTIALS
- - gcloud config set project $REVIEW_APPS_GCP_PROJECT
- - apt-get install -y jq
- - source scripts/review_apps/gcp_cleanup.sh
- script:
- gcp_cleanup
+ allow_failure: true
review-build-cng:
extends:
@@ -152,7 +127,6 @@ review-stop-failed-deployment:
stage: prepare
script:
- delete_failed_release
- - delete_helm2_release
review-stop:
extends:
diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml
index eecbdbba52f..f78717a333d 100644
--- a/.haml-lint_todo.yml
+++ b/.haml-lint_todo.yml
@@ -360,7 +360,6 @@ linters:
- "ee/app/views/notify/send_unsubscribed_notification.html.haml"
- "ee/app/views/notify/unapproved_merge_request_email.html.haml"
- "ee/app/views/oauth/geo_auth/error.html.haml"
- - "ee/app/views/profiles/pipeline_quota/index.haml"
- "ee/app/views/projects/commits/_mirror_status.html.haml"
- "ee/app/views/projects/jobs/_shared_runner_limit_warning.html.haml"
- "ee/app/views/projects/merge_requests/_approvals_count.html.haml"
diff --git a/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue b/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue
index 785598142fe..410c5c00e8a 100644
--- a/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue
+++ b/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue
@@ -6,7 +6,7 @@ import {
GlModal,
GlModalDirective,
} from '@gitlab/ui';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import ToggleButton from '~/vue_shared/components/toggle_button.vue';
import axios from '~/lib/utils/axios_utils';
@@ -65,7 +65,7 @@ export default {
'AlertService|%{linkStart}Learn more%{linkEnd} about configuring this endpoint to receive alerts.',
),
{
- linkStart: `<a href="${esc(
+ linkStart: `<a href="${escape(
this.learnMoreUrl,
)}" target="_blank" rel="noopener noreferrer">`,
linkEnd: '</a>',
diff --git a/app/assets/javascripts/behaviors/markdown/marks/inline_html.js b/app/assets/javascripts/behaviors/markdown/marks/inline_html.js
index 7e020139fe7..f8465111959 100644
--- a/app/assets/javascripts/behaviors/markdown/marks/inline_html.js
+++ b/app/assets/javascripts/behaviors/markdown/marks/inline_html.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
import { Mark } from 'tiptap';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
export default class InlineHTML extends Mark {
@@ -35,7 +35,7 @@ export default class InlineHTML extends Mark {
mixable: true,
open(state, mark) {
return `<${mark.attrs.tag}${
- mark.attrs.title ? ` title="${state.esc(esc(mark.attrs.title))}"` : ''
+ mark.attrs.title ? ` title="${state.esc(escape(mark.attrs.title))}"` : ''
}>`;
},
close(state, mark) {
diff --git a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js b/app/assets/javascripts/ci_variable_list/ajax_variable_list.js
index da33e092086..470649e63fb 100644
--- a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js
+++ b/app/assets/javascripts/ci_variable_list/ajax_variable_list.js
@@ -1,4 +1,4 @@
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import axios from '../lib/utils/axios_utils';
import { s__ } from '../locale';
import Flash from '../flash';
@@ -10,7 +10,7 @@ function generateErrorBoxContent(errors) {
const errorList = [].concat(errors).map(
errorString => `
<li>
- ${esc(errorString)}
+ ${escape(errorString)}
</li>
`,
);
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index 96c00480dfd..f6fb05ff0ec 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import helmInstallIllustration from '@gitlab/svgs/dist/illustrations/kubernetes-installation.svg';
import { GlLoadingIcon } from '@gitlab/ui';
import elasticsearchLogo from 'images/cluster_app_logos/elasticsearch.png';
@@ -138,7 +138,7 @@ export default {
},
ingressDescription() {
return sprintf(
- esc(
+ escape(
s__(
`ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}.`,
),
@@ -146,14 +146,14 @@ export default {
{
pricingLink: `<a href="https://cloud.google.com/compute/pricing#lb"
target="_blank" rel="noopener noreferrer">
- ${esc(s__('ClusterIntegration|pricing'))}</a>`,
+ ${escape(s__('ClusterIntegration|pricing'))}</a>`,
},
false,
);
},
certManagerDescription() {
return sprintf(
- esc(
+ escape(
s__(
`ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates.
Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates
@@ -163,14 +163,14 @@ export default {
{
letsEncrypt: `<a href="https://letsencrypt.org/"
target="_blank" rel="noopener noreferrer">
- ${esc(s__("ClusterIntegration|Let's Encrypt"))}</a>`,
+ ${escape(s__("ClusterIntegration|Let's Encrypt"))}</a>`,
},
false,
);
},
crossplaneDescription() {
return sprintf(
- esc(
+ escape(
s__(
`ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{kubectl} or %{gitlabIntegrationLink}.
Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on.`,
@@ -179,7 +179,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
{
gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ee/user/clusters/applications.html#crossplane"
target="_blank" rel="noopener noreferrer">
- ${esc(s__('ClusterIntegration|Gitlab Integration'))}</a>`,
+ ${escape(s__('ClusterIntegration|Gitlab Integration'))}</a>`,
kubectl: `<code>kubectl</code>`,
},
false,
@@ -188,7 +188,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
prometheusDescription() {
return sprintf(
- esc(
+ escape(
s__(
`ClusterIntegration|Prometheus is an open-source monitoring system
with %{gitlabIntegrationLink} to monitor deployed applications.`,
@@ -197,7 +197,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
{
gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html"
target="_blank" rel="noopener noreferrer">
- ${esc(s__('ClusterIntegration|GitLab Integration'))}</a>`,
+ ${escape(s__('ClusterIntegration|GitLab Integration'))}</a>`,
},
false,
);
@@ -223,11 +223,11 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
installedVia() {
if (this.cloudRun) {
return sprintf(
- esc(s__(`ClusterIntegration|installed via %{installed_via}`)),
+ escape(s__(`ClusterIntegration|installed via %{installed_via}`)),
{
installed_via: `<a href="${
this.cloudRunHelpPath
- }" target="_blank" rel="noopener noreferrer">${esc(
+ }" target="_blank" rel="noopener noreferrer">${escape(
s__('ClusterIntegration|Cloud Run'),
)}</a>`,
},
diff --git a/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue b/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue
index 95eb427a49c..c2f963f0b34 100644
--- a/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue
+++ b/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { s__, __ } from '../../locale';
import { APPLICATION_STATUS, INGRESS, LOGGING_MODE, BLOCKING_MODE } from '~/clusters/constants';
import {
@@ -87,7 +87,7 @@ export default {
);
},
ingressModSecurityDescription() {
- return esc(this.ingressModSecurityHelpPath);
+ return escape(this.ingressModSecurityHelpPath);
},
saving() {
return [UPDATING].includes(this.ingress.status);
diff --git a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
index b35adae3352..271f9f74838 100644
--- a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
+++ b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import SplitButton from '~/vue_shared/components/split_button.vue';
import { GlModal, GlDeprecatedButton, GlFormInput } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
@@ -82,7 +82,7 @@ export default {
)
: s__('ClusterIntegration|To remove your integration, type %{clusterName} to confirm:'),
{
- clusterName: `<code>${esc(this.clusterName)}</code>`,
+ clusterName: `<code>${escape(this.clusterName)}</code>`,
},
false,
);
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
index 74b5a62f754..d6c402fcb5d 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
@@ -1,6 +1,6 @@
<script>
import { createNamespacedHelpers, mapState, mapActions, mapGetters } from 'vuex';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { GlFormInput, GlFormCheckbox } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
import ClusterFormDropdown from '~/create_cluster/components/cluster_form_dropdown.vue';
@@ -137,7 +137,7 @@ export default {
: s__('ClusterIntegration|Create Kubernetes cluster');
},
kubernetesIntegrationHelpText() {
- const escapedUrl = esc(this.kubernetesIntegrationHelpPath);
+ const escapedUrl = escape(this.kubernetesIntegrationHelpPath);
return sprintf(
s__(
@@ -256,7 +256,7 @@ export default {
);
},
gitlabManagedHelpText() {
- const escapedUrl = esc(this.gitlabManagedClusterHelpPath);
+ const escapedUrl = escape(this.gitlabManagedClusterHelpPath);
return sprintf(
s__(
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue
index 47cc4e4ce67..e063f9edfd9 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue
@@ -1,6 +1,6 @@
<script>
import { GlFormInput } from '@gitlab/ui';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { mapState, mapActions } from 'vuex';
import { sprintf, s__, __ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
@@ -42,7 +42,7 @@ export default {
: s__('ClusterIntegration|Authenticate with AWS');
},
accountAndExternalIdsHelpText() {
- const escapedUrl = esc(this.accountAndExternalIdsHelpPath);
+ const escapedUrl = escape(this.accountAndExternalIdsHelpPath);
return sprintf(
s__(
@@ -59,7 +59,7 @@ export default {
);
},
provisionRoleArnHelpText() {
- const escapedUrl = esc(this.createRoleArnHelpPath);
+ const escapedUrl = escape(this.createRoleArnHelpPath);
return sprintf(
s__(
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue
index 6d8e6bbac11..b0bec10f64d 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue
+++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { mapState, mapGetters, mapActions } from 'vuex';
import { s__, sprintf } from '~/locale';
@@ -65,7 +65,7 @@ export default {
s__(message),
{
docsLinkEnd: '&nbsp;<i class="fa fa-external-link" aria-hidden="true"></i></a>',
- docsLinkStart: `<a href="${esc(
+ docsLinkStart: `<a href="${escape(
this.docsUrl,
)}" target="_blank" rel="noopener noreferrer">`,
},
diff --git a/app/assets/javascripts/create_item_dropdown.js b/app/assets/javascripts/create_item_dropdown.js
index 523e5592fd0..ec09dafebcb 100644
--- a/app/assets/javascripts/create_item_dropdown.js
+++ b/app/assets/javascripts/create_item_dropdown.js
@@ -1,4 +1,4 @@
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import '~/gl_dropdown';
export default class CreateItemDropdown {
@@ -37,14 +37,14 @@ export default class CreateItemDropdown {
},
selectable: true,
toggleLabel(selected) {
- return selected && 'id' in selected ? esc(selected.title) : this.defaultToggleLabel;
+ return selected && 'id' in selected ? escape(selected.title) : this.defaultToggleLabel;
},
fieldName: this.fieldName,
text(item) {
- return esc(item.text);
+ return escape(item.text);
},
id(item) {
- return esc(item.id);
+ return escape(item.id);
},
onFilter: this.toggleCreateNewButton.bind(this),
clicked: options => {
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index 82ca3749ac1..54852b113ae 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { GlLoadingIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import createFlash from '~/flash';
@@ -46,7 +46,7 @@ export default {
return sprintf(
__('You can %{linkStart}view the blob%{linkEnd} instead.'),
{
- linkStart: `<a href="${esc(this.file.view_path)}">`,
+ linkStart: `<a href="${escape(this.file.view_path)}">`,
linkEnd: '</a>',
},
false,
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index d601c3769a3..61bbf13aa53 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { mapActions, mapGetters } from 'vuex';
import { GlDeprecatedButton, GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
import { polyfillSticky } from '~/lib/utils/sticky';
@@ -91,7 +91,7 @@ export default {
return this.expanded ? 'chevron-down' : 'chevron-right';
},
viewFileButtonText() {
- const truncatedContentSha = esc(truncateSha(this.diffFile.content_sha));
+ const truncatedContentSha = escape(truncateSha(this.diffFile.content_sha));
return sprintf(
s__('MergeRequests|View file @ %{commitId}'),
{ commitId: truncatedContentSha },
@@ -99,7 +99,7 @@ export default {
);
},
viewReplacedFileButtonText() {
- const truncatedBaseSha = esc(truncateSha(this.diffFile.diff_refs.base_sha));
+ const truncatedBaseSha = escape(truncateSha(this.diffFile.diff_refs.base_sha));
return sprintf(
s__('MergeRequests|View replaced file @ %{commitId}'),
{
diff --git a/app/assets/javascripts/diffs/components/no_changes.vue b/app/assets/javascripts/diffs/components/no_changes.vue
index 5fd68471094..94c2695a945 100644
--- a/app/assets/javascripts/diffs/components/no_changes.vue
+++ b/app/assets/javascripts/diffs/components/no_changes.vue
@@ -1,6 +1,6 @@
<script>
import { mapGetters } from 'vuex';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { GlDeprecatedButton } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
@@ -24,8 +24,8 @@ export default {
{
ref_start: '<span class="ref-name">',
ref_end: '</span>',
- source_branch: esc(this.getNoteableData.source_branch),
- target_branch: esc(this.getNoteableData.target_branch),
+ source_branch: escape(this.getNoteableData.source_branch),
+ target_branch: escape(this.getNoteableData.target_branch),
},
false,
);
diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js
index 490f2330012..9a0b85bd610 100644
--- a/app/assets/javascripts/dropzone_input.js
+++ b/app/assets/javascripts/dropzone_input.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import Dropzone from 'dropzone';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import './behaviors/preview_markdown';
import PasteMarkdownTable from './behaviors/markdown/paste_markdown_table';
import csrf from './lib/utils/csrf';
@@ -233,7 +233,7 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
};
addFileToForm = path => {
- $(form).append(`<input type="hidden" name="files[]" value="${esc(path)}">`);
+ $(form).append(`<input type="hidden" name="files[]" value="${escape(path)}">`);
};
const showSpinner = () => $uploadingProgressContainer.removeClass('hide');
diff --git a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
index 5c03c008faf..f0723e96ddf 100644
--- a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
+++ b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
@@ -3,7 +3,7 @@
* Render modal to confirm rollback/redeploy.
*/
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { GlModal } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
@@ -30,7 +30,7 @@ export default {
: s__('Environments|Rollback environment %{name}?');
return sprintf(title, {
- name: esc(this.environment.name),
+ name: escape(this.environment.name),
});
},
@@ -50,10 +50,10 @@ export default {
},
modalText() {
- const linkStart = `<a class="commit-sha mr-0" href="${esc(this.commitUrl)}">`;
- const commitId = esc(this.commitShortSha);
+ const linkStart = `<a class="commit-sha mr-0" href="${escape(this.commitUrl)}">`;
+ const commitId = escape(this.commitShortSha);
const linkEnd = '</a>';
- const name = esc(this.name);
+ const name = escape(this.name);
const body = this.environment.isLastDeployment
? s__(
'Environments|This action will relaunch the job for commit %{linkStart}%{commitId}%{linkEnd}, putting the environment in a previous version. Are you sure you want to continue?',
diff --git a/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue b/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
index 8db0b1c5da0..f7f2c450be1 100644
--- a/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
+++ b/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { GlTooltip } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
@@ -62,7 +62,7 @@ export default {
? sprintf(
__(`%{spanStart}in%{spanEnd} %{errorFn}`),
{
- errorFn: `<strong>${esc(this.errorFn)}</strong>`,
+ errorFn: `<strong>${escape(this.errorFn)}</strong>`,
spanStart: `<span class="text-tertiary">`,
spanEnd: `</span>`,
},
diff --git a/app/assets/javascripts/filtered_search/visual_token_value.js b/app/assets/javascripts/filtered_search/visual_token_value.js
index b8f4cd8a1e1..02caf0851af 100644
--- a/app/assets/javascripts/filtered_search/visual_token_value.js
+++ b/app/assets/javascripts/filtered_search/visual_token_value.js
@@ -1,4 +1,4 @@
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { USER_TOKEN_TYPES } from 'ee_else_ce/filtered_search/constants';
import FilteredSearchContainer from '~/filtered_search/container';
import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
@@ -48,7 +48,7 @@ export default class VisualTokenValue {
tokenValueContainer.dataset.originalValue = tokenValue;
tokenValueElement.innerHTML = `
<img class="avatar s20" src="${user.avatar_url}" alt="">
- ${esc(user.name)}
+ ${escape(user.name)}
`;
/* eslint-enable no-param-reassign */
})
diff --git a/app/assets/javascripts/flash.js b/app/assets/javascripts/flash.js
index 40d820b1ed5..74c00d21535 100644
--- a/app/assets/javascripts/flash.js
+++ b/app/assets/javascripts/flash.js
@@ -1,4 +1,4 @@
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { spriteIcon } from './lib/utils/common_utils';
const FLASH_TYPES = {
@@ -39,14 +39,14 @@ const createAction = config => `
class="flash-action"
${config.href ? '' : 'role="button"'}
>
- ${esc(config.title)}
+ ${escape(config.title)}
</a>
`;
const createFlashEl = (message, type) => `
<div class="flash-${type}">
<div class="flash-text">
- ${esc(message)}
+ ${escape(message)}
<div class="close-icon-wrapper js-close-icon">
${spriteIcon('close', 'close-icon')}
</div>
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index c40b0949e70..f3ce30c942f 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import '@gitlab/at.js';
-import { escape as esc, template } from 'lodash';
+import { escape, template } from 'lodash';
import SidebarMediator from '~/sidebar/sidebar_mediator';
import glRegexp from './lib/utils/regexp';
import AjaxCache from './lib/utils/ajax_cache';
@@ -692,14 +692,14 @@ GfmAutoComplete.Emoji = {
// Team Members
GfmAutoComplete.Members = {
templateFunction({ avatarTag, username, title, icon }) {
- return `<li>${avatarTag} ${username} <small>${esc(title)}</small> ${icon}</li>`;
+ return `<li>${avatarTag} ${username} <small>${escape(title)}</small> ${icon}</li>`;
},
};
GfmAutoComplete.Labels = {
templateFunction(color, title) {
- return `<li><span class="dropdown-label-box" style="background: ${esc(color)}"></span> ${esc(
- title,
- )}</li>`;
+ return `<li><span class="dropdown-label-box" style="background: ${escape(
+ color,
+ )}"></span> ${escape(title)}</li>`;
},
};
// Issues, MergeRequests and Snippets
@@ -709,13 +709,13 @@ GfmAutoComplete.Issues = {
return value.reference || '${atwho-at}${id}';
},
templateFunction({ id, title, reference }) {
- return `<li><small>${reference || id}</small> ${esc(title)}</li>`;
+ return `<li><small>${reference || id}</small> ${escape(title)}</li>`;
},
};
// Milestones
GfmAutoComplete.Milestones = {
templateFunction(title) {
- return `<li>${esc(title)}</li>`;
+ return `<li>${escape(title)}</li>`;
},
};
GfmAutoComplete.Loading = {
diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js
index d9191d48d8f..1490498c511 100644
--- a/app/assets/javascripts/gl_dropdown.js
+++ b/app/assets/javascripts/gl_dropdown.js
@@ -1,7 +1,7 @@
/* eslint-disable max-classes-per-file, one-var, consistent-return */
import $ from 'jquery';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import axios from './lib/utils/axios_utils';
import { visitUrl } from './lib/utils/url_utility';
@@ -610,7 +610,7 @@ class GitLabDropdown {
// eslint-disable-next-line class-methods-use-this
highlightTemplate(text, template) {
- return `"<b>${esc(text)}</b>" ${template}`;
+ return `"<b>${escape(text)}</b>" ${template}`;
}
// eslint-disable-next-line class-methods-use-this
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
index 6a8ea506d1b..6c563776533 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { mapState, mapGetters, createNamespacedHelpers } from 'vuex';
import { sprintf, s__ } from '~/locale';
import consts from '../../stores/modules/commit/constants';
@@ -22,7 +22,7 @@ export default {
commitToCurrentBranchText() {
return sprintf(
s__('IDE|Commit to %{branchName} branch'),
- { branchName: `<strong class="monospace">${esc(this.currentBranchId)}</strong>` },
+ { branchName: `<strong class="monospace">${escape(this.currentBranchId)}</strong>` },
false,
);
},
diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue
index d3e5add2e83..1fc11de39d4 100644
--- a/app/assets/javascripts/ide/components/pipelines/list.vue
+++ b/app/assets/javascripts/ide/components/pipelines/list.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { GlLoadingIcon } from '@gitlab/ui';
import { sprintf, __ } from '../../../locale';
import Icon from '../../../vue_shared/components/icon.vue';
@@ -35,7 +35,7 @@ export default {
return sprintf(
__('You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}.'),
{
- linkStart: `<a href="${esc(this.currentProject.web_url)}/-/ci/lint">`,
+ linkStart: `<a href="${escape(this.currentProject.web_url)}/-/ci/lint">`,
linkEnd: '</a>',
},
false,
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index 04cf0ad53d5..1856a84359f 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import Vue from 'vue';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { __, sprintf } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility';
import flash from '~/flash';
@@ -296,7 +296,7 @@ export const getBranchData = ({ commit, state }, { projectId, branchId, force =
sprintf(
__('Branch not loaded - %{branchId}'),
{
- branchId: `<strong>${esc(projectId)}/${esc(branchId)}</strong>`,
+ branchId: `<strong>${escape(projectId)}/${escape(branchId)}</strong>`,
},
false,
),
diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js
index ae3829dc35e..6c8fb9f90aa 100644
--- a/app/assets/javascripts/ide/stores/actions/project.js
+++ b/app/assets/javascripts/ide/stores/actions/project.js
@@ -1,4 +1,4 @@
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import flash from '~/flash';
import { __, sprintf } from '~/locale';
import service from '../../services';
@@ -73,7 +73,7 @@ export const showBranchNotFoundError = ({ dispatch }, branchId) => {
text: sprintf(
__("Branch %{branchName} was not found in this project's repository."),
{
- branchName: `<strong>${esc(branchId)}</strong>`,
+ branchName: `<strong>${escape(branchId)}</strong>`,
},
false,
),
@@ -162,7 +162,7 @@ export const openBranch = ({ dispatch }, { projectId, branchId, basePath }) => {
sprintf(
__('An error occurred while getting files for - %{branchId}'),
{
- branchId: `<strong>${esc(projectId)}/${esc(branchId)}</strong>`,
+ branchId: `<strong>${escape(projectId)}/${escape(branchId)}</strong>`,
},
false,
),
diff --git a/app/assets/javascripts/importer_status.js b/app/assets/javascripts/importer_status.js
index 35d54816350..d6b519f7eac 100644
--- a/app/assets/javascripts/importer_status.js
+++ b/app/assets/javascripts/importer_status.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { __, sprintf } from './locale';
import axios from './lib/utils/axios_utils';
import flash from './flash';
@@ -73,9 +73,9 @@ class ImporterStatus {
const connectingVerb = this.ciCdOnly ? __('connecting') : __('importing');
job.find('.import-actions').html(
sprintf(
- esc(__('%{loadingIcon} Started')),
+ escape(__('%{loadingIcon} Started')),
{
- loadingIcon: `<i class="fa fa-spinner fa-spin" aria-label="${esc(
+ loadingIcon: `<i class="fa fa-spinner fa-spin" aria-label="${escape(
connectingVerb,
)}"></i>`,
},
diff --git a/app/assets/javascripts/jobs/components/environments_block.vue b/app/assets/javascripts/jobs/components/environments_block.vue
index d9168f57cc7..28cc03c88cb 100644
--- a/app/assets/javascripts/jobs/components/environments_block.vue
+++ b/app/assets/javascripts/jobs/components/environments_block.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc, isEmpty } from 'lodash';
+import { escape, isEmpty } from 'lodash';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import { sprintf, __ } from '../../locale';
@@ -43,7 +43,7 @@ export default {
'%{startLink}%{name}%{endLink}',
{
startLink: `<a href="${this.deploymentStatus.environment.environment_path}" class="js-environment-link">`,
- name: esc(this.deploymentStatus.environment.name),
+ name: escape(this.deploymentStatus.environment.name),
endLink: '</a>',
},
false,
@@ -74,8 +74,8 @@ export default {
}
const { name, path } = this.deploymentCluster;
- const escapedName = esc(name);
- const escapedPath = esc(path);
+ const escapedName = escape(name);
+ const escapedPath = escape(path);
if (!escapedPath) {
return escapedName;
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index 47d5a8253dd..03a8db754c0 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -3,7 +3,7 @@
/* global ListLabel */
import $ from 'jquery';
-import { isEqual, escape as esc, sortBy, template } from 'lodash';
+import { isEqual, escape, sortBy, template } from 'lodash';
import { sprintf, s__, __ } from './locale';
import axios from './lib/utils/axios_utils';
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
@@ -269,7 +269,7 @@ export default class LabelsSelect {
}
linkEl.className = selectedClass.join(' ');
- linkEl.innerHTML = `${colorEl} ${esc(label.title)}`;
+ linkEl.innerHTML = `${colorEl} ${escape(label.title)}`;
const listItemEl = document.createElement('li');
listItemEl.appendChild(linkEl);
@@ -557,7 +557,7 @@ export default class LabelsSelect {
scopedLabelTemplate,
tooltipTitleTemplate,
isScopedLabel,
- escapeStr: esc,
+ escapeStr: escape,
});
}
diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js
index 5d2825e3cd2..7073ce87f93 100644
--- a/app/assets/javascripts/milestone_select.js
+++ b/app/assets/javascripts/milestone_select.js
@@ -3,7 +3,7 @@
/* global ListMilestone */
import $ from 'jquery';
-import { template, escape as esc } from 'lodash';
+import { template, escape } from 'lodash';
import { __ } from '~/locale';
import '~/gl_dropdown';
import axios from './lib/utils/axios_utils';
@@ -106,12 +106,12 @@ export default class MilestoneSelect {
if (showMenuAbove) {
$dropdown.data('glDropdown').positionMenuAbove();
}
- $(`[data-milestone-id="${esc(selectedMilestone)}"] > a`).addClass('is-active');
+ $(`[data-milestone-id="${escape(selectedMilestone)}"] > a`).addClass('is-active');
}),
renderRow: milestone => `
- <li data-milestone-id="${esc(milestone.name)}">
+ <li data-milestone-id="${escape(milestone.name)}">
<a href='#' class='dropdown-menu-milestone-link'>
- ${esc(milestone.title)}
+ ${escape(milestone.title)}
</a>
</li>
`,
@@ -129,7 +129,7 @@ export default class MilestoneSelect {
},
defaultLabel,
fieldName: $dropdown.data('fieldName'),
- text: milestone => esc(milestone.title),
+ text: milestone => escape(milestone.title),
id: milestone => {
if (!useId && !$dropdown.is('.js-issuable-form-dropdown')) {
return milestone.name;
@@ -148,7 +148,7 @@ export default class MilestoneSelect {
selectedMilestone = $dropdown[0].dataset.selected || selectedMilestoneDefault;
}
$('a.is-active', $el).removeClass('is-active');
- $(`[data-milestone-id="${esc(selectedMilestone)}"] > a`, $el).addClass('is-active');
+ $(`[data-milestone-id="${escape(selectedMilestone)}"] > a`, $el).addClass('is-active');
},
vue: $dropdown.hasClass('js-issue-board-sidebar'),
clicked: clickEvent => {
diff --git a/app/assets/javascripts/mirrors/ssh_mirror.js b/app/assets/javascripts/mirrors/ssh_mirror.js
index 2276a723326..986785fdfbe 100644
--- a/app/assets/javascripts/mirrors/ssh_mirror.js
+++ b/app/assets/javascripts/mirrors/ssh_mirror.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { __ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
import Flash from '~/flash';
@@ -161,7 +161,7 @@ export default class SSHMirror {
const $fingerprintsList = this.$hostKeysInformation.find('.js-fingerprints-list');
let fingerprints = '';
sshHostKeys.fingerprints.forEach(fingerprint => {
- const escFingerprints = esc(fingerprint.fingerprint);
+ const escFingerprints = escape(fingerprint.fingerprint);
fingerprints += `<code>${escFingerprints}</code>`;
});
diff --git a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
index a99fde54981..b22fbf6b833 100644
--- a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
+++ b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { s__, sprintf } from '~/locale';
@@ -34,7 +34,7 @@ export default {
return sprintf(
s__('AdminProjects|Delete Project %{projectName}?'),
{
- projectName: `'${esc(this.projectName)}'`,
+ projectName: `'${escape(this.projectName)}'`,
},
false,
);
@@ -46,7 +46,7 @@ export default {
and all related resources including issues, merge requests, etc.. Once you confirm and press
%{strong_start}Delete project%{strong_end}, it cannot be undone or recovered.`),
{
- projectName: `<strong>${esc(this.projectName)}</strong>`,
+ projectName: `<strong>${escape(this.projectName)}</strong>`,
strong_start: '<strong>',
strong_end: '</strong>',
},
@@ -57,7 +57,7 @@ export default {
return sprintf(
s__('AdminUsers|To confirm, type %{projectName}'),
{
- projectName: `<code>${esc(this.projectName)}</code>`,
+ projectName: `<code>${escape(this.projectName)}</code>`,
},
false,
);
diff --git a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
index 5b7c8141084..b9cd309a320 100644
--- a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
+++ b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { GlModal, GlDeprecatedButton, GlFormInput } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
@@ -56,7 +56,7 @@ export default {
return sprintf(
this.content,
{
- username: `<strong>${esc(this.username)}</strong>`,
+ username: `<strong>${escape(this.username)}</strong>`,
strong_start: '<strong>',
strong_end: '</strong>',
},
@@ -67,7 +67,7 @@ export default {
return sprintf(
s__('AdminUsers|To confirm, type %{username}'),
{
- username: `<code>${esc(this.username)}</code>`,
+ username: `<code>${escape(this.username)}</code>`,
},
false,
);
diff --git a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue b/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
index 12e16b79d37..3b26047455d 100644
--- a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
+++ b/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
@@ -49,7 +49,7 @@ export default {
const label = `<span
class="label color-label"
style="background-color: ${this.labelColor}; color: ${this.labelTextColor};"
- >${esc(this.labelTitle)}</span>`;
+ >${escape(this.labelTitle)}</span>`;
return sprintf(
s__('Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>'),
diff --git a/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue b/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue
index 6af346ace67..cf0ebf05268 100644
--- a/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue
+++ b/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { GlModal, GlModalDirective } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
@@ -38,7 +38,7 @@ export default {
return sprintf(
s__('WikiPageConfirmDelete|Delete page %{pageTitle}?'),
{
- pageTitle: esc(this.pageTitle),
+ pageTitle: escape(this.pageTitle),
},
false,
);
diff --git a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
index 3d3dabbdf22..bed0ed51d5f 100644
--- a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
@@ -1,5 +1,5 @@
<script>
-import { isEmpty, escape as esc } from 'lodash';
+import { isEmpty, escape } from 'lodash';
import stageColumnMixin from '../../mixins/stage_column_mixin';
import JobItem from './job_item.vue';
import JobGroupDropdown from './job_group_dropdown.vue';
@@ -44,7 +44,7 @@ export default {
},
methods: {
groupId(group) {
- return `ci-badge-${esc(group.name)}`;
+ return `ci-badge-${escape(group.name)}`;
},
pipelineActionRequestComplete() {
this.$emit('refreshPipelineGraph');
diff --git a/app/assets/javascripts/profile/account/components/update_username.vue b/app/assets/javascripts/profile/account/components/update_username.vue
index fa09e063552..feb83e07607 100644
--- a/app/assets/javascripts/profile/account/components/update_username.vue
+++ b/app/assets/javascripts/profile/account/components/update_username.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import axios from '~/lib/utils/axios_utils';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { s__, sprintf } from '~/locale';
@@ -43,10 +43,10 @@ You are going to change the username %{currentUsernameBold} to %{newUsernameBold
Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group.
Please update your Git repository remotes as soon as possible.`),
{
- currentUsernameBold: `<strong>${esc(this.username)}</strong>`,
- newUsernameBold: `<strong>${esc(this.newUsername)}</strong>`,
- currentUsername: esc(this.username),
- newUsername: esc(this.newUsername),
+ currentUsernameBold: `<strong>${escape(this.username)}</strong>`,
+ newUsernameBold: `<strong>${escape(this.newUsername)}</strong>`,
+ currentUsername: escape(this.username),
+ newUsername: escape(this.newUsername),
},
false,
);
diff --git a/app/assets/javascripts/releases/components/app_edit.vue b/app/assets/javascripts/releases/components/app_edit.vue
index 8d68ff02116..1a1b2591cc8 100644
--- a/app/assets/javascripts/releases/components/app_edit.vue
+++ b/app/assets/javascripts/releases/components/app_edit.vue
@@ -1,7 +1,7 @@
<script>
import { mapState, mapActions, mapGetters } from 'vuex';
import { GlButton, GlFormInput, GlFormGroup } from '@gitlab/ui';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { __, sprintf } from '~/locale';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
@@ -58,7 +58,7 @@ export default {
'Changing a Release tag is only supported via Releases API. %{linkStart}More information%{linkEnd}',
),
{
- linkStart: `<a href="${esc(
+ linkStart: `<a href="${escape(
this.updateReleaseApiDocsPath,
)}" target="_blank" rel="noopener noreferrer">`,
linkEnd: '</a>',
diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js
index 0e32bb5e49f..cacaa585b5d 100644
--- a/app/assets/javascripts/search_autocomplete.js
+++ b/app/assets/javascripts/search_autocomplete.js
@@ -1,7 +1,7 @@
/* eslint-disable no-return-assign, consistent-return, class-methods-use-this */
import $ from 'jquery';
-import { escape as esc, throttle } from 'lodash';
+import { escape, throttle } from 'lodash';
import { s__, __ } from '~/locale';
import { getIdenticonBackgroundClass, getIdenticonTitle } from '~/helpers/avatar_helper';
import axios from './lib/utils/axios_utils';
@@ -448,7 +448,7 @@ export class SearchAutocomplete {
const avatar = avatarUrl
? `<img class="search-item-avatar" src="${avatarUrl}" />`
: `<div class="s16 avatar identicon ${getIdenticonBackgroundClass(id)}">${getIdenticonTitle(
- esc(label),
+ escape(label),
)}</div>`;
return avatar;
diff --git a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
index 2a61f7b5c05..0fb9cf22653 100644
--- a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
+++ b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import '~/gl_dropdown';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { __ } from '~/locale';
function isValidProjectId(id) {
@@ -49,7 +49,7 @@ class SidebarMoveIssue {
renderRow: project => `
<li>
<a href="#" class="js-move-issue-dropdown-item">
- ${esc(project.name_with_namespace)}
+ ${escape(project.name_with_namespace)}
</a>
</li>
`,
diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js
index debf8c57b43..ebbe8549656 100644
--- a/app/assets/javascripts/users_select.js
+++ b/app/assets/javascripts/users_select.js
@@ -3,7 +3,7 @@
/* global emitSidebarEvent */
import $ from 'jquery';
-import { escape as esc, template, uniqBy } from 'lodash';
+import { escape, template, uniqBy } from 'lodash';
import axios from './lib/utils/axios_utils';
import { s__, __, sprintf } from './locale';
import ModalStore from './boards/stores/modal_store';
@@ -205,7 +205,7 @@ function UsersSelect(currentUser, els, options = {}) {
username: data.assignee.username,
avatar: data.assignee.avatar_url,
};
- tooltipTitle = esc(user.name);
+ tooltipTitle = escape(user.name);
} else {
user = {
name: s__('UsersSelect|Unassigned'),
@@ -543,7 +543,7 @@ function UsersSelect(currentUser, els, options = {}) {
let img = '';
if (user.beforeDivider != null) {
- `<li><a href='#' class='${selected === true ? 'is-active' : ''}'>${esc(
+ `<li><a href='#' class='${selected === true ? 'is-active' : ''}'>${escape(
user.name,
)}</a></li>`;
} else {
@@ -672,10 +672,10 @@ UsersSelect.prototype.formatResult = function(user) {
</div>
<div class='user-info'>
<div class='user-name dropdown-menu-user-full-name'>
- ${esc(user.name)}
+ ${escape(user.name)}
</div>
<div class='user-username dropdown-menu-user-username text-secondary'>
- ${!user.invite ? `@${esc(user.username)}` : ''}
+ ${!user.invite ? `@${escape(user.username)}` : ''}
</div>
</div>
</div>
@@ -683,7 +683,7 @@ UsersSelect.prototype.formatResult = function(user) {
};
UsersSelect.prototype.formatSelection = function(user) {
- return esc(user.name);
+ return escape(user.name);
};
UsersSelect.prototype.user = function(user_id, callback) {
@@ -746,7 +746,7 @@ UsersSelect.prototype.renderRow = function(issuableType, user, selected, usernam
${this.renderRowAvatar(issuableType, user, img)}
<span class="d-flex flex-column overflow-hidden">
<strong class="dropdown-menu-user-full-name">
- ${esc(user.name)}
+ ${escape(user.name)}
</strong>
${username ? `<span class="dropdown-menu-user-username">${username}</span>` : ''}
</span>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
index c38272ab239..2433ba879aa 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
@@ -1,5 +1,5 @@
<script>
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { n__, s__, sprintf } from '~/locale';
import { mergeUrlParams, webIDEUrl } from '~/lib/utils/url_utility';
import Icon from '~/vue_shared/components/icon.vue';
@@ -35,7 +35,7 @@ export default {
'mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch',
),
{
- commitsBehindLinkStart: `<a href="${esc(this.mr.targetBranchPath)}">`,
+ commitsBehindLinkStart: `<a href="${escape(this.mr.targetBranchPath)}">`,
commitsBehind: n__('%d commit behind', '%d commits behind', this.mr.divergedCommitsCount),
commitsBehindLinkEnd: '</a>',
},
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
index dcf02a29f52..e4f4032776b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
@@ -1,6 +1,6 @@
<script>
import { GlDeprecatedButton } from '@gitlab/ui';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { __, n__, sprintf, s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
@@ -60,7 +60,7 @@ export default {
{
commitCount: `<strong class="commits-count-message">${this.commitsCountMessage}</strong>`,
mergeCommitCount: `<strong>${s__('mrWidgetCommitsAdded|1 merge commit')}</strong>`,
- targetBranch: `<span class="label-branch">${esc(this.targetBranch)}</span>`,
+ targetBranch: `<span class="label-branch">${escape(this.targetBranch)}</span>`,
},
false,
);
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
index 139cbe17e35..d421b744fa1 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
@@ -1,6 +1,6 @@
<script>
import $ from 'jquery';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { s__, sprintf } from '~/locale';
import { mouseenter, debouncedMouseleave, togglePopover } from '~/shared/popover';
import StatusIcon from '../mr_widget_status_icon.vue';
@@ -50,7 +50,7 @@ export default {
content: sprintf(
s__('mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}'),
{
- link_start: `<a href="${esc(
+ link_start: `<a href="${escape(
this.mr.conflictsDocsPath,
)}" target="_blank" rel="noopener noreferrer">`,
link_end: '</a>',
diff --git a/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue b/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
index 89a8595fc79..c1b18a7b2f7 100644
--- a/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
@@ -1,11 +1,11 @@
<script>
import { GlLink } from '@gitlab/ui';
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import { __, sprintf } from '~/locale';
import icon from '../../../vue_shared/components/icon.vue';
function buildDocsLinkStart(path) {
- return `<a href="${esc(path)}" target="_blank" rel="noopener noreferrer">`;
+ return `<a href="${escape(path)}" target="_blank" rel="noopener noreferrer">`;
}
export default {
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 26e878d56a0..8007ccb91d5 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -1,7 +1,7 @@
<script>
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
-import { unescape as unesc } from 'lodash';
+import { unescape } from 'lodash';
import { __, sprintf } from '~/locale';
import { stripHtml } from '~/lib/utils/text_utility';
import Flash from '../../../flash';
@@ -115,7 +115,7 @@ export default {
return text;
}
- return unesc(stripHtml(richText).replace(/\n/g, ''));
+ return unescape(stripHtml(richText).replace(/\n/g, ''));
}
return '';
diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb
index d03fa6eadb2..355aaf385c1 100644
--- a/app/helpers/export_helper.rb
+++ b/app/helpers/export_helper.rb
@@ -12,6 +12,16 @@ module ExportHelper
_('Issue Boards')
]
end
+
+ def group_export_descriptions
+ [
+ _('Milestones'),
+ _('Labels'),
+ _('Boards and Board Lists'),
+ _('Badges'),
+ _('Subgroups')
+ ]
+ end
end
ExportHelper.prepend_if_ee('EE::ExportHelper')
diff --git a/app/models/deploy_token.rb b/app/models/deploy_token.rb
index 69245710f01..395260b5201 100644
--- a/app/models/deploy_token.rb
+++ b/app/models/deploy_token.rb
@@ -7,7 +7,8 @@ class DeployToken < ApplicationRecord
include Gitlab::Utils::StrongMemoize
add_authentication_token_field :token, encrypted: :optional
- AVAILABLE_SCOPES = %i(read_repository read_registry write_registry).freeze
+ AVAILABLE_SCOPES = %i(read_repository read_registry write_registry
+ read_package_registry write_package_registry).freeze
GITLAB_DEPLOY_TOKEN_NAME = 'gitlab-deploy-token'
default_value_for(:expires_at) { Forever.date }
@@ -105,7 +106,7 @@ class DeployToken < ApplicationRecord
end
def ensure_at_least_one_scope
- errors.add(:base, _("Scopes can't be blank")) unless read_repository || read_registry || write_registry
+ errors.add(:base, _("Scopes can't be blank")) unless scopes.any?
end
def default_username
diff --git a/app/services/snippets/update_service.rb b/app/services/snippets/update_service.rb
index e56e01cf82b..055139bba13 100644
--- a/app/services/snippets/update_service.rb
+++ b/app/services/snippets/update_service.rb
@@ -98,7 +98,7 @@ module Snippets
end
def snippet_files(snippet)
- [{ previous_path: snippet.blobs.first&.path,
+ [{ previous_path: snippet.file_name_on_repo,
file_path: params[:file_name],
content: params[:content] }]
end
diff --git a/app/services/spam/spam_action_service.rb b/app/services/spam/spam_action_service.rb
index 9ab76b27f4a..3ae80975d4a 100644
--- a/app/services/spam/spam_action_service.rb
+++ b/app/services/spam/spam_action_service.rb
@@ -24,7 +24,7 @@ module Spam
def execute(api: false, recaptcha_verified:, spam_log_id:, user_id:)
if recaptcha_verified
- # If it's a request which is already verified through recaptcha,
+ # If it's a request which is already verified through reCAPTCHA,
# update the spam log accordingly.
SpamLog.verify_recaptcha!(user_id: user_id, id: spam_log_id)
else
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index fe5a00e3be9..2e58517fdc7 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -45,11 +45,11 @@
%section.settings.gs-advanced.no-animate#js-advanced-settings{ class: ('expanded' if expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' }
- = _('Path, transfer, remove')
+ = _('Advanced')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- = _('Perform advanced options such as changing path, transferring, or removing the group.')
+ = _('Perform advanced options such as changing path, transferring, exporting, or removing the group.')
.settings-content
= render 'groups/settings/advanced'
diff --git a/app/views/groups/settings/_advanced.html.haml b/app/views/groups/settings/_advanced.html.haml
index 2734ab538a0..0df82898644 100644
--- a/app/views/groups/settings/_advanced.html.haml
+++ b/app/views/groups/settings/_advanced.html.haml
@@ -1,3 +1,5 @@
+= render 'groups/settings/export', group: @group
+
.sub-section
%h4.warning-title= s_('GroupSettings|Change group path')
= form_for @group, html: { multipart: true, class: 'gl-show-field-errors' }, authenticity_token: true do |f|
diff --git a/app/views/groups/settings/_export.html.haml b/app/views/groups/settings/_export.html.haml
new file mode 100644
index 00000000000..895c2115240
--- /dev/null
+++ b/app/views/groups/settings/_export.html.haml
@@ -0,0 +1,28 @@
+- return unless Feature.enabled?(:group_import_export, @group, default_enabled: true)
+
+- group = local_assigns.fetch(:group)
+
+.sub-section
+ %h4= s_('GroupSettings|Export group')
+ %p= _('Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the "New Group" page.')
+
+ .bs-callout.bs-callout-info
+ %p.append-bottom-0
+ %p= _('The following items will be exported:')
+ %ul
+ - group_export_descriptions.each do |description|
+ %li= description
+ %p= _('The following items will NOT be exported:')
+ %ul
+ %li= _('Projects')
+ %li= _('Runner tokens')
+ %li= _('SAML discovery tokens')
+ %p= _('Once the exported file is ready you can download it from this page.')
+ - if group.export_file_exists?
+ = link_to _('Regenerate export'), export_group_path(group),
+ method: :post, class: 'btn btn-default', data: { qa_selector: 'regenerate_export_group_link' }
+ = link_to _('Download export'), download_export_group_path(group),
+ rel: 'nofollow', method: :get, class: 'btn btn-default', data: { qa_selector: 'download_export_link' }
+ - else
+ = link_to _('Export group'), export_group_path(group),
+ method: :post, class: 'btn btn-default', data: { qa_selector: 'export_group_link' }
diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml
index 15f1067f0d9..95d66786984 100644
--- a/app/views/layouts/nav/sidebar/_profile.html.haml
+++ b/app/views/layouts/nav/sidebar/_profile.html.haml
@@ -152,10 +152,6 @@
= link_to audit_log_profile_path do
%strong.fly-out-top-item-name
= _('Authentication Log')
-
- - if Feature.enabled?(:user_usage_quota)
= render_if_exists 'layouts/nav/sidebar/profile_usage_quotas_link'
- - else
- = render_if_exists 'layouts/nav/sidebar/profile_pipeline_quota_link'
= render 'shared/sidebar_toggle_button'
diff --git a/changelogs/unreleased/213566-package-deploy-tokens.yml b/changelogs/unreleased/213566-package-deploy-tokens.yml
new file mode 100644
index 00000000000..1301935eba5
--- /dev/null
+++ b/changelogs/unreleased/213566-package-deploy-tokens.yml
@@ -0,0 +1,5 @@
+---
+title: Add read/write_package_registry to deploy_tokens
+merge_request: 29383
+author:
+type: added
diff --git a/changelogs/unreleased/jh-group_export_ui_frontend.yml b/changelogs/unreleased/jh-group_export_ui_frontend.yml
new file mode 100644
index 00000000000..22d4819085f
--- /dev/null
+++ b/changelogs/unreleased/jh-group_export_ui_frontend.yml
@@ -0,0 +1,5 @@
+---
+title: Add UI for exporting group data to the group settings
+merge_request: 28573
+author:
+type: added
diff --git a/db/migrate/20200411125656_add_package_scopes_to_deploy_tokens.rb b/db/migrate/20200411125656_add_package_scopes_to_deploy_tokens.rb
new file mode 100644
index 00000000000..d20b36399f2
--- /dev/null
+++ b/db/migrate/20200411125656_add_package_scopes_to_deploy_tokens.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddPackageScopesToDeployTokens < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default(:deploy_tokens, :read_package_registry, :boolean, default: false, allow_null: false)
+ add_column_with_default(:deploy_tokens, :write_package_registry, :boolean, default: false, allow_null: false)
+ end
+
+ def down
+ remove_column(:deploy_tokens, :read_package_registry)
+ remove_column(:deploy_tokens, :write_package_registry)
+ end
+end
diff --git a/db/structure.sql b/db/structure.sql
index 89f0ab9c15d..9035626fb89 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -2005,7 +2005,9 @@ CREATE TABLE public.deploy_tokens (
username character varying,
token_encrypted character varying(255),
deploy_token_type smallint DEFAULT 2 NOT NULL,
- write_registry boolean DEFAULT false NOT NULL
+ write_registry boolean DEFAULT false NOT NULL,
+ read_package_registry boolean DEFAULT false NOT NULL,
+ write_package_registry boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE public.deploy_tokens_id_seq
@@ -13246,6 +13248,7 @@ COPY "schema_migrations" (version) FROM STDIN;
20200409211607
20200410104828
20200410232012
+20200411125656
20200413072059
20200413230056
20200414144547
diff --git a/doc/administration/auditor_users.md b/doc/administration/auditor_users.md
index 2bb229d4f68..ace210183b2 100644
--- a/doc/administration/auditor_users.md
+++ b/doc/administration/auditor_users.md
@@ -1,6 +1,6 @@
# Auditor users **(PREMIUM ONLY)**
->[Introduced][ee-998] in [GitLab Premium][eep] 8.17.
+>[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/998) in [GitLab Premium](https://about.gitlab.com/pricing/) 8.17.
Auditor users are given read-only access to all projects, groups, and other
resources on the GitLab instance.
@@ -12,7 +12,7 @@ snippets, etc.), and read-only access to **all** other resources, except the
Admin Area. To put another way, they are just regular users (who can be added
to projects, create personal snippets, create milestones on their groups, etc.)
who also happen to have read-only access to all projects on the system that
-they haven't been explicitly [given access][permissions] to.
+they haven't been explicitly [given access](../user/permissions.md) to.
The Auditor role is _not_ a read-only version of the Admin role. Auditor users
will not be able to access the project/group settings pages, or the Admin Area.
@@ -25,7 +25,7 @@ To sum up, assuming you have logged-in as an Auditor user:
- For a project the Auditor owns, the Auditor should have full access to
everything.
- For a project the Auditor has been added to as a member, the Auditor should
- have the same access as the [permissions] they were given to. For example, if
+ have the same access as the [permissions](../user/permissions.md) they were given to. For example, if
they were added as a Developer, they could then push commits or comment on
issues.
- The Auditor cannot view the Admin Area, or perform any admin actions.
@@ -82,7 +82,3 @@ instance, with the following permissions/restrictions:
- Cannot create/modify files from the Web UI
- Cannot merge a merge request
- Cannot create project snippets
-
-[ee-998]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/998
-[eep]: https://about.gitlab.com/pricing/
-[permissions]: ../user/permissions.md
diff --git a/doc/administration/auth/crowd.md b/doc/administration/auth/crowd.md
index 6c2e4edac31..71938d4fd2b 100644
--- a/doc/administration/auth/crowd.md
+++ b/doc/administration/auth/crowd.md
@@ -66,14 +66,11 @@ Authenticate to GitLab using the Atlassian Crowd OmniAuth provider.
1. Change `YOUR_APP_NAME` to the application name from Crowd applications page.
1. Change `YOUR_APP_PASSWORD` to the application password you've set.
1. Save the configuration file.
-1. [Reconfigure][] or [restart][] for the changes to take effect if you
+1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart](../restart_gitlab.md#installations-from-source) for the changes to take effect if you
installed GitLab via Omnibus or from source respectively.
On the sign in page there should now be a Crowd tab in the sign in form.
-[reconfigure]: ../restart_gitlab.md#omnibus-gitlab-reconfigure
-[restart]: ../restart_gitlab.md#installations-from-source
-
## Troubleshooting
If you see an error message like the one below when you sign in after Crowd authentication is configured, you may want to consult the Crowd administrator for the Crowd log file to know the exact cause:
diff --git a/doc/administration/auth/google_secure_ldap.md b/doc/administration/auth/google_secure_ldap.md
index cb7901ea5b4..b643dd2f7b9 100644
--- a/doc/administration/auth/google_secure_ldap.md
+++ b/doc/administration/auth/google_secure_ldap.md
@@ -133,7 +133,7 @@ values obtained during the LDAP client configuration earlier:
EOS
```
-1. Save the file and [reconfigure] GitLab for the changes to take effect.
+1. Save the file and [reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab for the changes to take effect.
---
@@ -204,10 +204,7 @@ values obtained during the LDAP client configuration earlier:
-----END PRIVATE KEY-----
```
-1. Save the file and [restart] GitLab for the changes to take effect.
-
-[reconfigure]: ../restart_gitlab.md#omnibus-gitlab-reconfigure
-[restart]: ../restart_gitlab.md#installations-from-source
+1. Save the file and [restart](../restart_gitlab.md#installations-from-source) GitLab for the changes to take effect.
<!-- ## Troubleshooting
diff --git a/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md b/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md
index 49bf786061e..01da4528eab 100644
--- a/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md
+++ b/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md
@@ -45,10 +45,7 @@ Configuring organizational units (**OU**s) is an important part of setting up Ac
| GitLab **OU** Design | GitLab AD Structure |
| :----------------------------: | :------------------------------: |
-| ![GitLab OU Design][gitlab_ou] | ![GitLab AD Structure][ldap_ou] |
-
-[gitlab_ou]: img/gitlab_ou.png
-[ldap_ou]: img/ldap_ou.gif
+| ![GitLab OU Design](img/gitlab_ou.png) | ![GitLab AD Structure](img/ldap_ou.gif) |
Using PowerShell you can output the **OU** structure as a table (_all names are examples only_):
diff --git a/doc/administration/auth/jwt.md b/doc/administration/auth/jwt.md
index 15eee50c771..5a773485842 100644
--- a/doc/administration/auth/jwt.md
+++ b/doc/administration/auth/jwt.md
@@ -64,7 +64,7 @@ JWT will provide you with a secret key for you to use.
1. Change `YOUR_APP_SECRET` to the client secret and set `auth_url` to your redirect URL.
1. Save the configuration file.
-1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you
+1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect if you
installed GitLab via Omnibus or from source respectively.
On the sign in page there should now be a JWT icon below the regular sign in form.
@@ -72,9 +72,6 @@ Click the icon to begin the authentication process. JWT will ask the user to
sign in and authorize the GitLab application. If everything goes well, the user
will be redirected to GitLab and will be signed in.
-[reconfigure]: ../restart_gitlab.md#omnibus-gitlab-reconfigure
-[restart GitLab]: ../restart_gitlab.md#installations-from-source
-
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/administration/file_hooks.md b/doc/administration/file_hooks.md
index 21ade36a2a5..043264519a8 100644
--- a/doc/administration/file_hooks.md
+++ b/doc/administration/file_hooks.md
@@ -14,12 +14,12 @@ ensure functionality is preserved across versions and covered by tests.
NOTE: **Note:**
File hooks must be configured on the filesystem of the GitLab server. Only GitLab
server administrators will be able to complete these tasks. Explore
-[system hooks] or [webhooks] as an option if you do not have filesystem access.
+[system hooks](../system_hooks/system_hooks.md) or [webhooks](../user/project/integrations/webhooks.md) as an option if you do not have filesystem access.
A file hook will run on each event so it's up to you to filter events or projects
within a file hook code. You can have as many file hooks as you want. Each file hook will
be triggered by GitLab asynchronously in case of an event. For a list of events
-see the [system hooks] documentation.
+see the [system hooks](../system_hooks/system_hooks.md) documentation.
## Setup
@@ -35,7 +35,7 @@ Follow the steps below to set up a custom hook:
`/home/git/gitlab/file_hooks/`. For Omnibus installs the path is
usually `/opt/gitlab/embedded/service/gitlab-rails/file_hooks`.
- For [highly available] configurations, your hook file should exist on each
+ For [highly available](availability/index.md) configurations, your hook file should exist on each
application server.
1. Inside the `file_hooks` directory, create a file with a name of your choice,
@@ -46,7 +46,7 @@ Follow the steps below to set up a custom hook:
language type. For example, if the script is in Ruby the shebang will
probably be `#!/usr/bin/env ruby`.
1. The data to the file hook will be provided as JSON on STDIN. It will be exactly
- same as for [system hooks]
+ same as for [system hooks](../system_hooks/system_hooks.md).
That's it! Assuming the file hook code is properly implemented, the hook will fire
as appropriate. The file hooks file list is updated for each event, there is no
@@ -110,7 +110,3 @@ Validating file hooks from /file_hooks directory
* /home/git/gitlab/file_hooks/save_to_file.clj succeed (zero exit code)
* /home/git/gitlab/file_hooks/save_to_file.rb failure (non-zero exit code)
```
-
-[system hooks]: ../system_hooks/system_hooks.md
-[webhooks]: ../user/project/integrations/webhooks.md
-[highly available]: ./availability/index.md
diff --git a/doc/administration/geo/replication/using_a_geo_server.md b/doc/administration/geo/replication/using_a_geo_server.md
index 0f55272f667..2fec2b2b59c 100644
--- a/doc/administration/geo/replication/using_a_geo_server.md
+++ b/doc/administration/geo/replication/using_a_geo_server.md
@@ -1,4 +1,4 @@
-[//]: # (Please update EE::GitLab::GeoGitAccess::GEO_SERVER_DOCS_URL if this file is moved)
+<!-- Please update EE::GitLab::GeoGitAccess::GEO_SERVER_DOCS_URL if this file is moved) -->
# Using a Geo Server **(PREMIUM ONLY)**
diff --git a/doc/administration/git_annex.md b/doc/administration/git_annex.md
index 4ac70e7fac2..cec78d8728d 100644
--- a/doc/administration/git_annex.md
+++ b/doc/administration/git_annex.md
@@ -5,8 +5,8 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/git_annex.html'
# Git annex
> **Warning:** GitLab has [completely
-removed][deprecate-annex-issue] in GitLab 9.0 (2017/03/22).
-Read through the [migration guide from git-annex to Git LFS][guide].
+removed](https://gitlab.com/gitlab-org/gitlab/issues/1648) in GitLab 9.0 (2017/03/22).
+Read through the [migration guide from git-annex to Git LFS](../topics/git/lfs/migrate_from_git_annex_to_git_lfs.md).
The biggest limitation of Git, compared to some older centralized version
control systems, has been the maximum size of the repositories.
@@ -24,7 +24,7 @@ only check in the final result. This results in using outdated files, not
having a complete history and increases the risk of losing work.
This problem is solved in GitLab Enterprise Edition by integrating the
-[git-annex] application.
+[git-annex](https://git-annex.branchable.com/) application.
`git-annex` allows managing large binaries with Git without checking the
contents into Git.
@@ -64,7 +64,7 @@ The Omnibus package will internally set the correct options in all locations.
gitlab_shell['git_annex_enabled'] = true
```
-1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
### Configuration for installations from source
@@ -86,7 +86,7 @@ one is located in `config.yml` of GitLab Shell.
git_annex_enabled: true
```
-1. Save the files and [restart GitLab][] for the changes to take effect.
+1. Save the files and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
## Using GitLab git-annex
@@ -186,7 +186,7 @@ access files of projects you have access to (developer, maintainer, or owner rol
## How it works
-Internally GitLab uses [GitLab Shell] to handle SSH access and this was a great
+Internally GitLab uses [GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell) to handle SSH access and this was a great
integration point for `git-annex`.
There is a setting in GitLab Shell so you can disable GitLab Annex support
if you want to.
@@ -196,7 +196,7 @@ if you want to.
Differences in version of `git-annex` on the GitLab server and on local machines
can cause `git-annex` to raise unpredicted warnings and errors.
-Consult the [Annex upgrade page][annex-upgrade] for more information about
+Consult the [Annex upgrade page](https://git-annex.branchable.com/upgrades/) for more information about
the differences between versions. You can find out which version is installed
on your server by navigating to <https://pkgs.org/download/git-annex> and
searching for your distribution.
@@ -208,7 +208,7 @@ on how to go around the warnings.
This warning can appear on the initial `git annex sync --content` and is caused
by differences in `git-annex-shell`. You can read more about it
-[in this git-annex issue][issue].
+[in this git-annex issue](https://git-annex.branchable.com/forum/Error_from_git-annex-shell_on_creation_of_gcrypt_special_remote/).
One important thing to note is that despite the warning, the `sync` succeeds
and the files are pushed to the GitLab repository.
@@ -231,12 +231,3 @@ pull origin
ok
push origin
```
-
-[annex-upgrade]: https://git-annex.branchable.com/upgrades/
-[deprecate-annex-issue]: https://gitlab.com/gitlab-org/gitlab/issues/1648
-[git-annex]: https://git-annex.branchable.com/ "git-annex website"
-[gitlab shell]: https://gitlab.com/gitlab-org/gitlab-shell "GitLab Shell repository"
-[guide]: ../topics/git/lfs/migrate_from_git_annex_to_git_lfs.md
-[issue]: https://git-annex.branchable.com/forum/Error_from_git-annex-shell_on_creation_of_gcrypt_special_remote/ "git-annex issue"
-[reconfigure GitLab]: restart_gitlab.md#omnibus-gitlab-reconfigure
-[restart GitLab]: restart_gitlab.md#installations-from-source
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index bdac66ffeff..4d3bc498e3e 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -45,6 +45,7 @@ package (highly recommended), follow the steps below:
1. [Configuring the Praefect database](#postgresql)
1. [Configuring the Praefect proxy/router](#praefect)
1. [Configuring each Gitaly node](#gitaly) (once for each Gitaly node)
+1. [Configure the load balancer](#load-balancer)
1. [Updating the GitLab server configuration](#gitlab)
1. [Configure Grafana](#grafana)
@@ -66,7 +67,7 @@ GitLab](https://about.gitlab.com/install/).
You will need the IP/host address for each node.
-1. `LOADBALANCER_SERVER_ADDRESS`: the IP/hots address of the load balancer
+1. `LOAD_BALANCER_SERVER_ADDRESS`: the IP/hots address of the load balancer
1. `POSTGRESQL_SERVER_ADDRESS`: the IP/host address of the PostgreSQL server
1. `PRAEFECT_HOST`: the IP/host address of the Praefect server
1. `GITALY_HOST`: the IP/host address of each Gitaly server
@@ -551,6 +552,24 @@ config.
gitlab-ctl reconfigure
```
+### Load Balancer
+
+In a highly available Gitaly configuration, a load balancer is needed to route
+internal traffic from the GitLab application to the Praefect nodes. The
+specifics on which load balancer to use or the exact configuration is beyond the
+scope of the GitLab documentation.
+
+We hope that if you’re managing HA systems like GitLab, you have a load balancer
+of choice already. Some examples include [HAProxy](https://www.haproxy.org/)
+(open-source), [Google Internal Load Balancer](https://cloud.google.com/load-balancing/docs/internal/),
+[AWS Elastic Load Balancer](https://aws.amazon.com/elasticloadbalancing/), F5
+Big-IP LTM, and Citrix Net Scaler. This documentation will outline what ports
+and protocols you need configure.
+
+| LB Port | Backend Port | Protocol |
+|---------|--------------|----------|
+| 2305 | 2305 | TCP |
+
### GitLab
To complete this section you will need:
@@ -579,7 +598,8 @@ Particular attention should be shown to:
You will need to replace:
- - `PRAEFECT_HOST` with the IP address or hostname of the Praefect node
+ - `LOAD_BALANCER_SERVER_ADDRESS` with the IP address or hostname of the load
+ balancer.
- `GITLAB_HOST` with the IP address or hostname of the GitLab server
- `PRAEFECT_EXTERNAL_TOKEN` with the real secret
@@ -589,7 +609,7 @@ Particular attention should be shown to:
"gitaly_address" => "tcp://GITLAB_HOST:8075"
},
"storage-1" => {
- "gitaly_address" => "tcp://PRAEFECT_HOST:2305",
+ "gitaly_address" => "tcp://LOAD_BALANCER_SERVER_ADDRESS:2305",
"gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
}
})
diff --git a/doc/administration/lfs/index.md b/doc/administration/lfs/index.md
index 71c1ae22305..b89984380d1 100644
--- a/doc/administration/lfs/index.md
+++ b/doc/administration/lfs/index.md
@@ -50,7 +50,7 @@ In `config/gitlab.yml`:
## Storing LFS objects in remote object storage
-> [Introduced][ee-2760] in [GitLab Premium][eep] 10.0. Brought to GitLab Core in 10.7.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2760) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.0. Brought to GitLab Core in 10.7.
It is possible to store LFS objects in remote object storage which allows you
to offload local hard disk R/W operations, and free up disk space significantly.
@@ -177,7 +177,7 @@ On Omnibus installations, the settings are prefixed by `lfs_object_store_`:
}
```
-1. Save the file and [reconfigure GitLab]s for the changes to take effect.
+1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Migrate any existing local LFS objects to the object storage:
```shell
@@ -213,7 +213,7 @@ For source installations the settings are nested under `lfs:` and then
path_style: true
```
-1. Save the file and [restart GitLab][] for the changes to take effect.
+1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
1. Migrate any existing local LFS objects to the object storage:
```shell
@@ -268,8 +268,3 @@ See more information in [!19581](https://gitlab.com/gitlab-org/gitlab-foss/-/mer
- Only compatible with the Git LFS client versions 1.1.0 and up, or 1.0.2.
- The storage statistics currently count each LFS object multiple times for
every project linking to it.
-
-[reconfigure gitlab]: ../restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
-[restart gitlab]: ../restart_gitlab.md#installations-from-source "How to restart GitLab"
-[eep]: https://about.gitlab.com/pricing/ "GitLab Premium"
-[ee-2760]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2760
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index b43a6546082..66f6942da01 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -554,7 +554,7 @@ This file lives in `/var/log/gitlab/gitlab-rails/repocheck.log` for
Omnibus GitLab packages or in `/home/git/gitlab/log/repocheck.log` for
installations from source.
-It logs information whenever a [repository check is run][repocheck] on a project.
+It logs information whenever a [repository check is run](repository_checks.md) on a project.
## `importer.log`
@@ -574,9 +574,9 @@ installations from source.
This log records:
-- Information whenever [Rack Attack] registers an abusive request.
-- Requests over the [Rate Limit] on raw endpoints.
-- [Protected paths] abusive requests.
+- Information whenever [Rack Attack](../security/rack_attack.md) registers an abusive request.
+- Requests over the [Rate Limit](../user/admin_area/settings/rate_limits_on_raw_endpoints.md) on raw endpoints.
+- [Protected paths](../user/admin_area/settings/protected_paths.md) abusive requests.
NOTE: **Note:**
From [%12.1](https://gitlab.com/gitlab-org/gitlab-foss/issues/62756), user ID and username are also
@@ -754,8 +754,3 @@ Below is the default GitLab NGINX access log format:
```plaintext
$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"
```
-
-[repocheck]: repository_checks.md
-[Rack Attack]: ../security/rack_attack.md
-[Rate Limit]: ../user/admin_area/settings/rate_limits_on_raw_endpoints.md
-[Protected paths]: ../user/admin_area/settings/protected_paths.md
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 84133205bd3..c5467edd32f 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -80,7 +80,7 @@ added `gitlab.io` [in 2016](https://gitlab.com/gitlab-com/infrastructure/issues/
### DNS configuration
GitLab Pages expect to run on their own virtual host. In your DNS server/provider
-you need to add a [wildcard DNS A record][wiki-wildcard-dns] pointing to the
+you need to add a [wildcard DNS A record](https://en.wikipedia.org/wiki/Wildcard_DNS_record) pointing to the
host that GitLab runs. For example, an entry would look like this:
```plaintext
@@ -95,8 +95,6 @@ IPv6 address. If you don't have IPv6, you can omit the AAAA record.
NOTE: **Note:**
You should not use the GitLab domain to serve user pages. For more information see the [security section](#security).
-[wiki-wildcard-dns]: https://en.wikipedia.org/wiki/Wildcard_DNS_record
-
## Configuration
Depending on your needs, you can set up GitLab Pages in 4 different ways.
diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md
index 94d2c5420aa..1bb3b86b419 100644
--- a/doc/administration/pages/source.md
+++ b/doc/administration/pages/source.md
@@ -61,7 +61,7 @@ Before proceeding with the Pages configuration, make sure that:
### DNS configuration
GitLab Pages expect to run on their own virtual host. In your DNS server/provider
-you need to add a [wildcard DNS A record][wiki-wildcard-dns] pointing to the
+you need to add a [wildcard DNS A record](https://en.wikipedia.org/wiki/Wildcard_DNS_record) pointing to the
host that GitLab runs. For example, an entry would look like this:
```plaintext
@@ -75,8 +75,6 @@ and `192.0.2.1` is the IP address of your GitLab instance.
You should not use the GitLab domain to serve user pages. For more information
see the [security section](#security).
-[wiki-wildcard-dns]: https://en.wikipedia.org/wiki/Wildcard_DNS_record
-
## Configuration
Depending on your needs, you can set up GitLab Pages in 4 different ways.
diff --git a/doc/administration/terraform_state.md b/doc/administration/terraform_state.md
index 0956edaf252..24e4ad3b6ba 100644
--- a/doc/administration/terraform_state.md
+++ b/doc/administration/terraform_state.md
@@ -30,7 +30,7 @@ below.
gitlab_rails['terraform_state_storage_path'] = "/mnt/storage/terraform_state"
```
-1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
**In installations from source:**
@@ -43,7 +43,7 @@ below.
storage_path: /mnt/storage/terraform_state
```
-1. Save the file and [restart GitLab][] for the changes to take effect.
+1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
## Using object storage **(CORE ONLY)**
@@ -111,7 +111,7 @@ The connection settings match those provided by [Fog](https://github.com/fog), a
}
```
-1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
**In installations from source:**
@@ -131,7 +131,4 @@ The connection settings match those provided by [Fog](https://github.com/fog), a
region: eu-central-1
```
-1. Save the file and [restart GitLab][] for the changes to take effect.
-
-[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
-[restart gitlab]: restart_gitlab.md#installations-from-source "How to restart GitLab"
+1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
diff --git a/doc/api/group_import_export.md b/doc/api/group_import_export.md
index 50e8bd9dcf2..ffaa15603f7 100644
--- a/doc/api/group_import_export.md
+++ b/doc/api/group_import_export.md
@@ -25,7 +25,7 @@ POST /groups/:id/export
| Attribute | Type | Required | Description |
| --------- | -------------- | -------- | ---------------------------------------- |
-| `id` | integer/string | yes | ID of the groupd owned by the authenticated user |
+| `id` | integer/string | yes | ID of the group owned by the authenticated user |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/export
diff --git a/doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_MR_v12_09.png b/doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_MR_v12_09.png
new file mode 100644
index 00000000000..3e4c72b9279
--- /dev/null
+++ b/doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_MR_v12_09.png
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_branch_v12_09.png b/doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_branch_v12_09.png
new file mode 100644
index 00000000000..dd70c3f8c20
--- /dev/null
+++ b/doc/ci/merge_request_pipelines/img/merge_request_pipelines_doubled_branch_v12_09.png
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md
index b57340347d2..6886e1bc3af 100644
--- a/doc/ci/merge_request_pipelines/index.md
+++ b/doc/ci/merge_request_pipelines/index.md
@@ -245,14 +245,68 @@ to integrate your job with [GitLab Merge Request API](../../api/merge_requests.m
You can find the list of available variables in [the reference sheet](../variables/predefined_variables.md).
The variable names begin with the `CI_MERGE_REQUEST_` prefix.
-<!-- ## Troubleshooting
+## Troubleshooting
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support, and to avoid doc comments with
-questions that you know someone might ask.
+### Two pipelines created when pushing to a merge request
-Each scenario can be a third-level heading, e.g. `### Getting error message X`.
-If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. -->
+If two pipelines are created when you push a new change to a merge request,
+check your CI configuration file.
+
+For example, with this `.gitlab-ci.yml` configuration:
+
+```yaml
+test:
+ script: ./test
+ rules:
+ - if: $CI_MERGE_REQUEST_ID # Include this job in pipelines for merge request
+ - if: $CI_COMMIT_BRANCH # Include this job in all branch pipelines
+ # Or, if you are using the `only:` keyword:
+ # only:
+ # - merge_requests
+ # - branches
+```
+
+Two pipelines are created when you push a commit to a branch that also has a pending
+merge request:
+
+- A merge request pipeline that runs for the changes in the merge request. In
+ **CI/CD > Pipelines**, the merge request icon (**{merge-request}**)
+ and the merge request ID are displayed. If you hover over the ID, the merge request name is displayed.
+
+ ![MR pipeline icon example](img/merge_request_pipelines_doubled_MR_v12_09.png)
+
+- A "branch" pipeline that runs for the commit pushed to the branch. In **CI/CD > Pipelines**,
+ the branch icon (**{branch}**) and branch name are displayed. This pipeline is
+ created even if no merge request exists.
+
+ ![branch pipeline icon example](img/merge_request_pipelines_doubled_branch_v12_09.png)
+
+With the example configuration above, there is overlap between these two events.
+When you push a commit to a branch that also has an open merge request pending,
+both types of pipelines are created.
+
+To fix this overlap, you must explicitly define which job should run for which
+purpose, for example:
+
+```yaml
+test:
+ script: ./test
+ rules:
+ - if: $CI_MERGE_REQUEST_ID # Include this job in pipelines for merge request
+ - if: $CI_COMMIT_BRANCH == 'master' # Include this job in master branch pipelines
+```
+
+Similar `rules:` should be added to all jobs to avoid any overlapping pipelines. Alternatively,
+you can use the [`workflow:`](../yaml/README.md#exclude-jobs-with-rules-from-certain-pipelines)
+parameter to add the same rules to all jobs globally.
+
+### Two pipelines created when pushing an invalid CI configuration file
+
+Similar to above, pushing to a branch with an invalid CI configuration file can trigger
+the creation of two types of failed pipelines. One pipeline is a failed merge request
+pipeline, and the other is a failed branch pipeline, but both are caused by the same
+invalid configuration.
+
+In rare cases, duplicate pipelines are created.
+
+See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/201845) for details.
diff --git a/doc/development/application_limits.md b/doc/development/application_limits.md
index b6e777dee15..ace86e0ded2 100644
--- a/doc/development/application_limits.md
+++ b/doc/development/application_limits.md
@@ -11,7 +11,7 @@ coordinate with others to [document](../administration/instance_limits.md)
and communicate those limits.
There is a guide about [introducing application
-limits](https://about.gitlab.com/handbook/product/#introducing-application-limits).
+limits](https://about.gitlab.com/handbook/product/product-management/process/index.html#introducing-application-limits).
## Development
diff --git a/doc/development/creating_enums.md b/doc/development/creating_enums.md
index 79ed465b121..e2ebad538d9 100644
--- a/doc/development/creating_enums.md
+++ b/doc/development/creating_enums.md
@@ -13,3 +13,92 @@ def change
add_column :ci_job_artifacts, :file_format, :integer, limit: 2
end
```
+
+## All of the key/value pairs should be defined in FOSS
+
+**Summary:** All enums needs to be defined in FOSS, if a model is also part of the FOSS.
+
+```ruby
+class Model < ApplicationRecord
+ enum platform: {
+ aws: 0,
+ gcp: 1 # EE-only
+ }
+end
+```
+
+When you add a new key/value pair to a `enum` and if it's EE-specific, you might be
+tempted to organize the `enum` as the following:
+
+```ruby
+# Define `failure_reason` enum in `Pipeline` model:
+class Pipeline < ApplicationRecord
+ enum failure_reason: ::PipelineEnums.failure_reasons
+end
+```
+
+```ruby
+# Define key/value pairs that used in FOSS and EE:
+module PipelineEnums
+ def self.failure_reasons
+ { unknown_failure: 0, config_error: 1 }
+ end
+end
+
+PipelineEnums.prepend_if_ee('EE::PipelineEnums')
+```
+
+```ruby
+# Define key/value pairs that used in EE only:
+module EE
+ module PipelineEnums
+ override :failure_reasons
+ def failure_reasons
+ super.merge(activity_limit_exceeded: 2)
+ end
+ end
+end
+```
+
+This works as-is, however, it has a couple of downside that:
+
+- Someone could define a key/value pair in EE that is **conflicted** with a value defined in FOSS.
+ e.g. Define `activity_limit_exceeded: 1` in `EE::PipelineEnums`.
+- When it happens, the feature works totally different.
+ e.g. We cannot figure out `failure_reason` is either `config_error` or `activity_limit_exceeded`.
+- When it happens, we have to ship a database migration to fix the data integrity,
+ which might be impossible if you cannot recover the original value.
+
+Also, you might observe a workaround for this concern by setting an offset in EE's values.
+For example, this example sets `1000` as the offset:
+
+```ruby
+module EE
+ module PipelineEnums
+ override :failure_reasons
+ def failure_reasons
+ super.merge(activity_limit_exceeded: 1_000, size_limit_exceeded: 1_001)
+ end
+ end
+end
+```
+
+This looks working as a workaround, however, this approach has some donwside that:
+
+- Features could move from EE to FOSS or vice versa. Therefore, the offset might be mixed between FOSS and EE in the future.
+ e.g. When you move `activity_limit_exceeded` to FOSS, you'll see `{ unknown_failure: 0, config_error: 1, activity_limit_exceeded: 1_000 }`.
+- The integer column for the `enum` is likely created [as `SMALLINT`](#creating-enums).
+ Therefore, you need to be careful of that the offset doesn't exceed the maximum value of 2 bytes integer.
+
+As a conclusion, you should define all of the key/value pairs in FOSS.
+For example, you can simply write the following code in the above case:
+
+```ruby
+class Pipeline < ApplicationRecord
+ enum failure_reason: {
+ unknown_failure: 0,
+ config_error: 1,
+ activity_limit_exceeded: 2
+ }
+end
+```
diff --git a/doc/user/admin_area/license.md b/doc/user/admin_area/license.md
index fd74b2f311f..59b71b05b16 100644
--- a/doc/user/admin_area/license.md
+++ b/doc/user/admin_area/license.md
@@ -10,8 +10,8 @@ by **signing into your GitLab instance as an admin** or add it at
installation time.
The license has the form of a base64 encoded ASCII text with a `.gitlab-license`
-extension and can be obtained when you [purchase one][pricing] or when you sign
-up for a [free trial].
+extension and can be obtained when you [purchase one](https://about.gitlab.com/pricing/) or when you sign
+up for a [free trial](https://about.gitlab.com/free-trial/).
NOTE: **Note:**
As of GitLab Enterprise Edition 9.4.0, a newly-installed instance without an
@@ -104,9 +104,6 @@ expired license(s).
It's possible to upload and view more than one license,
but only the latest license will be used as the active license.
-[free trial]: https://about.gitlab.com/free-trial/
-[pricing]: https://about.gitlab.com/pricing/
-
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md
index f69584fcb94..d3c8e6e7ad4 100644
--- a/doc/user/admin_area/monitoring/health_check.md
+++ b/doc/user/admin_area/monitoring/health_check.md
@@ -4,8 +4,8 @@ type: concepts, howto
# Health Check **(CORE ONLY)**
-> - Liveness and readiness probes were [introduced][ce-10416] in GitLab 9.1.
-> - The `health_check` endpoint was [introduced][ce-3888] in GitLab 8.8 and was
+> - Liveness and readiness probes were [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10416) in GitLab 9.1.
+> - The `health_check` endpoint was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3888) in GitLab 8.8 and was
> deprecated in GitLab 9.1.
> - [Access token](#access-token-deprecated) has been deprecated in GitLab 9.4
> in favor of [IP whitelist](#ip-whitelist).
@@ -163,9 +163,3 @@ questions that you know someone might ask.
Each scenario can be a third-level heading, e.g. `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->
-
-[ce-10416]: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10416
-[ce-3888]: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3888
-[pingdom]: https://www.pingdom.com
-[nagios-health]: https://nagios-plugins.org/doc/man/check_http.html
-[newrelic-health]: https://docs.newrelic.com/docs/alerts/alert-policies/downtime-alerts/availability-monitoring
diff --git a/doc/user/admin_area/settings/email.md b/doc/user/admin_area/settings/email.md
index 4fab560e081..a99897657ae 100644
--- a/doc/user/admin_area/settings/email.md
+++ b/doc/user/admin_area/settings/email.md
@@ -12,7 +12,7 @@ The logo in the header of some emails can be customized, see the [logo customiza
## Custom additional text **(PREMIUM ONLY)**
-> [Introduced][ee-5031] in [GitLab Premium][eep] 10.7.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5031) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.7.
The additional text will appear at the bottom of any email and can be used for
legal/auditing/compliance reasons.
@@ -22,9 +22,6 @@ legal/auditing/compliance reasons.
1. Enter your text in the **Additional text** field.
1. Click **Save**.
-[ee-5031]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5031
-[eep]: https://about.gitlab.com/pricing/
-
## Custom hostname for private commit emails
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22560) in GitLab 11.5.
diff --git a/doc/user/admin_area/settings/external_authorization.md b/doc/user/admin_area/settings/external_authorization.md
index abf3d79b9ed..3a03e46fa1f 100644
--- a/doc/user/admin_area/settings/external_authorization.md
+++ b/doc/user/admin_area/settings/external_authorization.md
@@ -33,7 +33,7 @@ authorization service.
Whenever access is granted or denied this is logged in a logfile called
`external-policy-access-control.log`.
-Read more about logs GitLab keeps in the [omnibus documentation][omnibus-log-docs].
+Read more about logs GitLab keeps in the [omnibus documentation](https://docs.gitlab.com/omnibus/settings/logs.html).
## Configuration
@@ -62,7 +62,7 @@ The available required properties are:
When using TLS Authentication with a self signed certificate, the CA certificate
needs to be trusted by the openssl installation. When using GitLab installed using
Omnibus, learn to install a custom CA in the
-[omnibus documentation][omnibus-ssl-docs]. Alternatively learn where to install
+[omnibus documentation](https://docs.gitlab.com/omnibus/settings/ssl.html). Alternatively learn where to install
custom certificates using `openssl version -d`.
## How it works
@@ -127,6 +127,3 @@ questions that you know someone might ask.
Each scenario can be a third-level heading, e.g. `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->
-
-[omnibus-ssl-docs]: https://docs.gitlab.com/omnibus/settings/ssl.html
-[omnibus-log-docs]: https://docs.gitlab.com/omnibus/settings/logs.html
diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md
index a7a6b0ecefd..8ef5ac8dc8f 100644
--- a/doc/user/admin_area/settings/sign_up_restrictions.md
+++ b/doc/user/admin_area/settings/sign_up_restrictions.md
@@ -50,14 +50,14 @@ the minimum number of characters a user must have in their password using the Gi
## Whitelist email domains
-> [Introduced][ce-598] in GitLab 7.11.0
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/598) in GitLab 7.11.0
You can restrict users to only sign up using email addresses matching the given
domains list.
## Blacklist email domains
-> [Introduced][ce-5259] in GitLab 8.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5259) in GitLab 8.10.
With this feature enabled, you can block email addresses of a specific domain
from creating an account on your GitLab server. This is particularly useful
@@ -94,6 +94,3 @@ questions that you know someone might ask.
Each scenario can be a third-level heading, e.g. `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->
-
-[ce-5259]: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5259
-[ce-598]: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/598
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
index 7869f7de1b6..4bd49335177 100644
--- a/doc/user/admin_area/settings/usage_statistics.md
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -58,10 +58,10 @@ sequenceDiagram
## Usage Ping **(CORE ONLY)**
-> - [Introduced][ee-557] in GitLab Enterprise Edition 8.10.
-> - More statistics [were added][ee-735] in GitLab Enterprise Edition 8.12.
-> - [Moved to GitLab Core][ce-23361] in 9.1.
-> - More statistics [were added][ee-6602] in GitLab Ultimate 11.2.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/557) in GitLab Enterprise Edition 8.10.
+> - More statistics [were added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/735) in GitLab Enterprise Edition 8.12.
+> - [Moved to GitLab Core](https://gitlab.com/gitlab-org/gitlab-foss/issues/23361) in 9.1.
+> - More statistics [were added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6602) in GitLab Ultimate 11.2.
GitLab sends a weekly payload containing usage data to GitLab Inc. The usage
ping uses high-level data to help our product, support, and sales teams. It does
@@ -149,11 +149,6 @@ Each scenario can be a third-level heading, e.g. `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->
-[ee-557]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/557
-[ee-735]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/735
-[ce-23361]: https://gitlab.com/gitlab-org/gitlab-foss/issues/23361
-[ee-6602]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6602
-
## Usage Statistics Collected
| Statistic | Section | Stage | Description |
diff --git a/doc/user/group/settings/img/export_panel.png b/doc/user/group/settings/img/export_panel.png
new file mode 100644
index 00000000000..2a987f04e35
--- /dev/null
+++ b/doc/user/group/settings/img/export_panel.png
Binary files differ
diff --git a/doc/user/group/settings/import_export.md b/doc/user/group/settings/import_export.md
new file mode 100644
index 00000000000..d50327f2a90
--- /dev/null
+++ b/doc/user/group/settings/import_export.md
@@ -0,0 +1,76 @@
+# Group Import/Export
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2888) in GitLab 13.0 as an experimental feature. May change in future releases.
+
+Existing groups running on any GitLab instance or GitLab.com can be exported with all their related data and moved to a
+new GitLab instance.
+
+The **GitLab import/export** button is displayed if the group import option in enabled.
+
+See also:
+
+- [Group Import/Export API](../../../api/group_import_export.md)
+- [Project Import/Export](../../project/settings/import_export.md)
+- [Project Import/Export API](../../../api/project_import_export.md)
+
+To enable GitLab import/export:
+
+1. Navigate to **{admin}** **Admin Area >** **{settings}** **Settings > Visibility and access controls**.
+1. Scroll to **Import sources**
+1. Enable desired **Import sources**
+
+## Important Notes
+
+Note the following:
+
+- Exports are stored in a temporary [shared directory](../../../development/shared_files.md) and are deleted every 24 hours by a specific worker.
+- To preserve group-level relationships from imported projects, run the Group Import/Export first, to allow projects to
+be imported into the desired group structure.
+- Imported groups are given a `private` visibility level, unless imported into a parent group.
+- If imported into a parent group, subgroups will inherit the same level of visibility unless otherwise restricted.
+- To preserve the member list and their respective permissions on imported groups, review the users in these groups. Make
+sure these users exist before importing the desired groups.
+
+### Exported Contents
+
+The following items will be exported:
+
+- Milestones
+- Labels
+- Boards and Board Lists
+- Badges
+- Subgroups (including all the aforementioned data)
+- Epics
+- Events
+
+The following items will NOT be exported:
+
+- Projects
+- Runners token
+- SAML discovery tokens
+
+NOTE: **Note:**
+For more details on the specific data persisted in a group export, see the
+[`import_export.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/import_export/group/import_export.yml) file.
+
+## Exporting a Group
+
+1. Navigate to your group's homepage.
+
+1. Click **{settings}** **Settings** in the sidebar.
+
+1. In the **Advanced** section, click the **Export Group** button.
+
+ ![Export group panel](img/export_panel.png)
+
+1. Once the export is generated, you can click **Download export** to download the [exported contents](#exported-contents)
+in a compressed tar archive, with contents in JSON format. You can also return to this page to regenerate the export data.
+
+## Rate Limits
+
+To help avoid abuse, users are rate limited to:
+
+| Request Type | Limit |
+| ---------------- | ------------------------------ |
+| Export | 1 group every 5 minutes |
+| Download export | 10 downloads every 10 minutes |
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 06e3d4f6e06..854744f3090 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -42,7 +42,7 @@ NOTE: **Note:**
In GitLab 11.0, the Master role was renamed to Maintainer.
While Maintainer is the highest project-level role, some actions can only be performed by a personal namespace or group owner,
-or an instance admin, who receives all permissions.
+or an instance admin, who receives all permissions. For more information, see [projects members documentation](project/members/index.md).
The following table depicts the various user permission levels in a project.
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index 026416f0190..82e2dfaaca2 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -295,11 +295,11 @@ The following tables outline the details of expected properties.
**Axis (`panels[].y_axis`) properties:**
-| Property | Type | Required | Description |
-| ----------- | ------ | ------------------------- | -------------------------------------------------------------------- |
-| `name` | string | no, but highly encouraged | Y-Axis label for the panel, it will replace `y_label` if set. |
-| `format` | string | no, defaults to `number` | Unit format used. See the [full list of units](prometheus_units.md). |
-| `precision` | number | no, defaults to `2` | Number of decimals to display in the number. |
+| Property | Type | Required | Description |
+| ----------- | ------ | ----------------------------- | -------------------------------------------------------------------- |
+| `name` | string | no, but highly encouraged | Y-Axis label for the panel. Replaces `y_label` if set. |
+| `format` | string | no, defaults to `engineering` | Unit format used. See the [full list of units](prometheus_units.md). |
+| `precision` | number | no, defaults to `2` | Number of decimal places to display in the number. | |
**Metrics (`metrics`) properties:**
diff --git a/doc/user/project/integrations/prometheus_units.md b/doc/user/project/integrations/prometheus_units.md
index 9df9f52ceb1..d649a14ecf2 100644
--- a/doc/user/project/integrations/prometheus_units.md
+++ b/doc/user/project/integrations/prometheus_units.md
@@ -5,19 +5,78 @@
You can select units to format your charts by adding `format` to your
[axis configuration](prometheus.md#dashboard-yaml-properties).
+## Internationalization and localization
+
+Currently, your [internationalization and localization options](https://en.wikipedia.org/wiki/Internationalization_and_localization) for number formatting are dependent on the system you are using i.e. your OS or browser.
+
+## Engineering Notation
+
+For generic or default data, numbers are formatted according to the current locale in [engineering notation](https://en.wikipedia.org/wiki/Engineering_notation).
+
+While an [engineering notation exists for the web](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat), GitLab uses a version based off the [scientific notation](https://en.wikipedia.org/wiki/Scientific_notation). GitLab formatting acts in accordance with SI prefixes. For example, using GitLab notation, `1500.00` becomes `1.5k` instead of `1.5E3`. Keep this distinction in mind when using the engineering notation for your metrics.
+
+Formats: `engineering`
+
+SI prefixes:
+
+| Name | Symbol | Value |
+| ---------- | ------- | -------------------------- |
+| `yotta` | Y | 1000000000000000000000000 |
+| `zetta` | Z | 1000000000000000000000 |
+| `exa` | E | 1000000000000000000 |
+| `peta` | P | 1000000000000000 |
+| `tera` | T | 1000000000000 |
+| `giga` | G | 1000000000 |
+| `mega` | M | 1000000 |
+| `kilo` | k | 1000 |
+| `milli` | m | 0.001 |
+| `micro` | μ | 0.000001 |
+| `nano` | n | 0.000000001 |
+| `pico` | p | 0.000000000001 |
+| `femto` | f | 0.000000000000001 |
+| `atto` | a | 0.000000000000000001 |
+| `zepto` | z | 0.000000000000000000001 |
+| `yocto` | y | 0.000000000000000000000001 |
+
+**Examples:**
+
+| Data | Displayed |
+| --------------------------------- | --------- |
+| `0.000000000000000000000008` | 8y |
+| `0.000000000000000000008` | 8z |
+| `0.000000000000000008` | 8a |
+| `0.000000000000008` | 8f |
+| `0.000000000008` | 8p |
+| `0.000000008` | 8n |
+| `0.000008` | 8μ |
+| `0.008` | 8m |
+| `10` | 10 |
+| `1080` | 1.08k |
+| `18000` | 18k |
+| `18888` | 18.9k |
+| `188888` | 189k |
+| `18888888` | 18.9M |
+| `1888888888` | 1.89G |
+| `1888888888888` | 1.89T |
+| `1888888888888888` | 1.89P |
+| `1888888888888888888` | 1.89E |
+| `1888888888888888888888` | 1.89Z |
+| `1888888888888888888888888` | 1.89Y |
+| `1888888888888888888888888888` | 1.89e+27 |
+
## Numbers
-For generic data, numbers are formatted according to the current locale.
+For number data, numbers are formatted according to the current locale.
Formats: `number`
**Examples:**
-| Data | Displayed |
-| --------- | --------- |
-| `10` | 1 |
-| `1000` | 1,000 |
-| `1000000` | 1,000,000 |
+| Data | Displayed |
+| ---------- | --------- |
+| `10` | 1 |
+| `1000` | 1,000 |
+| `1000000` | 1,000,000 |
## Percentage
diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md
index 27a5701e6c2..9020dc335b6 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -1,4 +1,4 @@
-# Project's members
+# Members of a project
You can manage the groups and users and their access levels in all of your
projects. You can also personalize the access level you give each user,
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 7f241a74820..17eac6bce51 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -12,6 +12,7 @@ See also:
- [Project import/export API](../../../api/project_import_export.md)
- [Project import/export administration Rake tasks](../../../administration/raketasks/project_import_export.md) **(CORE ONLY)**
+- [Group import/export](../../group/settings/import_export.md)
- [Group import/export API](../../../api/group_import_export.md)
To set up a project import/export:
diff --git a/lib/quality/helm3_client.rb b/lib/quality/helm3_client.rb
index f5eb0834386..afea73cbc50 100644
--- a/lib/quality/helm3_client.rb
+++ b/lib/quality/helm3_client.rb
@@ -17,10 +17,6 @@ module Quality
@revision ||= self[:revision].to_i
end
- def status
- @status ||= self[:status].downcase
- end
-
def last_update
@last_update ||= Time.parse(self[:last_update])
end
@@ -29,7 +25,7 @@ module Quality
# A single page of data and the corresponding page number.
Page = Struct.new(:releases, :number)
- def initialize(namespace:, tiller_namespace: nil)
+ def initialize(namespace:)
@namespace = namespace
end
diff --git a/lib/quality/helm_client.rb b/lib/quality/helm_client.rb
deleted file mode 100644
index fc4e1ca2d18..00000000000
--- a/lib/quality/helm_client.rb
+++ /dev/null
@@ -1,114 +0,0 @@
-# frozen_string_literal: true
-
-require 'time'
-require_relative '../gitlab/popen' unless defined?(Gitlab::Popen)
-
-module Quality
- class HelmClient
- CommandFailedError = Class.new(StandardError)
-
- attr_reader :tiller_namespace, :namespace
-
- RELEASE_JSON_ATTRIBUTES = %w[Name Revision Updated Status Chart AppVersion Namespace].freeze
-
- Release = Struct.new(:name, :revision, :last_update, :status, :chart, :app_version, :namespace) do
- def revision
- @revision ||= self[:revision].to_i
- end
-
- def last_update
- @last_update ||= Time.parse(self[:last_update])
- end
- end
-
- # A single page of data and the corresponding page number.
- Page = Struct.new(:releases, :number)
-
- def initialize(tiller_namespace:, namespace:)
- @tiller_namespace = tiller_namespace
- @namespace = namespace
- end
-
- def releases(args: [])
- each_release(args)
- end
-
- def delete(release_name:)
- run_command([
- 'delete',
- %(--tiller-namespace "#{tiller_namespace}"),
- '--purge',
- release_name
- ])
- end
-
- private
-
- def run_command(command)
- final_command = ['helm', *command].join(' ')
- puts "Running command: `#{final_command}`" # rubocop:disable Rails/Output
-
- result = Gitlab::Popen.popen_with_detail([final_command])
-
- if result.status.success?
- result.stdout.chomp.freeze
- else
- raise CommandFailedError, "The `#{final_command}` command failed (status: #{result.status}) with the following error:\n#{result.stderr}"
- end
- end
-
- def raw_releases(args = [])
- command = [
- 'list',
- %(--namespace "#{namespace}"),
- %(--tiller-namespace "#{tiller_namespace}" --output json),
- *args
- ]
- json = JSON.parse(run_command(command))
-
- releases = json['Releases'].map do |json_release|
- Release.new(*json_release.values_at(*RELEASE_JSON_ATTRIBUTES))
- end
-
- [releases, json['Next']]
- rescue JSON::ParserError => ex
- puts "Ignoring this JSON parsing error: #{ex}" # rubocop:disable Rails/Output
- [[], nil]
- end
-
- # Fetches data from Helm and yields a Page object for every page
- # of data, without loading all of them into memory.
- #
- # method - The Octokit method to use for getting the data.
- # args - Arguments to pass to the `helm list` command.
- def each_releases_page(args, &block)
- return to_enum(__method__, args) unless block_given?
-
- page = 1
- offset = ''
-
- loop do
- final_args = args.dup
- final_args << "--offset #{offset}" unless offset.to_s.empty?
- collection, offset = raw_releases(final_args)
-
- yield Page.new(collection, page += 1)
-
- break if offset.to_s.empty?
- end
- end
-
- # Iterates over all of the releases.
- #
- # args - Any arguments to pass to the `helm list` command.
- def each_release(args, &block)
- return to_enum(__method__, args) unless block_given?
-
- each_releases_page(args) do |page|
- page.releases.each do |release|
- yield release
- end
- end
- end
- end
-end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 66a16cd46c1..f38491dcc18 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -3087,6 +3087,9 @@ msgstr ""
msgid "Boards"
msgstr ""
+msgid "Boards and Board Lists"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -8645,12 +8648,18 @@ msgstr ""
msgid "Export as CSV"
msgstr ""
+msgid "Export group"
+msgstr ""
+
msgid "Export issues"
msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
+msgstr ""
+
msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
msgstr ""
@@ -10514,6 +10523,9 @@ msgstr ""
msgid "GroupSettings|Disable group mentions"
msgstr ""
+msgid "GroupSettings|Export group"
+msgstr ""
+
msgid "GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility."
msgstr ""
@@ -14111,6 +14123,9 @@ msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
msgstr ""
+msgid "Once the exported file is ready you can download it from this page."
+msgstr ""
+
msgid "Once the exported file is ready, you will receive a notification email with a download link, or you can download it from this page."
msgstr ""
@@ -14623,9 +14638,6 @@ msgstr ""
msgid "Path"
msgstr ""
-msgid "Path, transfer, remove"
-msgstr ""
-
msgid "Path:"
msgstr ""
@@ -14656,7 +14668,7 @@ msgstr ""
msgid "Percentage"
msgstr ""
-msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgid "Perform advanced options such as changing path, transferring, exporting, or removing the group."
msgstr ""
msgid "Perform common operations on GitLab project"
@@ -14737,9 +14749,6 @@ msgstr ""
msgid "Pipeline minutes quota"
msgstr ""
-msgid "Pipeline quota"
-msgstr ""
-
msgid "Pipeline subscriptions"
msgstr ""
@@ -16854,6 +16863,9 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate export"
+msgstr ""
+
msgid "Regenerate instance ID"
msgstr ""
@@ -17645,6 +17657,9 @@ msgstr ""
msgid "Runner token"
msgstr ""
+msgid "Runner tokens"
+msgstr ""
+
msgid "Runner was not updated."
msgstr ""
@@ -17699,6 +17714,9 @@ msgstr ""
msgid "SAML SSO for %{group_name}"
msgstr ""
+msgid "SAML discovery tokens"
+msgstr ""
+
msgid "SAML for %{group_name}"
msgstr ""
diff --git a/scripts/review_apps/automated_cleanup.rb b/scripts/review_apps/automated_cleanup.rb
index e3ed7143ea2..a9659071a2f 100755
--- a/scripts/review_apps/automated_cleanup.rb
+++ b/scripts/review_apps/automated_cleanup.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require 'gitlab'
-require_relative File.expand_path('../../lib/quality/helm_client.rb', __dir__)
require_relative File.expand_path('../../lib/quality/helm3_client.rb', __dir__)
require_relative File.expand_path('../../lib/quality/kubernetes_client.rb', __dir__)
@@ -9,7 +8,6 @@ class AutomatedCleanup
attr_reader :project_path, :gitlab_token
DEPLOYMENTS_PER_PAGE = 100
- HELM_RELEASES_BATCH_SIZE = 5
IGNORED_HELM_ERRORS = [
'transport is closing',
'error upgrading connection',
@@ -45,18 +43,8 @@ class AutomatedCleanup
self.class.ee? ? 'review-apps-ee' : 'review-apps-ce'
end
- def helm3?
- !ENV['HELM_3'].nil?
- end
-
- def helm_client_class
- helm3? ? Quality::Helm3Client : Quality::HelmClient
- end
-
def helm
- @helm ||= helm_client_class.new(
- tiller_namespace: review_apps_namespace,
- namespace: review_apps_namespace)
+ @helm ||= Quality::Helm3Client.new(namespace: review_apps_namespace)
end
def kubernetes
@@ -88,7 +76,7 @@ class AutomatedCleanup
if deployed_at < delete_threshold
deleted_environment = delete_environment(environment, deployment)
if deleted_environment
- release = helm_client_class::Release.new(environment.slug, 1, deployed_at.to_s, nil, nil, review_apps_namespace)
+ release = Quality::Helm3Client::Release.new(environment.slug, 1, deployed_at.to_s, nil, nil, review_apps_namespace)
releases_to_delete << release
end
else
@@ -117,7 +105,7 @@ class AutomatedCleanup
# Prevents deleting `dns-gitlab-review-app` releases or other unrelated releases
next unless release.name.start_with?('review-')
- if release.status.casecmp('failed') == 0 || release.last_update < threshold
+ if release.status == 'failed' || release.last_update < threshold
releases_to_delete << release
else
print_release_state(subject: 'Release', release_name: release.name, release_date: release.last_update, action: 'leaving')
@@ -154,7 +142,6 @@ class AutomatedCleanup
def helm_releases
args = ['--all', '--date']
- args << "--max #{HELM_RELEASES_BATCH_SIZE}" unless helm3?
helm.releases(args: args)
end
@@ -170,7 +157,7 @@ class AutomatedCleanup
helm.delete(release_name: releases_names)
kubernetes.cleanup(release_name: releases_names, wait: false)
- rescue helm_client_class::CommandFailedError => ex
+ rescue Quality::Helm3Client::CommandFailedError => ex
raise ex unless ignore_exception?(ex.message, IGNORED_HELM_ERRORS)
puts "Ignoring the following Helm error:\n#{ex}\n"
diff --git a/scripts/review_apps/gcp_cleanup.sh b/scripts/review_apps/gcp_cleanup.sh
index ea6b60ed5ff..efdde05a194 100755
--- a/scripts/review_apps/gcp_cleanup.sh
+++ b/scripts/review_apps/gcp_cleanup.sh
@@ -2,6 +2,13 @@
source scripts/utils.sh
+function setup_gcp_dependencies() {
+ apk add jq
+
+ gcloud auth activate-service-account --key-file="${REVIEW_APPS_GCP_CREDENTIALS}"
+ gcloud config set project "${REVIEW_APPS_GCP_PROJECT}"
+}
+
# These scripts require the following environment variables:
# - REVIEW_APPS_GCP_REGION - e.g `us-central1`
# - KUBE_NAMESPACE - e.g `review-apps-ee`
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index 915b4f5050b..c514b89e899 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -95,37 +95,6 @@ function delete_failed_release() {
fi
}
-function helm2_deploy_exists() {
- local namespace="${1}"
- local release="${2}"
- local deploy_exists
-
- echoinfo "Checking if Helm 2 ${release} exists in the ${namespace} namespace..." true
-
- kubectl get cm -l OWNER=TILLER -n ${namespace} | grep ${release} 2>&1
- deploy_exists=$?
-
- echoinfo "Helm 2 release for ${release} is ${deploy_exists}"
- return $deploy_exists
-}
-
-function delete_helm2_release() {
- local namespace="${KUBE_NAMESPACE}"
- local release="${CI_ENVIRONMENT_SLUG}"
-
- if [ -z "${release}" ]; then
- echoerr "No release given, aborting the delete!"
- return
- fi
-
- if ! helm2_deploy_exists "${namespace}" "${release}"; then
- echoinfo "No Review App with ${release} is currently deployed by Helm 2."
- else
- echoinfo "Cleaning up ${release} installed by Helm 2"
- kubectl_cleanup_release "${namespace}" "${release}"
- fi
-}
-
function get_pod() {
local namespace="${KUBE_NAMESPACE}"
local release="${CI_ENVIRONMENT_SLUG}"
@@ -290,7 +259,7 @@ HELM_CMD=$(cat << EOF
--namespace="${namespace}" \
--install \
--wait \
- --timeout 900s \
+ --timeout 15m \
--set ci.branch="${CI_COMMIT_REF_NAME}" \
--set ci.commit.sha="${CI_COMMIT_SHORT_SHA}" \
--set ci.job.url="${CI_JOB_URL}" \
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 123e022beca..8181be8929e 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -752,7 +752,7 @@ describe Projects::IssuesController do
expect { update_issue }.not_to change { issue.reload.title }
end
- it 'rejects an issue recognized as a spam when recaptcha disabled' do
+ it 'rejects an issue recognized as a spam when reCAPTCHA disabled' do
stub_application_setting(recaptcha_enabled: false)
expect { update_issue }.not_to change { issue.reload.title }
@@ -811,7 +811,7 @@ describe Projects::IssuesController do
expect(response).to have_gitlab_http_status(:ok)
end
- it 'accepts an issue after recaptcha is verified' do
+ it 'accepts an issue after reCAPTCHA is verified' do
expect { update_verified_issue }.to change { issue.reload.title }.to(spammy_title)
end
@@ -1017,7 +1017,7 @@ describe Projects::IssuesController do
expect { post_new_issue(title: '') }.not_to change(Issue, :count)
end
- it 'does not create an issue when recaptcha is not enabled' do
+ it 'does not create an issue when reCAPTCHA is not enabled' do
stub_application_setting(recaptcha_enabled: false)
expect { post_spam_issue }.not_to change(Issue, :count)
@@ -1052,7 +1052,7 @@ describe Projects::IssuesController do
expect(controller).to receive_messages(verify_recaptcha: true)
end
- it 'accepts an issue after recaptcha is verified' do
+ it 'accepts an issue after reCAPTCHA is verified' do
expect { post_verified_issue }.to change(Issue, :count)
end
diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb
index 284789305e2..5335234a87e 100644
--- a/spec/controllers/projects/snippets_controller_spec.rb
+++ b/spec/controllers/projects/snippets_controller_spec.rb
@@ -127,7 +127,7 @@ describe Projects::SnippetsController do
.to log_spam(title: 'Title', user_id: user.id, noteable_type: 'ProjectSnippet')
end
- it 'renders :new with recaptcha disabled' do
+ it 'renders :new with reCAPTCHA disabled' do
stub_application_setting(recaptcha_enabled: false)
create_snippet(project, visibility_level: Snippet::PUBLIC)
@@ -135,18 +135,18 @@ describe Projects::SnippetsController do
expect(response).to render_template(:new)
end
- context 'recaptcha enabled' do
+ context 'reCAPTCHA enabled' do
before do
stub_application_setting(recaptcha_enabled: true)
end
- it 'renders :verify with recaptcha enabled' do
+ it 'renders :verify with reCAPTCHA enabled' do
create_snippet(project, visibility_level: Snippet::PUBLIC)
expect(response).to render_template(:verify)
end
- it 'renders snippet page when recaptcha verified' do
+ it 'renders snippet page when reCAPTCHA verified' do
spammy_title = 'Whatever'
spam_logs = create_list(:spam_log, 2, user: user, title: spammy_title)
@@ -223,7 +223,7 @@ describe Projects::SnippetsController do
.to log_spam(title: 'Foo', user_id: user.id, noteable_type: 'ProjectSnippet')
end
- it 'renders :edit with recaptcha disabled' do
+ it 'renders :edit with reCAPTCHA disabled' do
stub_application_setting(recaptcha_enabled: false)
update_snippet(title: 'Foo')
@@ -231,18 +231,18 @@ describe Projects::SnippetsController do
expect(response).to render_template(:edit)
end
- context 'recaptcha enabled' do
+ context 'reCAPTCHA enabled' do
before do
stub_application_setting(recaptcha_enabled: true)
end
- it 'renders :verify with recaptcha enabled' do
+ it 'renders :verify with reCAPTCHA enabled' do
update_snippet(title: 'Foo')
expect(response).to render_template(:verify)
end
- it 'renders snippet page when recaptcha verified' do
+ it 'renders snippet page when reCAPTCHA verified' do
spammy_title = 'Whatever'
spam_logs = create_list(:spam_log, 2, user: user, title: spammy_title)
@@ -268,7 +268,7 @@ describe Projects::SnippetsController do
.to log_spam(title: 'Foo', user_id: user.id, noteable_type: 'ProjectSnippet')
end
- it 'renders :edit with recaptcha disabled' do
+ it 'renders :edit with reCAPTCHA disabled' do
stub_application_setting(recaptcha_enabled: false)
update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC)
@@ -276,18 +276,18 @@ describe Projects::SnippetsController do
expect(response).to render_template(:edit)
end
- context 'recaptcha enabled' do
+ context 'reCAPTCHA enabled' do
before do
stub_application_setting(recaptcha_enabled: true)
end
- it 'renders :verify with recaptcha enabled' do
+ it 'renders :verify' do
update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC)
expect(response).to render_template(:verify)
end
- it 'renders snippet page when recaptcha verified' do
+ it 'renders snippet page' do
spammy_title = 'Whatever'
spam_logs = create_list(:spam_log, 2, user: user, title: spammy_title)
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index 0b4ecb68cf7..eda8b8655a1 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -139,7 +139,7 @@ describe RegistrationsController do
expect(flash[:alert]).to eq(_('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'))
end
- it 'redirects to the dashboard when the recaptcha is solved' do
+ it 'redirects to the dashboard when the reCAPTCHA is solved' do
post(:create, params: user_params)
expect(flash[:notice]).to eq(I18n.t('devise.registrations.signed_up'))
diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb
index 05c48fb190c..81729122156 100644
--- a/spec/controllers/snippets_controller_spec.rb
+++ b/spec/controllers/snippets_controller_spec.rb
@@ -318,7 +318,7 @@ describe SnippetsController do
.to log_spam(title: 'Title', user: user, noteable_type: 'PersonalSnippet')
end
- it 'renders :new with recaptcha disabled' do
+ it 'renders :new with reCAPTCHA disabled' do
stub_application_setting(recaptcha_enabled: false)
create_snippet(visibility_level: Snippet::PUBLIC)
@@ -326,18 +326,18 @@ describe SnippetsController do
expect(response).to render_template(:new)
end
- context 'recaptcha enabled' do
+ context 'reCAPTCHA enabled' do
before do
stub_application_setting(recaptcha_enabled: true)
end
- it 'renders :verify with recaptcha enabled' do
+ it 'renders :verify' do
create_snippet(visibility_level: Snippet::PUBLIC)
expect(response).to render_template(:verify)
end
- it 'renders snippet page when recaptcha verified' do
+ it 'renders snippet page' do
spammy_title = 'Whatever'
spam_logs = create_list(:spam_log, 2, user: user, title: spammy_title)
@@ -403,7 +403,7 @@ describe SnippetsController do
.to log_spam(title: 'Foo', user: user, noteable_type: 'PersonalSnippet')
end
- it 'renders :edit with recaptcha disabled' do
+ it 'renders :edit with reCAPTCHA disabled' do
stub_application_setting(recaptcha_enabled: false)
update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC)
@@ -411,18 +411,18 @@ describe SnippetsController do
expect(response).to render_template(:edit)
end
- context 'recaptcha enabled' do
+ context 'reCAPTCHA enabled' do
before do
stub_application_setting(recaptcha_enabled: true)
end
- it 'renders :verify with recaptcha enabled' do
+ it 'renders :verify' do
update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC)
expect(response).to render_template(:verify)
end
- it 'renders snippet page when recaptcha verified' do
+ it 'renders snippet page when reCAPTCHA verified' do
spammy_title = 'Whatever'
spam_logs = create_list(:spam_log, 2, user: user, title: spammy_title)
@@ -446,7 +446,7 @@ describe SnippetsController do
.to log_spam(title: 'Foo', user: user, noteable_type: 'PersonalSnippet')
end
- it 'renders :edit with recaptcha disabled' do
+ it 'renders :edit with reCAPTCHA disabled' do
stub_application_setting(recaptcha_enabled: false)
update_snippet(title: 'Foo')
@@ -459,13 +459,13 @@ describe SnippetsController do
stub_application_setting(recaptcha_enabled: true)
end
- it 'renders :verify with recaptcha enabled' do
+ it 'renders :verify' do
update_snippet(title: 'Foo')
expect(response).to render_template(:verify)
end
- it 'renders snippet page when recaptcha verified' do
+ it 'renders snippet page when reCAPTCHA verified' do
spammy_title = 'Whatever'
spam_logs = create_list(:spam_log, 2, user: user, title: spammy_title)
diff --git a/spec/factories/deploy_tokens.rb b/spec/factories/deploy_tokens.rb
index 657915f9976..d4127f78ebf 100644
--- a/spec/factories/deploy_tokens.rb
+++ b/spec/factories/deploy_tokens.rb
@@ -8,6 +8,8 @@ FactoryBot.define do
read_repository { true }
read_registry { true }
write_registry { false }
+ read_package_registry { false }
+ write_package_registry { false }
revoked { false }
expires_at { 5.days.from_now }
deploy_token_type { DeployToken.deploy_token_types[:project_type] }
@@ -31,5 +33,11 @@ FactoryBot.define do
trait :project do
deploy_token_type { DeployToken.deploy_token_types[:project_type] }
end
+
+ trait :all_scopes do
+ write_registry { true}
+ read_package_registry { true }
+ write_package_registry { true }
+ end
end
end
diff --git a/spec/features/groups/import_export/export_file_spec.rb b/spec/features/groups/import_export/export_file_spec.rb
new file mode 100644
index 00000000000..5829e659722
--- /dev/null
+++ b/spec/features/groups/import_export/export_file_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Group Export', :js do
+ include ExportFileHelper
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ context 'when the signed in user has the required permission level' do
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ it 'allows the user to export the group', :sidekiq_inline do
+ visit edit_group_path(group)
+
+ expect(page).to have_content('Export group')
+
+ click_link('Export group')
+ expect(page).to have_content('Group export started')
+
+ expect(page).to have_content('Download export')
+ end
+ end
+
+ context 'when the group import/export FF is disabled' do
+ before do
+ stub_feature_flags(group_import_export: false)
+
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ it 'does not show the group export options' do
+ visit edit_group_path(group)
+
+ expect(page).to have_content('Advanced')
+ expect(page).not_to have_content('Export group')
+ end
+ end
+
+ context 'when the signed in user does not have the required permission level' do
+ before do
+ group.add_guest(user)
+
+ sign_in(user)
+ end
+
+ it 'does not let the user export the group' do
+ visit edit_group_path(group)
+
+ expect(page).to have_content('Page Not Found')
+ expect(page).not_to have_content('Export group')
+ end
+ end
+end
diff --git a/spec/features/issues/spam_issues_spec.rb b/spec/features/issues/spam_issues_spec.rb
index b6c936a6767..47e7022011d 100644
--- a/spec/features/issues/spam_issues_spec.rb
+++ b/spec/features/issues/spam_issues_spec.rb
@@ -103,8 +103,8 @@ describe 'New issue', :js do
click_button 'Submit issue'
- # it is impossible to test recaptcha automatically and there is no possibility to fill in recaptcha
- # recaptcha verification is skipped in test environment and it always returns true
+ # it is impossible to test reCAPTCHA automatically and there is no possibility to fill in recaptcha
+ # reCAPTCHA verification is skipped in test environment and it always returns true
expect(page).not_to have_content('issue title')
expect(page).to have_css('.recaptcha')
diff --git a/spec/features/snippets/spam_snippets_spec.rb b/spec/features/snippets/spam_snippets_spec.rb
index 8bba3e45824..bdcc1cc56e7 100644
--- a/spec/features/snippets/spam_snippets_spec.rb
+++ b/spec/features/snippets/spam_snippets_spec.rb
@@ -40,13 +40,13 @@ shared_examples_for 'snippet editor' do
end
end
- shared_examples 'solve recaptcha' do
- it 'creates a snippet after solving reCaptcha' do
+ shared_examples 'solve reCAPTCHA' do
+ it 'creates a snippet after solving reCAPTCHA' do
click_button('Create snippet')
wait_for_requests
- # it is impossible to test recaptcha automatically and there is no possibility to fill in recaptcha
- # recaptcha verification is skipped in test environment and it always returns true
+ # it is impossible to test reCAPTCHA automatically and there is no possibility to fill in recaptcha
+ # reCAPTCHA verification is skipped in test environment and it always returns true
expect(page).not_to have_content('My Snippet Title')
expect(page).to have_css('.recaptcha')
click_button('Submit personal snippet')
@@ -82,7 +82,7 @@ shared_examples_for 'snippet editor' do
end
context 'when allow_possible_spam feature flag is true' do
- it_behaves_like 'solve recaptcha'
+ it_behaves_like 'solve reCAPTCHA'
end
end
diff --git a/spec/javascripts/filtered_search/visual_token_value_spec.js b/spec/javascripts/filtered_search/visual_token_value_spec.js
index 4469ade1874..51a9b01231f 100644
--- a/spec/javascripts/filtered_search/visual_token_value_spec.js
+++ b/spec/javascripts/filtered_search/visual_token_value_spec.js
@@ -1,4 +1,4 @@
-import { escape as esc } from 'lodash';
+import { escape } from 'lodash';
import VisualTokenValue from '~/filtered_search/visual_token_value';
import AjaxCache from '~/lib/utils/ajax_cache';
import UsersCache from '~/lib/utils/users_cache';
@@ -121,7 +121,7 @@ describe('Filtered Search Visual Tokens', () => {
expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
tokenValueElement.querySelector('.avatar').remove();
- expect(tokenValueElement.innerHTML.trim()).toBe(esc(dummyUser.name));
+ expect(tokenValueElement.innerHTML.trim()).toBe(escape(dummyUser.name));
})
.then(done)
.catch(done.fail);
diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js
index f11d4f5ac33..2d4d3ea28ff 100644
--- a/spec/javascripts/issue_show/components/app_spec.js
+++ b/spec/javascripts/issue_show/components/app_spec.js
@@ -316,7 +316,7 @@ describe('Issuable output', () => {
});
});
- it('opens recaptcha modal if update rejected as spam', done => {
+ it('opens reCAPTCHA modal if update rejected as spam', done => {
function mockScriptSrc() {
const recaptchaChild = vm.$children.find(
// eslint-disable-next-line no-underscore-dangle
diff --git a/spec/javascripts/issue_show/components/description_spec.js b/spec/javascripts/issue_show/components/description_spec.js
index 83e498347f7..194f177d837 100644
--- a/spec/javascripts/issue_show/components/description_spec.js
+++ b/spec/javascripts/issue_show/components/description_spec.js
@@ -57,7 +57,7 @@ describe('Description component', () => {
});
});
- it('opens recaptcha dialog if update rejected as spam', done => {
+ it('opens reCAPTCHA dialog if update rejected as spam', done => {
let modal;
const recaptchaChild = vm.$children.find(
// eslint-disable-next-line no-underscore-dangle
diff --git a/spec/lib/quality/helm_client_spec.rb b/spec/lib/quality/helm_client_spec.rb
deleted file mode 100644
index 8d199fe3531..00000000000
--- a/spec/lib/quality/helm_client_spec.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-
-RSpec.describe Quality::HelmClient do
- let(:tiller_namespace) { 'review-apps-ee' }
- let(:namespace) { tiller_namespace }
- let(:release_name) { 'my-release' }
- let(:raw_helm_list_page1) do
- <<~OUTPUT
- {"Next":"review-6709-group-t40qbv",
- "Releases":[
- {"Name":"review-qa-60-reor-1mugd1", "Revision":1,"Updated":"Thu Oct 4 17:52:31 2018","Status":"FAILED", "Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
- {"Name":"review-7846-fix-s-261vd6","Revision":1,"Updated":"Thu Oct 4 17:33:29 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
- {"Name":"review-7867-snowp-lzo3iy","Revision":1,"Updated":"Thu Oct 4 17:22:14 2018","Status":"DEPLOYED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
- {"Name":"review-rename-geo-o4a780","Revision":1,"Updated":"Thu Oct 4 17:14:57 2018","Status":"DEPLOYED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
- {"Name":"review-5781-opera-0k93fx","Revision":1,"Updated":"Thu Oct 4 17:06:15 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
- {"Name":"review-6709-group-2pzeec","Revision":1,"Updated":"Thu Oct 4 16:36:59 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
- {"Name":"review-ce-to-ee-2-l554mn","Revision":1,"Updated":"Thu Oct 4 16:27:02 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
- {"Name":"review-epics-e2e-m690eb","Revision":1,"Updated":"Thu Oct 4 16:08:26 2018","Status":"DEPLOYED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
- {"Name":"review-7126-admin-06fae2","Revision":1,"Updated":"Thu Oct 4 15:56:35 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
- {"Name":"review-6983-promo-xyou11","Revision":1,"Updated":"Thu Oct 4 15:15:34 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"}
- ]}
- OUTPUT
- end
- let(:raw_helm_list_page2) do
- <<~OUTPUT
- {"Releases":[
- {"Name":"review-6709-group-t40qbv","Revision":1,"Updated":"Thu Oct 4 17:52:31 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"}
- ]}
- OUTPUT
- end
-
- subject { described_class.new(tiller_namespace: tiller_namespace, namespace: namespace) }
-
- describe '#releases' do
- it 'raises an error if the Helm command fails' do
- expect(Gitlab::Popen).to receive(:popen_with_detail)
- .with([%(helm list --namespace "#{namespace}" --tiller-namespace "#{tiller_namespace}" --output json)])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
-
- expect { subject.releases.to_a }.to raise_error(described_class::CommandFailedError)
- end
-
- it 'calls helm list with default arguments' do
- expect(Gitlab::Popen).to receive(:popen_with_detail)
- .with([%(helm list --namespace "#{namespace}" --tiller-namespace "#{tiller_namespace}" --output json)])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
-
- subject.releases.to_a
- end
-
- it 'calls helm list with extra arguments' do
- expect(Gitlab::Popen).to receive(:popen_with_detail)
- .with([%(helm list --namespace "#{namespace}" --tiller-namespace "#{tiller_namespace}" --output json --deployed)])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
-
- subject.releases(args: ['--deployed']).to_a
- end
-
- it 'returns a list of Release objects' do
- expect(Gitlab::Popen).to receive(:popen_with_detail)
- .with([%(helm list --namespace "#{namespace}" --tiller-namespace "#{tiller_namespace}" --output json --deployed)])
- .and_return(Gitlab::Popen::Result.new([], raw_helm_list_page2, '', double(success?: true)))
-
- releases = subject.releases(args: ['--deployed']).to_a
-
- expect(releases.size).to eq(1)
- expect(releases[0]).to have_attributes(
- name: 'review-6709-group-t40qbv',
- revision: 1,
- last_update: Time.parse('Thu Oct 4 17:52:31 2018'),
- status: 'FAILED',
- chart: 'gitlab-1.1.3',
- app_version: 'master',
- namespace: namespace
- )
- end
-
- it 'automatically paginates releases' do
- expect(Gitlab::Popen).to receive(:popen_with_detail).ordered
- .with([%(helm list --namespace "#{namespace}" --tiller-namespace "#{tiller_namespace}" --output json)])
- .and_return(Gitlab::Popen::Result.new([], raw_helm_list_page1, '', double(success?: true)))
- expect(Gitlab::Popen).to receive(:popen_with_detail).ordered
- .with([%(helm list --namespace "#{namespace}" --tiller-namespace "#{tiller_namespace}" --output json --offset review-6709-group-t40qbv)])
- .and_return(Gitlab::Popen::Result.new([], raw_helm_list_page2, '', double(success?: true)))
-
- releases = subject.releases.to_a
-
- expect(releases.size).to eq(11)
- expect(releases.last.name).to eq('review-6709-group-t40qbv')
- end
- end
-
- describe '#delete' do
- it 'raises an error if the Helm command fails' do
- expect(Gitlab::Popen).to receive(:popen_with_detail)
- .with([%(helm delete --tiller-namespace "#{tiller_namespace}" --purge #{release_name})])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
-
- expect { subject.delete(release_name: release_name) }.to raise_error(described_class::CommandFailedError)
- end
-
- it 'calls helm delete with default arguments' do
- expect(Gitlab::Popen).to receive(:popen_with_detail)
- .with([%(helm delete --tiller-namespace "#{tiller_namespace}" --purge #{release_name})])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
-
- expect(subject.delete(release_name: release_name)).to eq('')
- end
-
- context 'with multiple release names' do
- let(:release_name) { %w[my-release my-release-2] }
-
- it 'raises an error if the Helm command fails' do
- expect(Gitlab::Popen).to receive(:popen_with_detail)
- .with([%(helm delete --tiller-namespace "#{tiller_namespace}" --purge #{release_name.join(' ')})])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
-
- expect { subject.delete(release_name: release_name) }.to raise_error(described_class::CommandFailedError)
- end
-
- it 'calls helm delete with multiple release names' do
- expect(Gitlab::Popen).to receive(:popen_with_detail)
- .with([%(helm delete --tiller-namespace "#{tiller_namespace}" --purge #{release_name.join(' ')})])
- .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
-
- expect(subject.delete(release_name: release_name)).to eq('')
- end
- end
- end
-end
diff --git a/spec/models/deploy_token_spec.rb b/spec/models/deploy_token_spec.rb
index a2d4c046d46..819e2850644 100644
--- a/spec/models/deploy_token_spec.rb
+++ b/spec/models/deploy_token_spec.rb
@@ -72,8 +72,10 @@ describe DeployToken do
describe '#scopes' do
context 'with all the scopes' do
+ let_it_be(:deploy_token) { create(:deploy_token, :all_scopes) }
+
it 'returns scopes assigned to DeployToken' do
- expect(deploy_token.scopes).to eq([:read_repository, :read_registry])
+ expect(deploy_token.scopes).to eq(DeployToken::AVAILABLE_SCOPES)
end
end
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index 21ccebc53f4..ba2fa82d642 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -386,7 +386,7 @@ describe Issues::CreateService do
stub_feature_flags(allow_possible_spam: false)
end
- context 'when recaptcha was verified' do
+ context 'when reCAPTCHA was verified' do
let(:log_user) { user }
let(:spam_logs) { create_list(:spam_log, 2, user: log_user, title: title) }
let(:target_spam_log) { spam_logs.last }
@@ -423,7 +423,7 @@ describe Issues::CreateService do
end
end
- context 'when recaptcha was not verified' do
+ context 'when reCAPTCHA was not verified' do
before do
expect_next_instance_of(Spam::SpamActionService) do |spam_service|
expect(spam_service).to receive_messages(check_for_spam?: true)
diff --git a/spec/services/spam/spam_action_service_spec.rb b/spec/services/spam/spam_action_service_spec.rb
index 8c8685e9628..6c9aaf7e8ae 100644
--- a/spec/services/spam/spam_action_service_spec.rb
+++ b/spec/services/spam/spam_action_service_spec.rb
@@ -85,7 +85,7 @@ describe Spam::SpamActionService do
allow(Spam::SpamVerdictService).to receive(:new).and_return(fake_verdict_service)
end
- context 'when recaptcha was already verified' do
+ context 'when reCAPTCHA was already verified' do
let(:recaptcha_verified) { true }
it "doesn't check with the SpamVerdictService" do
@@ -102,7 +102,7 @@ describe Spam::SpamActionService do
end
end
- context 'when recaptcha was not verified' do
+ context 'when reCAPTCHA was not verified' do
let(:recaptcha_verified) { false }
context 'when spammable attributes have not changed' do