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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-12-16 15:08:27 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-12-16 15:08:27 +0300
commit377d420e3d7e3f066c409714cbb9f7bb0a4882b6 (patch)
tree4ba0cb1b9487bf386c3c0e5d76a2191f285b6243
parentbc9b43904d491c7b864c8fb6ba06ae0f6625db0d (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/behaviors/index.js1
-rw-r--r--app/assets/javascripts/behaviors/markdown/init_gfm.js13
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_gfm.js77
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_math.js6
-rw-r--r--app/assets/javascripts/behaviors/preview_markdown.js1
-rw-r--r--app/assets/javascripts/blob/viewer/index.js2
-rw-r--r--app/assets/javascripts/blob_edit/edit_blob.js1
-rw-r--r--app/assets/javascripts/deprecated_notes.js1
-rw-r--r--app/assets/javascripts/issues/show/components/description.vue3
-rw-r--r--app/assets/javascripts/merge_request_tabs.js3
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue5
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue3
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue2
-rw-r--r--app/assets/javascripts/pages/shared/wikis/render_gfm_facade.js5
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stages.vue8
-rw-r--r--app/assets/javascripts/releases/components/release_block.vue5
-rw-r--r--app/assets/javascripts/repository/components/preview/index.vue5
-rw-r--r--app/assets/javascripts/terms/components/app.vue5
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field_view.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown_drawer/markdown_drawer.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue4
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/components/issuable_description.vue10
-rw-r--r--app/assets/javascripts/work_items/components/notes/system_note.vue4
-rw-r--r--app/assets/javascripts/work_items/components/work_item_description_rendered.vue5
-rw-r--r--app/assets/stylesheets/page_bundles/pipelines.scss39
-rw-r--r--app/controllers/registrations_controller.rb1
-rw-r--r--app/finders/ci/freeze_periods_finder.rb16
-rw-r--r--app/finders/freeze_periods_finder.rb14
-rw-r--r--app/models/dependency_proxy/group_setting.rb2
-rw-r--r--app/views/projects/commit/_commit_box.html.haml4
-rw-r--r--config/feature_flags/development/automated_email_provision.yml8
-rw-r--r--db/migrate/20221213184314_change_enabled_default_in_dependency_proxy_group_settings.rb7
-rw-r--r--db/schema_migrations/202212131843141
-rw-r--r--db/structure.sql2
-rw-r--r--doc/administration/geo/secondary_proxy/index.md72
-rw-r--r--doc/administration/postgresql/multiple_databases.md141
-rw-r--r--doc/integration/saml.md64
-rw-r--r--doc/subscriptions/gitlab_dedicated/index.md4
-rw-r--r--doc/user/group/import/index.md28
-rw-r--r--doc/user/project/import/img/gitlab_import_history_page_v14_10.pngbin28219 -> 0 bytes
-rw-r--r--doc/user/project/import/index.md162
-rw-r--r--doc/user/project/settings/import_export.md60
-rw-r--r--lib/api/freeze_periods.rb2
-rw-r--r--locale/gitlab.pot6
-rw-r--r--metrics_server/metrics_server.rb1
-rw-r--r--spec/controllers/registrations_controller_spec.rb20
-rw-r--r--spec/features/merge_request/user_sees_pipelines_spec.rb2
-rw-r--r--spec/finders/ci/freeze_periods_finder_spec.rb (renamed from spec/finders/freeze_periods_finder_spec.rb)2
-rw-r--r--spec/frontend/batch_comments/components/draft_note_spec.js3
-rw-r--r--spec/frontend/batch_comments/components/preview_item_spec.js3
-rw-r--r--spec/frontend/batch_comments/components/publish_dropdown_spec.js3
-rw-r--r--spec/frontend/diffs/components/diff_discussions_spec.js3
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js2
-rw-r--r--spec/frontend/issues/show/components/app_spec.js2
-rw-r--r--spec/frontend/issues/show/components/description_spec.js6
-rw-r--r--spec/frontend/notes/components/discussion_notes_spec.js3
-rw-r--r--spec/frontend/notes/components/noteable_discussion_spec.js3
-rw-r--r--spec/frontend/notes/components/notes_app_spec.js3
-rw-r--r--spec/frontend/pages/shared/wikis/components/wiki_content_spec.js4
-rw-r--r--spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_mini_graph_spec.js3
-rw-r--r--spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stages_spec.js6
-rw-r--r--spec/frontend/releases/components/release_block_spec.js7
-rw-r--r--spec/frontend/terms/components/app_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/content_viewer/content_viewer_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/markdown/field_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/markdown/field_view_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/notes/system_note_spec.js8
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_description_spec.js18
-rw-r--r--spec/frontend/work_items/components/notes/system_note_spec.js8
-rw-r--r--spec/frontend/work_items/components/work_item_description_rendered_spec.js8
-rw-r--r--spec/frontend/work_items/router_spec.js2
-rw-r--r--spec/metrics_server/metrics_server_spec.rb3
-rw-r--r--spec/serializers/pipeline_serializer_spec.rb24
78 files changed, 573 insertions, 443 deletions
diff --git a/app/assets/javascripts/behaviors/index.js b/app/assets/javascripts/behaviors/index.js
index 30160248a77..220064e6673 100644
--- a/app/assets/javascripts/behaviors/index.js
+++ b/app/assets/javascripts/behaviors/index.js
@@ -1,6 +1,5 @@
import $ from 'jquery';
import './autosize';
-import './markdown/render_gfm';
import initCollapseSidebarOnWindowResize from './collapse_sidebar_on_window_resize';
import initCopyToClipboard from './copy_to_clipboard';
import installGlEmojiElement from './gl_emoji';
diff --git a/app/assets/javascripts/behaviors/markdown/init_gfm.js b/app/assets/javascripts/behaviors/markdown/init_gfm.js
new file mode 100644
index 00000000000..d9c7cee50da
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/init_gfm.js
@@ -0,0 +1,13 @@
+import $ from 'jquery';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
+
+$.fn.renderGFM = function plugin() {
+ this.get().forEach(renderGFM);
+ return this;
+};
+requestIdleCallback(
+ () => {
+ renderGFM(document.body);
+ },
+ { timeout: 500 },
+);
diff --git a/app/assets/javascripts/behaviors/markdown/render_gfm.js b/app/assets/javascripts/behaviors/markdown/render_gfm.js
index 50430f8e607..2eab5b84e3e 100644
--- a/app/assets/javascripts/behaviors/markdown/render_gfm.js
+++ b/app/assets/javascripts/behaviors/markdown/render_gfm.js
@@ -1,4 +1,3 @@
-import $ from 'jquery';
import syntaxHighlight from '~/syntax_highlight';
import highlightCurrentUser from './highlight_current_user';
import { renderKroki } from './render_kroki';
@@ -8,40 +7,46 @@ import renderMetrics from './render_metrics';
import renderObservability from './render_observability';
import { renderJSONTable } from './render_json_table';
-// Render GitLab flavoured Markdown
-//
-// Delegates to syntax highlight and render math & mermaid diagrams.
-//
-$.fn.renderGFM = function renderGFM() {
- syntaxHighlight(this.find('.js-syntax-highlight').get());
- renderKroki(this.find('.js-render-kroki[hidden]').get());
- renderMath(this.find('.js-render-math'));
- renderSandboxedMermaid(this.find('.js-render-mermaid').get());
- renderJSONTable(
- Array.from(this.find('[lang="json"][data-lang-params="table"]').get()).map((e) => e.parentNode),
- );
-
- highlightCurrentUser(this.find('.gfm-project_member').get());
+function initPopovers(elements) {
+ if (!elements.length) return;
+ import(/* webpackChunkName: 'IssuablePopoverBundle' */ '~/issuable/popover')
+ .then(({ default: initIssuablePopovers }) => {
+ initIssuablePopovers(elements);
+ })
+ .catch(() => {});
+}
- const issuablePopoverElements = this.find('.gfm-issue, .gfm-merge_request').get();
- if (issuablePopoverElements.length) {
- import(/* webpackChunkName: 'IssuablePopoverBundle' */ '~/issuable/popover')
- .then(({ default: initIssuablePopovers }) => {
- initIssuablePopovers(issuablePopoverElements);
- })
- .catch(() => {});
- }
-
- renderMetrics(this.find('.js-render-metrics').get());
- renderObservability(this.find('.js-render-observability').get());
- return this;
-};
+// Render GitLab flavoured Markdown
+export function renderGFM(element) {
+ const [
+ highlightEls,
+ krokiEls,
+ mathEls,
+ mermaidEls,
+ tableEls,
+ userEls,
+ popoverEls,
+ metricsEls,
+ observabilityEls,
+ ] = [
+ '.js-syntax-highlight',
+ '.js-render-kroki[hidden]',
+ '.js-render-math',
+ '.js-render-mermaid',
+ '[lang="json"][data-lang-params="table"]',
+ '.gfm-project_member',
+ '.gfm-issue, .gfm-merge_request',
+ '.js-render-metrics',
+ '.js-render-observability',
+ ].map((selector) => Array.from(element.querySelectorAll(selector)));
-$(() => {
- window.requestIdleCallback(
- () => {
- $('body').renderGFM();
- },
- { timeout: 500 },
- );
-});
+ syntaxHighlight(highlightEls);
+ renderKroki(krokiEls);
+ renderMath(mathEls);
+ renderSandboxedMermaid(mermaidEls);
+ renderJSONTable(tableEls.map((e) => e.parentNode));
+ highlightCurrentUser(userEls);
+ renderMetrics(metricsEls);
+ renderObservability(observabilityEls);
+ initPopovers(popoverEls);
+}
diff --git a/app/assets/javascripts/behaviors/markdown/render_math.js b/app/assets/javascripts/behaviors/markdown/render_math.js
index ac41af4df7a..7852a909160 100644
--- a/app/assets/javascripts/behaviors/markdown/render_math.js
+++ b/app/assets/javascripts/behaviors/markdown/render_math.js
@@ -175,14 +175,14 @@ class SafeMathRenderer {
}
}
-export default function renderMath($els) {
- if (!$els.length) return;
+export default function renderMath(elements) {
+ if (!elements.length) return;
Promise.all([
import(/* webpackChunkName: 'katex' */ 'katex'),
import(/* webpackChunkName: 'katex' */ 'katex/dist/katex.min.css'),
])
.then(([katex]) => {
- const renderer = new SafeMathRenderer($els.get(), katex);
+ const renderer = new SafeMathRenderer(elements, katex);
renderer.render();
renderer.attachEvents();
})
diff --git a/app/assets/javascripts/behaviors/preview_markdown.js b/app/assets/javascripts/behaviors/preview_markdown.js
index 68f5180cc03..86a05f24dfc 100644
--- a/app/assets/javascripts/behaviors/preview_markdown.js
+++ b/app/assets/javascripts/behaviors/preview_markdown.js
@@ -4,6 +4,7 @@ import $ from 'jquery';
import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
+import '~/behaviors/markdown/init_gfm';
// MarkdownPreview
//
diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js
index 8d323c335d3..439c4258805 100644
--- a/app/assets/javascripts/blob/viewer/index.js
+++ b/app/assets/javascripts/blob/viewer/index.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import '~/behaviors/markdown/render_gfm';
+import '~/behaviors/markdown/init_gfm';
import { createAlert } from '~/flash';
import { __ } from '~/locale';
import {
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index 97d8b206307..46b3f16df77 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -9,6 +9,7 @@ import { addEditorMarkdownListeners } from '~/lib/utils/text_markdown';
import { insertFinalNewline } from '~/lib/utils/text_utility';
import TemplateSelectorMediator from '../blob/file_template_mediator';
import { BLOB_EDITOR_ERROR, BLOB_PREVIEW_ERROR } from './constants';
+import '~/behaviors/markdown/init_gfm';
export default class EditBlob {
// The options object has:
diff --git a/app/assets/javascripts/deprecated_notes.js b/app/assets/javascripts/deprecated_notes.js
index eeb931543b2..c090a66a69d 100644
--- a/app/assets/javascripts/deprecated_notes.js
+++ b/app/assets/javascripts/deprecated_notes.js
@@ -40,6 +40,7 @@ import { localTimeAgo } from './lib/utils/datetime_utility';
import { getLocationHash } from './lib/utils/url_utility';
import { sprintf, s__, __ } from './locale';
import TaskList from './task_list';
+import '~/behaviors/markdown/init_gfm';
window.autosize = Autosize;
diff --git a/app/assets/javascripts/issues/show/components/description.vue b/app/assets/javascripts/issues/show/components/description.vue
index e225c858c8d..78e729b97da 100644
--- a/app/assets/javascripts/issues/show/components/description.vue
+++ b/app/assets/javascripts/issues/show/components/description.vue
@@ -28,6 +28,7 @@ import {
TASK_TYPE_NAME,
WIDGET_TYPE_DESCRIPTION,
} from '~/work_items/constants';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import animateMixin from '../mixins/animate';
import { convertDescriptionWithNewSort } from '../utils';
@@ -178,7 +179,7 @@ export default {
},
methods: {
renderGFM() {
- $(this.$refs['gfm-content']).renderGFM();
+ renderGFM(this.$refs['gfm-content']);
if (this.canUpdate) {
// eslint-disable-next-line no-new
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index b091fbadcd7..6aa4a024016 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -5,6 +5,7 @@ import { createAlert } from '~/flash';
import { getCookie, isMetaClick, parseBoolean, scrollToElement } from '~/lib/utils/common_utils';
import { parseUrlPathname } from '~/lib/utils/url_utility';
import createEventHub from '~/helpers/event_hub_factory';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import BlobForkSuggestion from './blob/blob_fork_suggestion';
import Diff from './diff';
import { initDiffStatsDropdown } from './init_diff_stats_dropdown';
@@ -346,7 +347,7 @@ export default class MergeRequestTabs {
this.commitPipelinesTable = destroyPipelines(this.commitPipelinesTable);
}
- $('.detail-page-description').renderGFM();
+ renderGFM(document.querySelector('.detail-page-description'));
if (shouldScroll) this.recallScroll(action);
} else if (action === this.currentAction) {
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index 7aa86864e03..20cf21cd1b6 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -1,11 +1,10 @@
<script>
-import $ from 'jquery';
import { escape } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
import SafeHtml from '~/vue_shared/directives/safe_html';
import { __ } from '~/locale';
-import '~/behaviors/markdown/render_gfm';
import Suggestions from '~/vue_shared/components/markdown/suggestions.vue';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import autosave from '../mixins/autosave';
import NoteAttachment from './note_attachment.vue';
import NoteAwardsList from './note_awards_list.vue';
@@ -121,7 +120,7 @@ export default {
'removeSuggestionInfoFromBatch',
]),
renderGFM() {
- $(this.$refs['note-body']).renderGFM();
+ renderGFM(this.$refs['note-body']);
},
handleFormUpdate(noteText, parentElement, callback, resolveDiscussion) {
this.$emit('handleFormUpdate', { noteText, parentElement, callback, resolveDiscussion });
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index 99809013bf6..7a73278bf7b 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -12,6 +12,7 @@ import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending';
import { truncateSha } from '~/lib/utils/text_utility';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import { __, s__, sprintf } from '~/locale';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import eventHub from '../event_hub';
import noteable from '../mixins/noteable';
import resolvable from '../mixins/resolvable';
@@ -287,7 +288,7 @@ export default {
this.isEditing = false;
this.isRequesting = false;
this.oldContent = null;
- $(this.$refs.noteBody.$el).renderGFM();
+ renderGFM(this.$refs.noteBody.$el);
this.$refs.noteBody.resetAutoSave();
this.$emit('updateSuccess');
},
diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue
index 64123919fd6..b19809aff53 100644
--- a/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue
+++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue
@@ -5,7 +5,7 @@ import { createAlert } from '~/flash';
import { __ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
import { handleLocationHash } from '~/lib/utils/common_utils';
-import { renderGFM } from '../render_gfm_facade';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
export default {
components: {
diff --git a/app/assets/javascripts/pages/shared/wikis/render_gfm_facade.js b/app/assets/javascripts/pages/shared/wikis/render_gfm_facade.js
deleted file mode 100644
index 90cc2983153..00000000000
--- a/app/assets/javascripts/pages/shared/wikis/render_gfm_facade.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import $ from 'jquery';
-
-export const renderGFM = (el) => {
- return $(el).renderGFM();
-};
diff --git a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue
index 92f627b9d12..827adf9f7f7 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue
@@ -35,11 +35,6 @@ export default {
required: true,
default: () => [],
},
- stagesClass: {
- type: [Array, Object, String],
- required: false,
- default: '',
- },
updateDropdown: {
type: Boolean,
required: false,
@@ -59,7 +54,7 @@ export default {
};
</script>
<template>
- <div class="stage-cell" data-testid="pipeline-mini-graph">
+ <div data-testid="pipeline-mini-graph">
<linked-pipelines-mini-list
v-if="upstreamPipeline"
:triggered-by="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ [
@@ -77,7 +72,6 @@ export default {
:is-merge-train="isMergeTrain"
:stages="stages"
:update-dropdown="updateDropdown"
- :stages-class="stagesClass"
data-testid="pipeline-stages"
@miniGraphStageClick="$emit('miniGraphStageClick')"
/>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stages.vue b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stages.vue
index ceb771132dd..ba549d9b423 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stages.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stages.vue
@@ -17,11 +17,6 @@ export default {
required: false,
default: false,
},
- stagesClass: {
- type: [Array, Object, String],
- required: false,
- default: '',
- },
isMergeTrain: {
type: Boolean,
required: false,
@@ -35,8 +30,7 @@ export default {
<div
v-for="stage in stages"
:key="stage.name"
- :class="stagesClass"
- class="dropdown gl-display-inline-block gl-mr-2 gl-my-2 gl-vertical-align-middle stage-container"
+ class="pipeline-mini-graph-stage-container dropdown gl-display-inline-block gl-mr-2 gl-my-2 gl-vertical-align-middle"
>
<pipeline-stage
:stage="stage"
diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue
index 4e9e047dbd5..49c349e7a7b 100644
--- a/app/assets/javascripts/releases/components/release_block.vue
+++ b/app/assets/javascripts/releases/components/release_block.vue
@@ -1,5 +1,4 @@
<script>
-import $ from 'jquery';
import { isEmpty } from 'lodash';
import SafeHtml from '~/vue_shared/directives/safe_html';
import { scrollToElement } from '~/lib/utils/common_utils';
@@ -7,7 +6,7 @@ import { slugify } from '~/lib/utils/text_utility';
import { getLocationHash } from '~/lib/utils/url_utility';
import { CREATED_ASC } from '~/releases/constants';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import '~/behaviors/markdown/render_gfm';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import EvidenceBlock from './evidence_block.vue';
import ReleaseBlockAssets from './release_block_assets.vue';
import ReleaseBlockFooter from './release_block_footer.vue';
@@ -86,7 +85,7 @@ export default {
},
methods: {
renderGFM() {
- $(this.$refs['gfm-content']).renderGFM();
+ renderGFM(this.$refs['gfm-content']);
},
},
safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
diff --git a/app/assets/javascripts/repository/components/preview/index.vue b/app/assets/javascripts/repository/components/preview/index.vue
index 29890a54abe..8feac6b8e35 100644
--- a/app/assets/javascripts/repository/components/preview/index.vue
+++ b/app/assets/javascripts/repository/components/preview/index.vue
@@ -1,9 +1,8 @@
<script>
import { GlIcon, GlLink, GlLoadingIcon } from '@gitlab/ui';
-import $ from 'jquery';
import SafeHtml from '~/vue_shared/directives/safe_html';
-import '~/behaviors/markdown/render_gfm';
import { handleLocationHash } from '~/lib/utils/common_utils';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import readmeQuery from '../../queries/readme.query.graphql';
export default {
@@ -43,7 +42,7 @@ export default {
if (newVal) {
this.$nextTick(() => {
handleLocationHash();
- $(this.$refs.readme).renderGFM();
+ renderGFM(this.$refs.readme);
});
}
},
diff --git a/app/assets/javascripts/terms/components/app.vue b/app/assets/javascripts/terms/components/app.vue
index be116dd6961..eecf32f83df 100644
--- a/app/assets/javascripts/terms/components/app.vue
+++ b/app/assets/javascripts/terms/components/app.vue
@@ -1,5 +1,4 @@
<script>
-import $ from 'jquery';
import { GlButton, GlIntersectionObserver } from '@gitlab/ui';
import SafeHtml from '~/vue_shared/directives/safe_html';
@@ -7,8 +6,8 @@ import { FLASH_TYPES, FLASH_CLOSED_EVENT } from '~/flash';
import { isLoggedIn } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
import csrf from '~/lib/utils/csrf';
-import '~/behaviors/markdown/render_gfm';
import { trackTrialAcceptTerms } from '~/google_tag_manager';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
export default {
name: 'TermsApp',
@@ -55,7 +54,7 @@ export default {
},
methods: {
renderGFM() {
- $(this.$refs.gfmContainer).renderGFM();
+ renderGFM(this.$refs.gfmContainer);
},
handleBottomReached() {
this.acceptDisabled = false;
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
index f8728b01cf5..d8a361066f4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
@@ -190,7 +190,7 @@ export default {
</template>
<template v-else-if="hasPipeline">
<a :href="status.details_path" class="gl-align-self-center gl-mr-3">
- <ci-icon :status="status" :size="24" />
+ <ci-icon :status="status" :size="24" class="gl-display-flex" />
</a>
<div class="ci-widget-container d-flex">
<div class="ci-widget-content">
@@ -280,7 +280,6 @@ export default {
:pipeline-path="pipeline.path"
:stages="pipeline.details.stages"
:upstream-pipeline="pipeline.triggered_by"
- stages-class="mr-widget-pipeline-stages"
/>
<pipeline-artifacts :pipeline-id="pipeline.id" :artifacts="artifacts" class="gl-ml-3" />
</span>
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
index a0379cf01ff..00d12654ee3 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
@@ -1,11 +1,10 @@
<script>
import { GlSkeletonLoader } from '@gitlab/ui';
-import $ from 'jquery';
-import '~/behaviors/markdown/render_gfm';
import { forEach, escape } from 'lodash';
import SafeHtml from '~/vue_shared/directives/safe_html';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
const { CancelToken } = axios;
let axiosSource;
@@ -97,7 +96,7 @@ export default {
this.isLoading = false;
this.$nextTick(() => {
- $(this.$refs.markdownPreview).renderGFM();
+ renderGFM(this.$refs.markdownPreview);
});
})
.catch(() => {
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 09f8ce6de6f..b5f2602af5e 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -1,7 +1,6 @@
<script>
import { GlIcon } from '@gitlab/ui';
import $ from 'jquery';
-import '~/behaviors/markdown/render_gfm';
import { debounce, unescape } from 'lodash';
import { createAlert } from '~/flash';
import GLForm from '~/gl_form';
@@ -11,6 +10,7 @@ import { stripHtml } from '~/lib/utils/text_utility';
import { __, sprintf } from '~/locale';
import Suggestions from '~/vue_shared/components/markdown/suggestions.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import MarkdownHeader from './header.vue';
import MarkdownToolbar from './toolbar.vue';
@@ -314,7 +314,9 @@ export default {
this.markdownPreview = data.body || __('Nothing to preview.');
this.$nextTick()
- .then(() => $(this.$refs['markdown-preview']).renderGFM())
+ .then(() => {
+ renderGFM(this.$refs['markdown-preview']);
+ })
.catch(() =>
createAlert({
message: __('Error rendering Markdown preview'),
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field_view.vue b/app/assets/javascripts/vue_shared/components/markdown/field_view.vue
index d77123371f2..84d40db07bb 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field_view.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field_view.vue
@@ -1,15 +1,9 @@
<script>
-import $ from 'jquery';
-import '~/behaviors/markdown/render_gfm';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
export default {
mounted() {
- this.renderGFM();
- },
- methods: {
- renderGFM() {
- $(this.$el).renderGFM();
- },
+ renderGFM(this.$el);
},
};
</script>
diff --git a/app/assets/javascripts/vue_shared/components/markdown_drawer/markdown_drawer.vue b/app/assets/javascripts/vue_shared/components/markdown_drawer/markdown_drawer.vue
index 015f024cffb..379f22fdc6f 100644
--- a/app/assets/javascripts/vue_shared/components/markdown_drawer/markdown_drawer.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown_drawer/markdown_drawer.vue
@@ -1,10 +1,9 @@
<script>
import { GlDrawer, GlAlert, GlSkeletonLoader } from '@gitlab/ui';
-import $ from 'jquery';
import SafeHtml from '~/vue_shared/directives/safe_html';
-import '~/behaviors/markdown/render_gfm';
import { s__ } from '~/locale';
import { contentTop } from '~/lib/utils/common_utils';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import { getRenderedMarkdown } from './utils/fetch';
export const cache = {};
@@ -78,7 +77,7 @@ export default {
},
renderGLFM() {
this.$nextTick(() => {
- $(this.$refs['content-element']).renderGFM();
+ renderGFM(this.$refs['content-element']);
});
},
closeDrawer() {
diff --git a/app/assets/javascripts/vue_shared/components/notes/system_note.vue b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
index ed486768134..1cbbdf0deb0 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -21,12 +21,12 @@ import $ from 'jquery';
import { mapGetters, mapActions, mapState } from 'vuex';
import SafeHtml from '~/vue_shared/directives/safe_html';
import descriptionVersionHistoryMixin from 'ee_else_ce/notes/mixins/description_version_history';
-import '~/behaviors/markdown/render_gfm';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import NoteHeader from '~/notes/components/note_header.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { spriteIcon } from '~/lib/utils/common_utils';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import TimelineEntryItem from './timeline_entry_item.vue';
const MAX_VISIBLE_COMMIT_LIST_COUNT = 3;
@@ -89,7 +89,7 @@ export default {
},
},
mounted() {
- $(this.$refs['gfm-content']).renderGFM();
+ renderGFM(this.$refs['gfm-content']);
},
methods: {
...mapActions(['fetchDescriptionVersion', 'softDeleteDescriptionVersion']),
diff --git a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_description.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_description.vue
index 9ced3826d19..ce1851ab873 100644
--- a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_description.vue
+++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_description.vue
@@ -1,7 +1,6 @@
<script>
-import $ from 'jquery';
import SafeHtml from '~/vue_shared/directives/safe_html';
-import '~/behaviors/markdown/render_gfm';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
export default {
directives: {
@@ -26,12 +25,7 @@ export default {
},
},
mounted() {
- this.renderGFM();
- },
- methods: {
- renderGFM() {
- $(this.$refs.gfmContainer).renderGFM();
- },
+ renderGFM(this.$refs.gfmContainer);
},
};
</script>
diff --git a/app/assets/javascripts/work_items/components/notes/system_note.vue b/app/assets/javascripts/work_items/components/notes/system_note.vue
index f91a0d01581..92a2fcaf1df 100644
--- a/app/assets/javascripts/work_items/components/notes/system_note.vue
+++ b/app/assets/javascripts/work_items/components/notes/system_note.vue
@@ -17,9 +17,9 @@
*/
import { GlButton, GlSkeletonLoader, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import $ from 'jquery';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import SafeHtml from '~/vue_shared/directives/safe_html';
import descriptionVersionHistoryMixin from 'ee_else_ce/notes/mixins/description_version_history';
-import '~/behaviors/markdown/render_gfm';
import axios from '~/lib/utils/axios_utils';
import { getLocationHash } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
@@ -89,7 +89,7 @@ export default {
},
},
mounted() {
- $(this.$refs['gfm-content']).renderGFM();
+ renderGFM(this.$refs['gfm-content']);
},
methods: {
fetchDescriptionVersion() {},
diff --git a/app/assets/javascripts/work_items/components/work_item_description_rendered.vue b/app/assets/javascripts/work_items/components/work_item_description_rendered.vue
index 2d1dcfaf0e5..d58983c013d 100644
--- a/app/assets/javascripts/work_items/components/work_item_description_rendered.vue
+++ b/app/assets/javascripts/work_items/components/work_item_description_rendered.vue
@@ -1,8 +1,7 @@
<script>
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
-import $ from 'jquery';
-import '~/behaviors/markdown/render_gfm';
import SafeHtml from '~/vue_shared/directives/safe_html';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
const isCheckbox = (target) => target?.classList.contains('task-list-item-checkbox');
@@ -47,7 +46,7 @@ export default {
async renderGFM() {
await this.$nextTick();
- $(this.$refs['gfm-content']).renderGFM();
+ renderGFM(this.$refs['gfm-content']);
if (this.canEdit) {
this.checkboxes = this.$el.querySelectorAll('.task-list-item-checkbox');
diff --git a/app/assets/stylesheets/page_bundles/pipelines.scss b/app/assets/stylesheets/page_bundles/pipelines.scss
index 4946bbbebe5..f9c49b0e6ca 100644
--- a/app/assets/stylesheets/page_bundles/pipelines.scss
+++ b/app/assets/stylesheets/page_bundles/pipelines.scss
@@ -70,33 +70,20 @@
}
}
-// Mini Pipelines
-
-.stage-cell {
- .stage-container {
- &:last-child {
- margin-right: 0;
- }
-
- // Hack to show a button tooltip inline
- button.has-tooltip + .tooltip {
- min-width: 105px;
- }
-
- // Bootstrap way of showing the content inline for anchors.
- a.has-tooltip {
- white-space: nowrap;
- }
+// Pipeline mini graph
+.pipeline-mini-graph-stage-container {
+ &:last-child {
+ margin-right: 0;
+ }
- &:not(:last-child) {
- &::after {
- content: '';
- border-bottom: 2px solid $gray-200;
- position: absolute;
- right: -4px;
- top: 11px;
- width: 4px;
- }
+ &:not(:last-child) {
+ &::after {
+ content: '';
+ border-bottom: 2px solid $gray-200;
+ position: absolute;
+ right: -4px;
+ top: 11px;
+ width: 4px;
}
}
}
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 1a13b8ca6e5..11f9f1cf0c6 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -135,6 +135,7 @@ class RegistrationsController < Devise::RegistrationsController
return identity_verification_redirect_path if custom_confirmation_enabled?
+ Gitlab::Tracking.event(self.class.name, 'render', user: resource)
users_almost_there_path(email: resource.email)
end
diff --git a/app/finders/ci/freeze_periods_finder.rb b/app/finders/ci/freeze_periods_finder.rb
new file mode 100644
index 00000000000..91df776abe6
--- /dev/null
+++ b/app/finders/ci/freeze_periods_finder.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Ci
+ class FreezePeriodsFinder
+ def initialize(project, current_user = nil)
+ @project = project
+ @current_user = current_user
+ end
+
+ def execute
+ return Ci::FreezePeriod.none unless Ability.allowed?(@current_user, :read_freeze_period, @project)
+
+ @project.freeze_periods
+ end
+ end
+end
diff --git a/app/finders/freeze_periods_finder.rb b/app/finders/freeze_periods_finder.rb
deleted file mode 100644
index 2a9bfbe12ba..00000000000
--- a/app/finders/freeze_periods_finder.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class FreezePeriodsFinder
- def initialize(project, current_user = nil)
- @project = project
- @current_user = current_user
- end
-
- def execute
- return Ci::FreezePeriod.none unless Ability.allowed?(@current_user, :read_freeze_period, @project)
-
- @project.freeze_periods
- end
-end
diff --git a/app/models/dependency_proxy/group_setting.rb b/app/models/dependency_proxy/group_setting.rb
index 3a7ae66a263..b39ea36644a 100644
--- a/app/models/dependency_proxy/group_setting.rb
+++ b/app/models/dependency_proxy/group_setting.rb
@@ -3,7 +3,5 @@
class DependencyProxy::GroupSetting < ApplicationRecord
belongs_to :group
- attribute :enabled, default: true
-
validates :group, presence: true
end
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index 6e202063900..079e24c6389 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -53,9 +53,7 @@
= ci_label_for_status(@last_pipeline.status)
- if @last_pipeline.stages_count.nonzero?
#{ n_(s_('Pipeline|with stage'), s_('Pipeline|with stages'), @last_pipeline.stages_count) }
- .mr-widget-pipeline-graph
- .stage-cell
- .js-commit-pipeline-mini-graph{ data: { stages: @last_pipeline_stages.to_json.html_safe, full_path: @project.full_path, iid: @last_pipeline.iid, graphql_resource_etag: graphql_etag_pipeline_path(@last_pipeline) } }
+ .js-commit-pipeline-mini-graph{ data: { stages: @last_pipeline_stages.to_json.html_safe, full_path: @project.full_path, iid: @last_pipeline.iid, graphql_resource_etag: graphql_etag_pipeline_path(@last_pipeline) } }
- if @last_pipeline.duration
in
= time_interval_in_words @last_pipeline.duration
diff --git a/config/feature_flags/development/automated_email_provision.yml b/config/feature_flags/development/automated_email_provision.yml
deleted file mode 100644
index 2734413dd8f..00000000000
--- a/config/feature_flags/development/automated_email_provision.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: automated_email_provision
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75872
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348317
-milestone: '14.6'
-type: development
-group: group::license
-default_enabled: true
diff --git a/db/migrate/20221213184314_change_enabled_default_in_dependency_proxy_group_settings.rb b/db/migrate/20221213184314_change_enabled_default_in_dependency_proxy_group_settings.rb
new file mode 100644
index 00000000000..6cddcb80949
--- /dev/null
+++ b/db/migrate/20221213184314_change_enabled_default_in_dependency_proxy_group_settings.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class ChangeEnabledDefaultInDependencyProxyGroupSettings < Gitlab::Database::Migration[2.0]
+ def change
+ change_column_default :dependency_proxy_group_settings, :enabled, from: false, to: true
+ end
+end
diff --git a/db/schema_migrations/20221213184314 b/db/schema_migrations/20221213184314
new file mode 100644
index 00000000000..2d297ebe7ee
--- /dev/null
+++ b/db/schema_migrations/20221213184314
@@ -0,0 +1 @@
+b14a060e05fc73c9d76d7c8bec3f9e1fa99b33eae6ec0057b4a398b28414a02a \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 754d9796403..2aad46280a3 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -14733,7 +14733,7 @@ CREATE TABLE dependency_proxy_group_settings (
group_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- enabled boolean DEFAULT false NOT NULL
+ enabled boolean DEFAULT true NOT NULL
);
CREATE SEQUENCE dependency_proxy_group_settings_id_seq
diff --git a/doc/administration/geo/secondary_proxy/index.md b/doc/administration/geo/secondary_proxy/index.md
index 2786982bb51..42834a9dc95 100644
--- a/doc/administration/geo/secondary_proxy/index.md
+++ b/doc/administration/geo/secondary_proxy/index.md
@@ -70,39 +70,6 @@ a single URL used by all Geo sites, including the primary.
In Kubernetes, you can use the same domain under `global.hosts.domain` as for the primary site.
-## Disable Geo proxying
-
-You can disable the secondary proxying on each Geo site, separately, by following these steps with Omnibus-based packages:
-
-1. SSH into each application node (serving user traffic directly) on your secondary Geo site
- and add the following environment variable:
-
- ```shell
- sudo editor /etc/gitlab/gitlab.rb
- ```
-
- ```ruby
- gitlab_workhorse['env'] = {
- "GEO_SECONDARY_PROXY" => "0"
- }
- ```
-
-1. Reconfigure the updated nodes for the change to take effect:
-
- ```shell
- gitlab-ctl reconfigure
- ```
-
-In Kubernetes, you can use `--set gitlab.webservice.extraEnv.GEO_SECONDARY_PROXY="0"`,
-or specify the following in your values file:
-
-```yaml
-gitlab:
- webservice:
- extraEnv:
- GEO_SECONDARY_PROXY: "0"
-```
-
## Geo proxying with Separate URLs
> Geo secondary proxying for separate URLs is [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/346112) in GitLab 15.1.
@@ -192,3 +159,42 @@ It does not cover all data types, more will be added in the future as they are t
1. Git reads are served from the local secondary while pushes get proxied to the primary.
Selective sync or cases where repositories don't exist locally on the Geo secondary throw a "not found" error.
1. Pages can use the same URL (without access control), but must be configured separately and are not proxied.
+
+## Disable Geo proxying
+
+Secondary proxying is enabled by default on a secondary site when it uses a unified URL, meaning, the same `external_url` as the primary site. Disabling proxying in this case tends to not be helpful due to completely different behavior being served at the same URL, depending on routing.
+
+Secondary proxying is enabled by default in GitLab 15.1 on a secondary site even without a unified URL. If proxying needs to be disabled on a secondary site, it is much easier to disable the feature flag in [Geo proxying with Separate URLs](#geo-proxying-with-separate-urls). However, if there are multiple secondary sites, then the instructions in this section can be used to disable secondary proxying per site.
+
+Additionally, the `gitlab-workhorse` service polls `/api/v4/geo/proxy` every 10 seconds. In GitLab 15.2 and later, it is only polled once, if Geo is not enabled. Prior to GitLab 15.2, you can stop this polling by disabling secondary proxying.
+
+You can disable the secondary proxying on each Geo site, separately, by following these steps with Omnibus-based packages:
+
+1. SSH into each application node (serving user traffic directly) on your secondary Geo site
+ and add the following environment variable:
+
+ ```shell
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+ ```ruby
+ gitlab_workhorse['env'] = {
+ "GEO_SECONDARY_PROXY" => "0"
+ }
+ ```
+
+1. Reconfigure the updated nodes for the change to take effect:
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
+
+In Kubernetes, you can use `--set gitlab.webservice.extraEnv.GEO_SECONDARY_PROXY="0"`,
+or specify the following in your values file:
+
+```yaml
+gitlab:
+ webservice:
+ extraEnv:
+ GEO_SECONDARY_PROXY: "0"
+```
diff --git a/doc/administration/postgresql/multiple_databases.md b/doc/administration/postgresql/multiple_databases.md
new file mode 100644
index 00000000000..ffccbf861e7
--- /dev/null
+++ b/doc/administration/postgresql/multiple_databases.md
@@ -0,0 +1,141 @@
+---
+stage: Data Stores
+group: Pods
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Multiple Databases **(FREE SELF)**
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6168) in GitLab 15.7.
+
+WARNING:
+This feature is not ready for production use
+
+By default, GitLab uses a single application database, referred to as the `main` database.
+
+To scale GitLab, you can configure GitLab to use multiple application databases.
+
+Due to [known issues](#known-issues), configuring GitLab with multiple databases is in [**Alpha**](../../policy/alpha-beta-support.md#alpha-features).
+
+## Known issues
+
+- Migrating data from the `main` database to the `ci` database is not supported or documented yet.
+- Once data is migrated to the `ci` database, you cannot migrate it back.
+
+## Set up multiple databases
+
+Use the following content to set up multiple databases with a new GitLab installation.
+
+There is no documentation for existing GitLab installations yet.
+
+After you have set up multiple databases, GitLab uses a second application database for
+[CI/CD features](../../ci/index.md), referred to as the `ci` database. For
+example, GitLab reads and writes to the `ci_pipelines` table in the `ci`
+database.
+
+WARNING:
+You must stop GitLab before setting up multiple databases. This prevents
+split-brain situations, where `main` data is written to the `ci` database, and
+the other way around.
+
+### Installations from source
+
+1. [Back up GitLab](../../raketasks/backup_restore.md)
+ in case of unforeseen issues.
+
+1. Stop GitLab:
+
+ ```shell
+ sudo service gitlab stop
+ ```
+
+1. Open `config/database.yml`, and add a `ci:` section under
+ `production:`. See `config/database.yml.decomposed-postgresql` for possible
+ values for this new `ci:` section. Once modified, the `config/database.yml` should
+ look like:
+
+ ```yaml
+ production:
+ main:
+ # ...
+ ci:
+ adapter: postgresql
+ encoding: unicode
+ database: gitlabhq_production_ci
+ # ...
+ ```
+
+1. Save the `config/database.yml` file.
+
+1. Create the `gitlabhq_production_ci` database:
+
+ ```shell
+ sudo -u postgres psql -d template1 -c "CREATE DATABASE gitlabhq_production OWNER git;"
+ sudo -u git -H bundle exec rake db:schema:load:ci
+ ```
+
+1. Lock writes for `ci` tables in `main` database, and the other way around:
+
+ ```shell
+ sudo -u git -H bundle exec rake gitlab:db:lock_writes
+ ```
+
+1. Restart GitLab:
+
+ ```shell
+ sudo service gitlab restart
+ ```
+
+### Omnibus GitLab installations
+
+1. [Back up GitLab](../../raketasks/backup_restore.md)
+ in case of unforeseen issues.
+
+1. Stop GitLab:
+
+ ```shell
+ sudo gitlab-ctl stop
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following lines:
+
+ ```ruby
+ gitlab_rails['databases']['ci']['enable'] = true
+ gitlab_rails['databases']['ci']['db_database'] = 'gitlabhq_production_ci'
+ ```
+
+1. Save the `/etc/gitlab/gitlab.rb` file.
+
+1. Reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+1. Optional. Reconfiguring GitLab should create the `gitlabhq_production_ci`. If it did not, manually create the `gitlabhq_production_ci`:
+
+ ```shell
+ sudo gitlab-ctl start postgresql
+ sudo -u gitlab-psql /opt/gitlab/embedded/bin/psql -h /var/opt/gitlab/postgresql -d template1 -c "CREATE DATABASE gitlabhq_production_ci OWNER gitlab;"
+ sudo gitlab-rake db:schema:load:ci
+
+1. Lock writes for `ci` tables in `main` database, and the other way around:
+
+ ```shell
+ sudo gitlab-ctl start postgresql
+ sudo gitlab-rake gitlab:db:lock_writes
+ ```
+
+1. Restart GitLab:
+
+ ```shell
+ sudo gitlab-ctl restart
+ ```
+
+## Further information
+
+For more information on multiple databases, see [issue 6168](https://gitlab.com/groups/gitlab-org/-/epics/6168).
+
+For more information on how multiple databases work in GitLab, see the [development guide for multiple databases](../../development/database/multiple_databases.md).
+
+Since 2022-07-02, GitLab.com has been running with two separate databases. For more information, see this [blog post](https://about.gitlab.com/blog/2022/06/02/splitting-database-into-main-and-ci/).
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index ee310cd3062..5e15a6c02f5 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -199,10 +199,16 @@ You can configure GitLab to use multiple SAML 2.0 identity providers if:
Example multiple providers configuration for Omnibus GitLab:
+To allow your users to use SAML to sign up without having to manually create an account from either of the providers, add the following values to your configuration.
+
+```ruby
+gitlab_rails['omniauth_allow_single_sign_on'] = ['saml', 'saml1']
+```
+
```ruby
gitlab_rails['omniauth_providers'] = [
{
- name: 'saml',
+ name: 'saml', # This must match the following name configuration parameter
args: {
name: 'saml', # This is mandatory and must match the provider name
strategy_class: 'OmniAuth::Strategies::SAML',
@@ -212,7 +218,7 @@ gitlab_rails['omniauth_providers'] = [
label: 'Provider 1' # Differentiate the two buttons and providers in the UI
},
{
- name: 'saml1',
+ name: 'saml1', # This must match the following name configuration parameter
args: {
name: 'saml1', # This is mandatory and must match the provider name
strategy_class: 'OmniAuth::Strategies::SAML',
@@ -351,13 +357,19 @@ For a full list of supported assertions, see the [OmniAuth SAML gem](https://git
## Configure users based on SAML group membership
-You can require users to be members of a certain group, or assign users [external](../user/admin_area/external_users.md), administrator or [auditor](../administration/auditor_users.md) access levels based on group membership.
-These groups are checked on each SAML login and user attributes updated as necessary.
-This feature **does not** allow you to
-automatically add users to GitLab [Groups](../user/group/index.md).
+You can:
-Support for these groups depends on your [subscription](https://about.gitlab.com/pricing/)
-and whether you've installed [GitLab Enterprise Edition (EE)](https://about.gitlab.com/install/).
+- Require users to be members of a certain group.
+- Assign users [external](../user/admin_area/external_users.md), administrator or [auditor](../administration/auditor_users.md) roles based on group membership.
+
+GitLab checks these groups on each SAML sign in and updates user attributes as necessary.
+This feature **does not** allow you to automatically add users to GitLab
+[Groups](../user/group/index.md).
+
+Support for these groups depends on:
+
+- Your [subscription](https://about.gitlab.com/pricing/).
+- Whether you've installed [GitLab Enterprise Edition (EE)](https://about.gitlab.com/install/).
| Group | Tier | GitLab Enterprise Edition (EE) Only? |
|------------------------------|--------------------|--------------------------------------|
@@ -368,9 +380,9 @@ and whether you've installed [GitLab Enterprise Edition (EE)](https://about.gitl
### Prerequisites
-First tell GitLab where to look for group information. For this, you
-must make sure that your IdP server sends a specific `AttributeStatement` along
-with the regular SAML response. Here is an example:
+You must tell GitLab where to look for group information. To do this, make sure
+that your IdP server sends a specific `AttributeStatement` along with the regular
+SAML response. For example:
```xml
<saml:AttributeStatement>
@@ -383,9 +395,9 @@ with the regular SAML response. Here is an example:
</saml:AttributeStatement>
```
-The name of the attribute can be anything you like, but it must contain the groups
-to which a user belongs. To tell GitLab where to find these groups, you need
-to add a `groups_attribute:` element to your SAML settings.
+The name of the attribute must contain the groups that a user belongs to.
+To tell GitLab where to find these groups, add a `groups_attribute:`
+element to your SAML settings.
### Required groups
@@ -585,17 +597,13 @@ list.
## Validate response signatures
-We require Identity Providers to sign SAML responses to ensure that the assertions are
-not tampered with.
-
-This prevents user impersonation and prevents privilege escalation when specific group
-membership is required. Typically this:
+IdPs must sign SAML responses to ensure that the assertions are not tampered with.
-- Is configured using `idp_cert_fingerprint`.
-- Includes the full certificate in the response, although if your Identity Provider
- doesn't support this, you can directly configure GitLab using the `idp_cert` option.
+This prevents user impersonation and privilege escalation when specific group
+membership is required.
-Example configuration with `idp_cert_fingerprint`:
+You configure the response signature validation using `idp_cert_fingerprint`.
+An example configuration:
```yaml
args: {
@@ -607,7 +615,8 @@ args: {
}
```
-Example configuration with `idp_cert`:
+If your IdP does not support configuring this using `idp_cert_fingerprint`, you
+can instead configure GitLab directly using `idp_cert`. An example configuration:
```yaml
args: {
@@ -621,15 +630,14 @@ args: {
}
```
-If the response signature validation is configured incorrectly, you can see error messages
-such as:
+If you have configured the response signature validation incorrectly, you might see
+error messages such as:
- A key validation error.
- Digest mismatch.
- Fingerprint mismatch.
-Refer to the [troubleshooting section](#troubleshooting) for more information on
-solving these errors.
+For more information on solving these errors, see the [troubleshooting SAML guide](../user/group/saml_sso/troubleshooting.md).
## Customize SAML settings
diff --git a/doc/subscriptions/gitlab_dedicated/index.md b/doc/subscriptions/gitlab_dedicated/index.md
index 6bea3ba8ffd..b471d1d971f 100644
--- a/doc/subscriptions/gitlab_dedicated/index.md
+++ b/doc/subscriptions/gitlab_dedicated/index.md
@@ -76,7 +76,9 @@ The following AWS regions are not available:
- Cape Town (`af-south-1`)
- Milan (`eu-south-1`)
- Paris (`eu-west-3`)
-- GovCloud
+- Zurich (`eu-central-2`)
+- GovCloud (US-East) (`us-gov-east-1`)
+- GovCloud (US-West) (`us-gov-west-1`)
## Planned features
diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md
index 477ac8ddc4b..9a671ff6679 100644
--- a/doc/user/group/import/index.md
+++ b/doc/user/group/import/index.md
@@ -18,6 +18,8 @@ You can migrate groups in two ways:
- By direct transfer (recommended).
- By uploading an export file.
+If you migrate from GitLab.com to self-managed GitLab, an administrator can create users on the self-managed GitLab instance.
+
## Migrate groups by direct transfer (recommended)
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/249160) in GitLab 13.7 for group resources [with a flag](../../feature_flags.md) named `bulk_import`. Disabled by default.
@@ -68,6 +70,12 @@ GitLab maps users and their contributions correctly provided:
You might need to reconfigure your firewall to prevent blocking the connection on the self-managed
instance.
+If you use [SAML SSO for GitLab.com groups](../../group/saml_sso/index.md),
+contributing users must have [linked their SAML identity to their GitLab.com account](../../group/saml_sso/index.md#linking-saml-to-your-existing-gitlabcom-account).
+
+When migrating to GitLab.com, you must create users manually unless [SCIM](../../group/saml_sso/scim_setup.md) is used. Creating users with the API is only
+available to self-managed instances because it requires administrator access.
+
### Connect to the source GitLab instance
Create the group you want to import to and connect the source:
@@ -252,6 +260,22 @@ import = BulkImports::Entity.where(namespace_id: Group.id).map(&:bulk_import)
import.status #=> 3 means that the import timed out.
```
+#### Error: `404 Group Not Found`
+
+If you attempt to import a group that has a path comprised of only numbers (for example, `5000`), GitLab attempts to
+find the group by ID instead of the path. This causes a `404 Group Not Found` error in GitLab 15.4 and earlier.
+
+To solve this, you must change the source group path to include a non-numerical character using either:
+
+- The GitLab UI:
+
+ 1. On the top bar, select **Main menu > Groups** and find your group.
+ 1. On the left sidebar, select **Settings > General**.
+ 1. Expand **Advanced**.
+ 1. Under **Change group URL**, change the group URL to include non-numeric characters.
+
+- The [Groups API](../../../api/groups.md#update-group).
+
### Provide feedback
Please leave your feedback about migrating groups by direct transfer in
@@ -286,7 +310,7 @@ Professional Services team.
Note the following:
- Exports are stored in a temporary directory and are deleted every 24 hours by a specific worker.
-- To preserve group-level relationships from imported projects, run the Group Import/Export first, to allow projects to
+- To preserve group-level relationships from imported projects, export and import groups first so that projects can
be imported into the desired group structure.
- Imported groups are given a `private` visibility level, unless imported into a parent group.
- If imported into a parent group, a subgroup inherits the same level of visibility unless otherwise restricted.
@@ -360,7 +384,7 @@ To export the contents of a group:
1. In the **Advanced** section, select **Download export**.
You can also generate a new file by selecting **Regenerate export**.
-You can also use the [group import/export API](../../../api/group_import_export.md).
+You can also export a group [using the API](../../../api/group_import_export.md).
### Import the group
diff --git a/doc/user/project/import/img/gitlab_import_history_page_v14_10.png b/doc/user/project/import/img/gitlab_import_history_page_v14_10.png
deleted file mode 100644
index 812696a8faa..00000000000
--- a/doc/user/project/import/img/gitlab_import_history_page_v14_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index 2cd4c3650b1..208bce90453 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -5,99 +5,59 @@ group: Import
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
-# Migrate projects to a GitLab instance **(FREE)**
-
-See these documents to migrate to GitLab:
-
-- [From Bitbucket Cloud](bitbucket.md)
-- [From Bitbucket Server (also known as Stash)](bitbucket_server.md)
-- [From ClearCase](clearcase.md)
-- [From CVS](cvs.md)
-- [From FogBugz](fogbugz.md)
-- [From GitHub.com or GitHub Enterprise](github.md)
-- [From GitLab.com](gitlab_com.md)
-- [From Gitea](gitea.md)
-- [From Perforce](perforce.md)
-- [From SVN](https://git-scm.com/book/en/v2/Git-and-Other-Systems-Git-as-a-Client)
-- [From TFVC](tfvc.md)
-- [From repository by URL](repo_by_url.md)
-- [By uploading a manifest file (AOSP)](manifest.md)
-- [From Phabricator](phabricator.md)
-- [From Jira (issues only)](jira.md)
-
-You can also import any Git repository through HTTP from the **New Project** page. Note that if the
-repository is too large, the import can timeout.
-
-You can also [connect your external repository to get CI/CD benefits](../../../ci/ci_cd_for_external_repos/index.md).
-
-## Project import history
-
-You can view all project imports created by you. This list includes the following:
-
-- Source (without credentials for security reasons)
-- Destination
-- Status
-- Error details if the import failed
-
-To view project import history:
-
-1. Sign in to GitLab.
-1. On the top bar, select **New** (**{plus}**).
-1. Select **New project/repository**.
-1. Select **Import project**.
-1. Select **History**.
-
-![Project import history page](img/gitlab_import_history_page_v14_10.png)
-
-The history also includes projects created from [built-in](../working_with_projects.md#create-a-project-from-a-built-in-template)
-or [custom](../working_with_projects.md#create-a-project-from-a-built-in-template)
-templates. GitLab uses [import repository by URL](repo_by_url.md)
-to create a new project from a template.
-
-## LFS authentication
-
-When importing a project that contains LFS objects, if the project has an [`.lfsconfig`](https://github.com/git-lfs/git-lfs/blob/master/docs/man/git-lfs-config.5.ronn)
-file with a URL host (`lfs.url`) different from the repository URL host, LFS files are not downloaded.
-
-## Migrate from self-managed GitLab to GitLab.com
+# Import and migrate projects **(FREE)**
-Depending on your requirements, there are several ways to migrate from self-managed GitLab to GitLab.com.
+If you want to bring existing projects to GitLab or copy GitLab projects to a different location, you can:
-### Migrate using GitLab Migration (recommended)
+- Import projects from external systems using one of the [available importers](#available-project-importers).
+- Migrate GitLab projects:
+ - Between two GitLab self-managed instances.
+ - Between a self-managed instance and GitLab.com in both directions.
+ - In the same GitLab instance.
-Using [GitLab Migration](../../group/import/index.md), you can migrate top-level groups you are the Owner of, with all their subgroups and projects included.
+For any type of source and target, you can migrate projects:
-GitLab Migration maps users and their contributions correctly on GitLab.com provided:
+- As part of a [GitLab group migration](../../group/import/index.md). You can't migrate only chosen projects,
+ but you can migrate many projects at once within a group.
+- Using [file exports](../settings/import_export.md). With this method you can migrate projects one by one. No network
+ connection between instances is required.
-- Contributing users exist on GitLab.com at the time of the import.
-- Those users have a public email on the source GitLab instance that matches their primary email on GitLab.com.
+If you only need to migrate Git repositories, you can [import each project by URL](repo_by_url.md). However, you can't
+import issues and merge requests this way. To retain metadata like issues and merge requests, either:
-If you use [SAML SSO for GitLab.com groups](../../group/saml_sso/index.md),
-contributing users must have [linked their SAML identity to their GitLab.com account](../../group/saml_sso/index.md#linking-saml-to-your-existing-gitlabcom-account).
+- [Migrate projects with groups](../../group/import/index.md).
+- Use [file exports](../settings/import_export.md) to import projects.
-When migrating to GitLab.com, you must create users manually unless [SCIM](../../group/saml_sso/scim_setup.md) is used. Creating users with the API is only
-available to self-managed instances because it requires administrator access.
+Keep in mind the limitations of [migrating using file exports](../settings/import_export.md#items-that-are-exported).
+When migrating from self-managed to GitLab.com, user associations (such as comment author)
+are changed to the user who is importing the projects.
-### Migrate specific projects only
+## Available project importers
-If you only need to migrate Git repositories, you can [import each project by URL](repo_by_url.md).
-However, you can't import issues and merge requests this way. To retain metadata like issues and
-merge requests, use the [import/export feature](../settings/import_export.md)
-to export projects from self-managed GitLab and import those projects into GitLab.com.
+You can import projects from:
-GitLab maps user contributions correctly when an admin access token is used to perform the import.
-
-As a result, the import/export feature does not map user contributions correctly when you are importing projects from a self-managed instance to GitLab.com.
-
-Instead, all GitLab user associations (such as comment author) are changed to the user importing the project. For more
-information, see the prerequisites and important notes in these sections:
+- [Bitbucket Cloud](bitbucket.md)
+- [Bitbucket Server (also known as Stash)](bitbucket_server.md)
+- [ClearCase](clearcase.md)
+- [CVS](cvs.md)
+- [FogBugz](fogbugz.md)
+- [GitHub.com or GitHub Enterprise](github.md)
+- [GitLab.com](gitlab_com.md)
+- [Gitea](gitea.md)
+- [Perforce](perforce.md)
+- [From SVN](https://git-scm.com/book/en/v2/Git-and-Other-Systems-Git-as-a-Client)
+- [TFVC](tfvc.md)
+- [Repository by URL](repo_by_url.md)
+- [Uloading a manifest file (AOSP)](manifest.md)
+- [Phabricator](phabricator.md)
+- [Jira (issues only)](jira.md)
-- [Export a project and its data](../settings/import_export.md#export-a-project-and-its-data).
-- [Import the project](../settings/import_export.md#import-a-project-and-its-data).
+You can also import any Git repository through HTTP from the **New Project** page. Note that if the
+repository is too large, the import can timeout.
-To preserve contribution history, [migrate using GitLab Migration](#migrate-using-gitlab-migration-recommended).
+You can then [connect your external repository to get CI/CD benefits](../../../ci/ci_cd_for_external_repos/index.md).
-### Migrate using the API
+## Migrate using the API
To migrate all data from self-managed to GitLab.com, you can leverage the [API](../../../api/index.md).
Migrate the assets in this order:
@@ -106,17 +66,9 @@ Migrate the assets in this order:
1. [Projects](../../../api/projects.md)
1. [Project variables](../../../api/project_level_variables.md)
-Keep in mind the limitations of the [import/export feature](../settings/import_export.md#items-that-are-exported). As with [Migrating specific projects using the import/export feature](#migrate-specific-projects-only) user associations (such as comment author) are changed to the user importing projects when migrating from self-managed to GitLab.com.
-
You must still migrate your [Container Registry](../../packages/container_registry/index.md)
over a series of Docker pulls and pushes. Re-run any CI pipelines to retrieve any build artifacts.
-## Migrate from GitLab.com to self-managed GitLab
-
-The process is essentially the same as [migrating from self-managed GitLab to GitLab.com](#migrate-from-self-managed-gitlab-to-gitlabcom).
-The main difference is that an administrator can create users on the self-managed GitLab instance
-through the UI or the [users API](../../../api/users.md#user-creation).
-
## Migrate between two self-managed GitLab instances
To migrate from an existing self-managed GitLab instance to a new self-managed GitLab instance, it's
@@ -128,12 +80,36 @@ The backups produced don't depend on the operating system running GitLab. You ca
the restore method to switch between different operating system distributions or versions, as long
as the same GitLab version [is available for installation](../../../administration/package_information/supported_os.md).
-To instead merge two self-managed GitLab instances together, use the instructions in
-[Migrate from self-managed GitLab to GitLab.com](#migrate-from-self-managed-gitlab-to-gitlabcom).
-This method is useful when both self-managed instances have existing data that must be preserved.
+Also note that administrators can use the [Users API](../../../api/users.md) to migrate users.
+
+## View project import history
+
+You can view all project imports created by you. This list includes the following:
+
+- Paths of source projects if projects were imported from external systems, or import method if GitLab projects were migrated.
+- Paths of destination projects.
+- Start date of each import.
+- Status of each import.
+- Error details if any errors occurred.
+
+To view project import history:
-Also note that administrators can use the [Users API](../../../api/users.md)
-to migrate users.
+1. Sign in to GitLab.
+1. On the top bar, select **Create new...** (**{plus-square}**).
+1. Select **New project/repository**.
+1. Select **Import project**.
+1. Select **History** in the upper right corner.
+1. If there are any errors for a particular import, you can see them by selecting **Details**.
+
+The history also includes projects created from [built-in](../working_with_projects.md#create-a-project-from-a-built-in-template)
+or [custom](../working_with_projects.md#create-a-project-from-a-built-in-template)
+templates. GitLab uses [import repository by URL](repo_by_url.md)
+to create a new project from a template.
+
+## LFS authentication
+
+When importing a project that contains LFS objects, if the project has an [`.lfsconfig`](https://github.com/git-lfs/git-lfs/blob/master/docs/man/git-lfs-config.5.ronn)
+file with a URL host (`lfs.url`) different from the repository URL host, LFS files are not downloaded.
## Project aliases **(PREMIUM SELF)**
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 02949813ce7..d83a80ddb13 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -12,7 +12,22 @@ then imported into a new GitLab instance. You can also:
- [Migrate groups](../../group/import/index.md) using the preferred method.
- [Migrate groups using file exports](../../group/settings/import_export.md).
-## Set up project import/export
+GitLab maps user contributions correctly when an admin access token is used to perform the import.
+
+As a result, migrating projects using file exports does not map user contributions correctly when you are importing
+projects from a self-managed instance to GitLab.com.
+
+Instead, all GitLab user associations (such as comment author) are changed to the user importing the project. For more
+information, see the prerequisites and important notes in these sections:
+
+- [Export a project and its data](../settings/import_export.md#export-a-project-and-its-data).
+- [Import the project](../settings/import_export.md#import-a-project-and-its-data).
+
+To preserve contribution history, [migrate using direct transfer](../../group/import/index.md#migrate-groups-by-direct-transfer-recommended).
+
+If you migrate from GitLab.com to self-managed GitLab, an administrator can create users on the self-managed GitLab instance.
+
+## Set up project to migrate using file exports
Before you can import or export a project and its data, you must set it up.
@@ -24,8 +39,7 @@ Before you can import or export a project and its data, you must set it up.
## Between CE and EE
You can export projects from the [Community Edition to the Enterprise Edition](https://about.gitlab.com/install/ce-or-ee/)
-and vice versa. This assumes [version history](#version-history)
-requirements are met.
+and vice versa. This assumes [version history](#version-history) requirements are met.
If you're exporting a project from the Enterprise Edition to the Community Edition, you may lose
data that is retained only in the Enterprise Edition. For more information, see
@@ -37,8 +51,7 @@ Before you can import a project, you must export it.
Prerequisites:
-- Review the list of [items that are exported](#items-that-are-exported).
- Not all items are exported.
+- Review the list of [items that are exported](#items-that-are-exported). Not all items are exported.
- You must have at least the Maintainer role for the project.
To export a project and its data, follow these steps:
@@ -134,7 +147,7 @@ To import a project:
1. Enter your project name and URL. Then select the file you exported previously.
1. Select **Import project** to begin importing. Your newly imported project page appears shortly.
-To get the status of an import, you can query it through the [Project import/export API](../../../api/project_import_export.md#import-status).
+To get the status of an import, you can query it through the [API](../../../api/project_import_export.md#import-status).
As described in the API documentation, the query may return an import error or exceptions.
### Changes to imported items
@@ -218,36 +231,9 @@ For example:
| 13.0 | 13.0, 12.10, 12.9 |
| 13.1 | 13.1, 13.0, 12.10 |
-### 12.x
-
-Prior to 13.0 this was a defined compatibility table:
-
-| Exporting GitLab version | Importing GitLab version |
-| -------------------------- | -------------------------- |
-| 11.7 to 12.10 | 11.7 to 12.10 |
-| 11.1 to 11.6 | 11.1 to 11.6 |
-| 10.8 to 11.0 | 10.8 to 11.0 |
-| 10.4 to 10.7 | 10.4 to 10.7 |
-| 10.3 | 10.3 |
-| 10.0 to 10.2 | 10.0 to 10.2 |
-| 9.4 to 9.6 | 9.4 to 9.6 |
-| 9.2 to 9.3 | 9.2 to 9.3 |
-| 8.17 to 9.1 | 8.17 to 9.1 |
-| 8.13 to 8.16 | 8.13 to 8.16 |
-| 8.12 | 8.12 |
-| 8.10.3 to 8.11 | 8.10.3 to 8.11 |
-| 8.10.0 to 8.10.2 | 8.10.0 to 8.10.2 |
-| 8.9.5 to 8.9.11 | 8.9.5 to 8.9.11 |
-| 8.9.0 to 8.9.4 | 8.9.0 to 8.9.4 |
-
-Projects can be exported and imported only between versions of GitLab with matching Import/Export versions.
-
-For example, 8.10.3 and 8.11 have the same Import/Export version (0.1.3)
-and the exports between them are compatible.
-
## Related topics
-- [Project import/export API](../../../api/project_import_export.md)
-- [Project import/export administration Rake tasks](../../../administration/raketasks/project_import_export.md)
-- [Group import/export](../../group/settings/import_export.md)
-- [Group import/export API](../../../api/group_import_export.md)
+- [Project import and export API](../../../api/project_import_export.md)
+- [Project import and export administration Rake tasks](../../../administration/raketasks/project_import_export.md)
+- [Migrating GitLab groups](../../group/import/index.md)
+- [Group import and export API](../../../api/group_import_export.md)
diff --git a/lib/api/freeze_periods.rb b/lib/api/freeze_periods.rb
index 40f1be83028..abd8f4c0b94 100644
--- a/lib/api/freeze_periods.rb
+++ b/lib/api/freeze_periods.rb
@@ -34,7 +34,7 @@ module API
get ":id/freeze_periods" do
authorize! :read_freeze_period, user_project
- freeze_periods = ::FreezePeriodsFinder.new(user_project, current_user).execute
+ freeze_periods = ::Ci::FreezePeriodsFinder.new(user_project, current_user).execute
present paginate(freeze_periods), with: Entities::FreezePeriod, current_user: current_user
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 5345dc4bd0f..134b071464d 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -750,6 +750,9 @@ msgstr ""
msgid "%{itemsCount} issues with a limit of %{maxIssueCount}"
msgstr ""
+msgid "%{key} is not a valid URL."
+msgstr ""
+
msgid "%{labelStart}Actual response:%{labelEnd} %{headers}"
msgstr ""
@@ -49329,9 +49332,6 @@ msgstr ""
msgid "is not a descendant of the Group owning the template"
msgstr ""
-msgid "is not a valid URL."
-msgstr ""
-
msgid "is not a valid X509 certificate."
msgstr ""
diff --git a/metrics_server/metrics_server.rb b/metrics_server/metrics_server.rb
index d1a64aa5b79..0516d711ffb 100644
--- a/metrics_server/metrics_server.rb
+++ b/metrics_server/metrics_server.rb
@@ -43,6 +43,7 @@ class MetricsServer # rubocop:disable Gitlab/NamespacedClass
path = options[:path]&.then { |p| Pathname.new(p) } || Pathname.new('')
cmd = path.join('gitlab-metrics-exporter').to_path
env = {
+ 'GOGC' => '10', # Set Go GC heap goal to 10% to curb memory growth.
'GME_MMAP_METRICS_DIR' => metrics_dir.to_s,
'GME_PROBES' => 'self,mmap',
'GME_SERVER_HOST' => settings['address'],
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index 0770f34d9de..699052fe37a 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -167,6 +167,16 @@ RSpec.describe RegistrationsController do
expect(controller.current_user).to be_nil
end
+ it 'tracks an almost there redirect' do
+ post_create
+
+ expect_snowplow_event(
+ category: described_class.name,
+ action: 'render',
+ user: User.find_by(email: base_user_params[:email])
+ )
+ end
+
context 'when registration is triggered from an accepted invite' do
context 'when it is part from the initial invite email', :snowplow do
let_it_be(:member) { create(:project_member, :invited, invite_email: user_params.dig(:user, :email)) }
@@ -260,6 +270,16 @@ RSpec.describe RegistrationsController do
expect(response).to redirect_to(users_sign_up_welcome_path)
end
+ it 'does not track an almost there redirect' do
+ post_create
+
+ expect_no_snowplow_event(
+ category: described_class.name,
+ action: 'render',
+ user: User.find_by(email: base_user_params[:email])
+ )
+ end
+
context 'when invite email matches email used on registration' do
let(:session_params) { { invite_email: user_params.dig(:user, :email) } }
diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb
index 0e03522040b..8faaf6bf39b 100644
--- a/spec/features/merge_request/user_sees_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js, feature_category: :co
end
wait_for_requests
- expect(page).to have_selector('.stage-cell')
+ expect(page).to have_css('[data-testid="pipeline-mini-graph"]')
end
context 'with a detached merge request pipeline' do
diff --git a/spec/finders/freeze_periods_finder_spec.rb b/spec/finders/ci/freeze_periods_finder_spec.rb
index 53cc07d91b0..6c58028a221 100644
--- a/spec/finders/freeze_periods_finder_spec.rb
+++ b/spec/finders/ci/freeze_periods_finder_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe FreezePeriodsFinder do
+RSpec.describe Ci::FreezePeriodsFinder, feature_category: :release_orchestration do
subject(:finder) { described_class.new(project, user).execute }
let(:project) { create(:project, :private) }
diff --git a/spec/frontend/batch_comments/components/draft_note_spec.js b/spec/frontend/batch_comments/components/draft_note_spec.js
index 3d4eddedf34..2dfcdd551a1 100644
--- a/spec/frontend/batch_comments/components/draft_note_spec.js
+++ b/spec/frontend/batch_comments/components/draft_note_spec.js
@@ -6,9 +6,10 @@ import DraftNote from '~/batch_comments/components/draft_note.vue';
import PublishButton from '~/batch_comments/components/publish_button.vue';
import { createStore } from '~/batch_comments/stores';
import NoteableNote from '~/notes/components/noteable_note.vue';
-import '~/behaviors/markdown/render_gfm';
import { createDraft } from '../mock_data';
+jest.mock('~/behaviors/markdown/render_gfm');
+
const NoteableNoteStub = stubComponent(NoteableNote, {
template: `
<div>
diff --git a/spec/frontend/batch_comments/components/preview_item_spec.js b/spec/frontend/batch_comments/components/preview_item_spec.js
index 6a104f0c787..6a99294f855 100644
--- a/spec/frontend/batch_comments/components/preview_item_spec.js
+++ b/spec/frontend/batch_comments/components/preview_item_spec.js
@@ -3,9 +3,10 @@ import PreviewItem from '~/batch_comments/components/preview_item.vue';
import { createStore } from '~/batch_comments/stores';
import diffsModule from '~/diffs/store/modules';
import notesModule from '~/notes/stores/modules';
-import '~/behaviors/markdown/render_gfm';
import { createDraft } from '../mock_data';
+jest.mock('~/behaviors/markdown/render_gfm');
+
describe('Batch comments draft preview item component', () => {
let wrapper;
let draft;
diff --git a/spec/frontend/batch_comments/components/publish_dropdown_spec.js b/spec/frontend/batch_comments/components/publish_dropdown_spec.js
index d1b7160d231..e89934c0192 100644
--- a/spec/frontend/batch_comments/components/publish_dropdown_spec.js
+++ b/spec/frontend/batch_comments/components/publish_dropdown_spec.js
@@ -4,9 +4,10 @@ import Vue from 'vue';
import Vuex from 'vuex';
import PreviewDropdown from '~/batch_comments/components/preview_dropdown.vue';
import { createStore } from '~/mr_notes/stores';
-import '~/behaviors/markdown/render_gfm';
import { createDraft } from '../mock_data';
+jest.mock('~/behaviors/markdown/render_gfm');
+
Vue.use(Vuex);
describe('Batch comments publish dropdown component', () => {
diff --git a/spec/frontend/diffs/components/diff_discussions_spec.js b/spec/frontend/diffs/components/diff_discussions_spec.js
index e9a0e0745fd..5092ae6ab6e 100644
--- a/spec/frontend/diffs/components/diff_discussions_spec.js
+++ b/spec/frontend/diffs/components/diff_discussions_spec.js
@@ -5,9 +5,10 @@ import { createStore } from '~/mr_notes/stores';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
-import '~/behaviors/markdown/render_gfm';
import discussionsMockData from '../mock_data/diff_discussions';
+jest.mock('~/behaviors/markdown/render_gfm');
+
describe('DiffDiscussions', () => {
let store;
let wrapper;
diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js
index 2f9fd957c6b..211fee31a9c 100644
--- a/spec/frontend/ide/components/repo_editor_spec.js
+++ b/spec/frontend/ide/components/repo_editor_spec.js
@@ -4,7 +4,6 @@ import { editor as monacoEditor, Range } from 'monaco-editor';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { shallowMount } from '@vue/test-utils';
-import '~/behaviors/markdown/render_gfm';
import waitForPromises from 'helpers/wait_for_promises';
import { stubPerformanceWebAPI } from 'helpers/performance';
import { exampleConfigs, exampleFiles } from 'jest/ide/lib/editorconfig/mock_data';
@@ -27,6 +26,7 @@ import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer
import SourceEditorInstance from '~/editor/source_editor_instance';
import { file } from '../helpers';
+jest.mock('~/behaviors/markdown/render_gfm');
jest.mock('~/editor/extensions/source_editor_ci_schema_ext');
const PREVIEW_MARKDOWN_PATH = '/foo/bar/preview_markdown';
diff --git a/spec/frontend/issues/show/components/app_spec.js b/spec/frontend/issues/show/components/app_spec.js
index f0e8affe4ce..6cf44e60092 100644
--- a/spec/frontend/issues/show/components/app_spec.js
+++ b/spec/frontend/issues/show/components/app_spec.js
@@ -5,7 +5,6 @@ import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import '~/behaviors/markdown/render_gfm';
import { createAlert } from '~/flash';
import { IssuableStatus, IssuableStatusText, IssuableType } from '~/issues/constants';
import IssuableApp from '~/issues/show/components/app.vue';
@@ -30,6 +29,7 @@ import {
jest.mock('~/flash');
jest.mock('~/issues/show/event_hub');
jest.mock('~/lib/utils/url_utility');
+jest.mock('~/behaviors/markdown/render_gfm');
const REALTIME_REQUEST_STACK = [initialRequest, secondRequest];
diff --git a/spec/frontend/issues/show/components/description_spec.js b/spec/frontend/issues/show/components/description_spec.js
index e777d6f4b21..889ff450825 100644
--- a/spec/frontend/issues/show/components/description_spec.js
+++ b/spec/frontend/issues/show/components/description_spec.js
@@ -1,7 +1,6 @@
import $ from 'jquery';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import '~/behaviors/markdown/render_gfm';
import { GlTooltip, GlModal } from '@gitlab/ui';
import setWindowLocation from 'helpers/set_window_location_helper';
@@ -21,6 +20,7 @@ import createWorkItemFromTaskMutation from '~/work_items/graphql/create_work_ite
import TaskList from '~/task_list';
import WorkItemDetailModal from '~/work_items/components/work_item_detail_modal.vue';
import { TRACKING_CATEGORY_SHOW } from '~/work_items/constants';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import {
projectWorkItemTypesQueryResponse,
createWorkItemFromTaskMutationResponse,
@@ -37,6 +37,7 @@ jest.mock('~/lib/utils/url_utility', () => ({
updateHistory: jest.fn(),
}));
jest.mock('~/task_list');
+jest.mock('~/behaviors/markdown/render_gfm');
const showModal = jest.fn();
const hideModal = jest.fn();
@@ -161,7 +162,6 @@ describe('Description component', () => {
});
it('applies syntax highlighting and math when description changed', async () => {
- const prototypeSpy = jest.spyOn($.prototype, 'renderGFM');
createComponent();
await wrapper.setProps({
@@ -169,7 +169,7 @@ describe('Description component', () => {
});
expect(findGfmContent().exists()).toBe(true);
- expect(prototypeSpy).toHaveBeenCalled();
+ expect(renderGFM).toHaveBeenCalled();
});
it('sets data-update-url', () => {
diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js
index a74d709ed3a..add2ed1ba8a 100644
--- a/spec/frontend/notes/components/discussion_notes_spec.js
+++ b/spec/frontend/notes/components/discussion_notes_spec.js
@@ -1,6 +1,5 @@
import { getByRole } from '@testing-library/dom';
import { shallowMount, mount } from '@vue/test-utils';
-import '~/behaviors/markdown/render_gfm';
import { nextTick } from 'vue';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import NoteableNote from '~/notes/components/noteable_note.vue';
@@ -11,6 +10,8 @@ import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_sys
import SystemNote from '~/vue_shared/components/notes/system_note.vue';
import { noteableDataMock, discussionMock, notesDataMock } from '../mock_data';
+jest.mock('~/behaviors/markdown/render_gfm');
+
const LINE_RANGE = {};
const DISCUSSION_WITH_LINE_RANGE = {
...discussionMock,
diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js
index 2175849aeb9..a90d8bdde06 100644
--- a/spec/frontend/notes/components/noteable_discussion_spec.js
+++ b/spec/frontend/notes/components/noteable_discussion_spec.js
@@ -9,7 +9,6 @@ import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_i
import NoteForm from '~/notes/components/note_form.vue';
import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
import createStore from '~/notes/stores';
-import '~/behaviors/markdown/render_gfm';
import {
noteableDataMock,
discussionMock,
@@ -18,6 +17,8 @@ import {
userDataMock,
} from '../mock_data';
+jest.mock('~/behaviors/markdown/render_gfm');
+
describe('noteable_discussion component', () => {
let store;
let wrapper;
diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js
index 9051fcab97f..29be9d59e5f 100644
--- a/spec/frontend/notes/components/notes_app_spec.js
+++ b/spec/frontend/notes/components/notes_app_spec.js
@@ -14,11 +14,12 @@ import NotesApp from '~/notes/components/notes_app.vue';
import NotesActivityHeader from '~/notes/components/notes_activity_header.vue';
import * as constants from '~/notes/constants';
import createStore from '~/notes/stores';
-import '~/behaviors/markdown/render_gfm';
// TODO: use generated fixture (https://gitlab.com/gitlab-org/gitlab-foss/issues/62491)
import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
import * as mockData from '../mock_data';
+jest.mock('~/behaviors/markdown/render_gfm');
+
const TYPE_COMMENT_FORM = 'comment-form';
const TYPE_NOTES_LIST = 'notes-list';
const TEST_NOTES_FILTER_VALUE = 1;
diff --git a/spec/frontend/pages/shared/wikis/components/wiki_content_spec.js b/spec/frontend/pages/shared/wikis/components/wiki_content_spec.js
index 982c81b9272..7c9aae13d25 100644
--- a/spec/frontend/pages/shared/wikis/components/wiki_content_spec.js
+++ b/spec/frontend/pages/shared/wikis/components/wiki_content_spec.js
@@ -3,13 +3,13 @@ import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import WikiContent from '~/pages/shared/wikis/components/wiki_content.vue';
-import { renderGFM } from '~/pages/shared/wikis/render_gfm_facade';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
import waitForPromises from 'helpers/wait_for_promises';
import { handleLocationHash } from '~/lib/utils/common_utils';
-jest.mock('~/pages/shared/wikis/render_gfm_facade');
+jest.mock('~/behaviors/markdown/render_gfm');
jest.mock('~/lib/utils/common_utils');
describe('pages/shared/wikis/components/wiki_content', () => {
diff --git a/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_mini_graph_spec.js b/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_mini_graph_spec.js
index b340a0b243f..036b82530d5 100644
--- a/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_mini_graph_spec.js
+++ b/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_mini_graph_spec.js
@@ -48,7 +48,6 @@ describe('Pipeline Mini Graph', () => {
isMergeTrain: false,
pipelinePath: '',
stages: expect.any(Array),
- stagesClass: '',
updateDropdown: false,
upstreamPipeline: undefined,
});
@@ -83,7 +82,6 @@ describe('Pipeline Mini Graph', () => {
isMergeTrain: false,
pipelinePath: '',
stages: expect.any(Array),
- stagesClass: '',
updateDropdown: false,
upstreamPipeline: expect.any(Object),
});
@@ -115,7 +113,6 @@ describe('Pipeline Mini Graph', () => {
isMergeTrain: false,
pipelinePath: 'my/pipeline/path',
stages: expect.any(Array),
- stagesClass: '',
updateDropdown: false,
upstreamPipeline: undefined,
});
diff --git a/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stages_spec.js b/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stages_spec.js
index 7a71c1b54c6..c123f53886e 100644
--- a/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stages_spec.js
+++ b/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stages_spec.js
@@ -26,12 +26,6 @@ describe('Pipeline Stages', () => {
expect(findPipelineStages()).toHaveLength(mockStages.length);
});
- it('renders stages with a custom class', () => {
- createComponent({ stagesClass: 'my-class' });
-
- expect(wrapper.findAll('.my-class')).toHaveLength(mockStages.length);
- });
-
it('does not fail when stages are empty', () => {
createComponent({ stages: [] });
diff --git a/spec/frontend/releases/components/release_block_spec.js b/spec/frontend/releases/components/release_block_spec.js
index 096c3db8902..f1b8554fbc3 100644
--- a/spec/frontend/releases/components/release_block_spec.js
+++ b/spec/frontend/releases/components/release_block_spec.js
@@ -1,5 +1,4 @@
import { mount } from '@vue/test-utils';
-import $ from 'jquery';
import { nextTick } from 'vue';
import originalOneReleaseQueryResponse from 'test_fixtures/graphql/releases/graphql/queries/one_release.query.graphql.json';
import { convertOneReleaseGraphQLResponse } from '~/releases/util';
@@ -10,6 +9,9 @@ import ReleaseBlock from '~/releases/components/release_block.vue';
import ReleaseBlockFooter from '~/releases/components/release_block_footer.vue';
import { BACK_URL_PARAM } from '~/releases/constants';
import timeagoMixin from '~/vue_shared/mixins/timeago';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
+
+jest.mock('~/behaviors/markdown/render_gfm');
describe('Release block', () => {
let wrapper;
@@ -34,7 +36,6 @@ describe('Release block', () => {
const editButton = () => wrapper.find('.js-edit-button');
beforeEach(() => {
- jest.spyOn($.fn, 'renderGFM');
release = convertOneReleaseGraphQLResponse(originalOneReleaseQueryResponse).data;
});
@@ -62,7 +63,7 @@ describe('Release block', () => {
it('renders release description', () => {
expect(wrapper.vm.$refs['gfm-content']).toBeDefined();
- expect($.fn.renderGFM).toHaveBeenCalledTimes(1);
+ expect(renderGFM).toHaveBeenCalledTimes(1);
});
it('renders release date', () => {
diff --git a/spec/frontend/terms/components/app_spec.js b/spec/frontend/terms/components/app_spec.js
index f1dbc004da8..ce1c126f868 100644
--- a/spec/frontend/terms/components/app_spec.js
+++ b/spec/frontend/terms/components/app_spec.js
@@ -1,4 +1,3 @@
-import $ from 'jquery';
import { merge } from 'lodash';
import { GlIntersectionObserver } from '@gitlab/ui';
import { nextTick } from 'vue';
@@ -7,13 +6,14 @@ import { mountExtended } from 'helpers/vue_test_utils_helper';
import { FLASH_TYPES, FLASH_CLOSED_EVENT } from '~/flash';
import { isLoggedIn } from '~/lib/utils/common_utils';
import TermsApp from '~/terms/components/app.vue';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
jest.mock('~/lib/utils/common_utils');
+jest.mock('~/behaviors/markdown/render_gfm');
describe('TermsApp', () => {
let wrapper;
- let renderGFMSpy;
const defaultProvide = {
terms: 'foo bar',
@@ -35,7 +35,6 @@ describe('TermsApp', () => {
};
beforeEach(() => {
- renderGFMSpy = jest.spyOn($.fn, 'renderGFM');
isLoggedIn.mockReturnValue(true);
});
@@ -65,7 +64,7 @@ describe('TermsApp', () => {
createComponent();
expect(wrapper.findByText(defaultProvide.terms).exists()).toBe(true);
- expect(renderGFMSpy).toHaveBeenCalled();
+ expect(renderGFM).toHaveBeenCalled();
});
describe('accept button', () => {
diff --git a/spec/frontend/vue_shared/components/content_viewer/content_viewer_spec.js b/spec/frontend/vue_shared/components/content_viewer/content_viewer_spec.js
index f28805471f8..a37071aec9b 100644
--- a/spec/frontend/vue_shared/components/content_viewer/content_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/content_viewer/content_viewer_spec.js
@@ -1,7 +1,8 @@
import { mount } from '@vue/test-utils';
import { GREEN_BOX_IMAGE_URL } from 'spec/test_constants';
import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer.vue';
-import '~/behaviors/markdown/render_gfm';
+
+jest.mock('~/behaviors/markdown/render_gfm');
describe('ContentViewer', () => {
let wrapper;
diff --git a/spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js b/spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js
index 01ef52c6af9..0d329b6a065 100644
--- a/spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js
@@ -1,11 +1,12 @@
import { GlSkeletonLoader } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import $ from 'jquery';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import MarkdownViewer from '~/vue_shared/components/content_viewer/viewers/markdown_viewer.vue';
+jest.mock('~/behaviors/markdown/render_gfm');
+
describe('MarkdownViewer', () => {
let wrapper;
let mock;
@@ -26,7 +27,6 @@ describe('MarkdownViewer', () => {
mock = new MockAdapter(axios);
jest.spyOn(axios, 'post');
- jest.spyOn($.fn, 'renderGFM');
});
afterEach(() => {
diff --git a/spec/frontend/vue_shared/components/markdown/field_spec.js b/spec/frontend/vue_shared/components/markdown/field_spec.js
index 50864a4bf25..285ea10c813 100644
--- a/spec/frontend/vue_shared/components/markdown/field_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/field_spec.js
@@ -1,12 +1,14 @@
import { nextTick } from 'vue';
import AxiosMockAdapter from 'axios-mock-adapter';
-import $ from 'jquery';
import { TEST_HOST, FIXTURES_PATH } from 'spec/test_constants';
import axios from '~/lib/utils/axios_utils';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import MarkdownFieldHeader from '~/vue_shared/components/markdown/header.vue';
import MarkdownToolbar from '~/vue_shared/components/markdown/toolbar.vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
+
+jest.mock('~/behaviors/markdown/render_gfm');
const markdownPreviewPath = `${TEST_HOST}/preview`;
const markdownDocsPath = `${TEST_HOST}/docs`;
@@ -138,15 +140,13 @@ describe('Markdown field component', () => {
});
it('renders markdown preview and GFM', async () => {
- const renderGFMSpy = jest.spyOn($.fn, 'renderGFM');
-
previewLink = getPreviewLink();
previewLink.vm.$emit('click', { target: {} });
await axios.waitFor(markdownPreviewPath);
expect(subject.find('.md-preview-holder').element.innerHTML).toContain(previewHTML);
- expect(renderGFMSpy).toHaveBeenCalled();
+ expect(renderGFM).toHaveBeenCalled();
});
it('calls video.pause() on comment input when isSubmitting is changed to true', async () => {
diff --git a/spec/frontend/vue_shared/components/markdown/field_view_spec.js b/spec/frontend/vue_shared/components/markdown/field_view_spec.js
index be1d840dd29..176ccfc5a69 100644
--- a/spec/frontend/vue_shared/components/markdown/field_view_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/field_view_spec.js
@@ -1,10 +1,11 @@
import { shallowMount } from '@vue/test-utils';
-import $ from 'jquery';
import MarkdownFieldView from '~/vue_shared/components/markdown/field_view.vue';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
+
+jest.mock('~/behaviors/markdown/render_gfm');
describe('Markdown Field View component', () => {
- let renderGFMSpy;
let wrapper;
function createComponent() {
@@ -12,7 +13,6 @@ describe('Markdown Field View component', () => {
}
beforeEach(() => {
- renderGFMSpy = jest.spyOn($.fn, 'renderGFM');
createComponent();
});
@@ -21,6 +21,6 @@ describe('Markdown Field View component', () => {
});
it('processes rendering with GFM', () => {
- expect(renderGFMSpy).toHaveBeenCalledTimes(1);
+ expect(renderGFM).toHaveBeenCalledTimes(1);
});
});
diff --git a/spec/frontend/vue_shared/components/notes/system_note_spec.js b/spec/frontend/vue_shared/components/notes/system_note_spec.js
index 98b04ede943..559f9bcb1a8 100644
--- a/spec/frontend/vue_shared/components/notes/system_note_spec.js
+++ b/spec/frontend/vue_shared/components/notes/system_note_spec.js
@@ -1,10 +1,12 @@
import MockAdapter from 'axios-mock-adapter';
import { mount } from '@vue/test-utils';
-import $ from 'jquery';
import waitForPromises from 'helpers/wait_for_promises';
import createStore from '~/notes/stores';
import IssueSystemNote from '~/vue_shared/components/notes/system_note.vue';
import axios from '~/lib/utils/axios_utils';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
+
+jest.mock('~/behaviors/markdown/render_gfm');
describe('system note component', () => {
let vm;
@@ -75,11 +77,9 @@ describe('system note component', () => {
});
it('should renderGFM onMount', () => {
- const renderGFMSpy = jest.spyOn($.fn, 'renderGFM');
-
createComponent(props);
- expect(renderGFMSpy).toHaveBeenCalled();
+ expect(renderGFM).toHaveBeenCalled();
});
it('renders outdated code lines', async () => {
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_description_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_description_spec.js
index f2211e5b2bb..ea58cc2baf5 100644
--- a/spec/frontend/vue_shared/issuable/show/components/issuable_description_spec.js
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_description_spec.js
@@ -1,10 +1,12 @@
import { shallowMount } from '@vue/test-utils';
-import $ from 'jquery';
import IssuableDescription from '~/vue_shared/issuable/show/components/issuable_description.vue';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import { mockIssuable } from '../mock_data';
+jest.mock('~/behaviors/markdown/render_gfm');
+
const createComponent = ({
issuable = mockIssuable,
enableTaskList = true,
@@ -16,11 +18,9 @@ const createComponent = ({
});
describe('IssuableDescription', () => {
- let renderGFMSpy;
let wrapper;
beforeEach(() => {
- renderGFMSpy = jest.spyOn($.fn, 'renderGFM');
wrapper = createComponent();
});
@@ -30,17 +30,7 @@ describe('IssuableDescription', () => {
describe('mounted', () => {
it('calls `renderGFM`', () => {
- expect(renderGFMSpy).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('methods', () => {
- describe('renderGFM', () => {
- it('calls `renderGFM` on container element', () => {
- wrapper.vm.renderGFM();
-
- expect(renderGFMSpy).toHaveBeenCalled();
- });
+ expect(renderGFM).toHaveBeenCalledTimes(1);
});
});
diff --git a/spec/frontend/work_items/components/notes/system_note_spec.js b/spec/frontend/work_items/components/notes/system_note_spec.js
index 12a45d88843..3e3b8bf65b2 100644
--- a/spec/frontend/work_items/components/notes/system_note_spec.js
+++ b/spec/frontend/work_items/components/notes/system_note_spec.js
@@ -1,12 +1,14 @@
import { GlIcon } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import { shallowMount } from '@vue/test-utils';
-import $ from 'jquery';
import waitForPromises from 'helpers/wait_for_promises';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import WorkItemSystemNote from '~/work_items/components/notes/system_note.vue';
import NoteHeader from '~/notes/components/note_header.vue';
import axios from '~/lib/utils/axios_utils';
+jest.mock('~/behaviors/markdown/render_gfm');
+
describe('system note component', () => {
let wrapper;
let props;
@@ -84,11 +86,9 @@ describe('system note component', () => {
});
it('should renderGFM onMount', () => {
- const renderGFMSpy = jest.spyOn($.fn, 'renderGFM');
-
createComponent(props);
- expect(renderGFMSpy).toHaveBeenCalled();
+ expect(renderGFM).toHaveBeenCalled();
});
// eslint-disable-next-line jest/no-disabled-tests
diff --git a/spec/frontend/work_items/components/work_item_description_rendered_spec.js b/spec/frontend/work_items/components/work_item_description_rendered_spec.js
index 01ab7824975..0ab2546440b 100644
--- a/spec/frontend/work_items/components/work_item_description_rendered_spec.js
+++ b/spec/frontend/work_items/components/work_item_description_rendered_spec.js
@@ -1,9 +1,11 @@
import { shallowMount } from '@vue/test-utils';
-import $ from 'jquery';
import { nextTick } from 'vue';
import WorkItemDescriptionRendered from '~/work_items/components/work_item_description_rendered.vue';
+import { renderGFM } from '~/behaviors/markdown/render_gfm';
import { descriptionTextWithCheckboxes, descriptionHtmlWithCheckboxes } from '../mock_data';
+jest.mock('~/behaviors/markdown/render_gfm');
+
describe('WorkItemDescription', () => {
let wrapper;
@@ -32,13 +34,11 @@ describe('WorkItemDescription', () => {
});
it('renders gfm', async () => {
- const renderGFMSpy = jest.spyOn($.fn, 'renderGFM');
-
createComponent();
await nextTick();
- expect(renderGFMSpy).toHaveBeenCalled();
+ expect(renderGFM).toHaveBeenCalled();
});
describe('with checkboxes', () => {
diff --git a/spec/frontend/work_items/router_spec.js b/spec/frontend/work_items/router_spec.js
index 32ed33a63fb..c8b8a41ce5b 100644
--- a/spec/frontend/work_items/router_spec.js
+++ b/spec/frontend/work_items/router_spec.js
@@ -23,6 +23,8 @@ import CreateWorkItem from '~/work_items/pages/create_work_item.vue';
import WorkItemsRoot from '~/work_items/pages/work_item_root.vue';
import { createRouter } from '~/work_items/router';
+jest.mock('~/behaviors/markdown/render_gfm');
+
describe('Work items router', () => {
let wrapper;
diff --git a/spec/metrics_server/metrics_server_spec.rb b/spec/metrics_server/metrics_server_spec.rb
index c7716184d48..58577d4d633 100644
--- a/spec/metrics_server/metrics_server_spec.rb
+++ b/spec/metrics_server/metrics_server_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
require_relative '../../metrics_server/metrics_server'
-RSpec.describe MetricsServer do # rubocop:disable RSpec/FilePath
+RSpec.describe MetricsServer, feature_category: :application_performance do # rubocop:disable RSpec/FilePath
let(:prometheus_config) { ::Prometheus::Client.configuration }
let(:metrics_dir) { Dir.mktmpdir }
@@ -118,6 +118,7 @@ RSpec.describe MetricsServer do # rubocop:disable RSpec/FilePath
let(:expected_port) { target == 'puma' ? '8083' : '8082' }
let(:expected_env) do
{
+ 'GOGC' => '10',
'GME_MMAP_METRICS_DIR' => metrics_dir,
'GME_PROBES' => 'self,mmap',
'GME_SERVER_HOST' => 'localhost',
diff --git a/spec/serializers/pipeline_serializer_spec.rb b/spec/serializers/pipeline_serializer_spec.rb
index 9caaeb3450b..33fee68a2f2 100644
--- a/spec/serializers/pipeline_serializer_spec.rb
+++ b/spec/serializers/pipeline_serializer_spec.rb
@@ -183,25 +183,25 @@ RSpec.describe PipelineSerializer do
context 'with triggered pipelines' do
before do
- pipeline_1 = create(:ci_pipeline)
+ pipeline_1 = create(:ci_pipeline, project: project)
build_1 = create(:ci_build, pipeline: pipeline_1)
create(:ci_sources_pipeline, source_job: build_1)
-
- pipeline_2 = create(:ci_pipeline)
- build_2 = create(:ci_build, pipeline: pipeline_2)
- create(:ci_sources_pipeline, source_job: build_2)
end
it 'verifies number of queries', :request_store do
- recorded = ActiveRecord::QueryRecorder.new { subject }
+ control = ActiveRecord::QueryRecorder.new do
+ serializer.represent(Ci::Pipeline.all, preload: true)
+ end
- # Existing numbers are high and require performance optimization
- # Ongoing issue:
- # https://gitlab.com/gitlab-org/gitlab/-/issues/225156
- expected_queries = Gitlab.ee? ? 78 : 74
+ pipeline_2 = create(:ci_pipeline, project: project)
+ build_2 = create(:ci_build, pipeline: pipeline_2)
+ create(:ci_sources_pipeline, source_job: build_2)
- expect(recorded.count).to be_within(2).of(expected_queries)
- expect(recorded.cached_count).to eq(0)
+ recorded = ActiveRecord::QueryRecorder.new do
+ serializer.represent(Ci::Pipeline.all, preload: true)
+ end
+
+ expect(recorded).not_to exceed_query_limit(control)
end
end