summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-02-14 00:10:09 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-02-14 00:10:09 +0000
commit8aea332821a78e83ce93f5b3bac7de5f95a3c7b8 (patch)
tree722cb345de067f3b62bbe0f849178c74dec657eb
parent4f4b85e1c7f7a5518f12a6981709cf3ef3f0f653 (diff)
downloadgitlab-ce-8aea332821a78e83ce93f5b3bac7de5f95a3c7b8.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo/layout/line_length.yml1
-rw-r--r--.rubocop_todo/style/bare_percent_literals.yml1
-rw-r--r--.rubocop_todo/style/guard_clause.yml1
-rw-r--r--.rubocop_todo/style/if_unless_modifier.yml1
-rw-r--r--.stylelintrc1
-rw-r--r--app/assets/images/select2-spinner.gifbin1849 -> 0 bytes
-rw-r--r--app/assets/images/select2.pngbin613 -> 0 bytes
-rw-r--r--app/assets/images/select2x2.pngbin845 -> 0 bytes
-rw-r--r--app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue2
-rw-r--r--app/assets/javascripts/ml/experiment_tracking/constants.js2
-rw-r--r--app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/components/ml_experiments_index.vue85
-rw-r--r--app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/constants.js17
-rw-r--r--app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/index.js3
-rw-r--r--app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/translations.js11
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/components/table/admin_jobs_table_app.vue19
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/index.js27
-rw-r--r--app/assets/javascripts/pages/dashboard/issues/index.js2
-rw-r--r--app/assets/javascripts/pages/dashboard/merge_requests/index.js2
-rw-r--r--app/assets/javascripts/pages/dashboard/milestones/index/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/edit/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/merge_requests/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/ml/experiments/index/index.js24
-rw-r--r--app/assets/javascripts/pages/projects/project.js8
-rw-r--r--app/assets/javascripts/project_select.js128
-rw-r--r--app/assets/javascripts/project_select_combo_button.js122
-rw-r--r--app/assets/stylesheets/framework/common.scss6
-rw-r--r--app/assets/stylesheets/framework/header.scss5
-rw-r--r--app/assets/stylesheets/framework/secondary_navigation_elements.scss15
-rw-r--r--app/assets/stylesheets/framework/variables.scss6
-rw-r--r--app/assets/stylesheets/lazy_bundles/select2.scss654
-rw-r--r--app/assets/stylesheets/lazy_bundles/select2_overrides.scss341
-rw-r--r--app/assets/stylesheets/pages/issues.scss6
-rw-r--r--app/controllers/admin/jobs_controller.rb4
-rw-r--r--app/controllers/projects/ml/experiments_controller.rb7
-rw-r--r--app/helpers/projects/ml/experiments_helper.rb20
-rw-r--r--app/helpers/selects_helper.rb35
-rw-r--r--app/services/export_csv/base_service.rb18
-rw-r--r--app/services/export_csv/map_export_fields_service.rb40
-rw-r--r--app/services/work_items/export_csv_service.rb26
-rw-r--r--app/views/admin/jobs/index.html.haml34
-rw-r--r--app/views/projects/ml/experiments/index.html.haml16
-rw-r--r--app/views/shared/_new_project_item_select.html.haml9
-rw-r--r--config/application.rb1
-rw-r--r--config/dependency_decisions.yml6
-rw-r--r--config/feature_flags/development/admin_jobs_vue.yml8
-rw-r--r--config/webpack.vendor.config.js1
-rw-r--r--db/docs/scan_result_policies.yml5
-rw-r--r--doc/administration/docs_self_host.md2
-rw-r--r--doc/administration/geo/replication/troubleshooting.md2
-rw-r--r--doc/administration/geo/replication/version_specific_upgrades.md8
-rw-r--r--doc/administration/get_started.md8
-rw-r--r--doc/administration/gitaly/troubleshooting.md14
-rw-r--r--doc/administration/instance_limits.md2
-rw-r--r--doc/administration/object_storage.md10
-rw-r--r--doc/administration/operations/puma.md2
-rw-r--r--doc/administration/reference_architectures/10k_users.md2
-rw-r--r--doc/administration/reference_architectures/25k_users.md2
-rw-r--r--doc/administration/reference_architectures/3k_users.md2
-rw-r--r--doc/administration/reference_architectures/50k_users.md2
-rw-r--r--doc/administration/reference_architectures/5k_users.md2
-rw-r--r--doc/api/graphql/index.md2
-rw-r--r--doc/api/group_releases.md2
-rw-r--r--doc/api/issues.md2
-rw-r--r--doc/api/repositories.md2
-rw-r--r--doc/api/rest/index.md4
-rw-r--r--doc/ci/docker/using_docker_build.md5
-rw-r--r--doc/ci/examples/authenticating-with-hashicorp-vault/index.md2
-rw-r--r--doc/ci/index.md2
-rw-r--r--doc/ci/pipelines/downstream_pipelines.md4
-rw-r--r--doc/ci/pipelines/pipeline_efficiency.md2
-rw-r--r--doc/ci/services/gitlab.md2
-rw-r--r--doc/ci/services/mysql.md2
-rw-r--r--doc/ci/services/postgres.md2
-rw-r--r--doc/ci/testing/code_quality.md4
-rw-r--r--doc/ci/yaml/index.md2
-rw-r--r--doc/cloud_seed/index.md2
-rw-r--r--doc/development/api_graphql_styleguide.md2
-rw-r--r--doc/development/application_slis/rails_request_apdex.md6
-rw-r--r--doc/development/architecture.md5
-rw-r--r--doc/development/cached_queries.md4
-rw-r--r--doc/development/contributing/index.md2
-rw-r--r--doc/development/contributing/merge_request_workflow.md2
-rw-r--r--doc/development/database/migrations_for_multiple_databases.md3
-rw-r--r--doc/development/fe_guide/design_anti_patterns.md4
-rw-r--r--doc/development/fe_guide/view_component.md4
-rw-r--r--doc/development/performance.md4
-rw-r--r--doc/development/ruby3_gotchas.md4
-rw-r--r--doc/development/secure_coding_guidelines.md5
-rw-r--r--doc/development/sidekiq/index.md4
-rw-r--r--doc/development/stage_group_observability/dashboards/stage_group_dashboard.md2
-rw-r--r--doc/development/stage_group_observability/index.md2
-rw-r--r--doc/development/testing_guide/contract/consumer_tests.md4
-rw-r--r--doc/development/testing_guide/contract/provider_tests.md4
-rw-r--r--doc/development/testing_guide/end_to_end/index.md3
-rw-r--r--doc/index.md2
-rw-r--r--doc/install/aws/gitlab_hybrid_on_aws.md2
-rw-r--r--doc/install/aws/manual_install_aws.md4
-rw-r--r--doc/install/azure/index.md4
-rw-r--r--doc/integration/gitpod.md2
-rw-r--r--doc/integration/jira/jira_server_configuration.md2
-rw-r--r--doc/operations/incident_management/incidents.md2
-rw-r--r--doc/operations/incident_management/slack.md2
-rw-r--r--doc/operations/metrics/index.md8
-rw-r--r--doc/subscriptions/gitlab_dedicated/index.md7
-rw-r--r--doc/subscriptions/index.md6
-rw-r--r--doc/subscriptions/self_managed/index.md6
-rw-r--r--doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md2
-rw-r--r--doc/topics/autodevops/requirements.md2
-rw-r--r--doc/topics/autodevops/stages.md28
-rw-r--r--doc/topics/git/lfs/index.md2
-rw-r--r--doc/topics/git/numerous_undo_possibilities_in_git/index.md4
-rw-r--r--doc/topics/offline/quick_start_guide.md2
-rw-r--r--doc/user/admin_area/settings/floc.md2
-rw-r--r--doc/user/application_security/index.md6
-rw-r--r--doc/user/application_security/sast/analyzers.md2
-rw-r--r--doc/user/application_security/sast/index.md2
-rw-r--r--doc/user/award_emojis.md4
-rw-r--r--doc/user/clusters/agent/gitops.md5
-rw-r--r--doc/user/clusters/cost_management.md4
-rw-r--r--doc/user/compliance/compliance_report/index.md6
-rw-r--r--doc/user/crm/index.md2
-rw-r--r--doc/user/gitlab_com/index.md6
-rw-r--r--doc/user/group/compliance_frameworks.md7
-rw-r--r--doc/user/group/epics/linked_epics.md2
-rw-r--r--doc/user/infrastructure/index.md4
-rw-r--r--doc/user/operations_dashboard/index.md2
-rw-r--r--doc/user/packages/container_registry/index.md2
-rw-r--r--doc/user/packages/infrastructure_registry/index.md5
-rw-r--r--doc/user/packages/package_registry/index.md2
-rw-r--r--doc/user/permissions.md4
-rw-r--r--doc/user/product_analytics/index.md2
-rw-r--r--doc/user/profile/preferences.md2
-rw-r--r--doc/user/project/clusters/add_gke_clusters.md4
-rw-r--r--doc/user/project/clusters/add_remove_clusters.md2
-rw-r--r--doc/user/project/clusters/deploy_to_cluster.md2
-rw-r--r--doc/user/project/file_lock.md2
-rw-r--r--doc/user/project/integrations/bugzilla.md4
-rw-r--r--doc/user/project/integrations/ewm.md2
-rw-r--r--doc/user/project/integrations/index.md4
-rw-r--r--doc/user/project/integrations/redmine.md4
-rw-r--r--doc/user/project/integrations/youtrack.md4
-rw-r--r--doc/user/project/issues/managing_issues.md2
-rw-r--r--doc/user/project/issues/related_issues.md4
-rw-r--r--doc/user/project/merge_requests/approvals/settings.md5
-rw-r--r--doc/user/project/merge_requests/reviews/index.md6
-rw-r--r--doc/user/project/merge_requests/status_checks.md4
-rw-r--r--doc/user/project/pages/index.md6
-rw-r--r--doc/user/project/pages/introduction.md6
-rw-r--r--doc/user/project/quick_actions.md4
-rw-r--r--doc/user/project/releases/index.md2
-rw-r--r--doc/user/project/repository/mirror/index.md4
-rw-r--r--doc/user/project/repository/mirror/pull.md2
-rw-r--r--doc/user/project/repository/mirror/push.md2
-rw-r--r--doc/user/project/repository/ssh_signed_commits/index.md4
-rw-r--r--doc/user/project/service_desk.md4
-rw-r--r--doc/user/ssh.md2
-rw-r--r--doc/user/usage_quotas.md2
-rw-r--r--lib/gitlab/database/async_ddl_exclusive_lease_guard.rb (renamed from lib/gitlab/database/indexing_exclusive_lease_guard.rb)6
-rw-r--r--lib/gitlab/database/async_indexes/index_base.rb4
-rw-r--r--lib/gitlab/database/reindexing/coordinator.rb4
-rw-r--r--lib/gitlab/github_import/parallel_scheduling.rb4
-rw-r--r--lib/gitlab/gon_helper.rb1
-rw-r--r--locale/gitlab.pot30
-rw-r--r--package.json1
-rw-r--r--qa/qa/page/component/dropdown.rb33
-rw-r--r--qa/qa/page/component/select2.rb68
-rw-r--r--qa/qa/page/project/import/github.rb2
-rw-r--r--qa/qa/page/project/secure/configuration_form.rb1
-rw-r--r--qa/qa/page/project/settings/main.rb1
-rw-r--r--spec/features/admin/admin_groups_spec.rb1
-rw-r--r--spec/features/admin/admin_jobs_spec.rb1
-rw-r--r--spec/features/projects/import_export/export_file_spec.rb1
-rw-r--r--spec/frontend/fixtures/static/project_select_combo_button.html13
-rw-r--r--spec/frontend/ml/experiment_tracking/routes/experiments/index/components/ml_experiments_index_spec.js110
-rw-r--r--spec/frontend/ml/experiment_tracking/routes/experiments/index/components/mock_data.js21
-rw-r--r--spec/frontend/project_select_combo_button_spec.js165
-rw-r--r--spec/helpers/projects/ml/experiments_helper_spec.rb20
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/references_pipeline_spec.rb2
-rw-r--r--spec/lib/gitlab/database/async_ddl_exclusive_lease_guard_spec.rb40
-rw-r--r--spec/lib/gitlab/database/async_indexes/index_creator_spec.rb2
-rw-r--r--spec/lib/gitlab/database/async_indexes/index_destructor_spec.rb2
-rw-r--r--spec/lib/gitlab/database/indexing_exclusive_lease_guard_spec.rb40
-rw-r--r--spec/lib/gitlab/database/reindexing/coordinator_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/issue_events_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/issues_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/notes_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/protected_branches_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_requests/review_requests_importer_spec.rb6
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/parallel_scheduling_spec.rb12
-rw-r--r--spec/requests/projects/ml/experiments_controller_spec.rb67
-rw-r--r--spec/services/export_csv/map_export_fields_service_spec.rb55
-rw-r--r--spec/services/issues/export_csv_service_spec.rb2
-rw-r--r--spec/services/work_items/export_csv_service_spec.rb67
-rw-r--r--spec/support/helpers/select2_helper.rb57
-rw-r--r--spec/support/shared_examples/services/export_csv/export_csv_invalid_fields_shared_examples.rb13
-rw-r--r--yarn.lock5
200 files changed, 960 insertions, 2050 deletions
diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml
index f8f5c6d6dfa..fab9438da06 100644
--- a/.rubocop_todo/layout/line_length.yml
+++ b/.rubocop_todo/layout/line_length.yml
@@ -3321,7 +3321,6 @@ Layout/LineLength:
- 'qa/qa/git/repository.rb'
- 'qa/qa/page/component/ci_badge_link.rb'
- 'qa/qa/page/component/issuable/sidebar.rb'
- - 'qa/qa/page/component/select2.rb'
- 'qa/qa/page/dashboard/snippet/index.rb'
- 'qa/qa/page/dashboard/todos.rb'
- 'qa/qa/page/group/settings/group_deploy_tokens.rb'
diff --git a/.rubocop_todo/style/bare_percent_literals.yml b/.rubocop_todo/style/bare_percent_literals.yml
index 0380a2e97b8..132f0854700 100644
--- a/.rubocop_todo/style/bare_percent_literals.yml
+++ b/.rubocop_todo/style/bare_percent_literals.yml
@@ -37,7 +37,6 @@ Style/BarePercentLiterals:
- 'qa/qa/ee/page/project/show.rb'
- 'qa/qa/ee/page/project/snippet/index.rb'
- 'qa/qa/ee/page/project/wiki/show.rb'
- - 'qa/qa/page/component/select2.rb'
- 'qa/qa/page/element.rb'
- 'qa/qa/page/file/form.rb'
- 'qa/qa/page/project/web_ide/edit.rb'
diff --git a/.rubocop_todo/style/guard_clause.yml b/.rubocop_todo/style/guard_clause.yml
index 37be7467127..f431211fbfa 100644
--- a/.rubocop_todo/style/guard_clause.yml
+++ b/.rubocop_todo/style/guard_clause.yml
@@ -635,7 +635,6 @@ Style/GuardClause:
- 'qa/qa/mobile/page/main/menu.rb'
- 'qa/qa/mobile/page/sub_menus/common.rb'
- 'qa/qa/page/component/invite_members_modal.rb'
- - 'qa/qa/page/component/select2.rb'
- 'qa/qa/page/component/snippet.rb'
- 'qa/qa/page/mattermost/login.rb'
- 'qa/qa/page/page_concern.rb'
diff --git a/.rubocop_todo/style/if_unless_modifier.yml b/.rubocop_todo/style/if_unless_modifier.yml
index 3794232db31..53414a62874 100644
--- a/.rubocop_todo/style/if_unless_modifier.yml
+++ b/.rubocop_todo/style/if_unless_modifier.yml
@@ -1003,7 +1003,6 @@ Style/IfUnlessModifier:
- 'lib/tasks/gitlab/storage.rake'
- 'lib/tasks/gitlab/update_templates.rake'
- 'qa/qa/ee/resource/settings/elasticsearch.rb'
- - 'qa/qa/page/component/select2.rb'
- 'qa/qa/page/component/snippet.rb'
- 'qa/qa/page/element.rb'
- 'qa/qa/page/mattermost/login.rb'
diff --git a/.stylelintrc b/.stylelintrc
index faab22862fc..ede0ce30d7d 100644
--- a/.stylelintrc
+++ b/.stylelintrc
@@ -4,7 +4,6 @@
"app/assets/stylesheets/pages/emojis.scss",
"app/assets/stylesheets/startup/startup-*.scss",
"ee/app/assets/stylesheets/startup/startup-*.scss",
- "app/assets/stylesheets/lazy_bundles/select2.scss",
"app/assets/stylesheets/highlight/themes/*.scss",
"app/assets/stylesheets/lazy_bundles/cropper.css"
]
diff --git a/app/assets/images/select2-spinner.gif b/app/assets/images/select2-spinner.gif
deleted file mode 100644
index 5b33f7e54f4..00000000000
--- a/app/assets/images/select2-spinner.gif
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/select2.png b/app/assets/images/select2.png
deleted file mode 100644
index 1d804ffb996..00000000000
--- a/app/assets/images/select2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/select2x2.png b/app/assets/images/select2x2.png
deleted file mode 100644
index 4bdd5c961d4..00000000000
--- a/app/assets/images/select2x2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue b/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue
index b13f7dae2c2..1d6a06a08dc 100644
--- a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue
+++ b/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue
@@ -453,7 +453,7 @@ export default {
data-testid="aws-guidance-tip"
@dismiss="dismissTip"
>
- <div class="gl-display-flex gl-flex-direction-row gl-flex-wrap-wrap gl-md-flex-wrap-nowrap">
+ <div class="gl-display-flex gl-flex-direction-row gl-md-flex-wrap-nowraps gl-gap-3">
<div>
<p>
<gl-sprintf :message="$options.i18n.awsTipMessage">
diff --git a/app/assets/javascripts/ml/experiment_tracking/constants.js b/app/assets/javascripts/ml/experiment_tracking/constants.js
index 4092180b988..15462b519e1 100644
--- a/app/assets/javascripts/ml/experiment_tracking/constants.js
+++ b/app/assets/javascripts/ml/experiment_tracking/constants.js
@@ -15,6 +15,8 @@ export const BASE_SORT_FIELDS = Object.freeze([
},
]);
+export const EMPTY_STATE_SVG = '/assets/illustrations/empty-state/empty-dag-md.svg';
+
export const FEATURE_NAME = s__('MlExperimentTracking|Machine learning experiment tracking');
export const FEATURE_FEEDBACK_ISSUE = 'https://gitlab.com/gitlab-org/gitlab/-/issues/381660';
diff --git a/app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/components/ml_experiments_index.vue b/app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/components/ml_experiments_index.vue
new file mode 100644
index 00000000000..4f2b8db3c00
--- /dev/null
+++ b/app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/components/ml_experiments_index.vue
@@ -0,0 +1,85 @@
+<script>
+import { GlTableLite, GlEmptyState, GlLink } from '@gitlab/ui';
+import IncubationAlert from '~/vue_shared/components/incubation/incubation_alert.vue';
+import Pagination from '~/vue_shared/components/incubation/pagination.vue';
+import {
+ FEATURE_NAME,
+ FEATURE_FEEDBACK_ISSUE,
+ EMPTY_STATE_SVG,
+} from '~/ml/experiment_tracking/constants';
+import * as constants from '~/ml/experiment_tracking/routes/experiments/index/constants';
+import * as translations from '~/ml/experiment_tracking/routes/experiments/index/translations';
+
+export default {
+ name: 'MlExperimentsIndexApp',
+ components: {
+ Pagination,
+ IncubationAlert,
+ GlTableLite,
+ GlEmptyState,
+ GlLink,
+ },
+ props: {
+ experiments: {
+ type: Array,
+ required: true,
+ },
+ pageInfo: {
+ type: Object,
+ required: true,
+ },
+ },
+ tableFields: constants.EXPERIMENTS_TABLE_FIELDS,
+ i18n: translations,
+ computed: {
+ hasExperiments() {
+ return this.experiments.length > 0;
+ },
+ tableItems() {
+ return this.experiments.map((exp) => ({
+ nameColumn: { name: exp.name, path: exp.path },
+ candidateCountColumn: exp.candidate_count,
+ }));
+ },
+ },
+ constants: {
+ FEATURE_NAME,
+ FEATURE_FEEDBACK_ISSUE,
+ EMPTY_STATE_SVG,
+ ...constants,
+ },
+};
+</script>
+
+<template>
+ <div v-if="hasExperiments">
+ <h1 class="page-title gl-font-size-h-display">
+ {{ $options.i18n.TITLE_LABEL }}
+ </h1>
+
+ <incubation-alert
+ :feature-name="$options.constants.FEATURE_NAME"
+ :link-to-feedback-issue="$options.constants.FEATURE_FEEDBACK_ISSUE"
+ />
+
+ <gl-table-lite :items="tableItems" :fields="$options.tableFields">
+ <template #cell(nameColumn)="data">
+ <gl-link :href="data.value.path">
+ {{ data.value.name }}
+ </gl-link>
+ </template>
+ </gl-table-lite>
+
+ <pagination v-if="hasExperiments" v-bind="pageInfo" />
+ </div>
+
+ <gl-empty-state
+ v-else
+ :title="$options.i18n.EMPTY_STATE_TITLE_LABEL"
+ :primary-button-text="$options.i18n.CREATE_NEW_LABEL"
+ :primary-button-link="$options.constants.CREATE_EXPERIMENT_HELP_PATH"
+ :svg-path="$options.constants.EMPTY_STATE_SVG"
+ :description="$options.i18n.EMPTY_STATE_DESCRIPTION_LABEL"
+ class="gl-py-8"
+ />
+</template>
diff --git a/app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/constants.js b/app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/constants.js
new file mode 100644
index 00000000000..3026bce0972
--- /dev/null
+++ b/app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/constants.js
@@ -0,0 +1,17 @@
+import { s__ } from '~/locale';
+import { helpPagePath } from '~/helpers/help_page_helper';
+
+export const CREATE_EXPERIMENT_HELP_PATH = helpPagePath(
+ 'user/project/ml/experiment_tracking/index.md',
+ {
+ anchor: 'tracking-new-experiments-and-trials',
+ },
+);
+
+export const EXPERIMENTS_TABLE_FIELDS = Object.freeze([
+ { key: 'nameColumn', label: s__('MlExperimentTracking|Experiment') },
+ {
+ key: 'candidateCountColumn',
+ label: s__('MlExperimentTracking|Logged candidates for experiment'),
+ },
+]);
diff --git a/app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/index.js b/app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/index.js
new file mode 100644
index 00000000000..b40735ebe22
--- /dev/null
+++ b/app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/index.js
@@ -0,0 +1,3 @@
+import MlExperimentsIndex from './components/ml_experiments_index.vue';
+
+export default MlExperimentsIndex;
diff --git a/app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/translations.js b/app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/translations.js
new file mode 100644
index 00000000000..e954c054cf5
--- /dev/null
+++ b/app/assets/javascripts/ml/experiment_tracking/routes/experiments/index/translations.js
@@ -0,0 +1,11 @@
+import { s__ } from '~/locale';
+
+export const TITLE_LABEL = s__('MlExperimentTracking|Model experiments');
+
+export const CREATE_NEW_LABEL = s__('MlExperimentTracking|Create a new experiment');
+
+export const EMPTY_STATE_TITLE_LABEL = s__('MlExperimentTracking|No experiments');
+
+export const EMPTY_STATE_DESCRIPTION_LABEL = s__(
+ 'MlExperimentTracking|There are no logged experiments for this project. Create a new experiment using the MLflow client.',
+);
diff --git a/app/assets/javascripts/pages/admin/application_settings/index.js b/app/assets/javascripts/pages/admin/application_settings/index.js
index f1e92cf195a..366be334e87 100644
--- a/app/assets/javascripts/pages/admin/application_settings/index.js
+++ b/app/assets/javascripts/pages/admin/application_settings/index.js
@@ -1,5 +1,4 @@
import initVariableList from '~/ci/ci_variable_list';
-import projectSelect from '~/project_select';
import initSearchSettings from '~/search_settings';
import selfMonitor from '~/self_monitor';
import initSettingsPanels from '~/settings_panels';
@@ -8,5 +7,4 @@ initVariableList('js-instance-variables');
selfMonitor();
// Initialize expandable settings panels
initSettingsPanels();
-projectSelect();
initSearchSettings();
diff --git a/app/assets/javascripts/pages/admin/jobs/index/components/table/admin_jobs_table_app.vue b/app/assets/javascripts/pages/admin/jobs/index/components/table/admin_jobs_table_app.vue
new file mode 100644
index 00000000000..c5a0509b625
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/jobs/index/components/table/admin_jobs_table_app.vue
@@ -0,0 +1,19 @@
+<script>
+export default {
+ inject: {
+ jobStatuses: {
+ default: null,
+ },
+ url: {
+ default: '',
+ },
+ emptyStateSvgPath: {
+ default: '',
+ },
+ },
+};
+</script>
+
+<template>
+ <div>{{ __('Jobs') }}</div>
+</template>
diff --git a/app/assets/javascripts/pages/admin/jobs/index/index.js b/app/assets/javascripts/pages/admin/jobs/index/index.js
index f9bc097da4c..9df52557212 100644
--- a/app/assets/javascripts/pages/admin/jobs/index/index.js
+++ b/app/assets/javascripts/pages/admin/jobs/index/index.js
@@ -3,6 +3,7 @@ import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import Translate from '~/vue_shared/translate';
import { CANCEL_JOBS_MODAL_ID } from './components/constants';
import CancelJobsModal from './components/cancel_jobs_modal.vue';
+import AdminJobsTableApp from './components/table/admin_jobs_table_app.vue';
Vue.use(Translate);
@@ -34,4 +35,28 @@ function initJobs() {
}
}
-initJobs();
+export function initAdminJobsApp() {
+ const containerEl = document.getElementById('admin-jobs-app');
+
+ if (!containerEl) return false;
+
+ const { jobStatuses, emptyStateSvgPath, url } = containerEl.dataset;
+
+ return new Vue({
+ el: containerEl,
+ provide: {
+ url,
+ emptyStateSvgPath,
+ jobStatuses: JSON.parse(jobStatuses),
+ },
+ render(createElement) {
+ return createElement(AdminJobsTableApp);
+ },
+ });
+}
+
+if (gon.features.adminJobsVue) {
+ initAdminJobsApp();
+} else {
+ initJobs();
+}
diff --git a/app/assets/javascripts/pages/dashboard/issues/index.js b/app/assets/javascripts/pages/dashboard/issues/index.js
index 659982fcc3a..2ca11e96f69 100644
--- a/app/assets/javascripts/pages/dashboard/issues/index.js
+++ b/app/assets/javascripts/pages/dashboard/issues/index.js
@@ -3,7 +3,6 @@ import { mountIssuesDashboardApp } from '~/issues/dashboard';
import initManualOrdering from '~/issues/manual_ordering';
import { FILTERED_SEARCH } from '~/filtered_search/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
-import projectSelect from '~/project_select';
import { initNewResourceDropdown } from '~/vue_shared/components/new_resource_dropdown/init_new_resource_dropdown';
initFilteredSearch({
@@ -12,7 +11,6 @@ initFilteredSearch({
useDefaultState: true,
});
-projectSelect();
initNewResourceDropdown();
initManualOrdering();
diff --git a/app/assets/javascripts/pages/dashboard/merge_requests/index.js b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
index f86dc2e2e30..a8c59ea6f3d 100644
--- a/app/assets/javascripts/pages/dashboard/merge_requests/index.js
+++ b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
@@ -2,7 +2,6 @@ import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/filtered_search/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
-import projectSelect from '~/project_select';
import { initNewResourceDropdown } from '~/vue_shared/components/new_resource_dropdown/init_new_resource_dropdown';
import { RESOURCE_TYPE_MERGE_REQUEST } from '~/vue_shared/components/new_resource_dropdown/constants';
import searchUserProjectsWithMergeRequestsEnabled from '~/vue_shared/components/new_resource_dropdown/graphql/search_user_projects_with_merge_requests_enabled.query.graphql';
@@ -15,7 +14,6 @@ initFilteredSearch({
useDefaultState: true,
});
-projectSelect();
initNewResourceDropdown({
resourceType: RESOURCE_TYPE_MERGE_REQUEST,
query: searchUserProjectsWithMergeRequestsEnabled,
diff --git a/app/assets/javascripts/pages/dashboard/milestones/index/index.js b/app/assets/javascripts/pages/dashboard/milestones/index/index.js
index 951941cc83d..88061d9ca22 100644
--- a/app/assets/javascripts/pages/dashboard/milestones/index/index.js
+++ b/app/assets/javascripts/pages/dashboard/milestones/index/index.js
@@ -1,9 +1,7 @@
-import projectSelect from '~/project_select';
import { initNewResourceDropdown } from '~/vue_shared/components/new_resource_dropdown/init_new_resource_dropdown';
import { RESOURCE_TYPE_MILESTONE } from '~/vue_shared/components/new_resource_dropdown/constants';
import searchUserGroupsAndProjects from '~/vue_shared/components/new_resource_dropdown/graphql/search_user_groups_and_projects.query.graphql';
-projectSelect();
initNewResourceDropdown({
resourceType: RESOURCE_TYPE_MILESTONE,
query: searchUserGroupsAndProjects,
diff --git a/app/assets/javascripts/pages/groups/edit/index.js b/app/assets/javascripts/pages/groups/edit/index.js
index 91a0ef07bc4..dec06fe6f4d 100644
--- a/app/assets/javascripts/pages/groups/edit/index.js
+++ b/app/assets/javascripts/pages/groups/edit/index.js
@@ -6,7 +6,6 @@ import { initGroupSelects } from '~/vue_shared/components/entity_select/init_gro
import { initProjectSelects } from '~/vue_shared/components/entity_select/init_project_selects';
import { initCascadingSettingsLockPopovers } from '~/namespaces/cascading_settings';
import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
-import projectSelect from '~/project_select';
import initSearchSettings from '~/search_settings';
import initSettingsPanels from '~/settings_panels';
import initConfirmDanger from '~/init_confirm_danger';
@@ -26,7 +25,5 @@ initGroupSelects();
// Initialize project selectors
initProjectSelects();
-projectSelect();
-
initSearchSettings();
initCascadingSettingsLockPopovers();
diff --git a/app/assets/javascripts/pages/groups/merge_requests/index.js b/app/assets/javascripts/pages/groups/merge_requests/index.js
index 40b4c289ab0..2cf75fcf666 100644
--- a/app/assets/javascripts/pages/groups/merge_requests/index.js
+++ b/app/assets/javascripts/pages/groups/merge_requests/index.js
@@ -3,7 +3,6 @@ import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered
import { FILTERED_SEARCH } from '~/filtered_search/constants';
import { initBulkUpdateSidebar } from '~/issuable';
import initFilteredSearch from '~/pages/search/init_filtered_search';
-import projectSelect from '~/project_select';
import { initNewResourceDropdown } from '~/vue_shared/components/new_resource_dropdown/init_new_resource_dropdown';
import { RESOURCE_TYPE_MERGE_REQUEST } from '~/vue_shared/components/new_resource_dropdown/constants';
import searchUserGroupProjectsWithMergeRequestsEnabled from '~/vue_shared/components/new_resource_dropdown/graphql/search_user_group_projects_with_merge_requests_enabled.query.graphql';
@@ -19,7 +18,6 @@ initFilteredSearch({
useDefaultState: true,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
});
-projectSelect();
initNewResourceDropdown({
resourceType: RESOURCE_TYPE_MERGE_REQUEST,
query: searchUserGroupProjectsWithMergeRequestsEnabled,
diff --git a/app/assets/javascripts/pages/projects/ml/experiments/index/index.js b/app/assets/javascripts/pages/projects/ml/experiments/index/index.js
new file mode 100644
index 00000000000..e9ffd4b528b
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/ml/experiments/index/index.js
@@ -0,0 +1,24 @@
+import Vue from 'vue';
+import MlExperimentsIndex from '~/ml/experiment_tracking/routes/experiments/index';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+
+const initIndexMlExperiments = () => {
+ const element = document.querySelector('#js-project-ml-experiments-index');
+ if (!element) {
+ return undefined;
+ }
+
+ const props = {
+ experiments: JSON.parse(element.dataset.experiments),
+ pageInfo: convertObjectPropsToCamelCase(JSON.parse(element.dataset.pageInfo)),
+ };
+
+ return new Vue({
+ el: element,
+ render(h) {
+ return h(MlExperimentsIndex, { props });
+ },
+ });
+};
+
+initIndexMlExperiments();
diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js
index 4c9eb830ff6..5773737c41b 100644
--- a/app/assets/javascripts/pages/projects/project.js
+++ b/app/assets/javascripts/pages/projects/project.js
@@ -9,7 +9,6 @@ import axios from '~/lib/utils/axios_utils';
import { serializeForm } from '~/lib/utils/forms';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
-import projectSelect from '~/project_select';
const BRANCH_REF_TYPE = 'heads';
const TAG_REF_TYPE = 'tags';
@@ -44,13 +43,6 @@ export default class Project {
$(this).parents('.auto-devops-implicitly-enabled-banner').remove();
return e.preventDefault();
});
-
- Project.projectSelectDropdown();
- }
-
- static projectSelectDropdown() {
- projectSelect();
- $('.project-item-select').on('click', (e) => Project.changeProject($(e.currentTarget).val()));
}
static changeProject(url) {
diff --git a/app/assets/javascripts/project_select.js b/app/assets/javascripts/project_select.js
deleted file mode 100644
index 705234537a8..00000000000
--- a/app/assets/javascripts/project_select.js
+++ /dev/null
@@ -1,128 +0,0 @@
-/* eslint-disable func-names */
-
-import $ from 'jquery';
-import { createAlert } from '~/flash';
-import Api from './api';
-import { loadCSSFile } from './lib/utils/css_utils';
-import { s__ } from './locale';
-import ProjectSelectComboButton from './project_select_combo_button';
-
-const projectSelect = async () => {
- await loadCSSFile(gon.select2_css_path);
-
- $('.ajax-project-select').each(function (i, select) {
- let placeholder;
- const simpleFilter = $(select).data('simpleFilter') || false;
- const isInstantiated = $(select).data('select2');
- this.groupId = $(select).data('groupId');
- this.userId = $(select).data('userId');
- this.includeGroups = $(select).data('includeGroups');
- this.allProjects = $(select).data('allProjects') || false;
- this.orderBy = $(select).data('orderBy') || 'id';
- this.withIssuesEnabled = $(select).data('withIssuesEnabled');
- this.withMergeRequestsEnabled = $(select).data('withMergeRequestsEnabled');
- this.withShared =
- $(select).data('withShared') === undefined ? true : $(select).data('withShared');
- this.includeProjectsInSubgroups = $(select).data('includeProjectsInSubgroups') || false;
- this.allowClear = $(select).data('allowClear') || false;
-
- placeholder = s__('ProjectSelect|Search for project');
- if (this.includeGroups) {
- placeholder += s__('ProjectSelect| or group');
- }
-
- $(select).select2({
- placeholder,
- minimumInputLength: 0,
- query: (query) => {
- let projectsCallback;
- const finalCallback = function (projects) {
- const data = {
- results: projects,
- };
- return query.callback(data);
- };
- if (this.includeGroups) {
- projectsCallback = function (projects) {
- const groupsCallback = function (groups) {
- const data = groups.concat(projects);
- return finalCallback(data);
- };
- return Api.groups(query.term, {}, groupsCallback);
- };
- } else {
- projectsCallback = finalCallback;
- }
- if (this.groupId) {
- return Api.groupProjects(
- this.groupId,
- query.term,
- {
- with_issues_enabled: this.withIssuesEnabled,
- with_merge_requests_enabled: this.withMergeRequestsEnabled,
- with_shared: this.withShared,
- include_subgroups: this.includeProjectsInSubgroups,
- order_by: 'similarity',
- simple: true,
- },
- projectsCallback,
- ).catch(() => {
- createAlert({
- message: s__('ProjectSelect|Something went wrong while fetching projects'),
- });
- });
- } else if (this.userId) {
- return Api.userProjects(
- this.userId,
- query.term,
- {
- with_issues_enabled: this.withIssuesEnabled,
- with_merge_requests_enabled: this.withMergeRequestsEnabled,
- with_shared: this.withShared,
- include_subgroups: this.includeProjectsInSubgroups,
- },
- projectsCallback,
- );
- }
- return Api.projects(
- query.term,
- {
- order_by: this.orderBy,
- with_issues_enabled: this.withIssuesEnabled,
- with_merge_requests_enabled: this.withMergeRequestsEnabled,
- membership: !this.allProjects,
- },
- projectsCallback,
- );
- },
- id(project) {
- if (simpleFilter) return project.id;
- return JSON.stringify({
- name: project.name,
- url: project.web_url,
- });
- },
- text(project) {
- return project.name_with_namespace || project.name;
- },
-
- initSelection(el, callback) {
- return Api.project(el.val()).then(({ data }) => callback(data));
- },
-
- allowClear: this.allowClear,
-
- dropdownCssClass: 'ajax-project-dropdown',
- });
- if (isInstantiated || simpleFilter) return select;
- return new ProjectSelectComboButton(select);
- });
-};
-
-export default () => {
- if ($('.ajax-project-select').length) {
- import(/* webpackChunkName: 'select2' */ 'select2/select2')
- .then(projectSelect)
- .catch(() => {});
- }
-};
diff --git a/app/assets/javascripts/project_select_combo_button.js b/app/assets/javascripts/project_select_combo_button.js
deleted file mode 100644
index ad80032c551..00000000000
--- a/app/assets/javascripts/project_select_combo_button.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import $ from 'jquery';
-import { sprintf, __ } from '~/locale';
-import { sanitizeUrl } from '~/lib/utils/url_utility';
-import AccessorUtilities from './lib/utils/accessor';
-import { loadCSSFile } from './lib/utils/css_utils';
-
-export default class ProjectSelectComboButton {
- constructor(select) {
- this.projectSelectInput = $(select);
- this.newItemBtn = $('.js-new-project-item-link');
- this.resourceType = this.newItemBtn.data('type');
- this.resourceLabel = this.newItemBtn.data('label');
- this.formattedText = this.deriveTextVariants();
- this.groupId = this.projectSelectInput.data('groupId');
- this.bindEvents();
- this.initLocalStorage();
- }
-
- bindEvents() {
- this.projectSelectInput
- .siblings('.new-project-item-select-button')
- .on('click', (e) => this.openDropdown(e));
-
- this.newItemBtn.on('click', (e) => {
- if (!this.getProjectFromLocalStorage()) {
- e.preventDefault();
- this.openDropdown(e);
- }
- });
-
- this.projectSelectInput.on('change', () => this.selectProject());
- }
-
- initLocalStorage() {
- const localStorageIsSafe = AccessorUtilities.canUseLocalStorage();
-
- if (localStorageIsSafe) {
- this.localStorageKey = [
- 'group',
- this.groupId,
- this.formattedText.localStorageItemType,
- 'recent-project',
- ].join('-');
- this.setBtnTextFromLocalStorage();
- }
- }
-
- // eslint-disable-next-line class-methods-use-this
- openDropdown(event) {
- import(/* webpackChunkName: 'select2' */ 'select2/select2')
- .then(() => {
- // eslint-disable-next-line promise/no-nesting
- loadCSSFile(gon.select2_css_path)
- .then(() => {
- $(event.currentTarget).siblings('.project-item-select').select2('open');
- })
- .catch(() => {});
- })
- .catch(() => {});
- }
-
- selectProject() {
- const selectedProjectData = JSON.parse(this.projectSelectInput.val());
- const projectUrl = `${selectedProjectData.url}/${this.projectSelectInput.data('relativePath')}`;
- const projectName = selectedProjectData.name;
-
- const projectMeta = {
- url: projectUrl,
- name: projectName,
- };
-
- this.setNewItemBtnAttributes(projectMeta);
- this.setProjectInLocalStorage(projectMeta);
- }
-
- setBtnTextFromLocalStorage() {
- const cachedProjectData = this.getProjectFromLocalStorage();
-
- this.setNewItemBtnAttributes(cachedProjectData);
- }
-
- setNewItemBtnAttributes(project) {
- if (project) {
- this.newItemBtn.attr('href', sanitizeUrl(project.url));
- this.newItemBtn.text(
- sprintf(__('New %{type} in %{project}'), {
- type: this.resourceLabel,
- project: project.name,
- }),
- );
- } else {
- this.newItemBtn.text(
- sprintf(__('Select project to create %{type}'), {
- type: this.formattedText.presetTextSuffix,
- }),
- );
- }
- }
-
- getProjectFromLocalStorage() {
- const projectString = localStorage.getItem(this.localStorageKey);
-
- return JSON.parse(projectString);
- }
-
- setProjectInLocalStorage(projectMeta) {
- const projectString = JSON.stringify(projectMeta);
-
- localStorage.setItem(this.localStorageKey, projectString);
- }
-
- deriveTextVariants() {
- // the trailing slice call depluralizes each of these strings (e.g. new-issues -> new-issue)
- const localStorageItemType = `new-${this.resourceType.split('_').join('-').slice(0, -1)}`;
- const presetTextSuffix = this.resourceType.split('_').join(' ').slice(0, -1);
-
- return {
- localStorageItemType, // new-issue / new-merge-request
- presetTextSuffix, // issue / merge request
- };
- }
-}
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 0bc920b1f73..cc7a45e1c82 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -301,12 +301,6 @@ img.emoji {
height: 4px;
}
-.project-item-select-holder {
- .project-item-select {
- min-width: 250px;
- }
-}
-
.gl-accessibility {
&:focus {
display: flex;
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index a131ab667e1..7baf84198e4 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -63,11 +63,6 @@ $search-input-field-x-min-width: 200px;
@include gl-focus($focus-ring: $focus-ring-dark);
}
}
-
- .project-item-select {
- right: auto;
- left: 0;
- }
}
.dropdown.open {
diff --git a/app/assets/stylesheets/framework/secondary_navigation_elements.scss b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
index 7e0a601223d..5ba0b1d0828 100644
--- a/app/assets/stylesheets/framework/secondary_navigation_elements.scss
+++ b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
@@ -179,11 +179,6 @@
display: inline-block;
}
- .project-item-select-holder {
- margin: 0;
- width: 100%;
- }
-
&.inline {
display: flex;
flex-flow: row wrap;
@@ -367,13 +362,3 @@
}
}
}
-
-.project-item-select-holder.btn-group {
- .new-project-item-select-button {
- max-width: 32px;
- }
-}
-
-.empty-state .project-item-select-holder.btn-group {
- max-width: 320px;
-}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index f136a8c3a08..c616915073e 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -788,12 +788,6 @@ $stat-graph-selection-fill: #333;
$stat-graph-selection-stroke: #333;
/*
-* Selects
-*/
-$select2-drop-shadow1: rgba(76, 86, 103, 0.247059);
-$select2-drop-shadow2: rgba(31, 37, 50, 0.317647);
-
-/*
* Typography
*/
$body-text-shadow: rgba(255, 255, 255, 0.01);
diff --git a/app/assets/stylesheets/lazy_bundles/select2.scss b/app/assets/stylesheets/lazy_bundles/select2.scss
deleted file mode 100644
index f2c372020ef..00000000000
--- a/app/assets/stylesheets/lazy_bundles/select2.scss
+++ /dev/null
@@ -1,654 +0,0 @@
-/*
-Version: 3.5.2 Timestamp: Sat Nov 1 14:43:36 EDT 2014
-Updated 2020-10-05 by TimZ
-*/
-.select2-container {
- margin: 0;
- position: relative;
- display: inline-block;
-}
-
-.select2-container,
-.select2-drop,
-.select2-search,
-.select2-search input {
- box-sizing: border-box;
-}
-
-.select2-container .select2-choice {
- display: block;
- height: 26px;
- padding: 0 0 0 8px;
- overflow: hidden;
- position: relative;
-
- border: 1px solid #aaa;
- white-space: nowrap;
- line-height: 26px;
- color: #444;
- text-decoration: none;
-
- border-radius: 4px;
-
- background-clip: padding-box;
-
- user-select: none;
-
- background-color: #fff;
- background-image: linear-gradient(to top, #eee 0%, #fff 50%);
-}
-
-html[dir='rtl'] .select2-container .select2-choice {
- padding: 0 8px 0 0;
-}
-
-.select2-container.select2-drop-above .select2-choice {
- border-bottom-color: #aaa;
-
- border-radius: 0 0 4px 4px;
-
- background-image: linear-gradient(to bottom, #eee 0%, #fff 90%);
-}
-
-.select2-container.select2-allowclear .select2-choice .select2-chosen {
- margin-right: 42px;
-}
-
-.select2-container .select2-choice > .select2-chosen {
- margin-right: 26px;
- display: block;
- overflow: hidden;
-
- white-space: nowrap;
-
- text-overflow: ellipsis;
- float: none;
- width: auto;
-}
-
-html[dir='rtl'] .select2-container .select2-choice > .select2-chosen {
- margin-left: 26px;
- margin-right: 0;
-}
-
-.select2-container .select2-choice abbr {
- display: none;
- width: 12px;
- height: 12px;
- position: absolute;
- right: 24px;
- top: 8px;
-
- font-size: 1px;
- text-decoration: none;
-
- border: 0;
- /* stylelint-disable-next-line function-url-quotes */
- background: url(image-path('select2.png')) right top no-repeat;
- cursor: pointer;
- outline: 0;
-}
-
-.select2-container.select2-allowclear .select2-choice abbr {
- display: inline-block;
-}
-
-.select2-container .select2-choice abbr:hover {
- background-position: right -11px;
- cursor: pointer;
-}
-
-.select2-drop-mask {
- border: 0;
- margin: 0;
- padding: 0;
- position: fixed;
- left: 0;
- top: 0;
- min-height: 100%;
- min-width: 100%;
- height: auto;
- width: auto;
- opacity: 0;
- z-index: 9998;
- /* styles required for IE to work */
- background-color: #fff;
- filter: alpha(opacity=0);
-}
-
-.select2-drop {
- width: 100%;
- margin-top: -1px;
- position: absolute;
- z-index: 9999;
- top: 100%;
-
- background: #fff;
- color: #000;
- border: 1px solid #aaa;
- border-top: 0;
-
- border-radius: 0 0 4px 4px;
-
- box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15);
-}
-
-.select2-drop.select2-drop-above {
- margin-top: 1px;
- border-top: 1px solid #aaa;
- border-bottom: 0;
-
- border-radius: 4px 4px 0 0;
-
- box-shadow: 0 -4px 5px rgba(0, 0, 0, 0.15);
-}
-
-.select2-drop-active {
- border: 1px solid #5897fb;
- border-top: 0;
-}
-
-.select2-drop.select2-drop-above.select2-drop-active {
- border-top: 1px solid #5897fb;
-}
-
-.select2-drop-auto-width {
- border-top: 1px solid #aaa;
- width: auto;
-}
-
-.select2-drop-auto-width .select2-search {
- padding-top: 4px;
-}
-
-.select2-container .select2-choice .select2-arrow {
- display: inline-block;
- width: 18px;
- height: 100%;
- position: absolute;
- right: 0;
- top: 0;
-
- border-left: 1px solid #aaa;
- border-radius: 0 4px 4px 0;
-
- background-clip: padding-box;
-
- background: #ccc;
- background-image: linear-gradient(to top, #ccc 0%, #eee 60%);
-}
-
-html[dir='rtl'] .select2-container .select2-choice .select2-arrow {
- left: 0;
- right: auto;
-
- border-left: 0;
- border-right: 1px solid #aaa;
- border-radius: 4px 0 0 4px;
-}
-
-.select2-container .select2-choice .select2-arrow b {
- display: block;
- width: 100%;
- height: 100%;
- /* stylelint-disable-next-line function-url-quotes */
- background: url(image-path("select2.png")) no-repeat 0 1px;
-}
-
-html[dir='rtl'] .select2-container .select2-choice .select2-arrow b {
- background-position: 2px 1px;
-}
-
-.select2-search {
- display: inline-block;
- width: 100%;
- min-height: 26px;
- margin: 0;
- padding-left: 4px;
- padding-right: 4px;
-
- position: relative;
- z-index: 10000;
-
- white-space: nowrap;
-}
-
-.select2-search input {
- width: 100%;
- height: auto !important;
- min-height: 26px;
- padding: 4px 20px 4px 5px;
- margin: 0;
-
- outline: 0;
- font-family: sans-serif;
- font-size: 1em;
-
- border: 1px solid #aaa;
- border-radius: 0;
-
- box-shadow: none;
- /* stylelint-disable-next-line function-url-quotes */
- background: url(image-path('select2.png')) no-repeat 100% -22px, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0;
-}
-
-html[dir='rtl'] .select2-search input {
- padding: 4px 5px 4px 20px;
- /* stylelint-disable-next-line function-url-quotes */
- background: url(image-path('select2.png')) no-repeat -37px -22px, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0;
-}
-
-.select2-drop.select2-drop-above .select2-search input {
- margin-top: 4px;
-}
-
-.select2-search input.select2-active {
- /* stylelint-disable-next-line function-url-quotes */
- background: url(image-path('select2-spinner.gif')) no-repeat 100%, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0;
-}
-
-.select2-container-active .select2-choice,
-.select2-container-active .select2-choices {
- border: 1px solid #5897fb;
- outline: none;
-
- box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
-}
-
-.select2-dropdown-open .select2-choice {
- border-bottom-color: transparent;
- box-shadow: 0 1px 0 #fff inset;
-
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
-
- background-color: #eee;
- background-image: linear-gradient(to top, #fff 0%, #eee 50%);
-}
-
-.select2-dropdown-open.select2-drop-above .select2-choice,
-.select2-dropdown-open.select2-drop-above .select2-choices {
- border: 1px solid #5897fb;
- border-top-color: transparent;
-
- background-image: linear-gradient(to bottom, #fff 0%, #eee 50%);
-}
-
-.select2-dropdown-open .select2-choice .select2-arrow {
- background: transparent;
- border-left: 0;
- filter: none;
-}
-
-html[dir='rtl'] .select2-dropdown-open .select2-choice .select2-arrow {
- border-right: 0;
-}
-
-.select2-dropdown-open .select2-choice .select2-arrow b {
- background-position: -18px 1px;
-}
-
-html[dir='rtl'] .select2-dropdown-open .select2-choice .select2-arrow b {
- background-position: -16px 1px;
-}
-
-.select2-hidden-accessible {
- border: 0;
- clip: rect(0 0 0 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- width: 1px;
-}
-
-/* results */
-.select2-results {
- max-height: 200px;
- padding: 0 0 0 4px;
- margin: 4px 4px 4px 0;
- position: relative;
- overflow-x: hidden;
- overflow-y: auto;
-}
-
-html[dir='rtl'] .select2-results {
- padding: 0 4px 0 0;
- margin: 4px 0 4px 4px;
-}
-
-.select2-results ul.select2-result-sub {
- margin: 0;
- padding-left: 0;
-}
-
-.select2-results li {
- list-style: none;
- display: list-item;
- background-image: none;
-}
-
-.select2-results li.select2-result-with-children > .select2-result-label {
- font-weight: bold;
-}
-
-.select2-results .select2-result-label {
- padding: 3px 7px 4px;
- margin: 0;
- cursor: pointer;
-
- min-height: 1em;
-
- user-select: none;
-}
-
-.select2-results-dept-1 .select2-result-label { padding-left: 20px; }
-.select2-results-dept-2 .select2-result-label { padding-left: 40px; }
-.select2-results-dept-3 .select2-result-label { padding-left: 60px; }
-.select2-results-dept-4 .select2-result-label { padding-left: 80px; }
-.select2-results-dept-5 .select2-result-label { padding-left: 100px; }
-.select2-results-dept-6 .select2-result-label { padding-left: 110px; }
-.select2-results-dept-7 .select2-result-label { padding-left: 120px; }
-
-.select2-results .select2-highlighted {
- background: #3875d7;
- color: #fff;
-}
-
-.select2-results li em {
- background: #feffde;
- font-style: normal;
-}
-
-.select2-results .select2-highlighted em {
- background: transparent;
-}
-
-.select2-results .select2-highlighted ul {
- background: #fff;
- color: #000;
-}
-
-.select2-results .select2-no-results,
-.select2-results .select2-searching,
-.select2-results .select2-ajax-error,
-.select2-results .select2-selection-limit {
- background: #f4f4f4;
- display: list-item;
- padding-left: 5px;
-}
-
-/*
-disabled look for disabled choices in the results dropdown
-*/
-.select2-results .select2-disabled.select2-highlighted {
- color: #666;
- background: #f4f4f4;
- display: list-item;
- cursor: default;
-}
-
-.select2-results .select2-disabled {
- background: #f4f4f4;
- display: list-item;
- cursor: default;
-}
-
-.select2-results .select2-selected {
- display: none;
-}
-
-.select2-more-results.select2-active {
- /* stylelint-disable-next-line function-url-quotes */
- background: #f4f4f4 url(image-path('select2-spinner.gif')) no-repeat 100%;
-}
-
-.select2-results .select2-ajax-error {
- background: rgba(255, 50, 50, 0.2);
-}
-
-.select2-more-results {
- background: #f4f4f4;
- display: list-item;
-}
-
-/* disabled styles */
-
-.select2-container.select2-container-disabled .select2-choice {
- background-color: #f4f4f4;
- background-image: none;
- border: 1px solid #ddd;
- cursor: default;
-}
-
-.select2-container.select2-container-disabled .select2-choice .select2-arrow {
- background-color: #f4f4f4;
- background-image: none;
- border-left: 0;
-}
-
-.select2-container.select2-container-disabled .select2-choice abbr {
- display: none;
-}
-
-
-/* multiselect */
-
-.select2-container-multi .select2-choices {
- height: auto !important;
- height: 1%;
- margin: 0;
- padding: 0 5px 0 0;
- position: relative;
-
- border: 1px solid #aaa;
- cursor: text;
- overflow: hidden;
-
- background-color: #fff;
- background-image: linear-gradient(to bottom, #eee 1%, #fff 15%);
-}
-
-html[dir='rtl'] .select2-container-multi .select2-choices {
- padding: 0 0 0 5px;
-}
-
-.select2-locked {
- padding: 3px 5px !important;
-}
-
-.select2-container-multi .select2-choices {
- min-height: 26px;
-}
-
-.select2-container-multi.select2-container-active .select2-choices {
- border: 1px solid #5897fb;
- outline: none;
-
- box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
-}
-
-.select2-container-multi .select2-choices li {
- float: left;
- list-style: none;
-}
-
-html[dir='rtl'] .select2-container-multi .select2-choices li {
- float: right;
-}
-
-.select2-container-multi .select2-choices .select2-search-field {
- margin: 0;
- padding: 0;
- white-space: nowrap;
-}
-
-.select2-container-multi .select2-choices .select2-search-field input {
- padding: 5px;
- margin: 1px 0;
-
- font-family: sans-serif;
- font-size: 100%;
- color: #666;
- outline: 0;
- border: 0;
-
- box-shadow: none;
- background: transparent !important;
-}
-
-.select2-container-multi .select2-choices .select2-search-field input.select2-active {
- /* stylelint-disable-next-line function-url-quotes */
- background: #fff url(image-path('select2-spinner.gif')) no-repeat 100% !important;
-}
-
-.select2-default {
- color: #999 !important;
-}
-
-.select2-container-multi .select2-choices .select2-search-choice {
- padding: 3px 5px 3px 18px;
- margin: 3px 0 3px 5px;
- position: relative;
-
- line-height: 13px;
- color: #333;
- cursor: default;
- border: 1px solid #aaa;
-
- border-radius: 3px;
-
- box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
-
- background-clip: padding-box;
-
- user-select: none;
-
- background-color: #e4e4e4;
- background-image: linear-gradient(to bottom, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
-}
-
-html[dir='rtl'] .select2-container-multi .select2-choices .select2-search-choice {
- margin: 3px 5px 3px 0;
- padding: 3px 18px 3px 5px;
-}
-
-.select2-container-multi .select2-choices .select2-search-choice .select2-chosen {
- cursor: default;
-}
-
-.select2-container-multi .select2-choices .select2-search-choice-focus {
- background: #d4d4d4;
-}
-
-.select2-search-choice-close {
- display: block;
- width: 12px;
- height: 13px;
- position: absolute;
- right: 3px;
- top: 4px;
-
- font-size: 1px;
- outline: none;
- /* stylelint-disable-next-line function-url-quotes */
- background: url(image-path('select2.png')) right top no-repeat;
-}
-
-html[dir='rtl'] .select2-search-choice-close {
- right: auto;
- left: 3px;
-}
-
-.select2-container-multi .select2-search-choice-close {
- left: 3px;
-}
-
-html[dir='rtl'] .select2-container-multi .select2-search-choice-close {
- left: auto;
- right: 2px;
-}
-
-.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover {
- background-position: right -11px;
-}
-
-.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close {
- background-position: right -11px;
-}
-
-/* disabled styles */
-.select2-container-multi.select2-container-disabled .select2-choices {
- background-color: #f4f4f4;
- background-image: none;
- border: 1px solid #ddd;
- cursor: default;
-}
-
-.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice {
- padding: 3px 5px;
- border: 1px solid #ddd;
- background-image: none;
- background-color: #f4f4f4;
-}
-
-.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close {
- display: none;
- background: none;
-}
-/* end multiselect */
-
-
-.select2-result-selectable .select2-match,
-.select2-result-unselectable .select2-match {
- text-decoration: underline;
-}
-
-.select2-offscreen,
-.select2-offscreen:focus {
- clip: rect(0 0 0 0) !important;
- width: 1px !important;
- height: 1px !important;
- border: 0 !important;
- margin: 0 !important;
- padding: 0 !important;
- overflow: hidden !important;
- position: absolute !important;
- outline: 0 !important;
- left: 0 !important;
- top: 0 !important;
-}
-
-.select2-display-none {
- display: none;
-}
-
-.select2-measure-scrollbar {
- position: absolute;
- top: -10000px;
- left: -10000px;
- width: 100px;
- height: 100px;
- overflow: scroll;
-}
-
-@media only screen and (min-resolution: 120dpi) {
- .select2-search input,
- .select2-search-choice-close,
- .select2-container .select2-choice abbr,
- .select2-container .select2-choice .select2-arrow b {
- /* stylelint-disable-next-line function-url-quotes */
- background-image: url(image-path("select2x2.png")) !important;
- background-repeat: no-repeat !important;
- background-size: 60px 40px !important;
- }
-
- .select2-search input {
- background-position: 100% -21px !important;
- }
-}
-
-/* End of select2.css */
-
-@import './select2_overrides';
diff --git a/app/assets/stylesheets/lazy_bundles/select2_overrides.scss b/app/assets/stylesheets/lazy_bundles/select2_overrides.scss
deleted file mode 100644
index e3cec187fab..00000000000
--- a/app/assets/stylesheets/lazy_bundles/select2_overrides.scss
+++ /dev/null
@@ -1,341 +0,0 @@
-@import 'page_bundles/mixins_and_variables_and_functions';
-/** Select2 selectbox style override **/
-.select2-container {
- width: 100% !important;
-
- &.input-md,
- &.input-lg {
- display: block;
- }
-}
-
-.select2-container,
-.select2-container.select2-drop-above {
- .select2-choice {
- background: var(--white, $white);
- color: var(--gl-text-color, $gl-text-color);
- border-color: var(--gray-400, $gray-400);
- height: 34px;
- padding: $gl-vert-padding $gl-input-padding;
- font-size: $gl-font-size;
- line-height: 1.42857143;
- border-radius: $gl-border-radius-base;
-
- .select2-arrow {
- padding-top: 12px;
- padding-right: 20px;
- /* stylelint-disable-next-line function-url-quotes */
- background: url(asset_path('chevron-down.png')) no-repeat 2px 8px;
-
- .gl-dark & {
- filter: invert(0.9);
- }
-
- b {
- display: none;
- }
- }
-
- .select2-chosen {
- margin-right: 15px;
- }
-
- &:hover {
- border-color: var(--gray-400, $gray-400);
- color: var(--gl-text-color, $gl-text-color);
- }
- }
-
- // Essentially we’re doing @include form-control-focus here (from
- // bootstrap/scss/mixins/_forms.scss), except that the bootstrap mixin adds a
- // `&:focus` selector and we’re never actually focusing the .select2-choice
- // link nor the .select2-container, the Select2 library focuses an off-screen
- // .select2-focusser element instead.
- &.select2-container-active:not(.select2-dropdown-open) {
- .select2-choice {
- color: var(--gray-700, $gray-700);
- background-color: var(--white, $white);
- border-color: $input-focus-border-color;
- outline: 0;
- }
-
- // Reusable focus “glow” box-shadow
- @mixin form-control-focus-glow {
- @if $enable-shadows {
- box-shadow: $input-box-shadow, $input-focus-box-shadow;
- } @else {
- box-shadow: $input-focus-box-shadow;
- }
- }
-
- // Apply the focus “glow” shadow to the .select2-container if it also has
- // the .block-truncated class as that applies an overflow: hidden, thereby
- // hiding the glow of the nested .select2-choice element.
- &.block-truncated {
- @include form-control-focus-glow;
- }
-
- // Apply the glow directly to the .select2-choice link if we’re not
- // block-truncating the container.
- &:not(.block-truncated) .select2-choice {
- @include form-control-focus-glow;
- }
- }
-
- &.is-invalid {
- ~ .invalid-feedback {
- display: block;
- }
-
- .select2-choices,
- .select2-choice {
- border-color: var(--red-500, $red-500);
- }
- }
-}
-
-.select2-drop,
-.select2-drop.select2-drop-above {
- background: var(--white, $white);
- box-shadow: 0 2px 4px $dropdown-shadow-color;
- border-radius: $gl-border-radius-base;
- border: 1px solid var(--gray-400, $gray-400);
- min-width: 175px;
- color: var(--gl-text-color, $gl-text-color);
- z-index: 999;
-
- .modal-open & {
- z-index: $zindex-modal + 200;
- }
-}
-
-.select2-drop-mask {
- z-index: 998;
-
- .modal-open & {
- z-index: $zindex-modal + 100;
- }
-}
-
-.select2-drop.select2-drop-above.select2-drop-active {
- border-top: 1px solid var(--gray-400, $gray-400);
- margin-top: -6px;
-}
-
-.select2-container-active {
- .select2-choice,
- .select2-choices {
- box-shadow: none;
- }
-}
-
-.select2-dropdown-open,
-.select2-dropdown-open.select2-drop-above {
- .select2-choice {
- border-color: var(--gray-400, $gray-400);
- outline: 0;
- }
-}
-
-.select2-container-multi {
- .select2-choices {
- border-radius: $border-radius-default;
- border-color: var(--gray-400, $gray-400);
- background: none;
-
- .select2-search-field input {
- padding: 5px $gl-input-padding;
- height: auto;
- font-family: inherit;
- font-size: inherit;
- }
-
- .select2-search-choice {
- margin: 5px 0 0 8px;
- box-shadow: none;
- border-color: var(--gray-400, $gray-400);
- color: var(--gl-text-color, $gl-text-color);
- line-height: 15px;
- background-color: var(--gray-50, $gray-50);
- background-image: none;
- padding: 3px 18px 3px 5px;
-
- .select2-search-choice-close {
- top: 5px;
- left: initial;
- right: 3px;
- }
-
- &.select2-search-choice-focus {
- border-color: var(--gray-400, $gray-400);
- }
- }
- }
-}
-
-.select2-drop-active {
- margin-top: $dropdown-vertical-offset;
- font-size: 14px;
-
- .select2-results {
- max-height: 350px;
- }
-}
-
-.select2-search {
- padding: $grid-size;
-
- .select2-drop-auto-width & {
- padding: $grid-size;
- }
-
- input {
- padding: $grid-size;
- background: transparent image-url('select2.png');
- color: var(--gl-text-color, $gl-text-color);
- background-clip: content-box;
- background-origin: content-box;
- background-repeat: no-repeat;
- background-position: right 0 bottom 0 !important;
- border: 1px solid var(--gray-400, $gray-400);
- border-radius: $border-radius-default;
- line-height: 16px;
- transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
-
- &:focus {
- border-color: var(--blue-300, $blue-300);
- }
-
- &.select2-active {
- background-color: var(--white, $white);
- background-image: image-url('select2-spinner.gif') !important;
- background-origin: content-box;
- background-repeat: no-repeat;
- background-position: right 6px center !important;
- background-size: 16px 16px !important;
- }
- }
-
- + .select2-results {
- padding-top: 0;
- }
-}
-
-.select2-results {
- margin: 0;
- padding: #{$gl-padding / 2} 0;
-
- .select2-no-results,
- .select2-searching,
- .select2-ajax-error,
- .select2-selection-limit {
- background: transparent;
- padding: #{$gl-padding / 2} $gl-padding;
- }
-
- .select2-result-label,
- .select2-more-results {
- padding: #{$gl-padding / 2} $gl-padding;
- }
-
- .select2-highlighted {
- background: transparent;
- color: var(--gl-text-color, $gl-text-color);
-
- .select2-result-label {
- background: var(--gray-50, $gray-50);
- }
- }
-
- .select2-result {
- padding: 0 1px;
- }
-
- li.select2-result-with-children > .select2-result-label {
- font-weight: $gl-font-weight-bold;
- color: var(--gl-text-color, $gl-text-color);
- }
-}
-
-.select2-highlighted {
- .group-result {
- .group-path {
- color: var(--gray-700, $gray-700);
- }
- }
-}
-
-.select2-result-selectable,
-.select2-result-unselectable {
- .select2-match {
- font-weight: $gl-font-weight-bold;
- text-decoration: none;
- }
-}
-
-.input-group {
- .select2-container {
- display: table-cell;
- max-width: 180px;
- }
-}
-
-.file-editor {
- .select2 {
- float: right;
- }
-}
-
-.import-namespace-select {
- > .select2-choice {
- border-radius: $border-radius-default 0 0 $border-radius-default;
- position: relative;
- left: 1px;
- }
-}
-
-.issue-form {
- .select2-container {
- width: 250px !important;
- }
-}
-
-.new_project,
-.edit-project,
-.import-project {
- .input-group {
- .select2-container {
- display: unset;
- max-width: unset;
- flex-grow: 1;
- }
- }
-
- .input-group-prepend,
- .input-group-append {
- + .select2 a {
- border-radius: 0 $gl-border-radius-base $gl-border-radius-base 0;
- }
- }
-}
-
-.project-path {
- .select2-choice {
- border-top-right-radius: 0;
- border-bottom-right-radius: 0;
- }
-}
-
-.right-sidebar {
- .block {
- .select2-container span {
- margin-top: 0;
- }
- }
-}
-
-.block-truncated {
- > div:not(.block):not(.select2-display-none) {
- display: inline;
- }
-}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index c2ac4f32480..75c81b74ba7 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -101,12 +101,6 @@ ul.related-merge-requests > li gl-emoji {
}
}
-.issue-form {
- .select2-container {
- width: 250px !important;
- }
-}
-
.issues-nav-controls {
.btn-group:empty {
display: none;
diff --git a/app/controllers/admin/jobs_controller.rb b/app/controllers/admin/jobs_controller.rb
index ef9264d1615..5ea8c672993 100644
--- a/app/controllers/admin/jobs_controller.rb
+++ b/app/controllers/admin/jobs_controller.rb
@@ -6,6 +6,10 @@ class Admin::JobsController < Admin::ApplicationController
feature_category :continuous_integration
urgency :low
+ before_action do
+ push_frontend_feature_flag(:admin_jobs_vue)
+ end
+
def index
# We need all builds for tabs counters
@all_builds = Ci::JobsFinder.new(current_user: current_user).execute
diff --git a/app/controllers/projects/ml/experiments_controller.rb b/app/controllers/projects/ml/experiments_controller.rb
index 20f5b39bac7..00b965542f6 100644
--- a/app/controllers/projects/ml/experiments_controller.rb
+++ b/app/controllers/projects/ml/experiments_controller.rb
@@ -13,7 +13,12 @@ module Projects
MAX_CANDIDATES_PER_PAGE = 30
def index
- @experiments = ::Ml::Experiment.by_project_id(@project.id).page(params[:page]).per(MAX_EXPERIMENTS_PER_PAGE)
+ paginator = ::Ml::Experiment.by_project_id(@project.id)
+ .with_candidate_count
+ .keyset_paginate(cursor: params[:cursor], per_page: MAX_EXPERIMENTS_PER_PAGE)
+
+ @experiments = paginator.records
+ @page_info = page_info(paginator)
end
def show
diff --git a/app/helpers/projects/ml/experiments_helper.rb b/app/helpers/projects/ml/experiments_helper.rb
index 9f41db2f8b9..8467ee61b35 100644
--- a/app/helpers/projects/ml/experiments_helper.rb
+++ b/app/helpers/projects/ml/experiments_helper.rb
@@ -33,7 +33,7 @@ module Projects
iid: candidate.iid,
path_to_artifact: link_to_artifact(candidate),
experiment_name: candidate.experiment.name,
- path_to_experiment: link_to_experiment(candidate),
+ path_to_experiment: link_to_experiment(candidate.project, candidate.experiment),
status: candidate.status
},
metadata: candidate.metadata
@@ -42,6 +42,18 @@ module Projects
Gitlab::Json.generate(data)
end
+ def experiments_as_data(project, experiments)
+ data = experiments.map do |exp|
+ {
+ name: exp.name,
+ path: link_to_experiment(project, exp),
+ candidate_count: exp.candidate_count
+ }
+ end
+
+ Gitlab::Json.generate(data)
+ end
+
def page_info(paginator)
{
has_next_page: paginator.has_next_page?,
@@ -67,10 +79,8 @@ module Projects
project_ml_candidate_path(candidate.project, candidate.iid)
end
- def link_to_experiment(candidate)
- experiment = candidate.experiment
-
- project_ml_experiment_path(experiment.project, experiment.iid)
+ def link_to_experiment(project, experiment)
+ project_ml_experiment_path(project, experiment.iid)
end
def user_info(candidate)
diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb
deleted file mode 100644
index 7ee40c28bad..00000000000
--- a/app/helpers/selects_helper.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-module SelectsHelper
- def project_select_tag(id, opts = {})
- opts[:class] = [*opts[:class], 'ajax-project-select'].join(' ')
-
- unless opts.delete(:scope) == :all
- if @group
- opts['data-group-id'] = @group.id
- end
- end
-
- with_feature_enabled_data_attribute =
- case opts.delete(:with_feature_enabled)
- when 'issues' then 'data-with-issues-enabled'
- when 'merge_requests' then 'data-with-merge-requests-enabled'
- end
-
- opts[with_feature_enabled_data_attribute] = true
-
- hidden_field_tag(id, opts[:selected], opts)
- end
-
- def select2_tag(id, opts = {})
- klass_opts = [opts[:class]]
- klass_opts << 'multiselect' if opts[:multiple]
-
- opts[:class] = klass_opts.join(' ')
- value = opts[:selected] || ''
-
- hidden_field_tag(id, value, opts)
- end
-end
-
-SelectsHelper.prepend_mod_with('SelectsHelper')
diff --git a/app/services/export_csv/base_service.rb b/app/services/export_csv/base_service.rb
index 98ab33d4c33..84d44fd75fc 100644
--- a/app/services/export_csv/base_service.rb
+++ b/app/services/export_csv/base_service.rb
@@ -5,9 +5,10 @@ module ExportCsv
# Target attachment size before base64 encoding
TARGET_FILESIZE = 15.megabytes
- def initialize(relation, resource_parent)
+ def initialize(relation, resource_parent, fields = [])
@objects = relation
@resource_parent = resource_parent
+ @fields = fields
end
def csv_data
@@ -18,18 +19,25 @@ module ExportCsv
raise NotImplementedError
end
+ def invalid_fields
+ ::ExportCsv::MapExportFieldsService.new(fields, header_to_value_hash).invalid_fields
+ end
+
private
- attr_reader :resource_parent, :objects
+ attr_reader :resource_parent, :objects, :fields
# rubocop: disable CodeReuse/ActiveRecord
def csv_builder
- @csv_builder ||=
+ @csv_builder ||= begin
+ data_hash = MapExportFieldsService.new(fields, header_to_value_hash).execute
+
if preload_associations_in_batches?
- CsvBuilder.new(objects, header_to_value_hash, associations_to_preload)
+ CsvBuilder.new(objects, data_hash, associations_to_preload)
else
- CsvBuilder.new(objects.preload(associations_to_preload), header_to_value_hash, [])
+ CsvBuilder.new(objects.preload(associations_to_preload), data_hash, [])
end
+ end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/export_csv/map_export_fields_service.rb b/app/services/export_csv/map_export_fields_service.rb
new file mode 100644
index 00000000000..d4f46c65328
--- /dev/null
+++ b/app/services/export_csv/map_export_fields_service.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module ExportCsv
+ class MapExportFieldsService < BaseService
+ attr_reader :fields, :data
+
+ def initialize(fields, data)
+ @fields = fields
+ @data = data
+ end
+
+ def execute
+ return data if fields.empty?
+
+ selected_fields_to_hash
+ end
+
+ def invalid_fields
+ fields.reject { |field| permitted_field?(field) }
+ end
+
+ private
+
+ def selected_fields_to_hash
+ data.select { |key| requested_field?(key) }
+ end
+
+ def requested_field?(field)
+ field.downcase.in?(fields.map(&:downcase))
+ end
+
+ def permitted_field?(field)
+ field.downcase.in?(keys.map(&:downcase))
+ end
+
+ def keys
+ data.keys
+ end
+ end
+end
diff --git a/app/services/work_items/export_csv_service.rb b/app/services/work_items/export_csv_service.rb
new file mode 100644
index 00000000000..e0a1b90b597
--- /dev/null
+++ b/app/services/work_items/export_csv_service.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module WorkItems
+ class ExportCsvService < ExportCsv::BaseService
+ def email(mail_to_user)
+ # TODO - will be implemented as part of https://gitlab.com/gitlab-org/gitlab/-/issues/379082
+ end
+
+ private
+
+ def associations_to_preload
+ [:work_item_type, :author]
+ end
+
+ def header_to_value_hash
+ {
+ 'Id' => 'iid',
+ 'Title' => 'title',
+ 'Type' => ->(work_item) { work_item.work_item_type.name },
+ 'Author' => 'author_name',
+ 'Author Username' => ->(work_item) { work_item.author.username },
+ 'Created At (UTC)' => ->(work_item) { work_item.created_at.to_s(:csv) }
+ }
+ end
+ end
+end
diff --git a/app/views/admin/jobs/index.html.haml b/app/views/admin/jobs/index.html.haml
index 667c90f0228..7b00019cc21 100644
--- a/app/views/admin/jobs/index.html.haml
+++ b/app/views/admin/jobs/index.html.haml
@@ -4,21 +4,25 @@
- breadcrumb_title _("Jobs")
- page_title _("Jobs")
-.top-area
- .scrolling-tabs-container.inner-page-scroll-tabs.gl-flex-grow-1.gl-min-w-0.gl-w-full
- .fade-left= sprite_icon('chevron-lg-left', size: 12)
- .fade-right= sprite_icon('chevron-lg-right', size: 12)
- - build_path_proc = ->(scope) { admin_jobs_path(scope: scope) }
- = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope
+- if Feature.enabled?(:admin_jobs_vue)
+ #admin-jobs-app{ data: { job_statuses: job_statuses.to_json, empty_state_svg_path: image_path('jobs-empty-state.svg'), url: cancel_all_admin_jobs_path } }
- - if @all_builds.running_or_pending.any?
- #js-stop-jobs-modal
- .nav-controls
- = render Pajamas::ButtonComponent.new(variant: :danger, button_options: { id: 'js-stop-jobs-button', data: { url: cancel_all_admin_jobs_path } }) do
- = s_('AdminArea|Stop all jobs')
+- else
+ .top-area
+ .scrolling-tabs-container.inner-page-scroll-tabs.gl-flex-grow-1.gl-min-w-0.gl-w-full
+ .fade-left= sprite_icon('chevron-lg-left', size: 12)
+ .fade-right= sprite_icon('chevron-lg-right', size: 12)
+ - build_path_proc = ->(scope) { admin_jobs_path(scope: scope) }
+ = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope
-.row-content-block.second-block
- #{(@scope || 'all').capitalize} jobs
+ - if @all_builds.running_or_pending.any?
+ #js-stop-jobs-modal
+ .nav-controls
+ = render Pajamas::ButtonComponent.new(variant: :danger, button_options: { id: 'js-stop-jobs-button', data: { url: cancel_all_admin_jobs_path } }) do
+ = s_('AdminArea|Stop all jobs')
-%ul.content-list.builds-content-list.admin-builds-table
- = render "projects/jobs/table", builds: @builds, admin: true
+ .row-content-block.second-block
+ #{(@scope || 'all').capitalize} jobs
+
+ %ul.content-list.builds-content-list.admin-builds-table
+ = render "projects/jobs/table", builds: @builds, admin: true
diff --git a/app/views/projects/ml/experiments/index.html.haml b/app/views/projects/ml/experiments/index.html.haml
index a84cb15d940..dd064239e36 100644
--- a/app/views/projects/ml/experiments/index.html.haml
+++ b/app/views/projects/ml/experiments/index.html.haml
@@ -1,11 +1,7 @@
-- breadcrumb_title _('ML Experiments')
-- page_title _('ML Experiments')
+- breadcrumb_title s_('MlExperimentTracking|Model experiments')
+- page_title s_('MlExperimentTracking|Model experiments')
-.page-title-holder.d-flex.align-items-center
- %h1.page-title.gl-font-size-h-display= _('Machine Learning Experiments')
-
-= render "incubation_banner"
-
-%div{ class: container_class }
- .content-list.builds-content-list
- = render "experiment_list", experiments: @experiments, project: @project
+#js-project-ml-experiments-index{ data: {
+ experiments: experiments_as_data(@project, @experiments),
+ page_info: formatted_page_info(@page_info)
+} }
diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml
deleted file mode 100644
index 2249fb03f62..00000000000
--- a/app/views/shared/_new_project_item_select.html.haml
+++ /dev/null
@@ -1,9 +0,0 @@
--# This view is used to initialize a select2-based selector, which we are migrating away from.
--# To initialize the Vue selector, use the new_project_item_vue_select view instead.
--# Refer to https://gitlab.com/gitlab-org/gitlab/-/issues/374098 for more information.
-- if any_projects?(@projects)
- .dropdown.b-dropdown.gl-dropdown.btn-group.project-item-select-holder{ class: 'gl-display-inline-flex!' }
- %a.btn.gl-button.btn-confirm.split-content-button.js-new-project-item-link.block-truncated{ href: '', data: { label: local_assigns[:label], type: local_assigns[:type] } }
- = gl_loading_icon(inline: true, color: 'light')
- = project_select_tag :project_path, class: "project-item-select gl-absolute! gl-visibility-hidden", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at', relative_path: local_assigns[:path], with_shared: local_assigns[:with_shared], include_projects_in_subgroups: local_assigns[:include_projects_in_subgroups] }, with_feature_enabled: local_assigns[:with_feature_enabled]
- %button.btn.dropdown-toggle.btn-confirm.btn-md.gl-button.gl-dropdown-toggle.dropdown-toggle-split.new-project-item-select-button{ 'aria-label': _('Toggle project select') }
diff --git a/config/application.rb b/config/application.rb
index 2d97bb1c0af..c6ecfcc0cb1 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -336,7 +336,6 @@ module Gitlab
config.assets.precompile << "page_bundles/work_items.css"
config.assets.precompile << "page_bundles/xterm.css"
config.assets.precompile << "lazy_bundles/cropper.css"
- config.assets.precompile << "lazy_bundles/select2.css"
config.assets.precompile << "lazy_bundles/gridstack.css"
config.assets.precompile << "performance_bar.css"
config.assets.precompile << "disable_animations.css"
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index 9afa2b6fca3..959d6f23156 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -127,12 +127,6 @@
:versions: []
:when: 2017-01-14 20:50:20.037775000 Z
- - :approve
- - select2
- - :who: Matt Lee
- :why: https://github.com/select2/select2/blob/master/LICENSE.md
- :versions: []
- :when: 2017-01-14 20:10:53.909618000 Z
-- - :approve
- opener
- :who: Mike Greiling
:why: https://github.com/domenic/opener/blob/1.4.3/LICENSE.txt
diff --git a/config/feature_flags/development/admin_jobs_vue.yml b/config/feature_flags/development/admin_jobs_vue.yml
new file mode 100644
index 00000000000..3c8402a83f4
--- /dev/null
+++ b/config/feature_flags/development/admin_jobs_vue.yml
@@ -0,0 +1,8 @@
+---
+name: admin_jobs_vue
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98769
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/391194
+milestone: '15.9'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/webpack.vendor.config.js b/config/webpack.vendor.config.js
index 1300bf16e56..a43febe5e25 100644
--- a/config/webpack.vendor.config.js
+++ b/config/webpack.vendor.config.js
@@ -37,7 +37,6 @@ module.exports = {
'mermaid',
'katex',
'three',
- 'select2',
'moment-mini',
'dompurify',
'bootstrap/dist/js/bootstrap.js',
diff --git a/db/docs/scan_result_policies.yml b/db/docs/scan_result_policies.yml
index 6a6eb12a270..6533a133a6e 100644
--- a/db/docs/scan_result_policies.yml
+++ b/db/docs/scan_result_policies.yml
@@ -1,9 +1,10 @@
---
table_name: scan_result_policies
-classes: []
+classes:
+- Security::ScanResultPolicyRead
feature_categories:
- security_policy_management
-description: 'Stores rules of a Security Orchestration Policy.'
+description: Stores rules of a Security Orchestration Policy.
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109624
milestone: '15.9'
gitlab_schema: gitlab_main
diff --git a/doc/administration/docs_self_host.md b/doc/administration/docs_self_host.md
index f049dafea76..97eff35da91 100644
--- a/doc/administration/docs_self_host.md
+++ b/doc/administration/docs_self_host.md
@@ -177,7 +177,7 @@ documentation URL requests as needed. For example, if your GitLab version is
- When you select the link, you are redirected to
`http://0.0.0.0:4000/14.5/ee/user/admin_area/settings/help_page/#destination-requirements`.
-To test the setting, select a **Learn more** link within the GitLab application.
+To test the setting, select a **Learn more** link in the GitLab application.
## Upgrade the product documentation to a later version
diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
index 618462cc4b5..403f8525d39 100644
--- a/doc/administration/geo/replication/troubleshooting.md
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -238,7 +238,7 @@ This machine's Geo node name matches a database record ... no
doc/administration/geo/replication/troubleshooting.md#can-geo-detect-the-current-node-correctly
```
-Learn more about recommended site names in the description of the Name field in
+For more information about recommended site names in the description of the Name field, see
[Geo Admin Area Common Settings](../../../user/admin_area/geo_sites.md#common-settings).
### Reverify all uploads (or any SSF data type which is verified)
diff --git a/doc/administration/geo/replication/version_specific_upgrades.md b/doc/administration/geo/replication/version_specific_upgrades.md
index aa8e5d77f67..f8e013a8776 100644
--- a/doc/administration/geo/replication/version_specific_upgrades.md
+++ b/doc/administration/geo/replication/version_specific_upgrades.md
@@ -8,10 +8,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
NOTE:
We're in the process of merging all the version-specific upgrade information
-into a single page. See [epic 9581](https://gitlab.com/groups/gitlab-org/-/epics/9581)
-for more information. For the time being, visit the
-[general upgrade page](../../../update/index.md)
-for the newest Geo version-specific upgrade instructions.
+into a single page. For more information,
+see [epic 9581](https://gitlab.com/groups/gitlab-org/-/epics/9581).
+For the latest Geo version-specific upgrade instructions,
+see the [general upgrade page](../../../update/index.md).
Review this page for upgrade instructions for your version. These steps
accompany the [general steps](upgrading_the_geo_sites.md#general-upgrade-steps)
diff --git a/doc/administration/get_started.md b/doc/administration/get_started.md
index ca0408c2ba5..f27adfcb100 100644
--- a/doc/administration/get_started.md
+++ b/doc/administration/get_started.md
@@ -45,11 +45,11 @@ Get started:
**More resources**
-- Learn more about [running multiple Agile teams](https://www.youtube.com/watch?v=VR2r1TJCDew).
-- Sync group memberships [by using LDAP](../administration/auth/ldap/ldap_synchronization.md#group-sync).
+- [Run multiple Agile teams](https://www.youtube.com/watch?v=VR2r1TJCDew).
+- [Sync group memberships by using LDAP](../administration/auth/ldap/ldap_synchronization.md#group-sync).
- Manage user access with inherited permissions. Use up to 20 levels of subgroups to organize both teams and projects.
- - Learn more about [inherited permissions](../user/project/members/index.md#inherited-membership).
- - View an [example](../user/group/subgroups/index.md).
+ - [Inherited membership](../user/project/members/index.md#inherited-membership).
+ - [Example](../user/group/subgroups/index.md).
## Import projects
diff --git a/doc/administration/gitaly/troubleshooting.md b/doc/administration/gitaly/troubleshooting.md
index df189f97941..5f05b6322b0 100644
--- a/doc/administration/gitaly/troubleshooting.md
+++ b/doc/administration/gitaly/troubleshooting.md
@@ -401,6 +401,20 @@ push, which causes a significant delay.
If Git pushes are too slow when Dynatrace is enabled, disable Dynatrace.
+## Gitaly fails to fork processes stored on `noexec` file systems
+
+Because of changes [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5999) in GitLab 14.10, applying the `noexec` option to a mount
+point (for example, `/var`) causes Gitaly to throw `permission denied` errors related to forking processes. For example:
+
+```shell
+fork/exec /var/opt/gitlab/gitaly/run/gitaly-2057/gitaly-git2go: permission denied
+```
+
+To resolve this, remove the `noexec` option from the file system mount. An alternative is to change the Gitaly runtime directory:
+
+1. Add `gitaly['runtime_dir'] = '<PATH_WITH_EXEC_PERM>'` to `/etc/gitlab/gitlab.rb` and specify a location without `noexec` set.
+1. Run `sudo gitlab-ctl reconfigure`.
+
## Troubleshoot Praefect (Gitaly Cluster)
The following sections provide possible solutions to Gitaly Cluster errors.
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index e4f4b234a15..b1d97fd16a9 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -1073,7 +1073,7 @@ varies by file type:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/320902) in GitLab 13.9.
If a branch is merged while open merge requests still point to it, GitLab can
-retarget merge requests pointing to the now-merged branch. To learn more, read
+retarget merge requests pointing to the now-merged branch. For more information, see
[Update merge requests when target branch merges](../user/project/merge_requests/index.md#update-merge-requests-when-target-branch-merges).
## Maximum number of assignees and reviewers
diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md
index 0161e4ff855..4b3e251d407 100644
--- a/doc/administration/object_storage.md
+++ b/doc/administration/object_storage.md
@@ -481,9 +481,8 @@ Here are the valid connection parameters for GCS:
GitLab reads the value of `google_json_key_location`, then `google_json_key_string`, and finally, `google_application_default`.
It uses the first of these settings that has a value.
-The service account must have permission to access the bucket. Learn more
-in Google's
-[Cloud Storage authentication documentation](https://cloud.google.com/storage/docs/authentication).
+The service account must have permission to access the bucket. For more information,
+see the [Cloud Storage authentication documentation](https://cloud.google.com/storage/docs/authentication).
NOTE:
Bucket encryption with the [Cloud Key Management Service (KMS)](https://cloud.google.com/kms/docs) is not supported and results in [ETag mismatch errors](#etag-mismatch).
@@ -540,9 +539,8 @@ because a single set of credentials are used to access multiple
containers. The [storage-specific form](#storage-specific-configuration)
is not supported. For more details, see [how to transition to consolidated form](#transition-to-consolidated-form).
-The following are the valid connection parameters for Azure. Read the
-[Azure Blob storage documentation](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
-to learn more.
+The following are the valid connection parameters for Azure. For more information, see the
+[Azure Blob Storage documentation](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction).
| Setting | Description | Example |
|------------------------------|----------------|-----------|
diff --git a/doc/administration/operations/puma.md b/doc/administration/operations/puma.md
index 81a96ca698c..f2f9f1cdcda 100644
--- a/doc/administration/operations/puma.md
+++ b/doc/administration/operations/puma.md
@@ -138,7 +138,7 @@ When running Puma in single mode, some features are not supported:
- [Phased restart](https://gitlab.com/gitlab-org/gitlab/-/issues/300665)
- [Memory killers](#reducing-memory-use)
-To learn more, visit [epic 5303](https://gitlab.com/groups/gitlab-org/-/epics/5303).
+For more information, see [epic 5303](https://gitlab.com/groups/gitlab-org/-/epics/5303).
## Performance caveat when using Puma with Rugged
diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index dcba034b381..529621813aa 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -653,7 +653,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts.
Like most failover handling methods, this has a small chance of leading to data loss.
-Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
+For more information, see the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index 48e6d01a2e5..71fe8b301e2 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -670,7 +670,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts.
Like most failover handling methods, this has a small chance of leading to data loss.
-Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
+For more information, see the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index 2f65f3ba2e1..1d5dad02b18 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -946,7 +946,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts.
Like most failover handling methods, this has a small chance of leading to data loss.
-Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
+For more information, see the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index e12f40b734e..3bcffa8f606 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -663,7 +663,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts.
Like most failover handling methods, this has a small chance of leading to data loss.
-Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
+For more information, see the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index 113e9a26a54..691f71289c3 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -942,7 +942,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
PostgreSQL, with Patroni managing its failover, defaults to use `pg_rewind` by default to handle conflicts.
Like most failover handling methods, this has a small chance of leading to data loss.
-Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
+For more information, see the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method).
1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Omnibus node you configured and add or replace
the file of the same name on this server. If this is the first Omnibus node you are configuring then you can skip this step.
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index 5f2a2388bbb..4286d459e54 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -75,7 +75,7 @@ frequently [verify your API calls against the future breaking-change schema](#ve
Fields behind a feature flag and disabled by default do not follow the deprecation and removal process, and can be removed at any time without notice.
-Learn more about [breaking changes](../../development/deprecation_guidelines/index.md).
+For more information, see [Deprecating GitLab features](../../development/deprecation_guidelines/index.md).
WARNING:
GitLab makes all attempts to follow the [deprecation and removal process](#deprecation-and-removal-process).
diff --git a/doc/api/group_releases.md b/doc/api/group_releases.md
index e00693a2fd5..9c395adbe04 100644
--- a/doc/api/group_releases.md
+++ b/doc/api/group_releases.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Review your groups' [releases](../user/project/releases/index.md) with the REST API.
NOTE:
-For information about the project releases API, visit the [Releases API](releases/index.md) page.
+For more information about the project releases API, see [Releases API](releases/index.md).
FLAG:
On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `group_releases_finder_inoperator`.
diff --git a/doc/api/issues.md b/doc/api/issues.md
index 8f621574061..e252655f781 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -1950,7 +1950,7 @@ The `assignee` column is deprecated. We now show it as a single-sized array `ass
Promotes an issue to an epic by adding a comment with the `/promote`
[quick action](../user/project/quick_actions.md).
-To learn more about promoting issues to epics, visit [Manage epics](../user/group/epics/manage_epics.md#promote-an-issue-to-an-epic).
+For more information about promoting issues to epics, see [Manage epics](../user/group/epics/manage_epics.md#promote-an-issue-to-an-epic).
```plaintext
POST /projects/:id/issues/:issue_iid/notes
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index 3121b0658e7..a34fde54e90 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -35,7 +35,7 @@ Supported attributes:
| `page_token` | string | no | The tree record ID at which to fetch the next page. Used only with keyset pagination. |
| `pagination` | string | no | If `keyset`, use the [keyset-based pagination method](rest/index.md#keyset-based-pagination). |
| `path` | string | no | The path inside the repository. Used to get content of subdirectories. |
-| `per_page` | integer | no | Number of results to show per page. If not specified, defaults to `20`. [Learn more on pagination](rest/index.md#pagination). |
+| `per_page` | integer | no | Number of results to show per page. If not specified, defaults to `20`. For more information, see [Pagination](rest/index.md#pagination). |
| `recursive` | boolean | no | Boolean value used to get a recursive tree. Default is `false`. |
| `ref` | string | no | The name of a repository branch or tag or, if not given, the default branch. |
diff --git a/doc/api/rest/index.md b/doc/api/rest/index.md
index 527677975ef..57d13f2a54f 100644
--- a/doc/api/rest/index.md
+++ b/doc/api/rest/index.md
@@ -733,8 +733,8 @@ The correct encoding for the query parameter would be:
## Clients
-There are many unofficial GitLab API Clients for most of the popular programming
-languages. For a complete list, visit the [GitLab website](https://about.gitlab.com/partners/technology-partners/#api-clients).
+Many unofficial GitLab API Clients are available for most of the popular programming
+languages. For a complete list, see the [GitLab website](https://about.gitlab.com/partners/technology-partners/#api-clients).
## Rate limits
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index 2d5e3d5a26f..a8c192dc944 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -25,9 +25,6 @@ To enable Docker commands for your CI/CD jobs, you can use:
- [Docker-in-Docker](#use-docker-in-docker)
- [Docker socket binding](#use-docker-socket-binding)
-If you are using shared runners on GitLab.com,
-[learn more about how these runners are configured](../runners/index.md).
-
### Use the shell executor
To include Docker commands in your CI/CD jobs, you can configure your runner to
@@ -76,7 +73,7 @@ the Docker commands, but needs permission to do so.
You can now use `docker` commands (and install `docker-compose` if needed).
When you add `gitlab-runner` to the `docker` group, you are effectively granting `gitlab-runner` full root permissions.
-Learn more about the [security of the `docker` group](https://blog.zopyx.com/on-docker-security-docker-group-considered-harmful/).
+For more information, see the [security of the `docker` group](https://blog.zopyx.com/on-docker-security-docker-group-considered-harmful/).
### Use Docker-in-Docker
diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
index 125ae3650c9..7bb14c4c900 100644
--- a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
+++ b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
@@ -13,7 +13,7 @@ NOTE:
[GitLab Premium](https://about.gitlab.com/pricing/) supports read access to a
HashiCorp Vault, and enables you to
[use Vault secrets in a CI job](../../secrets/index.md#use-vault-secrets-in-a-ci-job).
-To learn more, read [Using external secrets in CI](../../secrets/index.md).
+For more information, see [Using external secrets in CI](../../secrets/index.md).
## Requirements
diff --git a/doc/ci/index.md b/doc/ci/index.md
index 63db23f8c48..ea48a5e461d 100644
--- a/doc/ci/index.md
+++ b/doc/ci/index.md
@@ -129,8 +129,6 @@ See also:
## Related topics
-Learn more about GitLab CI/CD:
-
- [Why you might choose GitLab CI/CD](https://about.gitlab.com/blog/2016/10/17/gitlab-ci-oohlala/).
- [Reasons you might migrate from another platform](https://about.gitlab.com/blog/2016/07/22/building-our-web-app-on-gitlab-ci/).
- [Five teams that made the switch to GitLab CI/CD](https://about.gitlab.com/blog/2019/04/25/5-teams-that-made-the-switch-to-gitlab-ci-cd/).
diff --git a/doc/ci/pipelines/downstream_pipelines.md b/doc/ci/pipelines/downstream_pipelines.md
index b84bc28de3f..e4560cd882d 100644
--- a/doc/ci/pipelines/downstream_pipelines.md
+++ b/doc/ci/pipelines/downstream_pipelines.md
@@ -68,8 +68,8 @@ Multi-project pipelines:
- Are visible in the downstream project's pipeline list.
- Are independent, so there are no nesting limits.
-Learn more in the "Cross-project Pipeline Triggering and Visualization" demo at
-[GitLab@learn](https://about.gitlab.com/learn/), in the Continuous Integration section.
+For more information, see the **Cross-project Pipeline Triggering and Visualization** demo at
+[GitLab@learn](https://about.gitlab.com/learn/) in the **Continuous Integration** section.
If you use a public project to trigger downstream pipelines in a private project,
make sure there are no confidentiality problems. The upstream project's pipelines page
diff --git a/doc/ci/pipelines/pipeline_efficiency.md b/doc/ci/pipelines/pipeline_efficiency.md
index 50215a9908a..0795005aa8e 100644
--- a/doc/ci/pipelines/pipeline_efficiency.md
+++ b/doc/ci/pipelines/pipeline_efficiency.md
@@ -254,7 +254,7 @@ Document CI/CD pipeline problems and incidents in issues, including research don
and solutions found. This helps onboarding new team members, and also helps
identify recurring problems with CI pipeline efficiency.
-### Learn More
+### Related topics
- [CI Monitoring Webcast Slides](https://docs.google.com/presentation/d/1ONwIIzRB7GWX-WOSziIIv8fz1ngqv77HO1yVfRooOHM/edit?usp=sharing)
- [GitLab.com Monitoring Handbook](https://about.gitlab.com/handbook/engineering/monitoring/)
diff --git a/doc/ci/services/gitlab.md b/doc/ci/services/gitlab.md
index f2ea969f430..bd31f1b8e91 100644
--- a/doc/ci/services/gitlab.md
+++ b/doc/ci/services/gitlab.md
@@ -26,7 +26,7 @@ tests access to the GitLab API.
NOTE:
Variables set in the GitLab UI are not passed down to the service containers.
-[Learn more](../variables/index.md#).
+For more information, see [GitLab CI/CD variables](../variables/index.md).
Then, commands in `script` sections in your `.gitlab-ci.yml` file can access the API at `http://gitlab/api/v4`.
diff --git a/doc/ci/services/mysql.md b/doc/ci/services/mysql.md
index ea11719cef1..e795c4ffc5f 100644
--- a/doc/ci/services/mysql.md
+++ b/doc/ci/services/mysql.md
@@ -18,7 +18,7 @@ This example shows you how to set a username and password that GitLab uses to ac
NOTE:
Variables set in the GitLab UI are not passed down to the service containers.
-[Learn more](../variables/index.md).
+For more information, see [GitLab CI/CD variables](../variables/index.md).
1. To specify a MySQL image, add the following to your `.gitlab-ci.yml` file:
diff --git a/doc/ci/services/postgres.md b/doc/ci/services/postgres.md
index 139a4a2f742..afb14bd976f 100644
--- a/doc/ci/services/postgres.md
+++ b/doc/ci/services/postgres.md
@@ -18,7 +18,7 @@ you basically have everything set up already.
NOTE:
Variables set in the GitLab UI are not passed down to the service containers.
-[Learn more](../variables/index.md).
+For more information, see [GitLab CI/CD variables](../variables/index.md).
First, in your `.gitlab-ci.yml` add:
diff --git a/doc/ci/testing/code_quality.md b/doc/ci/testing/code_quality.md
index 175a250d75e..4b826991bb5 100644
--- a/doc/ci/testing/code_quality.md
+++ b/doc/ci/testing/code_quality.md
@@ -191,8 +191,8 @@ Code Quality now runs in standard Docker mode.
## Disable Code Quality
The `code_quality` job doesn't run if the `$CODE_QUALITY_DISABLED` CI/CD variable
-is present. Refer to the CI/CD variables [documentation](../variables/index.md)
-to learn more about how to define one.
+is present. For more information about how to define a variable, see
+[GitLab CI/CD variables](../variables/index.md).
To disable Code Quality, create a custom CI/CD variable named `CODE_QUALITY_DISABLED`, for either:
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index dd36d649227..a0015d39adb 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -1124,7 +1124,7 @@ for example to override:
- A default cache defined with [`default`](#default).
- The configuration for a job added with [`include`](#include).
-Learn more about caches in [Caching in GitLab CI/CD](../caching/index.md).
+For more information about caches, see [Caching in GitLab CI/CD](../caching/index.md).
#### `cache:paths`
diff --git a/doc/cloud_seed/index.md b/doc/cloud_seed/index.md
index 04b560f7f87..1021c7f7700 100644
--- a/doc/cloud_seed/index.md
+++ b/doc/cloud_seed/index.md
@@ -70,7 +70,7 @@ The generated service account has the following roles:
- `roles/cloudsql.client`
- `roles/browser`
-You can enhance security by storing CI variables in secret managers. Learn more about [secret management with GitLab](../ci/secrets/index.md).
+You can enhance security by storing CI variables in secret managers. For more information, see [secret management with GitLab](../ci/secrets/index.md).
### Configure your preferred GCP region
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index 0b47a7be7f2..94abbda9671 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -1907,7 +1907,7 @@ code so that we have a single source of truth and we do not trigger a subscripti
## Pagination implementation
-To learn more, visit [GraphQL pagination](graphql_guide/pagination.md).
+For more information, see [GraphQL pagination](graphql_guide/pagination.md).
## Validating arguments
diff --git a/doc/development/application_slis/rails_request_apdex.md b/doc/development/application_slis/rails_request_apdex.md
index 19a9c67eb8e..dc9d67b0a2b 100644
--- a/doc/development/application_slis/rails_request_apdex.md
+++ b/doc/development/application_slis/rails_request_apdex.md
@@ -247,7 +247,7 @@ request rates on the
In the **Budget Attribution** row, the **Puma Apdex** log link shows you
how many requests are not meeting a 1s or 5s target.
-Learn more about the content of the dashboard in the documentation for
+For more information about the content of the dashboard, see
[Dashboards for stage groups](../stage_group_observability/index.md). For more information
-on our exploration of the error budget itself, read the infrastructure issue
-[Stage group error budget exploration dashboard](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1365).
+about our exploration of the error budget itself, see
+[issue 1365](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1365).
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index 984ac49c514..96b70e2fbd8 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -18,7 +18,7 @@ GitLab is available under [different subscriptions](https://about.gitlab.com/pri
New versions of GitLab are released from stable branches, and the `main` branch is used for
bleeding-edge development.
-For more information, visit the [GitLab Release Process](https://about.gitlab.com/handbook/engineering/releases/).
+For more information, see the [GitLab release process](https://about.gitlab.com/handbook/engineering/releases/).
Both distributions require additional components. These components are described in the
[Component details](#components) section, and all have their own repositories.
@@ -771,7 +771,8 @@ Whenever a client requests to pull or push an image from the registry, it
returns a `401` response along with a header detailing where to get an
authentication token, in this case the GitLab instance. The client then
requests a pull or push auth token from GitLab and retries the original request
-to the registry. Learn more about [token authentication](https://docs.docker.com/registry/spec/auth/token/).
+to the registry. For more information, see
+[token authentication](https://docs.docker.com/registry/spec/auth/token/).
An external registry can also be configured to use GitLab as an auth endpoint.
diff --git a/doc/development/cached_queries.md b/doc/development/cached_queries.md
index c8fa3c40f4a..0525603893f 100644
--- a/doc/development/cached_queries.md
+++ b/doc/development/cached_queries.md
@@ -65,8 +65,8 @@ to view the list of database queries, including cached queries. The
performance bar shows a warning when the number of total executed and cached queries is
greater than 100.
-To learn more about the statistics available to you, read the
-[Performance Bar documentation](../administration/monitoring/performance/performance_bar.md).
+For more information about the statistics available to you, see
+[Performance bar](../administration/monitoring/performance/performance_bar.md).
## What to look for
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index b3d79bec9be..55827e00e43 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -26,7 +26,7 @@ Throughout this guide you will see references to CE and EE for abbreviation.
## Code of conduct
We want to create a welcoming environment for everyone who is interested in contributing.
-Visit our [Code of Conduct page](https://about.gitlab.com/community/contribute/code-of-conduct/) to learn more about our commitment to an open and welcoming environment.
+For more information about our commitment to an open and welcoming environment, see our [Code of Conduct page](https://about.gitlab.com/community/contribute/code-of-conduct/).
Issues and merge requests should be in English and contain appropriate language
for audiences of all ages.
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 680cc06d792..be5f8c217b7 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -228,7 +228,7 @@ To reach the definition of done, the merge request must create no regressions an
- Verified as working in production on GitLab.com.
- Verified as working for self-managed instances.
-- Verified as supporting [Geo](../../administration/geo/index.md) via the [self-service framework](../geo/framework.md). To learn more see [here](../geo/framework.md#geo-is-a-requirement-in-the-definition-of-done).
+- Verified as supporting [Geo](../../administration/geo/index.md) through the [self-service framework](../geo/framework.md). For more information, see [Geo is a requirement in the definition of done](../geo/framework.md#geo-is-a-requirement-in-the-definition-of-done).
If a regression occurs, we prefer you revert the change.
Your contribution is *incomplete* until you have made sure it meets all of these
diff --git a/doc/development/database/migrations_for_multiple_databases.md b/doc/development/database/migrations_for_multiple_databases.md
index bc0ef654336..b903c56651d 100644
--- a/doc/development/database/migrations_for_multiple_databases.md
+++ b/doc/development/database/migrations_for_multiple_databases.md
@@ -10,8 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
This document describes how to properly write database migrations
for [the decomposed GitLab application using multiple databases](https://gitlab.com/groups/gitlab-org/-/epics/6168).
-
-Learn more about general multiple databases support in a [separate document](multiple_databases.md).
+For more information, see [Multiple databases](multiple_databases.md).
The design for multiple databases (except for the Geo database) assumes
that all decomposed databases have **the same structure** (for example, schema), but **the data is different** in each database. This means that some tables do not contain data on each database.
diff --git a/doc/development/fe_guide/design_anti_patterns.md b/doc/development/fe_guide/design_anti_patterns.md
index 21f257ca4b6..f087fbd8235 100644
--- a/doc/development/fe_guide/design_anti_patterns.md
+++ b/doc/development/fe_guide/design_anti_patterns.md
@@ -67,9 +67,7 @@ side-effects can be notoriously difficult to reason with.
### References
-To read more on this topic, check out the following references:
-
-- [GlobalVariablesAreBad from C2 wiki](https://wiki.c2.com/?GlobalVariablesAreBad)
+For more information, see [Global Variables Are Bad on the C2 wiki](https://wiki.c2.com/?GlobalVariablesAreBad).
## Singleton (Anti-pattern)
diff --git a/doc/development/fe_guide/view_component.md b/doc/development/fe_guide/view_component.md
index f9d148d8b82..0245110ec75 100644
--- a/doc/development/fe_guide/view_component.md
+++ b/doc/development/fe_guide/view_component.md
@@ -10,8 +10,8 @@ ViewComponent is a framework for creating reusable, testable & encapsulated view
components with Ruby on Rails, without the need for a JavaScript framework like Vue.
They are rendered server-side and can be seamlessly used with template languages like [Haml](haml.md).
-Refer to the official [documentation](https://viewcomponent.org/) to learn more or
-watch this [introduction video](https://youtu.be/akRhUbvtnmo).
+For more information, see the [official documentation](https://viewcomponent.org/) or
+[this introduction video](https://youtu.be/akRhUbvtnmo).
## Browse components with Lookbook
diff --git a/doc/development/performance.md b/doc/development/performance.md
index 02e6c2fd884..346f70e04b0 100644
--- a/doc/development/performance.md
+++ b/doc/development/performance.md
@@ -583,8 +583,8 @@ You may find the results:
**Metrics Reports** [dropdown list](../ci/testing/metrics_reports.md).
- In the `memory-on-boot` artifacts for a full report and a dependency breakdown.
-`derailed_benchmarks` also provides other methods to investigate memory. To learn more,
-refer to the [gem documentation](https://github.com/zombocom/derailed_benchmarks#running-derailed-exec).
+`derailed_benchmarks` also provides other methods to investigate memory. For more information, see
+the [gem documentation](https://github.com/zombocom/derailed_benchmarks#running-derailed-exec).
Most of the methods (`derailed exec perf:*`) attempt to boot your Rails app in a
`production` environment and run benchmarks against it.
It is possible both in GDK and GCK:
diff --git a/doc/development/ruby3_gotchas.md b/doc/development/ruby3_gotchas.md
index 4768d6e1182..0d000bc68df 100644
--- a/doc/development/ruby3_gotchas.md
+++ b/doc/development/ruby3_gotchas.md
@@ -57,7 +57,7 @@ To write code that works under both 2.7 and 3.0, consider the following options:
We recommend always passing the block explicitly, and prefer two required arguments as block parameters.
-To learn more, see [Ruby issue 12706](https://bugs.ruby-lang.org/issues/12706).
+For more information, see [Ruby issue 12706](https://bugs.ruby-lang.org/issues/12706).
## `Symbol#to_proc` returns signature metadata consistent with lambdas
@@ -92,7 +92,7 @@ called without a receiver.
Ruby 3 corrects this: the code that tests `Proc` object arity or parameter lists might now break and
has to be updated.
-To learn more, see [Ruby issue 16260](https://bugs.ruby-lang.org/issues/16260).
+For more information, see [Ruby issue 16260](https://bugs.ruby-lang.org/issues/16260).
## `OpenStruct` does not evaluate fields lazily
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index 876def53b2d..6c64e3b2acc 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -266,8 +266,7 @@ value, we **will not** be protected against DNS rebinding.
This is the case with validators such as the `AddressableUrlValidator` (called with `validates :url, addressable_url: {opts}` or `public_url: {opts}`).
Validation errors are only raised when validations are called, for example when a record is created or saved. If we ignore the value returned by the validation
-when persisting the record, **we need to recheck** its validity before using it. You can learn more about [Time of Check to Time of Use bugs](#time-of-check-to-time-of-use-bugs) in a later section
-of these guidelines.
+when persisting the record, **we need to recheck** its validity before using it. For more information, see [Time of check to time of use bugs](#time-of-check-to-time-of-use-bugs).
#### Feature-specific mitigations
@@ -291,7 +290,7 @@ implement.
- For HTTP connections: Disable redirects or validate the redirect destination
- To mitigate DNS rebinding attacks, validate and use the first IP address received.
-See [`url_blocker_spec.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/lib/gitlab/url_blocker_spec.rb) for examples of SSRF payloads. See [time of check to time of use bugs](#time-of-check-to-time-of-use-bugs) to learn more about DNS rebinding's class of bug.
+See [`url_blocker_spec.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/lib/gitlab/url_blocker_spec.rb) for examples of SSRF payloads. For more information about the DNS-rebinding class of bugs, see [Time of check to time of use bugs](#time-of-check-to-time-of-use-bugs).
Don't rely on methods like `.start_with?` when validating a URL, or make assumptions about which
part of a string maps to which part of a URL. Use the `URI` class to parse the string, and validate
diff --git a/doc/development/sidekiq/index.md b/doc/development/sidekiq/index.md
index ea6f613a1f2..355f5a3b753 100644
--- a/doc/development/sidekiq/index.md
+++ b/doc/development/sidekiq/index.md
@@ -131,8 +131,8 @@ gitlab:sidekiq:all_queues_yml:generate` to regenerate
`app/workers/all_queues.yml` or `ee/app/workers/all_queues.yml` so that
it can be picked up by
[`sidekiq-cluster`](../../administration/sidekiq/extra_sidekiq_processes.md)
-in installations that don't use routing rules. To learn more about potential changes,
-read [Use routing rules by default and deprecate queue selectors for self-managed](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/596).
+in installations that don't use routing rules. For more information about potential changes,
+see [epic 596](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/596).
Additionally, run
`bin/rake gitlab:sidekiq:sidekiq_queues_yml:generate` to regenerate
diff --git a/doc/development/stage_group_observability/dashboards/stage_group_dashboard.md b/doc/development/stage_group_observability/dashboards/stage_group_dashboard.md
index abc46c52407..7c596e544b5 100644
--- a/doc/development/stage_group_observability/dashboards/stage_group_dashboard.md
+++ b/doc/development/stage_group_observability/dashboards/stage_group_dashboard.md
@@ -168,7 +168,7 @@ stageGroupDashboards.dashboard('source_code')
If you want to see the workflow in action, we've recorded a pairing session on customizing a dashboard,
available on [GitLab Unfiltered](https://youtu.be/shEd_eiUjdI).
-For deeper customization and more complicated metrics, visit the
+For deeper customization and more complicated metrics, see the
[Grafonnet lib](https://github.com/grafana/grafonnet-lib) project and the
[GitLab Prometheus Metrics](../../../administration/monitoring/prometheus/gitlab_metrics.md#gitlab-prometheus-metrics)
documentation.
diff --git a/doc/development/stage_group_observability/index.md b/doc/development/stage_group_observability/index.md
index 08f751c508e..b275b0bfec2 100644
--- a/doc/development/stage_group_observability/index.md
+++ b/doc/development/stage_group_observability/index.md
@@ -35,7 +35,7 @@ stage group is comparable to the
[monthly availability](https://about.gitlab.com/handbook/engineering/infrastructure/performance-indicators/#gitlabcom-availability)
we calculate for GitLab.com, except it's scoped to the features of a group.
-To learn more about how we use error budgets, see the
+For more information about how we use error budgets, see the
[Engineering Error Budgets](https://about.gitlab.com/handbook/engineering/error-budgets/) handbook page.
By default, the first row of panels on both dashboards shows the
diff --git a/doc/development/testing_guide/contract/consumer_tests.md b/doc/development/testing_guide/contract/consumer_tests.md
index 39cc34d6153..60ce71db79d 100644
--- a/doc/development/testing_guide/contract/consumer_tests.md
+++ b/doc/development/testing_guide/contract/consumer_tests.md
@@ -17,7 +17,7 @@ Then, populate it with the following function and parameters:
- [`PactOptions`](#the-pactoptions-parameter)
- [`PactFn`](#the-pactfn-parameter)
-To learn more about how the contract test directory is structured, see the contract testing [test suite folder structure](index.md#test-suite-folder-structure).
+For more information about how the contract test directory is structured, see [Test suite folder structure](index.md#test-suite-folder-structure).
### The `pactWith` function
@@ -47,7 +47,7 @@ pactWith(
);
```
-To learn more about how to name the consumers and providers, see contract testing [naming conventions](index.md#naming-conventions).
+For more information about how to name consumers and providers, see [Naming conventions](index.md#naming-conventions).
### The `PactFn` parameter
diff --git a/doc/development/testing_guide/contract/provider_tests.md b/doc/development/testing_guide/contract/provider_tests.md
index 3ce9f91a307..cb3aeae529d 100644
--- a/doc/development/testing_guide/contract/provider_tests.md
+++ b/doc/development/testing_guide/contract/provider_tests.md
@@ -12,7 +12,7 @@ This tutorial guides you through writing a provider test from scratch. It is a c
Provider tests are quite simple. The goal is to set up the test data and then link that with the corresponding contract. Start by creating a file called `get_discussions_helper.rb` under `spec/contracts/provider/pact_helpers/project/merge_request`. Note that the files are called `helpers` to match how they are called by Pact in the Rake tasks, which are set up at the end of this tutorial.
-To learn more about how the contract test directory is structured, see the contract testing [test suite folder structure](index.md#test-suite-folder-structure).
+For more information about how the contract test directory is structured, see [Test suite folder structure](index.md#test-suite-folder-structure).
### The `service_provider` block
@@ -48,7 +48,7 @@ module Provider
end
```
-To learn more about how to name the consumers and providers, see contract testing [naming conventions](index.md#naming-conventions).
+For more information about how to name consumers and providers, see [Naming conventions](index.md#naming-conventions).
## Configure the test app
diff --git a/doc/development/testing_guide/end_to_end/index.md b/doc/development/testing_guide/end_to_end/index.md
index 1481b4364a7..77ceb9fa546 100644
--- a/doc/development/testing_guide/end_to_end/index.md
+++ b/doc/development/testing_guide/end_to_end/index.md
@@ -259,8 +259,7 @@ Learn how to perform [tests that require special setup or consideration to run o
## How do you write tests?
-In order to write new tests, you first need to learn more about GitLab QA
-architecture. See the [documentation about it](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/architecture.md).
+Before you write new tests, review the [GitLab QA architecture](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/architecture.md).
After you've decided where to put [test environment orchestration scenarios](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/lib/gitlab/qa/scenario) and
[instance-level scenarios](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features), take a look at the [GitLab QA README](https://gitlab.com/gitlab-org/gitlab/-/tree/master/qa/README.md),
diff --git a/doc/index.md b/doc/index.md
index d532004f6c2..492320d93aa 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -59,7 +59,7 @@ GitLab provides solutions for [each of the stages of the DevOps lifecycle](https
### User account
-Learn more about GitLab account management:
+For more information about GitLab account management, see:
| Topic | Description |
|:-----------------------------------------------------------|:------------|
diff --git a/doc/install/aws/gitlab_hybrid_on_aws.md b/doc/install/aws/gitlab_hybrid_on_aws.md
index 7f45eb96e86..b8c840782b1 100644
--- a/doc/install/aws/gitlab_hybrid_on_aws.md
+++ b/doc/install/aws/gitlab_hybrid_on_aws.md
@@ -34,7 +34,7 @@ Amazon provides a managed Kubernetes service offering known as [Amazon Elastic K
The [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/README.md) is an effort made by GitLab to create a multi-cloud, multi-GitLab (Omnibus + Cloud Native Hybrid) toolkit to provision GitLab. GET is developed by GitLab developers and is open to community contributions. GET is where GitLab is investing its resources as the primary option for Infrastructure as Code, and is being actively used in production as a part of [GitLab Dedicated](../../subscriptions/gitlab_dedicated/index.md).
-Read the [GitLab Environment Toolkit (GET) direction](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/README.md#direction) to learn more about the project and where it is going.
+For more information about the project, see [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/README.md).
The [AWS Quick Start for GitLab Cloud Native Hybrid on EKS](https://aws-quickstart.github.io/quickstart-eks-gitlab/) is developed by AWS, GitLab, and the community that contributes to AWS Quick Starts, whether directly to the GitLab Quick Start or to the underlying Quick Start dependencies GitLab inherits (for example, EKS Quick Start).
diff --git a/doc/install/aws/manual_install_aws.md b/doc/install/aws/manual_install_aws.md
index 29e0c56a16b..51ae16ccd17 100644
--- a/doc/install/aws/manual_install_aws.md
+++ b/doc/install/aws/manual_install_aws.md
@@ -732,8 +732,8 @@ Because our instances are created by the auto scaling group, go back to your ins
Apart from Amazon's Cloudwatch which you can enable on various services,
GitLab provides its own integrated monitoring solution based on Prometheus.
-For more information on how to set it up, visit the
-[GitLab Prometheus documentation](../../administration/monitoring/prometheus/index.md)
+For more information about how to set it up, see
+[GitLab Prometheus](../../administration/monitoring/prometheus/index.md).
GitLab also has various [health check endpoints](../../user/admin_area/monitoring/health_check.md)
that you can ping and get reports.
diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md
index 9d825bbadcd..d92859d518f 100644
--- a/doc/install/azure/index.md
+++ b/doc/install/azure/index.md
@@ -71,8 +71,8 @@ The first items you need to configure are the basic settings of the underlying v
the user Azure uses to connect to the VM through SSH. By default, the user
has root access.
1. Determine if you want to provide your own SSH key or let Azure create one for you.
- Read the [SSH documentation](../../user/ssh.md) to learn more about how to set up SSH
- public keys.
+ For more information about how to set up SSH
+ public keys, see [SSH](../../user/ssh.md).
Review your entered settings, and then proceed to the Disks tab.
diff --git a/doc/integration/gitpod.md b/doc/integration/gitpod.md
index 759e5297014..53a05f66675 100644
--- a/doc/integration/gitpod.md
+++ b/doc/integration/gitpod.md
@@ -28,7 +28,7 @@ To use the GitLab Gitpod integration, it must be enabled for your GitLab instanc
1. It's [enabled and configured by a GitLab administrator](#configure-a-self-managed-instance).
1. It's [enabled in their user settings](#enable-gitpod-in-your-user-settings).
-To learn more about Gitpod, see their [features](https://www.gitpod.io/) and
+For more information about Gitpod, see the Gitpod [features](https://www.gitpod.io/) and
[documentation](https://www.gitpod.io/docs/).
## Enable Gitpod in your user settings
diff --git a/doc/integration/jira/jira_server_configuration.md b/doc/integration/jira/jira_server_configuration.md
index fd8e018fd0c..7dee99b024e 100644
--- a/doc/integration/jira/jira_server_configuration.md
+++ b/doc/integration/jira/jira_server_configuration.md
@@ -29,7 +29,7 @@ This process creates a user named `gitlab`:
- **Username**: Jira creates the username by using the email prefix. You can change
this username later.
- **Password**: You must create a password, because the GitLab integration doesn't
- support SSO, such as SAML. To create the password, visit the user profile, look up
+ support SSO, such as SAML. To create the password, go to the user profile, look up
the username, and set a password.
1. Select **Create user**.
diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md
index 5cfb8a77fc9..45f1e10d2f1 100644
--- a/doc/operations/incident_management/incidents.md
+++ b/doc/operations/incident_management/incidents.md
@@ -43,7 +43,7 @@ When you [view the incidents list](manage_incidents.md#view-incidents-list), it
![Incidents List](img/incident_list_v15_6.png)
-For an example of the incident list in action, visit this
+For an example of the incident list in action, see this
[demo project](https://gitlab.com/gitlab-org/monitor/monitor-sandbox/-/incidents).
### Sort the incident list
diff --git a/doc/operations/incident_management/slack.md b/doc/operations/incident_management/slack.md
index 0e7a85142f6..434c481900c 100644
--- a/doc/operations/incident_management/slack.md
+++ b/doc/operations/incident_management/slack.md
@@ -41,7 +41,7 @@ Prerequisites:
To start the authorization flow, try executing a non-incident [Slack slash command](../../integration/slash_commands.md),
like `/gitlab <project-alias> issue show <id>`.
The `<project-alias>` you select must be a project that has the GitLab for Slack app set up.
- For more context, visit [issue 377548](https://gitlab.com/gitlab-org/gitlab/-/issues/377548).
+ For more information, see [issue 377548](https://gitlab.com/gitlab-org/gitlab/-/issues/377548).
<!-- The below content is commented out until these features are implemented in https://gitlab.com/groups/gitlab-org/-/epics/8545 -->
<!--
diff --git a/doc/operations/metrics/index.md b/doc/operations/metrics/index.md
index 0ecb63807fb..11350d65237 100644
--- a/doc/operations/metrics/index.md
+++ b/doc/operations/metrics/index.md
@@ -25,7 +25,7 @@ critical. For GitLab to display your information in charts, you must:
Use applications like Elasticsearch, Prometheus, and Jaeger to gather
the data you've exposed.
1. **GitLab collects metrics** - GitLab uses Prometheus to scrape the data you've
- captured in your applications, and prepares the data for display. To learn more, read
+ captured in your applications, and prepares the data for display. For more information, see
[Collect and process metrics](#collect-and-process-metrics).
1. **Display charts in the GitLab user interface** - GitLab converts your metrics
into easy-to-read charts on a default dashboard. You can create as many custom charts
@@ -54,9 +54,9 @@ GitLab attempts to retrieve performance metrics for any [environment](../../ci/e
a successful deployment.
GitLab scans the Prometheus server for metrics from known servers like Kubernetes
-and NGINX, and attempts to identify individual environments. To learn more about
-the supported metrics and scan processes, see the
-[Prometheus Metrics Library documentation](../../user/project/integrations/prometheus_library/index.md).
+and NGINX, and attempts to identify individual environments. For more information about
+the supported metrics and scan processes, see
+[Prometheus Metrics library](../../user/project/integrations/prometheus_library/index.md).
To view the [default metrics dashboard](dashboards/default.md) for an environment that is
[configured to gather metrics](#configure-prometheus-to-gather-metrics):
diff --git a/doc/subscriptions/gitlab_dedicated/index.md b/doc/subscriptions/gitlab_dedicated/index.md
index 9d779675c2d..2d684edb992 100644
--- a/doc/subscriptions/gitlab_dedicated/index.md
+++ b/doc/subscriptions/gitlab_dedicated/index.md
@@ -84,8 +84,9 @@ The following AWS regions are not available:
## Planned features
-Learn more about the planned improvements to GitLab Dedicated on the public [direction page](https://about.gitlab.com/direction/saas-platforms/dedicated/).
+For more information about the planned improvements to GitLab Dedicated,
+see the [category direction page](https://about.gitlab.com/direction/saas-platforms/dedicated/).
-## Learn more about GitLab Dedicated and join our waitlist
+## Join the GitLab Dedicated waitlist
-As we scale this new offering, we are making GitLab Dedicated available by inviting customers to learn more and join our waitlist [on our website](https://about.gitlab.com/single-tenant-saas).
+As we scale this new offering, we are making GitLab Dedicated available by inviting customers to [join our waitlist](https://about.gitlab.com/dedicated/).
diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md
index 9fec4abe8e7..2c9f93886bf 100644
--- a/doc/subscriptions/index.md
+++ b/doc/subscriptions/index.md
@@ -234,10 +234,8 @@ For qualifying startups, the [GitLab for Startups](https://about.gitlab.com/solu
## Contact Support
-Learn more about:
-
-- The tiers of [GitLab Support](https://about.gitlab.com/support/).
-- [Submit a request via the Support Portal](https://support.gitlab.com/hc/en-us/requests/new).
+- See the tiers of [GitLab Support](https://about.gitlab.com/support/).
+- [Submit a request](https://support.gitlab.com/hc/en-us/requests/new) through the Support Portal.
We also encourage all users to search our project trackers for known issues and existing feature requests in the [GitLab project](https://gitlab.com/gitlab-org/gitlab/-/issues/).
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
index 8c3b49a4374..b5436b6cb72 100644
--- a/doc/subscriptions/self_managed/index.md
+++ b/doc/subscriptions/self_managed/index.md
@@ -478,10 +478,8 @@ If you have a license file or key, you can activate it [in the Admin Area](../..
## Contact Support
-Learn more about:
-
-- The tiers of [GitLab Support](https://about.gitlab.com/support/).
-- [Submit a request via the Support Portal](https://support.gitlab.com/hc/en-us/requests/new).
+- See the tiers of [GitLab Support](https://about.gitlab.com/support/).
+- [Submit a request](https://support.gitlab.com/hc/en-us/requests/new) through the Support Portal.
We also encourage all users to search our project trackers for known issues and
existing feature requests in the [GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/) project.
diff --git a/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md b/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md
index 9b0ba196042..9bd1d30e1b1 100644
--- a/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md
+++ b/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md
@@ -188,7 +188,7 @@ The jobs are separated into stages:
([Auto License Compliance](../stages.md#auto-license-compliance))
- **Review** - Pipelines on the default branch include this stage with a `dast_environment_deploy` job.
- To learn more, see [Dynamic Application Security Testing (DAST)](../../../user/application_security/dast/index.md).
+ For more information, see [Dynamic Application Security Testing (DAST)](../../../user/application_security/dast/index.md).
- **Production** - After the tests and checks finish, the application deploys in
Kubernetes ([Auto Deploy](../stages.md#auto-deploy)).
diff --git a/doc/topics/autodevops/requirements.md b/doc/topics/autodevops/requirements.md
index aa9627c1247..a409c6f1520 100644
--- a/doc/topics/autodevops/requirements.md
+++ b/doc/topics/autodevops/requirements.md
@@ -152,7 +152,7 @@ To make full use of Auto DevOps with Kubernetes, you need:
The [Prometheus integration](../../user/project/integrations/prometheus.md)
integration must be activated for the project, or activated at the group or instance level.
- Learn more about [Project integration management](../../user/admin_area/settings/project_integration_management.md).
+ For more information, see [Project integration management](../../user/admin_area/settings/project_integration_management.md).
To get response metrics (in addition to system metrics), you must
[configure Prometheus to monitor NGINX](../../user/project/integrations/prometheus_library/nginx_ingress.md#configuring-nginx-ingress-monitoring).
diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md
index d07cb29dbcc..0c5c87cdf0f 100644
--- a/doc/topics/autodevops/stages.md
+++ b/doc/topics/autodevops/stages.md
@@ -63,7 +63,7 @@ For the requirements of other languages and frameworks, read the
NOTE:
Auto Test still uses Herokuish, as test suite detection is not
yet part of the Cloud Native Buildpack specification. For more information, see
-[this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/212689).
+[issue 212689](https://gitlab.com/gitlab-org/gitlab/-/issues/212689).
#### Mount volumes into the build container
@@ -210,8 +210,8 @@ After creating the report, it's uploaded as an artifact which you can later
download and check out. The merge request widget also displays any security
warnings on [Ultimate](https://about.gitlab.com/pricing/) licenses.
-To learn more about [how SAST works](../../user/application_security/sast/index.md),
-see the documentation.
+For more information, see
+[Static Application Security Testing (SAST)](../../user/application_security/sast/index.md).
## Auto Secret Detection
@@ -225,7 +225,7 @@ After creating the report, it's uploaded as an artifact which you can later
download and evaluate. The merge request widget also displays any security
warnings on [Ultimate](https://about.gitlab.com/pricing/) licenses.
-To learn more, see [Secret Detection](../../user/application_security/secret_detection/index.md).
+For more information, see [Secret Detection](../../user/application_security/secret_detection/index.md).
## Auto Dependency Scanning **(ULTIMATE)**
@@ -237,9 +237,8 @@ The Auto Dependency Scanning stage is skipped on licenses other than
After creating the report, it's uploaded as an artifact which you can later download and
check out. The merge request widget displays any security warnings detected,
-To learn more about
-[Dependency Scanning](../../user/application_security/dependency_scanning/index.md),
-see the documentation.
+For more information, see
+[Dependency Scanning](../../user/application_security/dependency_scanning/index.md).
## Auto License Compliance **(ULTIMATE)**
@@ -253,9 +252,8 @@ is skipped on licenses other than [Ultimate](https://about.gitlab.com/pricing/).
After creating the report, it's uploaded as an artifact which you can later download and
check out. The merge request displays any detected licenses.
-To learn more about
-[License Compliance](../../user/compliance/license_compliance/index.md), see the
-documentation.
+For more information, see
+[License Compliance](../../user/compliance/license_compliance/index.md).
## Auto Container Scanning
@@ -266,9 +264,8 @@ skipped on licenses other than [Ultimate](https://about.gitlab.com/pricing/).
After creating the report, it's uploaded as an artifact which you can later download and
check out. The merge request displays any detected security issues.
-To learn more about
-[Container Scanning](../../user/application_security/container_scanning/index.md),
-see the documentation.
+For more information, see
+[Container Scanning](../../user/application_security/container_scanning/index.md).
## Auto Review Apps
@@ -323,9 +320,8 @@ After the DAST scan completes, any security warnings are displayed
on the [Security Dashboard](../../user/application_security/security_dashboard/index.md)
and the merge request widget.
-To learn more about
-[Dynamic Application Security Testing](../../user/application_security/dast/index.md),
-see the documentation.
+For more information, see
+[Dynamic Application Security Testing (DAST)](../../user/application_security/dast/index.md).
### Overriding the DAST target
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index 163848fb256..cac203ffac0 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -254,7 +254,7 @@ Git LFS authenticates the user with HTTP Basic Authentication on every push for
every object, so user HTTPS credentials are required.
By default, Git has support for remembering the credentials for each repository
-you use. To learn more, read the [Git credentials man pages](https://git-scm.com/docs/gitcredentials).
+you use. For more information, see the [official Git documentation](https://git-scm.com/docs/gitcredentials).
For example, you can tell Git to remember the password for a period of time in
which you expect to push the objects:
diff --git a/doc/topics/git/numerous_undo_possibilities_in_git/index.md b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
index 29f1be3617a..56223e7bcbd 100644
--- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md
+++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
@@ -391,8 +391,8 @@ Tools are available to execute Git commands more quickly.
These tools are faster because they do not provide the same
feature set as `git filter-branch` does, but focus on specific use cases.
-Refer to [Reduce repository size](../../../user/project/repository/reducing_the_repo_size_using_git.md) to
-learn more about purging files from repository history and GitLab storage.
+For more information about purging files from the repository history and GitLab storage,
+see [Reduce repository size](../../../user/project/repository/reducing_the_repo_size_using_git.md).
<!-- ## Troubleshooting
diff --git a/doc/topics/offline/quick_start_guide.md b/doc/topics/offline/quick_start_guide.md
index c67fad32095..80ce703f7db 100644
--- a/doc/topics/offline/quick_start_guide.md
+++ b/doc/topics/offline/quick_start_guide.md
@@ -204,7 +204,7 @@ The Version Check and Service Ping services improve the GitLab user experience a
users are on the most up-to-date instances of GitLab. These two services can be turned off for offline
environments so that they do not attempt and fail to reach out to GitLab services.
-Learn more about [disabling usage statistics](../../user/admin_area/settings/usage_statistics.md#enable-or-disable-usage-statistics).
+For more information, see [Enable or disable usage statistics](../../user/admin_area/settings/usage_statistics.md#enable-or-disable-usage-statistics).
### Configure NTP
diff --git a/doc/user/admin_area/settings/floc.md b/doc/user/admin_area/settings/floc.md
index f8137afa40f..451acc07240 100644
--- a/doc/user/admin_area/settings/floc.md
+++ b/doc/user/admin_area/settings/floc.md
@@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Federated Learning of Cohorts (FLoC) is a new feature of the Chrome browser.
It works by categorizing users into different cohorts, so that
advertisers can use this data to uniquely target and track users. For more
-information, visit the [FLoC repository](https://github.com/WICG/floc).
+information, see the [FLoC repository](https://github.com/WICG/floc).
To avoid users being tracked and categorized in any GitLab instance, FLoC is
disabled by default by sending the following header:
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index 58db404f809..a118dfb71a8 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -397,7 +397,7 @@ To fix this issue, you can either:
- echo "custom job"
```
-Learn more on overriding security jobs:
+For more information about overriding security jobs, see:
- [Overriding SAST jobs](sast/index.md#overriding-sast-jobs).
- [Overriding Dependency Scanning jobs](dependency_scanning/index.md#overriding-dependency-scanning-jobs).
@@ -602,7 +602,7 @@ To fix this issue, you must either:
- [Transition your `only/except` syntax to `rules`](#transitioning-your-onlyexcept-syntax-to-rules).
- (Temporarily) [Pin your templates to the deprecated versions](#pin-your-templates-to-the-deprecated-versions)
-[Learn more on overriding SAST jobs](sast/index.md#overriding-sast-jobs).
+For more information, see [Overriding SAST jobs](sast/index.md#overriding-sast-jobs).
#### Transitioning your `only/except` syntax to `rules`
@@ -664,7 +664,7 @@ spotbugs-sast:
- if: $CI_COMMIT_TAG == null
```
-[Learn more on the usage of `rules`](../../ci/yaml/index.md#rules).
+For more information, see [`rules`](../../ci/yaml/index.md#rules).
#### Pin your templates to the deprecated versions
diff --git a/doc/user/application_security/sast/analyzers.md b/doc/user/application_security/sast/analyzers.md
index 8e58af35855..c8542142830 100644
--- a/doc/user/application_security/sast/analyzers.md
+++ b/doc/user/application_security/sast/analyzers.md
@@ -151,7 +151,7 @@ To preview the upcoming changes to the CI/CD configuration in GitLab 15.3 or ear
1. Verify that scanning jobs succeed in the MR. You notice findings from the removed analyzers in _Fixed_ and findings from Semgrep in _New_. (Some findings may show different names, descriptions, and severities, since GitLab manages and edits the Semgrep rulesets.)
1. Close the MR.
-To learn more about Stable and Latest templates, see documentation on [CI/CD template versioning](../../../development/cicd/templates.md#versioning).
+For more information about Stable and Latest templates, see [CI/CD template versioning](../../../development/cicd/templates.md#versioning).
## Customize analyzers
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index d55f9cf3382..90b8a34a9cb 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -73,7 +73,7 @@ is **not** `19.03.0`. See [troubleshooting information](#error-response-from-dae
GitLab SAST supports scanning a variety of programming languages and frameworks.
Once you [enable SAST](#configuration), the right set of analyzers runs automatically even if your project uses more than one language.
-Check the [SAST direction page](https://about.gitlab.com/direction/secure/static-analysis/sast/#language-support) to learn more about our plans for language support in SAST.
+For more information about our plans for language support in SAST, see the [category direction page](https://about.gitlab.com/direction/secure/static-analysis/sast/#language-support).
| Language / framework | [Analyzer](analyzers.md) used for scanning | Minimum supported GitLab version |
|------------------------------|--------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|
diff --git a/doc/user/award_emojis.md b/doc/user/award_emojis.md
index 71aeb463b4f..e1459717241 100644
--- a/doc/user/award_emojis.md
+++ b/doc/user/award_emojis.md
@@ -44,11 +44,11 @@ To remove an award emoji, select the emoji again.
## Custom emojis
You can upload custom emojis to a GitLab instance with the GraphQL API.
-For more, visit [Use custom emojis with GraphQL](../api/graphql/custom_emoji.md).
+For more information, see [Use custom emojis with GraphQL](../api/graphql/custom_emoji.md).
Custom emojis don't show in the emoji picker.
To use them in a text box, type the filename without the extension and surrounded by colons.
For example, for a file named `thank-you.png`, type `:thank-you:`.
-For the list of custom emojis available for GitLab.com, visit
+For a list of custom emojis available for GitLab.com, see
[the `custom_emoji` project](https://gitlab.com/custom_emoji/custom_emoji/-/tree/main/img).
diff --git a/doc/user/clusters/agent/gitops.md b/doc/user/clusters/agent/gitops.md
index ba5029229c0..787b0062017 100644
--- a/doc/user/clusters/agent/gitops.md
+++ b/doc/user/clusters/agent/gitops.md
@@ -115,10 +115,7 @@ The agent has [default sorting](https://github.com/kubernetes-sigs/cli-utils/blo
but with annotations, you can fine-tune the order and apply time-value injection.
To provide the GitOps functionality, the GitLab agent for Kubernetes uses the [`cli-utils` library](https://github.com/kubernetes-sigs/cli-utils/),
-a Kubernetes SIG project. You can read more about the available annotations in the [`cli-utils` documentation](https://github.com/kubernetes-sigs/cli-utils/blob/master/README.md#apply-sort-ordering).
-
-- [Learn more about apply sort ordering](https://github.com/kubernetes-sigs/cli-utils#apply-sort-ordering).
-- [Learn more about apply-time mutation](https://github.com/kubernetes-sigs/cli-utils#apply-time-mutation).
+a Kubernetes SIG project. For more information, see the available annotations in the [`cli-utils` documentation](https://github.com/kubernetes-sigs/cli-utils/blob/master/README.md).
## Automatic drift remediation
diff --git a/doc/user/clusters/cost_management.md b/doc/user/clusters/cost_management.md
index 3d5641c8ceb..74bfab49c55 100644
--- a/doc/user/clusters/cost_management.md
+++ b/doc/user/clusters/cost_management.md
@@ -60,8 +60,8 @@ this dashboard.
### Customize the cost dashboard
You can customize the cost dashboard by editing the `.gitlab/dashboards/default_costs.yml`
-file or creating similar dashboard configuration files. To learn more, read about
-[customizing dashboards in our documentation](../../operations/metrics/dashboards/index.md).
+file or creating similar dashboard configuration files. For more information, see
+[Custom dashboards](../../operations/metrics/dashboards/index.md).
#### Available metrics
diff --git a/doc/user/compliance/compliance_report/index.md b/doc/user/compliance/compliance_report/index.md
index 15bc78147ae..04609026793 100644
--- a/doc/user/compliance/compliance_report/index.md
+++ b/doc/user/compliance/compliance_report/index.md
@@ -55,9 +55,9 @@ The following is a list of violations that are either:
| Violation | Severity level | Category | Description | Availability |
|:-------------------------------------|:----------------|:---------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------|
-| Author approved merge request | High | [Separation of duties](#separation-of-duties) | The author of the merge request approved their own merge request. [Learn more](../../project/merge_requests/approvals/settings.md#prevent-approval-by-author). | [Available in GitLab 14.10](https://gitlab.com/groups/gitlab-org/-/epics/6870) |
-| Committers approved merge request | High | [Separation of duties](#separation-of-duties) | The committers of the merge request approved the merge request they contributed to. [Learn more](../../project/merge_requests/approvals/settings.md#prevent-approvals-by-users-who-add-commits). | [Available in GitLab 14.10](https://gitlab.com/groups/gitlab-org/-/epics/6870) |
-| Fewer than two approvals | High | [Separation of duties](#separation-of-duties) | The merge request was merged with fewer than two approvals. [Learn more](../../project/merge_requests/approvals/rules.md). | [Available in GitLab 14.10](https://gitlab.com/groups/gitlab-org/-/epics/6870) |
+| Author approved merge request | High | [Separation of duties](#separation-of-duties) | The author of the merge request approved their own merge request. For more information, see [Prevent approval by author](../../project/merge_requests/approvals/settings.md#prevent-approval-by-author). | [Available in GitLab 14.10](https://gitlab.com/groups/gitlab-org/-/epics/6870) |
+| Committers approved merge request | High | [Separation of duties](#separation-of-duties) | The committers of the merge request approved the merge request they contributed to. For more information, see [Prevent approvals by users who add commits](../../project/merge_requests/approvals/settings.md#prevent-approvals-by-users-who-add-commits). | [Available in GitLab 14.10](https://gitlab.com/groups/gitlab-org/-/epics/6870) |
+| Fewer than two approvals | High | [Separation of duties](#separation-of-duties) | The merge request was merged with fewer than two approvals. For more information, see [Merge request approval rules](../../project/merge_requests/approvals/rules.md). | [Available in GitLab 14.10](https://gitlab.com/groups/gitlab-org/-/epics/6870) |
| Pipeline failed | Medium | [Pipeline results](../../../ci/pipelines/index.md) | The merge requests pipeline failed and was merged. | [Unavailable](https://gitlab.com/gitlab-org/gitlab/-/issues/346011) |
| Pipeline passed with warnings | Info | [Pipeline results](../../../ci/pipelines/index.md) | The merge request pipeline passed with warnings and was merged. | [Unavailable](https://gitlab.com/gitlab-org/gitlab/-/issues/346011) |
| Code coverage down more than 10% | High | [Code coverage](../../../ci/pipelines/settings.md#merge-request-test-coverage-results) | The code coverage report for the merge request indicates a reduction in coverage of more than 10%. | [Unavailable](https://gitlab.com/gitlab-org/gitlab/-/issues/346011) |
diff --git a/doc/user/crm/index.md b/doc/user/crm/index.md
index 8c4fb6f1334..ebacda506b4 100644
--- a/doc/user/crm/index.md
+++ b/doc/user/crm/index.md
@@ -17,7 +17,7 @@ With customer relations management (CRM) you can create a record of contacts
Contacts and organizations can only be created for root groups.
You can use contacts and organizations to tie work to customers for billing and reporting purposes.
-To read more about what is planned for the future, see [issue 2256](https://gitlab.com/gitlab-org/gitlab/-/issues/2256).
+For more information about what is planned for the future, see [issue 2256](https://gitlab.com/gitlab-org/gitlab/-/issues/2256).
## Permissions
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index b0052be3f4e..d3fa8f28d5c 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -377,9 +377,9 @@ More details are available on the rate limits for
GitLab can rate-limit requests at several layers. The rate limits listed here
are configured in the application. These limits are the most
-restrictive per IP address. To learn more about the rate limiting
-for GitLab.com, read our runbook page
-[Overview of rate limits for GitLab.com](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/rate-limiting).
+restrictive per IP address. For more information about the rate limits
+for GitLab.com, see
+[an overview](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/rate-limiting).
### Rate limiting responses
diff --git a/doc/user/group/compliance_frameworks.md b/doc/user/group/compliance_frameworks.md
index 4d3d9318f33..01248d55b2d 100644
--- a/doc/user/group/compliance_frameworks.md
+++ b/doc/user/group/compliance_frameworks.md
@@ -203,9 +203,14 @@ audit trail:
include: # Execute individual project's configuration (if project contains .gitlab-ci.yml)
project: '$CI_PROJECT_PATH'
file: '$CI_CONFIG_PATH'
- ref: '$CI_COMMIT_REF_NAME' # Must be defined or MR pipelines always use the use default branch
+ ref: '$CI_COMMIT_SHA' # Must be defined or MR pipelines always use the use default branch
+ rules:
+ - if: $CI_PROJECT_PATH != "my-group/project-1" # Must be the hardcoded path to the project that hosts this configuration.
```
+The `rules` configuration in the `include` definition avoids circular inclusion in case the compliance pipeline must be able to run in the host project itself.
+You can leave it out if your compliance pipeline only ever runs in labeled projects.
+
#### CF pipelines in Merge Requests originating in project forks
When an MR originates in a fork, the branch to be merged usually only exists in the fork.
diff --git a/doc/user/group/epics/linked_epics.md b/doc/user/group/epics/linked_epics.md
index 63bf1a4471c..9ce4a585d14 100644
--- a/doc/user/group/epics/linked_epics.md
+++ b/doc/user/group/epics/linked_epics.md
@@ -16,7 +16,7 @@ The relationship only shows up in the UI if the user can see both epics. When yo
epic that has open blockers, a warning is displayed.
NOTE:
-To manage linked epics through our API, visit the [epic links API documentation](../../../api/linked_epics.md).
+To manage linked epics through our API, see [Linked epics API](../../../api/linked_epics.md).
## Add a linked epic
diff --git a/doc/user/infrastructure/index.md b/doc/user/infrastructure/index.md
index 811e4ad6ad6..87633932e0d 100644
--- a/doc/user/infrastructure/index.md
+++ b/doc/user/infrastructure/index.md
@@ -25,7 +25,7 @@ The various GitLab integrations help you:
with code changes.
- Scale using a module registry.
-Learn more about how GitLab can help you run [Infrastructure as Code](iac/index.md).
+For more information, see how GitLab can help you run [Infrastructure as Code](iac/index.md).
## Integrated Kubernetes management
@@ -34,7 +34,7 @@ cluster applications. With the GitLab agent, you can connect clusters behind a f
have real-time access to API endpoints, perform pull-based or push-based deployments for production
and non-production environments, and much more.
-Learn more about the [GitLab agent](../clusters/agent/index.md).
+For more information, see the [GitLab agent](../clusters/agent/index.md).
## Runbooks in GitLab
diff --git a/doc/user/operations_dashboard/index.md b/doc/user/operations_dashboard/index.md
index 619d822adf2..2911a700e14 100644
--- a/doc/user/operations_dashboard/index.md
+++ b/doc/user/operations_dashboard/index.md
@@ -36,4 +36,4 @@ You can drag project cards to change their order. The card order is currently on
## Making it the default dashboard when you sign in
The Operations Dashboard can also be made the default GitLab dashboard shown when
-you sign in. To make it the default, visit your [profile preferences](../profile/preferences.md).
+you sign in. To make it the default, see [Profile preferences](../profile/preferences.md).
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index c3790c252cc..e9cfae0fbdb 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -72,7 +72,7 @@ NOTE:
You must [authenticate with the container registry](authenticate_with_container_registry.md) to download
container images from a private repository.
-For more information on running container images, visit the [Docker documentation](https://docs.docker.com/get-started/).
+For more information on running container images, see the [Docker documentation](https://docs.docker.com/get-started/).
## Naming convention for your container images
diff --git a/doc/user/packages/infrastructure_registry/index.md b/doc/user/packages/infrastructure_registry/index.md
index ac31b491a0e..d06c5e7fb1e 100644
--- a/doc/user/packages/infrastructure_registry/index.md
+++ b/doc/user/packages/infrastructure_registry/index.md
@@ -34,9 +34,8 @@ authenticate with the [`CI_JOB_TOKEN` predefined variable](../../../ci/variables
CI/CD templates, which you can use to get started, are in [this repository](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
-Learn more about using CI/CD to build:
-
-- [Terraform modules](../terraform_module_registry/index.md#publish-a-terraform-module-by-using-cicd)
+For more information about using CI/CD to build Terraform modules,
+see [Publish a Terraform module by using CI/CD](../terraform_module_registry/index.md#publish-a-terraform-module-by-using-cicd).
If you use CI/CD to build a package, you can find extended activity information
when you view the package details:
diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md
index 104b9e0a666..cd60a229479 100644
--- a/doc/user/packages/package_registry/index.md
+++ b/doc/user/packages/package_registry/index.md
@@ -79,7 +79,7 @@ authenticate with GitLab by using the `CI_JOB_TOKEN`.
CI/CD templates, which you can use to get started, are in [this repository](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
-Learn more about using the GitLab Package Registry with CI/CD:
+For more information about using the GitLab Package Registry with CI/CD, see:
- [Composer](../composer_repository/index.md#publish-a-composer-package-by-using-cicd)
- [Conan](../conan_repository/index.md#publish-a-conan-package-by-using-cicd)
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 61cfe307e65..caba19b374b 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -423,8 +423,8 @@ When you add a member to a subgroup, they inherit the membership and
permission level from the parent groups. This model allows access to
nested groups if you have membership in one of its parents.
-To learn more, read through the documentation on
-[subgroups memberships](group/subgroups/index.md#subgroup-membership).
+For more information, see
+[subgroup memberships](group/subgroups/index.md#subgroup-membership).
## Users with minimal access **(PREMIUM)**
diff --git a/doc/user/product_analytics/index.md b/doc/user/product_analytics/index.md
index 86bbb78e3d4..6d6a609618b 100644
--- a/doc/user/product_analytics/index.md
+++ b/doc/user/product_analytics/index.md
@@ -15,7 +15,7 @@ On GitLab.com, this feature is not available.
This feature is not ready for production use.
This page is a work in progress, and we're updating the information as we add more features.
-For more information, visit the [Product Analytics group direction page](https://about.gitlab.com/direction/analytics/product-analytics/).
+For more information, see the [group direction page](https://about.gitlab.com/direction/analytics/product-analytics/).
## How Product Analytics works
diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md
index 6496ca523e6..68354501eba 100644
--- a/doc/user/profile/preferences.md
+++ b/doc/user/profile/preferences.md
@@ -67,7 +67,7 @@ GitLab uses the [rouge Ruby library](http://rouge.jneen.net/ "Rouge website")
for syntax highlighting outside of any Editor context. The WebIDE (like Snippets)
uses [Monaco Editor](https://microsoft.github.io/monaco-editor/) and it's provided
[Monarch](https://microsoft.github.io/monaco-editor/monarch.html) library for
-syntax highlighting. For a list of supported languages, visit the documentation of
+syntax highlighting. For a list of supported languages, see the documentation of
the respective libraries.
Changing this setting allows you to customize the color theme when viewing any
diff --git a/doc/user/project/clusters/add_gke_clusters.md b/doc/user/project/clusters/add_gke_clusters.md
index 7b010bf4478..b1c5bbfc4f7 100644
--- a/doc/user/project/clusters/add_gke_clusters.md
+++ b/doc/user/project/clusters/add_gke_clusters.md
@@ -72,8 +72,8 @@ cluster certificates:
- **Kubernetes cluster name** - The name you wish to give the cluster.
- **Environment scope** - The [associated environment](multiple_kubernetes_clusters.md#setting-the-environment-scope) to this cluster.
- **Google Cloud Platform project** - Choose the project you created in your GCP
- console to host the Kubernetes cluster. Learn more about
- [Google Cloud Platform projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects).
+ console to host the Kubernetes cluster. For more information, see
+ [Creating and managing projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects).
- **Zone** - Choose the [region zone](https://cloud.google.com/compute/docs/regions-zones/)
under which to create the cluster.
- **Number of nodes** - Enter the number of nodes you wish the cluster to have.
diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md
index 523a6fd65f6..d3048158958 100644
--- a/doc/user/project/clusters/add_remove_clusters.md
+++ b/doc/user/project/clusters/add_remove_clusters.md
@@ -29,7 +29,7 @@ When you successfully connect an existing cluster using cluster certificates, th
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26815) in GitLab 12.6, you can remove cluster integrations and resources.
When you remove a cluster integration, you only remove the cluster relationship
-to GitLab, not the cluster. To remove the cluster itself, visit your cluster's
+to GitLab, not the cluster. To remove the cluster itself, go to your cluster's
GKE or EKS dashboard to do it from their UI or use `kubectl`.
You need at least Maintainer [permissions](../../permissions.md) to your
diff --git a/doc/user/project/clusters/deploy_to_cluster.md b/doc/user/project/clusters/deploy_to_cluster.md
index 6e188a4923b..173f1f39a66 100644
--- a/doc/user/project/clusters/deploy_to_cluster.md
+++ b/doc/user/project/clusters/deploy_to_cluster.md
@@ -65,7 +65,7 @@ GitLab CI/CD build environment to deployment jobs. Deployment jobs have
The Kubernetes integration provides a `KUBECONFIG` with an auto-generated namespace
to deployment jobs. It defaults to using project-environment specific namespaces
of the form `<prefix>-<environment>`, where `<prefix>` is of the form
-`<project_name>-<project_id>`. To learn more, read [Deployment variables](#deployment-variables).
+`<project_name>-<project_id>`. For more information, see [Deployment variables](#deployment-variables).
You can customize the deployment namespace in a few ways:
diff --git a/doc/user/project/file_lock.md b/doc/user/project/file_lock.md
index a4867a6f25e..8d3446994e8 100644
--- a/doc/user/project/file_lock.md
+++ b/doc/user/project/file_lock.md
@@ -73,7 +73,7 @@ you can skip this step. If you're unsure, re-installing it does no harm:
git lfs install
```
-Check this document to learn more about [using Git LFS](../../topics/git/lfs/index.md#using-git-lfs).
+For more information, see [Using Git LFS](../../topics/git/lfs/index.md#using-git-lfs).
### Configure Exclusive File Locks
diff --git a/doc/user/project/integrations/bugzilla.md b/doc/user/project/integrations/bugzilla.md
index 9221250e17f..00a96679e96 100644
--- a/doc/user/project/integrations/bugzilla.md
+++ b/doc/user/project/integrations/bugzilla.md
@@ -37,8 +37,8 @@ After you configure and enable Bugzilla, a link appears on the GitLab
project pages. This link takes you to the appropriate Bugzilla project.
You can also disable [GitLab internal issue tracking](../issues/index.md) in this project.
-Learn more about the steps and consequences of disabling GitLab issues in
-[Sharing and permissions](../settings/index.md#configure-project-visibility-features-and-permissions).
+For more information about the steps and consequences of disabling GitLab issues, see
+[Configure project visibility, features, and permissions](../settings/index.md#configure-project-visibility-features-and-permissions).
## Reference Bugzilla issues in GitLab
diff --git a/doc/user/project/integrations/ewm.md b/doc/user/project/integrations/ewm.md
index d972509c0f6..ae09fce4d5e 100644
--- a/doc/user/project/integrations/ewm.md
+++ b/doc/user/project/integrations/ewm.md
@@ -51,5 +51,5 @@ You can use the following keywords:
- `work item`
- `workitem`
-Avoid using the keyword `#`. Learn more in the EWM documentation page
+Avoid using the keyword `#`. For more information, see
[Creating links from commit comments](https://www.ibm.com/docs/en/elm/7.0.0?topic=commits-creating-links-from-commit-comments).
diff --git a/doc/user/project/integrations/index.md b/doc/user/project/integrations/index.md
index 769a45fc6ff..57947e21736 100644
--- a/doc/user/project/integrations/index.md
+++ b/doc/user/project/integrations/index.md
@@ -90,7 +90,7 @@ You can configure a project webhook to listen for specific events
like pushes, issues, or merge requests. When the webhook is triggered, GitLab
sends a POST request with data to a specified webhook URL.
-Learn more [about webhooks](webhooks.md).
+For more information, see [Webhooks](webhooks.md).
## Push hooks limit
@@ -104,7 +104,7 @@ You can change the number of supported branches or tags by changing the
## Troubleshooting integrations
-Some integrations use hooks to integrate with external applications. To confirm which ones use integration hooks, see the [available integrations](#available-integrations). Learn more about [troubleshooting integration hooks](webhooks.md#troubleshoot-webhooks).
+Some integrations use hooks to integrate with external applications. To confirm which ones use integration hooks, see the [available integrations](#available-integrations). For more information, see [Troubleshooting webhooks](webhooks.md#troubleshoot-webhooks).
### `Test Failed. Save Anyway` error
diff --git a/doc/user/project/integrations/redmine.md b/doc/user/project/integrations/redmine.md
index e9752d7ce6c..373c6d51854 100644
--- a/doc/user/project/integrations/redmine.md
+++ b/doc/user/project/integrations/redmine.md
@@ -37,8 +37,8 @@ For example, this is a configuration for a project named `gitlab-ci`:
- New issue URL: `https://redmine.example.com/projects/gitlab-ci/issues/new`
You can also disable [GitLab internal issue tracking](../issues/index.md) in this project.
-Learn more about the steps and consequences of disabling GitLab issues in
-[Sharing and permissions](../settings/index.md#configure-project-visibility-features-and-permissions).
+For more information about the steps and consequences of disabling GitLab issues, see
+[Configure project visibility, features, and permissions](../settings/index.md#configure-project-visibility-features-and-permissions).
## Reference Redmine issues in GitLab
diff --git a/doc/user/project/integrations/youtrack.md b/doc/user/project/integrations/youtrack.md
index fb6807aeeb0..8ace2b9e89d 100644
--- a/doc/user/project/integrations/youtrack.md
+++ b/doc/user/project/integrations/youtrack.md
@@ -28,8 +28,8 @@ After you configure and enable YouTrack, a link appears on the GitLab
project pages. This link takes you to the appropriate YouTrack project.
You can also disable [GitLab internal issue tracking](../issues/index.md) in this project.
-Learn more about the steps and consequences of disabling GitLab issues in
-[Sharing and permissions](../settings/index.md#configure-project-visibility-features-and-permissions).
+For more information about the steps and consequences of disabling GitLab issues, see
+[Configure project visibility, features, and permissions](../settings/index.md#configure-project-visibility-features-and-permissions).
## Reference YouTrack issues in GitLab
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index a76557a93e6..034e7903af0 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -478,7 +478,7 @@ Read more about issue references in [GitLab-Flavored Markdown](../../markdown.md
You can create a comment in an issue by sending an email.
Sending an email to this address creates a comment that contains the email body.
-To learn more about creating comments by sending an email and the necessary configuration, see
+For more information about creating comments by sending an email and the necessary configuration, see
[Reply to a comment by sending email](../../discussions/index.md#reply-to-a-comment-by-sending-email).
To copy the issue's email address:
diff --git a/doc/user/project/issues/related_issues.md b/doc/user/project/issues/related_issues.md
index 1a8f19b80ba..43acaaf9c2f 100644
--- a/doc/user/project/issues/related_issues.md
+++ b/doc/user/project/issues/related_issues.md
@@ -15,7 +15,7 @@ The relationship only shows up in the UI if the user can see both issues. When y
issue that has open blockers, a warning is displayed.
NOTE:
-To manage linked issues through our API, visit the [issue links API documentation](../../../api/issue_links.md).
+To manage linked issues through our API, see [Issue links API](../../../api/issue_links.md).
## Add a linked issue
@@ -57,7 +57,7 @@ them categorized so their relationships can be better understood visually.
![Related issue block](img/related_issue_block_v15_3.png)
You can also add a linked issue from a commit message or the description in another issue or MR.
-[Learn more about crosslinking issues](crosslinking_issues.md).
+For more information, see [Crosslinking issues](crosslinking_issues.md).
## Remove a linked issue
diff --git a/doc/user/project/merge_requests/approvals/settings.md b/doc/user/project/merge_requests/approvals/settings.md
index bfc854b9f2c..1ab564c108b 100644
--- a/doc/user/project/merge_requests/approvals/settings.md
+++ b/doc/user/project/merge_requests/approvals/settings.md
@@ -87,8 +87,7 @@ to a merge request may or may not be able to approve the work:
[code owners](../../code_owners.md) who commit
to a merge request cannot approve it, when the merge request affects files they own.
-To learn more about the [differences between authors and committers](https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History),
-read the official Git documentation for an explanation.
+For more information, see the [official Git documentation](https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History).
## Prevent editing approval rules in merge requests
@@ -159,7 +158,7 @@ To do this:
You can require specific approvals if a merge request would result in a decline in code test
coverage.
-To learn more, see [Coverage check approval rule](../../../../ci/pipelines/settings.md#coverage-check-approval-rule).
+For more information, see [Coverage check approval rule](../../../../ci/pipelines/settings.md#coverage-check-approval-rule).
## Settings cascading
diff --git a/doc/user/project/merge_requests/reviews/index.md b/doc/user/project/merge_requests/reviews/index.md
index b17fd52ea7b..5291a845437 100644
--- a/doc/user/project/merge_requests/reviews/index.md
+++ b/doc/user/project/merge_requests/reviews/index.md
@@ -31,7 +31,7 @@ GitLab can suggest reviewers. Using the changes in a merge request and a project
This feature is currently in [Open Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#open-beta) behind a [feature flag](https://gitlab.com/gitlab-org/gitlab/-/issues/368356).
-Learn more about [how suggested reviewers works and data privacy](data_usage.md).
+For more information, see [Data usage in Suggested Reviewers](data_usage.md).
### Enable suggested reviewers
@@ -57,8 +57,8 @@ to you. When you're ready, you can publish them together in a single action.
To start your review:
1. Go to the merge request you want to review, and select the **Changes** tab.
- To learn more about navigating the diffs displayed in this tab, read
- [Changes tab in merge requests](../changes.md).
+ For more information about navigating the diffs displayed in this tab, see
+ [Changes in merge requests](../changes.md).
1. Select the **{comment}** **comment** icon in the gutter to expand the diff lines
and display a comment box. In GitLab version 13.2 and later, you can
[select multiple lines](#comment-on-multiple-lines).
diff --git a/doc/user/project/merge_requests/status_checks.md b/doc/user/project/merge_requests/status_checks.md
index c9f63ffd3da..62a2baa049b 100644
--- a/doc/user/project/merge_requests/status_checks.md
+++ b/doc/user/project/merge_requests/status_checks.md
@@ -24,8 +24,8 @@ at the merge request level itself.
You can configure merge request status checks for each individual project. These are not shared between projects.
-To learn more about use cases, feature discovery, and development timelines,
-see the [external status checks epic](https://gitlab.com/groups/gitlab-org/-/epics/3869).
+For more information about use cases, feature discovery, and development timelines,
+see [epic 3869](https://gitlab.com/groups/gitlab-org/-/epics/3869).
## Block merges of merge requests unless all status checks have passed
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index 89d8fd093b2..691757e3eca 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -31,8 +31,8 @@ like Gatsby, Jekyll, Hugo, Middleman, Harp, Hexo, or Brunch. You can also
publish any website written directly in plain HTML, CSS, and JavaScript.
Pages does not support dynamic server-side processing, for instance, as `.php` and `.asp` requires.
-Learn more about
-[static websites compared to dynamic websites](https://about.gitlab.com/blog/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/).
+For more information, see
+[Static vs dynamic websites](https://about.gitlab.com/blog/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/).
## Menu Position Test
@@ -63,7 +63,7 @@ To update a GitLab Pages website:
| [Let's Encrypt integration](custom_domains_ssl_tls_certification/lets_encrypt_integration.md) | Secure your Pages sites with Let's Encrypt certificates, which are automatically obtained and renewed by GitLab. |
| [Redirects](redirects.md) | Set up HTTP redirects to forward one page to another. |
-Learn more and see examples:
+For more information, see:
| Document | Description |
|----------|-------------|
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index 935c5fff907..51c42eeecb8 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -59,8 +59,8 @@ If the case of `404.html`, there are different scenarios. For example:
## Redirects in GitLab Pages
-You can configure redirects for your site using a `_redirects` file. To learn more, read
-the [redirects documentation](redirects.md).
+You can configure redirects for your site using a `_redirects` file. For more information, see
+[Create redirects for GitLab Pages](redirects.md).
## Remove your pages
@@ -261,7 +261,7 @@ for both the `/data` and `/data/` URL paths.
## Known issues
-For a list of known issues, visit the GitLab [public issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name[]=Category%3APages).
+For a list of known issues, see the GitLab [public issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name[]=Category%3APages).
## Troubleshooting
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 55689b1b714..90da47f7995 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -74,7 +74,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/due <date>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set due date. Examples of valid `<date>` include `in 2 days`, `this Friday` and `December 31st`. See [Chronic](https://gitlab.com/gitlab-org/ruby/gems/gitlab-chronic#examples) for more examples. |
| `/duplicate <#issue>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Close this issue. Mark as a duplicate of, and related to, issue `<#issue>`. |
| `/epic <epic>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Add to epic `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic. |
-| `/estimate <time>` or `/estimate_time <time>` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Set time estimate. For example, `/estimate 1mo 2w 3d 4h 5m`. Learn more about [time tracking](time_tracking.md). Alias `/estimate_time` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16501) in GitLab 15.6. |
+| `/estimate <time>` or `/estimate_time <time>` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Set time estimate. For example, `/estimate 1mo 2w 3d 4h 5m`. For more information, see [Time tracking](time_tracking.md). Alias `/estimate_time` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16501) in GitLab 15.6. |
| `/health_status <value>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set [health status](issues/managing_issues.md#health-status). Valid options for `<value>` are `on_track`, `needs_attention`, and `at_risk` ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213814) in GitLab 14.7). |
| `/invite_email email1 email2` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Add up to six email participants. This action is behind feature flag `issue_email_participants` and is not yet supported in issue templates. |
| `/iteration *iteration:"iteration name"` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set iteration. For example, to set the `Late in July` iteration: `/iteration *iteration:"Late in July"` ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196795) in GitLab 13.1). |
@@ -108,7 +108,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/reopen` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Reopen. |
| `/severity <severity>` | **{check-circle}** Yes | **{check-circle}** No | **{check-circle}** No | Set the severity. Issue type must be `Incident`. Options for `<severity>` are `S1` ... `S4`, `critical`, `high`, `medium`, `low`, `unknown`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334045) in GitLab 14.2. |
| `/shrug <comment>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Append the comment with `¯\_(ツ)_/¯`. |
-| `/spend <time> [<date>]` or `/spend_time <time> [<date>]` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Add or subtract spent time. Optionally, specify the date that time was spent on. For example, `/spend 1mo 2w 3d 4h 5m 2018-08-26` or `/spend -1h 30m`. Learn more about [time tracking](time_tracking.md). Alias `/spend_time` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16501) in GitLab 15.6. |
+| `/spend <time> [<date>]` or `/spend_time <time> [<date>]` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Add or subtract spent time. Optionally, specify the date that time was spent on. For example, `/spend 1mo 2w 3d 4h 5m 2018-08-26` or `/spend -1h 30m`. For more information, see [Time tracking](time_tracking.md). Alias `/spend_time` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16501) in GitLab 15.6. |
| `/submit_review` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Submit a pending review ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8041) in GitLab 12.7). |
| `/subscribe` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Subscribe to notifications. |
| `/tableflip <comment>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Append the comment with `(╯°□°)╯︵ ┻━┻`. |
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index 2820e8961c1..dca34af41b4 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -435,7 +435,7 @@ release evidence.
If you [schedule release evidence collection](#schedule-release-evidence-collection),
some artifacts may already be expired by the time of evidence collection. To avoid this you can use
the [`artifacts:expire_in`](../../../ci/yaml/index.md#artifactsexpire_in)
-keyword. Learn more in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/222351).
+keyword. For more information, see [issue 222351](https://gitlab.com/gitlab-org/gitlab/-/issues/222351).
### Schedule release evidence collection
diff --git a/doc/user/project/repository/mirror/index.md b/doc/user/project/repository/mirror/index.md
index bc0073e6ec8..7a50c294dfc 100644
--- a/doc/user/project/repository/mirror/index.md
+++ b/doc/user/project/repository/mirror/index.md
@@ -55,7 +55,7 @@ Prerequisite:
When mirroring the repository, GitLab confirms at least one of the stored host keys
matches before connecting. This check can protect your mirror from malicious code injections,
or your password from being stolen.
-1. Select an **Authentication method**. To learn more, read
+1. Select an **Authentication method**. For more information, see
[Authentication methods for mirrors](#authentication-methods-for-mirrors).
1. If you authenticate with SSH host keys, [verify the host key](#verify-a-host-key)
to ensure it is correct.
@@ -65,7 +65,7 @@ Prerequisite:
If you select `SSH public key` as your authentication method, GitLab generates a
public key for your GitLab repository. You must provide this key to the non-GitLab server.
-To learn more, read [Get your SSH public key](#get-your-ssh-public-key).
+For more information, see [Get your SSH public key](#get-your-ssh-public-key).
## Update a mirror
diff --git a/doc/user/project/repository/mirror/pull.md b/doc/user/project/repository/mirror/pull.md
index e2e86bfbde0..0eb51f40208 100644
--- a/doc/user/project/repository/mirror/pull.md
+++ b/doc/user/project/repository/mirror/pull.md
@@ -72,7 +72,7 @@ Prerequisite:
or `https://gitlab.com/gitlab-org/gitlab.git`.
1. In **Mirror direction**, select **Pull**.
-1. In **Authentication method**, select your authentication method. To learn more, read
+1. In **Authentication method**, select your authentication method. For more information, see
[Authentication methods for mirrors](index.md#authentication-methods-for-mirrors).
1. Select any of the options you need:
- [**Overwrite diverged branches**](#overwrite-diverged-branches)
diff --git a/doc/user/project/repository/mirror/push.md b/doc/user/project/repository/mirror/push.md
index 11d53b0c1d1..f06dd747897 100644
--- a/doc/user/project/repository/mirror/push.md
+++ b/doc/user/project/repository/mirror/push.md
@@ -38,7 +38,7 @@ To set up push mirroring for an existing project:
1. Expand **Mirroring repositories**.
1. Enter a repository URL.
1. In the **Mirror direction** dropdown list, select **Push**.
-1. Select an **Authentication method**. To learn more, read
+1. Select an **Authentication method**. For more information, see
[Authentication methods for mirrors](index.md#authentication-methods-for-mirrors).
1. Select **Only mirror protected branches**, if necessary.
1. Select **Keep divergent refs**, if desired.
diff --git a/doc/user/project/repository/ssh_signed_commits/index.md b/doc/user/project/repository/ssh_signed_commits/index.md
index 62b8e6cc44f..f2ce80263c8 100644
--- a/doc/user/project/repository/ssh_signed_commits/index.md
+++ b/doc/user/project/repository/ssh_signed_commits/index.md
@@ -19,8 +19,8 @@ You may use the same SSH keys for `git+ssh` authentication to GitLab
and signing commit signatures as long as their usage type is **Authentication & Signing**.
It can be verified on the page for [adding an SSH key to your GitLab account](../../../ssh.md#add-an-ssh-key-to-your-gitlab-account).
-To learn more about managing the SSH keys associated with your GitLab account, read
-[use SSH keys to communicate with GitLab](../../../ssh.md).
+For more information about managing the SSH keys associated with your GitLab account, see
+[Use SSH keys to communicate with GitLab](../../../ssh.md).
## Configure Git to sign commits with your SSH key
diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md
index b707f979079..b62bd75f3bc 100644
--- a/doc/user/project/service_desk.md
+++ b/doc/user/project/service_desk.md
@@ -217,9 +217,9 @@ To configure a custom mailbox for Service Desk with IMAP, add the following snip
NOTE:
In GitLab 15.3 and later, Service Desk uses `webhook` (internal API call) by default instead of enqueuing a Sidekiq job.
To use `webhook` on an Omnibus installation running GitLab 15.3, you must generate a secret file.
-For more context, visit [Omnibus GitLab MR 5927](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5927).
+For more information, see [merge request 5927](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5927).
In GitLab 15.4, reconfiguring an Omnibus installation generates this secret file automatically, so no secret file configuration setting is needed.
-For details, visit [issue 1462](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1462).
+For more information, see [issue 1462](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1462).
```ruby
gitlab_rails['service_desk_email_enabled'] = true
diff --git a/doc/user/ssh.md b/doc/user/ssh.md
index 2be126e4452..d44e6a0e071 100644
--- a/doc/user/ssh.md
+++ b/doc/user/ssh.md
@@ -291,7 +291,7 @@ You can use [1Password](https://1password.com/) and the [1Password browser exten
1. Optional. Update **Expiration date** to modify the default expiration date.
1. Select **Add key**.
-To learn more about using 1Password with SSH keys, see [1Password's documentation](https://developer.1password.com/docs/ssh/get-started).
+For more information about using 1Password with SSH keys, see the [1Password documentation](https://developer.1password.com/docs/ssh/get-started).
## Add an SSH key to your GitLab account
diff --git a/doc/user/usage_quotas.md b/doc/user/usage_quotas.md
index b9f57ebff01..0740108a168 100644
--- a/doc/user/usage_quotas.md
+++ b/doc/user/usage_quotas.md
@@ -157,7 +157,7 @@ To prevent exceeding the namespace storage quota, you can:
- Consider using a [self-managed instance](../subscriptions/self_managed/index.md) of GitLab which does not have these limits on the free tier.
- [Purchase additional storage](../subscriptions/gitlab_com/index.md#purchase-more-storage-and-transfer) units at $60/year for 10 GB of storage.
- [Start a trial](https://about.gitlab.com/free-trial/) or [upgrade to GitLab Premium or Ultimate](https://about.gitlab.com/pricing/) which include higher limits and features that enable growing teams to ship faster without sacrificing on quality.
-- [Talk to an expert](https://page.gitlab.com/usage_limits_help.html) to learn more about your options and ask questions.
+- [Talk to an expert](https://page.gitlab.com/usage_limits_help.html) for more information about your options.
### Namespace storage limit application schedule
diff --git a/lib/gitlab/database/indexing_exclusive_lease_guard.rb b/lib/gitlab/database/async_ddl_exclusive_lease_guard.rb
index fb45de347e6..5742e96c9b3 100644
--- a/lib/gitlab/database/indexing_exclusive_lease_guard.rb
+++ b/lib/gitlab/database/async_ddl_exclusive_lease_guard.rb
@@ -2,16 +2,16 @@
module Gitlab
module Database
- module IndexingExclusiveLeaseGuard
+ module AsyncDdlExclusiveLeaseGuard
extend ActiveSupport::Concern
include ExclusiveLeaseGuard
def lease_key
- @lease_key ||= "gitlab/database/indexing/actions/#{database_config_name}"
+ @lease_key ||= "gitlab/database/asyncddl/actions/#{database_config_name}"
end
def database_config_name
- Gitlab::Database.db_config_name(connection)
+ connection_db_config.name
end
end
end
diff --git a/lib/gitlab/database/async_indexes/index_base.rb b/lib/gitlab/database/async_indexes/index_base.rb
index 2891618e978..bde75e12295 100644
--- a/lib/gitlab/database/async_indexes/index_base.rb
+++ b/lib/gitlab/database/async_indexes/index_base.rb
@@ -4,7 +4,7 @@ module Gitlab
module Database
module AsyncIndexes
class IndexBase
- include IndexingExclusiveLeaseGuard
+ include AsyncDdlExclusiveLeaseGuard
extend ::Gitlab::Utils::Override
TIMEOUT_PER_ACTION = 1.day
@@ -30,7 +30,7 @@ module Gitlab
attr_reader :async_index
- delegate :connection, to: :async_index
+ delegate :connection, :connection_db_config, to: :async_index
def preconditions_met?
raise NotImplementedError, 'must implement preconditions_met?'
diff --git a/lib/gitlab/database/reindexing/coordinator.rb b/lib/gitlab/database/reindexing/coordinator.rb
index eca118a4ff2..57e2e0c1beb 100644
--- a/lib/gitlab/database/reindexing/coordinator.rb
+++ b/lib/gitlab/database/reindexing/coordinator.rb
@@ -4,7 +4,7 @@ module Gitlab
module Database
module Reindexing
class Coordinator
- include IndexingExclusiveLeaseGuard
+ include AsyncDdlExclusiveLeaseGuard
# Maximum lease time for the global Redis lease
# This should be higher than the maximum time for any
@@ -54,7 +54,7 @@ module Gitlab
private
- delegate :connection, to: :index
+ delegate :connection, :connection_db_config, to: :index
def with_notifications(action)
notifier.notify_start(action)
diff --git a/lib/gitlab/github_import/parallel_scheduling.rb b/lib/gitlab/github_import/parallel_scheduling.rb
index 6ecf2a8511f..4b54a77983d 100644
--- a/lib/gitlab/github_import/parallel_scheduling.rb
+++ b/lib/gitlab/github_import/parallel_scheduling.rb
@@ -276,9 +276,9 @@ module Gitlab
end
def calculate_job_delay(job_index)
- multiplier = (job_index / parallel_import_batch[:size]) + 1
+ multiplier = (job_index / parallel_import_batch[:size])
- multiplier * parallel_import_batch[:delay]
+ (multiplier * parallel_import_batch[:delay]) + 1.second
end
end
end
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index b6b80b0ee23..c9766ee095a 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -40,7 +40,6 @@ module Gitlab
gon.sprite_icons = IconsHelper.sprite_icon_path
gon.sprite_file_icons = IconsHelper.sprite_file_icons_path
gon.emoji_sprites_css_path = ActionController::Base.helpers.stylesheet_path('emoji_sprites')
- gon.select2_css_path = ActionController::Base.helpers.stylesheet_path('lazy_bundles/select2.css')
gon.gridstack_css_path = ActionController::Base.helpers.stylesheet_path('lazy_bundles/gridstack.css')
gon.test_env = Rails.env.test?
gon.disable_animations = Gitlab.config.gitlab['disable_animations']
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 47d3a9f12c3..914037a5557 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -25582,9 +25582,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "ML Experiments"
-msgstr ""
-
msgid "MR widget|Back to the merge request"
msgstr ""
@@ -25624,9 +25621,6 @@ msgstr ""
msgid "Machine Learning Experiment Tracking is in Incubating Phase"
msgstr ""
-msgid "Machine Learning Experiments"
-msgstr ""
-
msgid "Made this %{type} confidential."
msgstr ""
@@ -27384,27 +27378,45 @@ msgstr ""
msgid "MlExperimentTracking|Artifacts"
msgstr ""
+msgid "MlExperimentTracking|Create a new experiment"
+msgstr ""
+
msgid "MlExperimentTracking|Created at"
msgstr ""
msgid "MlExperimentTracking|Details"
msgstr ""
+msgid "MlExperimentTracking|Experiment"
+msgstr ""
+
msgid "MlExperimentTracking|Experiment candidates"
msgstr ""
msgid "MlExperimentTracking|Filter candidates"
msgstr ""
+msgid "MlExperimentTracking|Logged candidates for experiment"
+msgstr ""
+
msgid "MlExperimentTracking|Machine learning experiment tracking"
msgstr ""
+msgid "MlExperimentTracking|Model experiments"
+msgstr ""
+
msgid "MlExperimentTracking|Name"
msgstr ""
msgid "MlExperimentTracking|No candidates to display"
msgstr ""
+msgid "MlExperimentTracking|No experiments"
+msgstr ""
+
+msgid "MlExperimentTracking|There are no logged experiments for this project. Create a new experiment using the MLflow client."
+msgstr ""
+
msgid "MlExperimentTracking|User"
msgstr ""
@@ -33281,9 +33293,6 @@ msgstr ""
msgid "ProjectQualitySummary|This page helps you understand the code testing trends for your project. Let us know how we can improve it!"
msgstr ""
-msgid "ProjectSelect| or group"
-msgstr ""
-
msgid "ProjectSelect|No matching results"
msgstr ""
@@ -33296,9 +33305,6 @@ msgstr ""
msgid "ProjectSelect|Select a project"
msgstr ""
-msgid "ProjectSelect|Something went wrong while fetching projects"
-msgstr ""
-
msgid "ProjectSelect|There was an error fetching the projects. Please try again."
msgstr ""
diff --git a/package.json b/package.json
index 39939ea702f..12802b528a3 100644
--- a/package.json
+++ b/package.json
@@ -174,7 +174,6 @@
"remark-parse": "^10.0.1",
"remark-rehype": "^10.1.0",
"scrollparent": "^2.0.1",
- "select2": "3.5.2-browserify",
"sentrybrowser5": "npm:@sentry/browser@5.30.0",
"sentrybrowser7": "npm:@sentry/browser@^7.21.1",
"sortablejs": "^1.10.2",
diff --git a/qa/qa/page/component/dropdown.rb b/qa/qa/page/component/dropdown.rb
index 7062c5c7132..01ef3533ff8 100644
--- a/qa/qa/page/component/dropdown.rb
+++ b/qa/qa/page/component/dropdown.rb
@@ -4,36 +4,24 @@ module QA
module Page
module Component
module Dropdown
- include Select2
-
def select_item(item_text)
- return super if use_select2?
-
find('li.gl-new-dropdown-item', text: item_text, match: :prefer_exact).click
end
def has_item?(item_text)
- return super if use_select2?
-
has_css?('li.gl-new-dropdown-item', text: item_text, match: :prefer_exact)
end
def current_selection
- return super if use_select2?
-
expand_select_list unless dropdown_open?
find('span.gl-new-dropdown-button-text').text
end
def all_items
- raise NotImplementedError if use_select2?
-
find_all("li.gl-new-dropdown-item").map(&:text)
end
def clear_current_selection_if_present
- return super if use_select2?
-
expand_select_list unless dropdown_open?
if has_css?('button[data-testid="listbox-reset-button"]')
@@ -44,8 +32,6 @@ module QA
end
def search_item(item_text)
- return super if use_select2?
-
QA::Runtime::Logger.info "Searching in dropdown: \"#{item_text}\""
find('div.gl-listbox-search input[type="Search"]').set(item_text, rapid: false)
@@ -58,8 +44,6 @@ module QA
end
def search_and_select(item_text)
- return super if use_select2?
-
search_item(item_text)
unless has_item?(item_text)
@@ -70,8 +54,6 @@ module QA
end
def search_and_select_exact(item_text)
- return super if use_select2?
-
QA::Runtime::Logger.info "Searching and selecting exact: \"#{item_text}\""
search_item(item_text)
@@ -84,14 +66,10 @@ module QA
end
def expand_select_list
- return super if use_select2?
-
find('.gl-new-dropdown-toggle').click
end
def wait_for_search_to_complete
- return super if use_select2?
-
Support::WaitForRequests.wait_for_requests
has_css?('div[data-testid="listbox-search-loader"]', wait: 1)
@@ -99,23 +77,12 @@ module QA
end
def dropdown_open?
- return super if use_select2?
-
has_css?('ul.gl-new-dropdown-contents', wait: 1)
end
def find_input_by_prefix_and_set(element_prefix, item_text)
find("input[id^=\"#{element_prefix}\"]").set(item_text)
end
-
- private
-
- # rubocop:disable Gitlab/PredicateMemoization
- def use_select2?
- @use_select2 ||= has_css?('.select2-container', wait: 1)
- end
-
- # rubocop:enable Gitlab/PredicateMemoization
end
end
end
diff --git a/qa/qa/page/component/select2.rb b/qa/qa/page/component/select2.rb
deleted file mode 100644
index 7a835af2575..00000000000
--- a/qa/qa/page/component/select2.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Component
- module Select2
- def select_item(item_text)
- find('.select2-result-label', text: item_text, match: :prefer_exact).click
- end
-
- def has_item?(item_text)
- has_css?('.select2-result-label', text: item_text, match: :prefer_exact)
- end
-
- def current_selection
- find('.select2-chosen').text
- end
-
- def clear_current_selection_if_present
- if has_css?('a > abbr.select2-search-choice-close', wait: 1.0)
- find('a > abbr.select2-search-choice-close').click
- end
- end
-
- def search_item(item_text)
- find('.select2-input').set(item_text)
-
- wait_for_search_to_complete
- end
-
- def search_and_select(item_text)
- QA::Runtime::Logger.info "Searching and selecting: #{item_text}"
-
- search_item(item_text)
-
- raise QA::Page::Base::ElementNotFound, %Q(Couldn't find option named "#{item_text}") unless has_item?(item_text)
-
- select_item(item_text)
- end
-
- def search_and_select_exact(item_text)
- QA::Runtime::Logger.info "Searching and selecting: #{item_text}"
-
- search_item(item_text)
-
- raise QA::Page::Base::ElementNotFound, %Q(Couldn't find option named "#{item_text}") unless has_item?(item_text)
-
- find('.select2-result-label', text: item_text, exact_text: true).click
- end
-
- def expand_select_list
- find('span.select2-arrow').click
- end
-
- def wait_for_search_to_complete
- Support::WaitForRequests.wait_for_requests
-
- has_css?('.select2-active', wait: 1)
- has_no_css?('.select2-active', wait: 30)
- end
-
- def dropdown_open?
- find('.select2-focusser').disabled?
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb
index c48b1a67d90..4ea0575b6e0 100644
--- a/qa/qa/page/project/import/github.rb
+++ b/qa/qa/page/project/import/github.rb
@@ -5,8 +5,6 @@ module QA
module Project
module Import
class Github < Page::Base
- include Page::Component::Select2
-
view 'app/views/import/github/new.html.haml' do
element :personal_access_token_field
element :authenticate_button
diff --git a/qa/qa/page/project/secure/configuration_form.rb b/qa/qa/page/project/secure/configuration_form.rb
index 20999f7c92a..493ec08d023 100644
--- a/qa/qa/page/project/secure/configuration_form.rb
+++ b/qa/qa/page/project/secure/configuration_form.rb
@@ -5,7 +5,6 @@ module QA
module Project
module Secure
class ConfigurationForm < QA::Page::Base
- include QA::Page::Component::Select2
include QA::Page::Settings::Common
view 'app/assets/javascripts/security_configuration/components/app.vue' do
diff --git a/qa/qa/page/project/settings/main.rb b/qa/qa/page/project/settings/main.rb
index ca5d13abdae..8b9b72758d8 100644
--- a/qa/qa/page/project/settings/main.rb
+++ b/qa/qa/page/project/settings/main.rb
@@ -6,7 +6,6 @@ module QA
module Settings
class Main < Page::Base
include QA::Page::Settings::Common
- include Component::Select2
include SubMenus::Project
include Component::Breadcrumbs
include Layout::Flash
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index 119e09f9b09..a07a5c48713 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -3,7 +3,6 @@
require 'spec_helper'
RSpec.describe 'Admin Groups', feature_category: :subgroups do
- include Select2Helper
include Spec::Support::Helpers::Features::MembersHelpers
include Spec::Support::Helpers::Features::InviteMembersModalHelper
include Spec::Support::Helpers::ModalHelpers
diff --git a/spec/features/admin/admin_jobs_spec.rb b/spec/features/admin/admin_jobs_spec.rb
index 626605868cb..d46b314c144 100644
--- a/spec/features/admin/admin_jobs_spec.rb
+++ b/spec/features/admin/admin_jobs_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Admin Jobs', feature_category: :continuous_integration do
before do
+ stub_feature_flags(admin_jobs_vue: false)
admin = create(:admin)
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb
index 0230c9e835b..6630956f835 100644
--- a/spec/features/projects/import_export/export_file_spec.rb
+++ b/spec/features/projects/import_export/export_file_spec.rb
@@ -7,7 +7,6 @@ require 'spec_helper'
# we'll have to either include it adding the model that includes it to the +safe_list+
# or make sure the attribute is blacklisted in the +import_export.yml+ configuration
RSpec.describe 'Import/Export - project export integration test', :js, feature_category: :importers do
- include Select2Helper
include ExportFileHelper
let(:user) { create(:admin) }
diff --git a/spec/frontend/fixtures/static/project_select_combo_button.html b/spec/frontend/fixtures/static/project_select_combo_button.html
deleted file mode 100644
index 3776610ed4c..00000000000
--- a/spec/frontend/fixtures/static/project_select_combo_button.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<div class="project-item-select-holder">
- <input class="project-item-select" data-group-id="12345" data-relative-path="issues/new" />
- <a class="js-new-project-item-link" data-label="issue" data-type="issues" href="">
- <span class="gl-spinner"></span>
- </a>
- <a class="new-project-item-select-button">
- <svg data-testid="chevron-down-icon" class="gl-icon s16">
- <use
- href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#chevron-down"
- ></use>
- </svg>
- </a>
-</div>
diff --git a/spec/frontend/ml/experiment_tracking/routes/experiments/index/components/ml_experiments_index_spec.js b/spec/frontend/ml/experiment_tracking/routes/experiments/index/components/ml_experiments_index_spec.js
new file mode 100644
index 00000000000..017db647ac6
--- /dev/null
+++ b/spec/frontend/ml/experiment_tracking/routes/experiments/index/components/ml_experiments_index_spec.js
@@ -0,0 +1,110 @@
+import { GlEmptyState, GlLink, GlTableLite } from '@gitlab/ui';
+import MlExperimentsIndexApp from '~/ml/experiment_tracking/routes/experiments/index';
+import IncubationAlert from '~/vue_shared/components/incubation/incubation_alert.vue';
+import Pagination from '~/vue_shared/components/incubation/pagination.vue';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import {
+ startCursor,
+ firstExperiment,
+ secondExperiment,
+ experiments,
+ defaultPageInfo,
+} from './mock_data';
+
+let wrapper;
+const createWrapper = (defaultExperiments = [], pageInfo = defaultPageInfo) => {
+ wrapper = mountExtended(MlExperimentsIndexApp, {
+ propsData: { experiments: defaultExperiments, pageInfo },
+ });
+};
+
+const findAlert = () => wrapper.findComponent(IncubationAlert);
+const findPagination = () => wrapper.findComponent(Pagination);
+const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+const findTable = () => wrapper.findComponent(GlTableLite);
+const findTableHeaders = () => findTable().findAll('th');
+const findTableRows = () => findTable().findAll('tbody > tr');
+const findNthTableRow = (idx) => findTableRows().at(idx);
+const findColumnInRow = (row, col) => findNthTableRow(row).findAll('td').at(col);
+const hrefInRowAndColumn = (row, col) =>
+ findColumnInRow(row, col).findComponent(GlLink).attributes().href;
+
+describe('MlExperimentsIndex', () => {
+ describe('empty state', () => {
+ beforeEach(() => createWrapper());
+
+ it('displays empty state when no experiment', () => {
+ expect(findEmptyState().exists()).toBe(true);
+ });
+
+ it('does not show table', () => {
+ expect(findTable().exists()).toBe(false);
+ });
+
+ it('does not show pagination', () => {
+ expect(findPagination().exists()).toBe(false);
+ });
+ });
+
+ it('displays IncubationAlert', () => {
+ createWrapper(experiments);
+
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ describe('experiments table', () => {
+ const firstRow = 0;
+ const secondRow = 1;
+ const nameColumn = 0;
+ const candidateCountColumn = 1;
+
+ beforeEach(() => createWrapper(experiments));
+
+ it('displays the table', () => {
+ expect(findTable().exists()).toBe(true);
+ });
+
+ it('sets headers correctly', () => {
+ const expectedColumnNames = ['Experiment', 'Logged candidates for experiment'];
+
+ expect(findTableHeaders().wrappers.map((h) => h.text())).toEqual(expectedColumnNames);
+ });
+
+ describe('experiment name column', () => {
+ it('displays the experiment name', () => {
+ expect(findColumnInRow(firstRow, nameColumn).text()).toBe(firstExperiment.name);
+ expect(findColumnInRow(secondRow, nameColumn).text()).toBe(secondExperiment.name);
+ });
+
+ it('is a link to the experiment', () => {
+ expect(hrefInRowAndColumn(firstRow, nameColumn)).toBe(firstExperiment.path);
+ expect(hrefInRowAndColumn(secondRow, nameColumn)).toBe(secondExperiment.path);
+ });
+ });
+
+ describe('candidate count column', () => {
+ it('shows the candidate count', () => {
+ expect(findColumnInRow(firstRow, candidateCountColumn).text()).toBe(
+ `${firstExperiment.candidate_count}`,
+ );
+ expect(findColumnInRow(secondRow, candidateCountColumn).text()).toBe(
+ `${secondExperiment.candidate_count}`,
+ );
+ });
+ });
+ });
+
+ describe('pagination', () => {
+ describe('Pagination behaviour', () => {
+ beforeEach(() => createWrapper(experiments));
+
+ it('should show', () => {
+ expect(findPagination().exists()).toBe(true);
+ });
+
+ it('Passes pagination to pagination component', () => {
+ expect(findPagination().props('startCursor')).toBe(startCursor);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/ml/experiment_tracking/routes/experiments/index/components/mock_data.js b/spec/frontend/ml/experiment_tracking/routes/experiments/index/components/mock_data.js
new file mode 100644
index 00000000000..ea02584a7cc
--- /dev/null
+++ b/spec/frontend/ml/experiment_tracking/routes/experiments/index/components/mock_data.js
@@ -0,0 +1,21 @@
+export const startCursor = 'eyJpZCI6IjE2In0';
+export const defaultPageInfo = Object.freeze({
+ startCursor,
+ endCursor: 'eyJpZCI6IjIifQ',
+ hasNextPage: true,
+ hasPreviousPage: true,
+});
+
+export const firstExperiment = Object.freeze({
+ name: 'Experiment 1',
+ path: 'path/to/experiment/1',
+ candidate_count: 2,
+});
+
+export const secondExperiment = Object.freeze({
+ name: 'Experiment 2',
+ path: 'path/to/experiment/2',
+ candidate_count: 3,
+});
+
+export const experiments = [firstExperiment, secondExperiment];
diff --git a/spec/frontend/project_select_combo_button_spec.js b/spec/frontend/project_select_combo_button_spec.js
deleted file mode 100644
index b8d5a1a61f3..00000000000
--- a/spec/frontend/project_select_combo_button_spec.js
+++ /dev/null
@@ -1,165 +0,0 @@
-import $ from 'jquery';
-import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
-import ProjectSelectComboButton from '~/project_select_combo_button';
-
-const fixturePath = 'static/project_select_combo_button.html';
-
-describe('Project Select Combo Button', () => {
- let testContext;
-
- beforeEach(() => {
- testContext = {};
- });
-
- beforeEach(() => {
- testContext.defaults = {
- label: 'Select project to create issue',
- groupId: 12345,
- projectMeta: {
- name: 'My Cool Project',
- url: 'http://mycoolproject.com',
- },
- newProjectMeta: {
- name: 'My Other Cool Project',
- url: 'http://myothercoolproject.com',
- },
- vulnerableProject: {
- name: 'Self XSS',
- // eslint-disable-next-line no-script-url
- url: 'javascript:alert(1)',
- },
- localStorageKey: 'group-12345-new-issue-recent-project',
- relativePath: 'issues/new',
- };
-
- loadHTMLFixture(fixturePath);
-
- testContext.newItemBtn = document.querySelector('.js-new-project-item-link');
- testContext.projectSelectInput = document.querySelector('.project-item-select');
- });
-
- afterEach(() => {
- resetHTMLFixture();
- });
-
- describe('on page load when localStorage is empty', () => {
- beforeEach(() => {
- testContext.comboButton = new ProjectSelectComboButton(testContext.projectSelectInput);
- });
-
- it('newItemBtn href is null', () => {
- expect(testContext.newItemBtn.getAttribute('href')).toBe('');
- });
-
- it('newItemBtn text is the plain default label', () => {
- expect(testContext.newItemBtn.textContent).toBe(testContext.defaults.label);
- });
- });
-
- describe('on page load when localStorage is filled', () => {
- beforeEach(() => {
- window.localStorage.setItem(
- testContext.defaults.localStorageKey,
- JSON.stringify(testContext.defaults.projectMeta),
- );
- testContext.comboButton = new ProjectSelectComboButton(testContext.projectSelectInput);
- });
-
- it('newItemBtn href is correctly set', () => {
- expect(testContext.newItemBtn.getAttribute('href')).toBe(
- testContext.defaults.projectMeta.url,
- );
- });
-
- it('newItemBtn text is the cached label', () => {
- expect(testContext.newItemBtn.textContent).toBe(
- `New issue in ${testContext.defaults.projectMeta.name}`,
- );
- });
-
- afterEach(() => {
- window.localStorage.clear();
- });
- });
-
- describe('after selecting a new project', () => {
- beforeEach(() => {
- testContext.comboButton = new ProjectSelectComboButton(testContext.projectSelectInput);
-
- // mock the effect of selecting an item from the projects dropdown (select2)
- $('.project-item-select')
- .val(JSON.stringify(testContext.defaults.newProjectMeta))
- .trigger('change');
- });
-
- it('newItemBtn href is correctly set', () => {
- expect(testContext.newItemBtn.getAttribute('href')).toBe(
- 'http://myothercoolproject.com/issues/new',
- );
- });
-
- it('newItemBtn text is the selected project label', () => {
- expect(testContext.newItemBtn.textContent).toBe(
- `New issue in ${testContext.defaults.newProjectMeta.name}`,
- );
- });
-
- afterEach(() => {
- window.localStorage.clear();
- });
- });
-
- describe('after selecting a vulnerable project', () => {
- beforeEach(() => {
- testContext.comboButton = new ProjectSelectComboButton(testContext.projectSelectInput);
-
- // mock the effect of selecting an item from the projects dropdown (select2)
- $('.project-item-select')
- .val(JSON.stringify(testContext.defaults.vulnerableProject))
- .trigger('change');
- });
-
- it('newItemBtn href is correctly sanitized', () => {
- expect(testContext.newItemBtn.getAttribute('href')).toBe('about:blank');
- });
-
- afterEach(() => {
- window.localStorage.clear();
- });
- });
-
- describe('deriveTextVariants', () => {
- beforeEach(() => {
- testContext.mockExecutionContext = {
- resourceType: '',
- resourceLabel: '',
- };
-
- testContext.comboButton = new ProjectSelectComboButton(testContext.projectSelectInput);
-
- testContext.method = testContext.comboButton.deriveTextVariants.bind(
- testContext.mockExecutionContext,
- );
- });
-
- it('correctly derives test variants for merge requests', () => {
- testContext.mockExecutionContext.resourceType = 'merge_requests';
- testContext.mockExecutionContext.resourceLabel = 'New merge request';
-
- const returnedVariants = testContext.method();
-
- expect(returnedVariants.localStorageItemType).toBe('new-merge-request');
- expect(returnedVariants.presetTextSuffix).toBe('merge request');
- });
-
- it('correctly derives text variants for issues', () => {
- testContext.mockExecutionContext.resourceType = 'issues';
- testContext.mockExecutionContext.resourceLabel = 'New issue';
-
- const returnedVariants = testContext.method();
-
- expect(returnedVariants.localStorageItemType).toBe('new-issue');
- expect(returnedVariants.presetTextSuffix).toBe('issue');
- });
- });
-});
diff --git a/spec/helpers/projects/ml/experiments_helper_spec.rb b/spec/helpers/projects/ml/experiments_helper_spec.rb
index d9194d19a7f..6f6a5bceb2e 100644
--- a/spec/helpers/projects/ml/experiments_helper_spec.rb
+++ b/spec/helpers/projects/ml/experiments_helper_spec.rb
@@ -110,6 +110,26 @@ RSpec.describe Projects::Ml::ExperimentsHelper, feature_category: :mlops do
end
end
+ describe '#experiments_as_data' do
+ let(:experiments) { [experiment] }
+
+ subject { Gitlab::Json.parse(helper.experiments_as_data(project, experiments)) }
+
+ before do
+ allow(experiment).to receive(:candidate_count).and_return(2)
+ end
+
+ it 'generates the correct info' do
+ expected_info = {
+ "name" => experiment.name,
+ "path" => "/#{project.full_path}/-/ml/experiments/#{experiment.iid}",
+ "candidate_count" => 2
+ }
+
+ expect(subject[0]).to eq(expected_info)
+ end
+ end
+
describe '#page_info' do
def paginator(cursor = nil)
experiment.candidates.keyset_paginate(cursor: cursor, per_page: 1)
diff --git a/spec/lib/bulk_imports/projects/pipelines/references_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/references_pipeline_spec.rb
index 8cc128860e0..895d37ea385 100644
--- a/spec/lib/bulk_imports/projects/pipelines/references_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/projects/pipelines/references_pipeline_spec.rb
@@ -79,7 +79,7 @@ RSpec.describe BulkImports::Projects::Pipelines::ReferencesPipeline, feature_cat
expect(system_note.note_html).not_to eq(old_note_html)
expect(system_note.note_html)
.to include("class=\"gfm gfm-merge_request\">!#{mr.iid}</a></p>")
- .and include("<a href=\"/namespace1/project")
+ .and include(project.full_path.to_s)
end
end
diff --git a/spec/lib/gitlab/database/async_ddl_exclusive_lease_guard_spec.rb b/spec/lib/gitlab/database/async_ddl_exclusive_lease_guard_spec.rb
new file mode 100644
index 00000000000..60ccf5ec685
--- /dev/null
+++ b/spec/lib/gitlab/database/async_ddl_exclusive_lease_guard_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::AsyncDdlExclusiveLeaseGuard, feature_category: :database do
+ let(:helper_class) do
+ Class.new do
+ include Gitlab::Database::AsyncDdlExclusiveLeaseGuard
+
+ attr_reader :connection_db_config
+
+ def initialize(connection_db_config)
+ @connection_db_config = connection_db_config
+ end
+ end
+ end
+
+ describe '#lease_key' do
+ let(:helper) { helper_class.new(connection_db_config) }
+ let(:lease_key) { "gitlab/database/asyncddl/actions/#{database_name}" }
+
+ context 'with CI database connection' do
+ let(:connection_db_config) { Ci::ApplicationRecord.connection_db_config }
+ let(:database_name) { Gitlab::Database::CI_DATABASE_NAME }
+
+ before do
+ skip_if_multiple_databases_not_setup
+ end
+
+ it { expect(helper.lease_key).to eq(lease_key) }
+ end
+
+ context 'with MAIN database connection' do
+ let(:connection_db_config) { ApplicationRecord.connection_db_config }
+ let(:database_name) { Gitlab::Database::MAIN_DATABASE_NAME }
+
+ it { expect(helper.lease_key).to eq(lease_key) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/async_indexes/index_creator_spec.rb b/spec/lib/gitlab/database/async_indexes/index_creator_spec.rb
index f980e458f14..51a09ba0b5e 100644
--- a/spec/lib/gitlab/database/async_indexes/index_creator_spec.rb
+++ b/spec/lib/gitlab/database/async_indexes/index_creator_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Gitlab::Database::AsyncIndexes::IndexCreator, feature_category: :
let(:connection) { model.connection }
let!(:lease) { stub_exclusive_lease(lease_key, :uuid, timeout: lease_timeout) }
- let(:lease_key) { "gitlab/database/indexing/actions/#{Gitlab::Database::PRIMARY_DATABASE_NAME}" }
+ let(:lease_key) { "gitlab/database/asyncddl/actions/#{Gitlab::Database::PRIMARY_DATABASE_NAME}" }
let(:lease_timeout) { described_class::TIMEOUT_PER_ACTION }
around do |example|
diff --git a/spec/lib/gitlab/database/async_indexes/index_destructor_spec.rb b/spec/lib/gitlab/database/async_indexes/index_destructor_spec.rb
index c70acf53dc2..7f0febdcacd 100644
--- a/spec/lib/gitlab/database/async_indexes/index_destructor_spec.rb
+++ b/spec/lib/gitlab/database/async_indexes/index_destructor_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Gitlab::Database::AsyncIndexes::IndexDestructor, feature_category
let(:connection) { model.connection }
let!(:lease) { stub_exclusive_lease(lease_key, :uuid, timeout: lease_timeout) }
- let(:lease_key) { "gitlab/database/indexing/actions/#{Gitlab::Database::PRIMARY_DATABASE_NAME}" }
+ let(:lease_key) { "gitlab/database/asyncddl/actions/#{Gitlab::Database::PRIMARY_DATABASE_NAME}" }
let(:lease_timeout) { described_class::TIMEOUT_PER_ACTION }
before do
diff --git a/spec/lib/gitlab/database/indexing_exclusive_lease_guard_spec.rb b/spec/lib/gitlab/database/indexing_exclusive_lease_guard_spec.rb
deleted file mode 100644
index 16142679c3e..00000000000
--- a/spec/lib/gitlab/database/indexing_exclusive_lease_guard_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Database::IndexingExclusiveLeaseGuard, feature_category: :database do
- let(:helper_class) do
- Class.new do
- include Gitlab::Database::IndexingExclusiveLeaseGuard
-
- attr_reader :connection
-
- def initialize(connection)
- @connection = connection
- end
- end
- end
-
- describe '#lease_key' do
- let(:helper) { helper_class.new(connection) }
- let(:lease_key) { "gitlab/database/indexing/actions/#{database_name}" }
-
- context 'with CI database connection' do
- let(:connection) { Ci::ApplicationRecord.connection }
- let(:database_name) { Gitlab::Database::CI_DATABASE_NAME }
-
- before do
- skip_if_multiple_databases_not_setup(:ci)
- end
-
- it { expect(helper.lease_key).to eq(lease_key) }
- end
-
- context 'with MAIN database connection' do
- let(:connection) { ApplicationRecord.connection }
- let(:database_name) { Gitlab::Database::MAIN_DATABASE_NAME }
-
- it { expect(helper.lease_key).to eq(lease_key) }
- end
- end
-end
diff --git a/spec/lib/gitlab/database/reindexing/coordinator_spec.rb b/spec/lib/gitlab/database/reindexing/coordinator_spec.rb
index bf993e85cb8..9482700df5f 100644
--- a/spec/lib/gitlab/database/reindexing/coordinator_spec.rb
+++ b/spec/lib/gitlab/database/reindexing/coordinator_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Gitlab::Database::Reindexing::Coordinator, feature_category: :dat
end
let!(:lease) { stub_exclusive_lease(lease_key, uuid, timeout: lease_timeout) }
- let(:lease_key) { "gitlab/database/indexing/actions/#{Gitlab::Database::PRIMARY_DATABASE_NAME}" }
+ let(:lease_key) { "gitlab/database/asyncddl/actions/#{Gitlab::Database::PRIMARY_DATABASE_NAME}" }
let(:lease_timeout) { 1.day }
let(:uuid) { 'uuid' }
diff --git a/spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb b/spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb
index 8488d39bc4e..945b742b025 100644
--- a/spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb
@@ -98,7 +98,7 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNotesImporter, feature_catego
.and_yield(github_comment)
expect(Gitlab::GithubImport::ImportDiffNoteWorker).to receive(:perform_in)
- .with(1.minute, project.id, an_instance_of(Hash), an_instance_of(String))
+ .with(1.second, project.id, an_instance_of(Hash), an_instance_of(String))
waiter = importer.parallel_import
diff --git a/spec/lib/gitlab/github_import/importer/issue_events_importer_spec.rb b/spec/lib/gitlab/github_import/importer/issue_events_importer_spec.rb
index 3ab238bce9e..04b694dc0cb 100644
--- a/spec/lib/gitlab/github_import/importer/issue_events_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/issue_events_importer_spec.rb
@@ -78,7 +78,7 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueEventsImporter, feature_cate
allow(importer).to receive(:each_object_to_import).and_yield(issue_event)
expect(Gitlab::GithubImport::ImportIssueEventWorker).to receive(:perform_in).with(
- 1.minute, project.id, an_instance_of(Hash), an_instance_of(String)
+ 1.second, project.id, an_instance_of(Hash), an_instance_of(String)
)
waiter = importer.parallel_import
diff --git a/spec/lib/gitlab/github_import/importer/issues_importer_spec.rb b/spec/lib/gitlab/github_import/importer/issues_importer_spec.rb
index 6ba65754ac5..d6fd1a4739c 100644
--- a/spec/lib/gitlab/github_import/importer/issues_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/issues_importer_spec.rb
@@ -92,7 +92,7 @@ RSpec.describe Gitlab::GithubImport::Importer::IssuesImporter, feature_category:
expect(Gitlab::GithubImport::ImportIssueWorker)
.to receive(:perform_in)
- .with(1.minute, project.id, an_instance_of(Hash), an_instance_of(String))
+ .with(1.second, project.id, an_instance_of(Hash), an_instance_of(String))
waiter = importer.parallel_import
diff --git a/spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb b/spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb
index 35a6f6d5814..fab9d26532d 100644
--- a/spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb
@@ -119,7 +119,7 @@ RSpec.describe Gitlab::GithubImport::Importer::LfsObjectsImporter, feature_categ
end
expect(Gitlab::GithubImport::ImportLfsObjectWorker).to receive(:perform_in)
- .with(1.minute, project.id, an_instance_of(Hash), an_instance_of(String))
+ .with(1.second, project.id, an_instance_of(Hash), an_instance_of(String))
waiter = importer.parallel_import
diff --git a/spec/lib/gitlab/github_import/importer/notes_importer_spec.rb b/spec/lib/gitlab/github_import/importer/notes_importer_spec.rb
index 0ca27782084..841cc8178ea 100644
--- a/spec/lib/gitlab/github_import/importer/notes_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/notes_importer_spec.rb
@@ -84,7 +84,7 @@ RSpec.describe Gitlab::GithubImport::Importer::NotesImporter, feature_category:
.and_yield(github_comment)
expect(Gitlab::GithubImport::ImportNoteWorker).to receive(:perform_in)
- .with(1.minute, project.id, an_instance_of(Hash), an_instance_of(String))
+ .with(1.second, project.id, an_instance_of(Hash), an_instance_of(String))
waiter = importer.parallel_import
diff --git a/spec/lib/gitlab/github_import/importer/protected_branches_importer_spec.rb b/spec/lib/gitlab/github_import/importer/protected_branches_importer_spec.rb
index f3d8dc9373f..6a8b14a2690 100644
--- a/spec/lib/gitlab/github_import/importer/protected_branches_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/protected_branches_importer_spec.rb
@@ -144,7 +144,7 @@ RSpec.describe Gitlab::GithubImport::Importer::ProtectedBranchesImporter, featur
it 'imports each protected branch in parallel' do
expect(Gitlab::GithubImport::ImportProtectedBranchWorker)
.to receive(:perform_in)
- .with(1.minute, project.id, an_instance_of(Hash), an_instance_of(String))
+ .with(1.second, project.id, an_instance_of(Hash), an_instance_of(String))
expect(Gitlab::GithubImport::ObjectCounter)
.to receive(:increment).with(project, :protected_branch, :fetched)
diff --git a/spec/lib/gitlab/github_import/importer/pull_requests/review_requests_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests/review_requests_importer_spec.rb
index 53a0e718eb6..536983fea06 100644
--- a/spec/lib/gitlab/github_import/importer/pull_requests/review_requests_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_requests/review_requests_importer_spec.rb
@@ -108,10 +108,10 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequests::ReviewRequestsImpor
it 'schedule import for each merge request reviewers' do
expect(Gitlab::GithubImport::PullRequests::ImportReviewRequestWorker)
- .to receive(:perform_in).with(1.minute, *expected_worker_payload.first)
+ .to receive(:perform_in).with(1.second, *expected_worker_payload.first)
expect(Gitlab::GithubImport::PullRequests::ImportReviewRequestWorker)
- .to receive(:perform_in).with(1.minute, *expected_worker_payload.second)
+ .to receive(:perform_in).with(1.second, *expected_worker_payload.second)
importer.parallel_import
end
@@ -126,7 +126,7 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequests::ReviewRequestsImpor
it "doesn't schedule import this merge request reviewers" do
expect(Gitlab::GithubImport::PullRequests::ImportReviewRequestWorker)
- .to receive(:perform_in).with(1.minute, *expected_worker_payload.second)
+ .to receive(:perform_in).with(1.second, *expected_worker_payload.second)
importer.parallel_import
end
diff --git a/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb
index e8a3764228f..eddde272d2c 100644
--- a/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb
@@ -102,7 +102,7 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter, feature_cat
expect(Gitlab::GithubImport::ImportPullRequestWorker)
.to receive(:perform_in)
- .with(1.minute, project.id, an_instance_of(Hash), an_instance_of(String))
+ .with(1.second, project.id, an_instance_of(Hash), an_instance_of(String))
waiter = importer.parallel_import
diff --git a/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb b/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb
index 1003f2cdc2b..c351ead91eb 100644
--- a/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb
+++ b/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb
@@ -320,11 +320,11 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling, feature_category: :impo
expect(importer).to receive(:each_object_to_import)
.and_yield(object).and_yield(object).and_yield(object)
expect(worker_class).to receive(:perform_in)
- .with(1.minute, project.id, { title: 'One' }, 'waiter-key').ordered
+ .with(1.second, project.id, { title: 'One' }, 'waiter-key').ordered
expect(worker_class).to receive(:perform_in)
- .with(1.minute, project.id, { title: 'Two' }, 'waiter-key').ordered
+ .with(1.second, project.id, { title: 'Two' }, 'waiter-key').ordered
expect(worker_class).to receive(:perform_in)
- .with(2.minutes, project.id, { title: 'Three' }, 'waiter-key').ordered
+ .with(1.minute + 1.second, project.id, { title: 'Three' }, 'waiter-key').ordered
job_waiter = importer.parallel_import
@@ -349,11 +349,11 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling, feature_category: :impo
expect(importer).to receive(:each_object_to_import).and_yield(object).and_yield(object).and_yield(object)
expect(worker_class).to receive(:perform_in)
- .with(1.minute, project.id, { title: 'One' }, 'waiter-key').ordered
+ .with(1.second, project.id, { title: 'One' }, 'waiter-key').ordered
expect(worker_class).to receive(:perform_in)
- .with(2.minutes, project.id, { title: 'Two' }, 'waiter-key').ordered
+ .with(1.minute + 1.second, project.id, { title: 'Two' }, 'waiter-key').ordered
expect(worker_class).to receive(:perform_in)
- .with(3.minutes, project.id, { title: 'Three' }, 'waiter-key').ordered
+ .with(2.minutes + 1.second, project.id, { title: 'Three' }, 'waiter-key').ordered
job_waiter = importer.parallel_import
diff --git a/spec/requests/projects/ml/experiments_controller_spec.rb b/spec/requests/projects/ml/experiments_controller_spec.rb
index 474194cf1d4..9b071efc1f1 100644
--- a/spec/requests/projects/ml/experiments_controller_spec.rb
+++ b/spec/requests/projects/ml/experiments_controller_spec.rb
@@ -38,31 +38,74 @@ RSpec.describe Projects::Ml::ExperimentsController, feature_category: :mlops do
end
describe 'GET index' do
- before do
- list_experiments
- end
+ describe 'renderering' do
+ before do
+ list_experiments
+ end
- it 'renders the template' do
- expect(response).to render_template('projects/ml/experiments/index')
+ it 'renders the template' do
+ expect(response).to render_template('projects/ml/experiments/index')
+ end
+
+ it 'does not perform N+1 sql queries' do
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { list_experiments }
+
+ create_list(:ml_experiments, 2, project: project, user: user)
+
+ expect { list_experiments }.not_to exceed_all_query_limit(control_count)
+ end
end
- it 'does not perform N+1 sql queries' do
- control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { list_experiments }
+ describe 'pagination' do
+ let_it_be(:experiments) do
+ create_list(:ml_experiments, 3, project: project_with_feature)
+ end
+
+ let(:params) { basic_params.merge(id: experiment.iid) }
+
+ before do
+ stub_const("Projects::Ml::ExperimentsController::MAX_EXPERIMENTS_PER_PAGE", 2)
- create_list(:ml_experiments, 2, project: project, user: user)
+ list_experiments
+ end
- expect { list_experiments }.not_to exceed_all_query_limit(control_count)
+ it 'fetches only MAX_CANDIDATES_PER_PAGE candidates' do
+ expect(assigns(:experiments).size).to eq(2)
+ end
+
+ it 'paginates', :aggregate_failures do
+ page = assigns(:experiments)
+
+ expect(page.first).to eq(experiments.last)
+ expect(page.last).to eq(experiments[1])
+
+ new_params = params.merge(cursor: assigns(:page_info)[:end_cursor])
+
+ list_experiments(new_params)
+
+ new_page = assigns(:experiments)
+
+ expect(new_page.first).to eq(experiments.first)
+ end
end
context 'when :ml_experiment_tracking is disabled for the project' do
let(:project) { project_without_feature }
+ before do
+ list_experiments
+ end
+
it 'responds with a 404' do
expect(response).to have_gitlab_http_status(:not_found)
end
end
- it_behaves_like '404 if feature flag disabled'
+ it_behaves_like '404 if feature flag disabled' do
+ before do
+ list_experiments
+ end
+ end
end
describe 'GET show' do
@@ -178,7 +221,7 @@ RSpec.describe Projects::Ml::ExperimentsController, feature_category: :mlops do
get project_ml_experiment_path(project, experiment.iid), params: new_params || params
end
- def list_experiments
- get project_ml_experiments_path(project), params: params
+ def list_experiments(new_params = nil)
+ get project_ml_experiments_path(project), params: new_params || params
end
end
diff --git a/spec/services/export_csv/map_export_fields_service_spec.rb b/spec/services/export_csv/map_export_fields_service_spec.rb
new file mode 100644
index 00000000000..0060baf30e4
--- /dev/null
+++ b/spec/services/export_csv/map_export_fields_service_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ExportCsv::MapExportFieldsService, feature_category: :team_planning do
+ let(:selected_fields) { ['Title', 'Author username', 'state'] }
+ let(:invalid_fields) { ['Title', 'Author Username', 'State', 'Invalid Field', 'Other Field'] }
+ let(:data) do
+ {
+ 'Requirement ID' => '1',
+ 'Title' => 'foo',
+ 'Description' => 'bar',
+ 'Author' => 'root',
+ 'Author Username' => 'admin',
+ 'Created At (UTC)' => '2023-02-01 15:16:35',
+ 'State' => 'opened',
+ 'State Updated At (UTC)' => '2023-02-01 15:16:35'
+ }
+ end
+
+ describe '#execute' do
+ it 'returns a hash with selected fields only' do
+ result = described_class.new(selected_fields, data).execute
+
+ expect(result).to be_a(Hash)
+ expect(result.keys).to match_array(selected_fields.map(&:titleize))
+ end
+
+ context 'when the fields collection is empty' do
+ it 'returns a hash with all fields' do
+ result = described_class.new([], data).execute
+
+ expect(result).to be_a(Hash)
+ expect(result.keys).to match_array(data.keys)
+ end
+ end
+
+ context 'when fields collection includes invalid fields' do
+ it 'returns a hash with valid selected fields only' do
+ result = described_class.new(invalid_fields, data).execute
+
+ expect(result).to be_a(Hash)
+ expect(result.keys).to eq(selected_fields.map(&:titleize))
+ end
+ end
+ end
+
+ describe '#invalid_fields' do
+ it 'returns an array containing invalid fields' do
+ result = described_class.new(invalid_fields, data).invalid_fields
+
+ expect(result).to match_array(['Invalid Field', 'Other Field'])
+ end
+ end
+end
diff --git a/spec/services/issues/export_csv_service_spec.rb b/spec/services/issues/export_csv_service_spec.rb
index 3beb28c6009..1ac64c0301d 100644
--- a/spec/services/issues/export_csv_service_spec.rb
+++ b/spec/services/issues/export_csv_service_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Issues::ExportCsvService, :with_license, feature_category: :importers do
+RSpec.describe Issues::ExportCsvService, :with_license, feature_category: :team_planning do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, :public, group: group) }
diff --git a/spec/services/work_items/export_csv_service_spec.rb b/spec/services/work_items/export_csv_service_spec.rb
new file mode 100644
index 00000000000..fdf195fa9fd
--- /dev/null
+++ b/spec/services/work_items/export_csv_service_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WorkItems::ExportCsvService, :with_license, feature_category: :team_planning do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :public, group: group) }
+ let_it_be(:work_item_1) { create(:work_item, project: project) }
+ let_it_be(:work_item_2) { create(:work_item, :incident, project: project) }
+
+ subject { described_class.new(WorkItem.all, project) }
+
+ def csv
+ CSV.parse(subject.csv_data, headers: true)
+ end
+
+ it 'renders csv to string' do
+ expect(subject.csv_data).to be_a String
+ end
+
+ describe '#email' do
+ # TODO - will be implemented as part of https://gitlab.com/gitlab-org/gitlab/-/issues/379082
+ xit 'emails csv' do
+ expect { subject.email(user) }.o change { ActionMailer::Base.deliveries.count }.from(0).to(1)
+ end
+ end
+
+ it 'returns two work items' do
+ expect(csv.count).to eq(2)
+ end
+
+ specify 'iid' do
+ expect(csv[0]['Id']).to eq work_item_1.iid.to_s
+ end
+
+ specify 'title' do
+ expect(csv[0]['Title']).to eq work_item_1.title
+ end
+
+ specify 'type' do
+ expect(csv[0]['Type']).to eq('Issue')
+ expect(csv[1]['Type']).to eq('Incident')
+ end
+
+ specify 'author name' do
+ expect(csv[0]['Author']).to eq(work_item_1.author_name)
+ end
+
+ specify 'author username' do
+ expect(csv[0]['Author Username']).to eq(work_item_1.author.username)
+ end
+
+ specify 'created_at' do
+ expect(csv[0]['Created At (UTC)']).to eq(work_item_1.created_at.to_s(:csv))
+ end
+
+ it 'preloads fields to avoid N+1 queries' do
+ control = ActiveRecord::QueryRecorder.new { subject.csv_data }
+
+ create(:work_item, :task, project: project)
+
+ expect { subject.csv_data }.not_to exceed_query_limit(control)
+ end
+
+ it_behaves_like 'a service that returns invalid fields from selection'
+end
diff --git a/spec/support/helpers/select2_helper.rb b/spec/support/helpers/select2_helper.rb
deleted file mode 100644
index 38bf34bdd61..00000000000
--- a/spec/support/helpers/select2_helper.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'wait_for_requests'
-
-# Select2 ajax programmatic helper
-# It allows you to select value from select2
-#
-# Params
-# value - real value of selected item
-# opts - options containing css selector
-#
-# Usage:
-#
-# select2(2, from: '#user_ids')
-#
-
-module Select2Helper
- include WaitForRequests
-
- def select2(value, options = {})
- raise ArgumentError, 'options must be a Hash' unless options.is_a?(Hash)
-
- wait_for_requests unless options[:async]
-
- selector = options.fetch(:from)
-
- ensure_select2_loaded(selector)
-
- if options[:multiple]
- execute_script("$('#{selector}').select2('val', ['#{value}']).trigger('change');")
- else
- execute_script("$('#{selector}').select2('val', '#{value}').trigger('change');")
- end
- end
-
- def open_select2(selector)
- ensure_select2_loaded(selector)
-
- execute_script("$('#{selector}').select2('open');")
- end
-
- def close_select2(selector)
- ensure_select2_loaded(selector)
-
- execute_script("$('#{selector}').select2('close');")
- end
-
- def scroll_select2_to_bottom(selector)
- evaluate_script "$('#{selector}').scrollTop($('#{selector}')[0].scrollHeight); $('#{selector}');"
- end
-
- private
-
- def ensure_select2_loaded(selector)
- first(selector, visible: :all).sibling('.select2-container')
- end
-end
diff --git a/spec/support/shared_examples/services/export_csv/export_csv_invalid_fields_shared_examples.rb b/spec/support/shared_examples/services/export_csv/export_csv_invalid_fields_shared_examples.rb
new file mode 100644
index 00000000000..25899f93914
--- /dev/null
+++ b/spec/support/shared_examples/services/export_csv/export_csv_invalid_fields_shared_examples.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'a service that returns invalid fields from selection' do
+ describe '#invalid_fields' do
+ it 'returns invalid fields from selection' do
+ fields = %w[title invalid_1 invalid_2]
+
+ service = described_class.new(WorkItem.all, project, fields)
+
+ expect(service.invalid_fields).to eq(%w[invalid_1 invalid_2])
+ end
+ end
+end
diff --git a/yarn.lock b/yarn.lock
index 2735a71c5d6..fe595bfd9b4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11006,11 +11006,6 @@ select-hose@^2.0.0:
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=
-select2@3.5.2-browserify:
- version "3.5.2-browserify"
- resolved "https://registry.yarnpkg.com/select2/-/select2-3.5.2-browserify.tgz#dc4dafda38d67a734e8a97a46f0d3529ae05391d"
- integrity sha1-3E2v2jjWenNOipekbw01Ka4FOR0=
-
select@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"