Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-08-24 18:12:18 +00:00
parent 53ab147992
commit 06c57a8378
77 changed files with 841 additions and 291 deletions

View File

@ -320,9 +320,7 @@ gem 'premailer-rails', '~> 1.10.3'
# LabKit: Tracing and Correlation
gem 'gitlab-labkit', '~> 0.24.0'
# Thrift is a dependency of gitlab-labkit, we want a version higher than 0.14.0
# because of https://gitlab.com/gitlab-org/gitlab/-/issues/321900
gem 'thrift', '>= 0.14.0'
gem 'thrift', '>= 0.16.0'
# I18n
gem 'ruby_parser', '~> 3.15', require: false
@ -408,7 +406,7 @@ group :development, :test do
end
group :development, :test, :danger do
gem 'gitlab-dangerfiles', '~> 3.5.0', require: false
gem 'gitlab-dangerfiles', '~> 3.5.1', require: false
end
group :development, :test, :coverage do

View File

@ -516,7 +516,7 @@ GEM
terminal-table (~> 1.5, >= 1.5.1)
gitlab-chronic (0.10.5)
numerizer (~> 0.2)
gitlab-dangerfiles (3.5.0)
gitlab-dangerfiles (3.5.1)
danger (>= 8.4.5)
danger-gitlab (>= 8.0.0)
rake
@ -1364,7 +1364,7 @@ GEM
faraday (~> 1.0)
text (1.3.1)
thor (1.2.1)
thrift (0.14.0)
thrift (0.16.0)
tilt (2.0.10)
timecop (0.9.1)
timeliness (0.3.10)
@ -1577,7 +1577,7 @@ DEPENDENCIES
gitaly (~> 15.3.0.pre.rc4)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
gitlab-dangerfiles (~> 3.5.0)
gitlab-dangerfiles (~> 3.5.1)
gitlab-experiment (~> 0.7.1)
gitlab-fog-azure-rm (~> 1.3.0)
gitlab-labkit (~> 0.24.0)
@ -1759,7 +1759,7 @@ DEPENDENCIES
terser (= 1.0.2)
test-prof (~> 1.0.7)
test_file_finder (~> 0.1.3)
thrift (>= 0.14.0)
thrift (>= 0.16.0)
timecop (~> 0.9.1)
timfel-krb5-auth (~> 0.8)
toml-rb (~> 2.0)

View File

@ -0,0 +1,31 @@
function addBlameLink(containerSelector, linkClass) {
const containerEl = document.querySelector(containerSelector);
if (!containerEl) {
return;
}
containerEl.addEventListener('mouseover', (e) => {
const isLineLink = e.target.classList.contains(linkClass);
if (isLineLink) {
const lineLink = e.target;
const lineLinkCopy = lineLink.cloneNode(true);
lineLinkCopy.classList.remove(linkClass, 'diff-line-num');
const { lineNumber } = lineLink.dataset;
const { blamePath } = document.querySelector('.line-numbers').dataset;
const blameLink = document.createElement('a');
blameLink.classList.add('file-line-blame');
blameLink.href = `${blamePath}#L${lineNumber}`;
const wrapper = document.createElement('div');
wrapper.classList.add('line-links', 'diff-line-num');
wrapper.appendChild(blameLink);
wrapper.appendChild(lineLinkCopy);
lineLink.replaceWith(wrapper);
}
});
}
export default addBlameLink;

View File

@ -1,7 +1,12 @@
import Tracking from '~/tracking';
function addBlobLinksTracking(containerSelector, eventsToTrack) {
const containerEl = document.querySelector(containerSelector);
const eventsToTrack = [
{ selector: '.file-line-blame', property: 'blame' },
{ selector: '.file-line-num', property: 'link' },
];
function addBlobLinksTracking() {
const containerEl = document.querySelector('.file-holder');
if (!containerEl) {
return;

View File

@ -1,8 +1,7 @@
<script>
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { mapActions, mapGetters } from 'vuex';
import { mapActions, mapGetters, mapState } from 'vuex';
import { s__ } from '~/locale';
import { DEFAULT_BOARD_LIST_ITEMS_SIZE } from 'ee_else_ce/boards/constants';
import Tracking from '~/tracking';
@ -34,6 +33,7 @@ export default {
},
},
computed: {
...mapState(['pageInfoByListId']),
...mapGetters(['getBoardItemsByList']),
tracking() {
return {
@ -45,6 +45,9 @@ export default {
listItems() {
return this.getBoardItemsByList(this.list.id);
},
listHasNextPage() {
return this.pageInfoByListId[this.list.id]?.hasNextPage;
},
firstItemInListId() {
return this.listItems[0]?.id;
},
@ -58,7 +61,7 @@ export default {
return `${this.item.id}-${this.item.iid}-${this.index}`;
},
showMoveToEndOfList() {
return this.lengthOfListItemsInBoard <= DEFAULT_BOARD_LIST_ITEMS_SIZE;
return !this.listHasNextPage;
},
isFirstItemInList() {
return this.index === 0;

View File

@ -0,0 +1,60 @@
<script>
import { BubbleMenuPlugin } from '@tiptap/extension-bubble-menu';
export default {
name: 'BubbleMenu',
inject: ['tiptapEditor'],
props: {
pluginKey: {
type: String,
required: true,
},
shouldShow: {
type: Function,
required: true,
},
tippyOptions: {
type: Object,
required: false,
default: () => ({}),
},
},
data() {
return {
menuVisible: false,
};
},
async mounted() {
await this.$nextTick();
this.tiptapEditor.registerPlugin(
BubbleMenuPlugin({
pluginKey: this.pluginKey,
editor: this.tiptapEditor,
element: this.$el,
shouldShow: this.shouldShow,
tippyOptions: {
...this.tippyOptions,
onShow: (...args) => {
this.$emit('show', ...args);
this.menuVisible = true;
},
onHidden: (...args) => {
this.$emit('hidden', ...args);
this.menuVisible = false;
},
},
}),
);
},
beforeDestroy() {
this.tiptapEditor.unregisterPlugin(this.pluginKey);
},
};
</script>
<template>
<div>
<slot v-if="menuVisible"></slot>
</div>
</template>

View File

@ -10,13 +10,13 @@ import {
GlSearchBoxByType,
GlTooltipDirective as GlTooltip,
} from '@gitlab/ui';
import { BubbleMenu } from '@tiptap/vue-2';
import { getParentByTagName } from '~/lib/utils/dom_utils';
import codeBlockLanguageLoader from '../../services/code_block_language_loader';
import CodeBlockHighlight from '../../extensions/code_block_highlight';
import Diagram from '../../extensions/diagram';
import Frontmatter from '../../extensions/frontmatter';
import EditorStateObserver from '../editor_state_observer.vue';
import BubbleMenu from './bubble_menu.vue';
const CODE_BLOCK_NODE_TYPES = [CodeBlockHighlight.name, Diagram.name, Frontmatter.name];
@ -129,6 +129,10 @@ export default {
deleteCodeBlock() {
this.tiptapEditor.chain().focus().deleteNode(this.codeBlockType).run();
},
tippyOptions() {
return { getReferenceClientRect: this.getReferenceClientRect.bind(this) };
},
},
};
</script>
@ -136,12 +140,9 @@ export default {
<bubble-menu
data-testid="code-block-bubble-menu"
class="gl-shadow gl-rounded-base gl-bg-white"
:editor="tiptapEditor"
plugin-key="bubbleMenuCodeBlock"
:should-show="shouldShow"
:tippy-options="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ {
getReferenceClientRect,
} /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
:tippy-options="tippyOptions()"
>
<editor-state-observer @transaction="updateCodeBlockInfoToState">
<gl-button-group>

View File

@ -1,6 +1,5 @@
<script>
import { GlButtonGroup } from '@gitlab/ui';
import { BubbleMenu } from '@tiptap/vue-2';
import { BUBBLE_MENU_TRACKING_ACTION } from '../../constants';
import trackUIControl from '../../services/track_ui_control';
import Paragraph from '../../extensions/paragraph';
@ -9,6 +8,7 @@ import Audio from '../../extensions/audio';
import Video from '../../extensions/video';
import Image from '../../extensions/image';
import ToolbarButton from '../toolbar_button.vue';
import BubbleMenu from './bubble_menu.vue';
export default {
components: {
@ -34,14 +34,17 @@ export default {
);
},
},
toggleLinkCommandParams: {
href: '',
},
};
</script>
<template>
<bubble-menu
data-testid="formatting-bubble-menu"
class="gl-shadow gl-rounded-base gl-bg-white"
:editor="tiptapEditor"
:should-show="shouldShow"
:plugin-key="'formatting'"
>
<gl-button-group>
<toolbar-button
@ -109,9 +112,7 @@ export default {
content-type="link"
icon-name="link"
editor-command="toggleLink"
:editor-command-params="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ {
href: '',
} /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
:editor-command-params="$options.toggleLinkCommandParams"
category="tertiary"
size="medium"
:label="__('Insert link')"

View File

@ -8,9 +8,9 @@ import {
GlButtonGroup,
GlTooltipDirective as GlTooltip,
} from '@gitlab/ui';
import { BubbleMenu } from '@tiptap/vue-2';
import Link from '../../extensions/link';
import EditorStateObserver from '../editor_state_observer.vue';
import BubbleMenu from './bubble_menu.vue';
export default {
components: {
@ -109,18 +109,18 @@ export default {
this.tiptapEditor.chain().focus().extendMarkRange(Link.name).unsetLink().run();
},
},
tippyOptions: {
placement: 'bottom',
},
};
</script>
<template>
<bubble-menu
data-testid="link-bubble-menu"
class="gl-shadow gl-rounded-base gl-bg-white"
:editor="tiptapEditor"
plugin-key="bubbleMenuLink"
:should-show="() => shouldShow()"
:tippy-options="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ {
placement: 'bottom',
} /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
:should-show="shouldShow"
:tippy-options="$options.tippyOptions"
>
<editor-state-observer @transaction="updateLinkToState">
<gl-button-group v-if="!isEditing" class="gl-display-flex gl-align-items-center">

View File

@ -9,13 +9,13 @@ import {
GlButtonGroup,
GlTooltipDirective as GlTooltip,
} from '@gitlab/ui';
import { BubbleMenu } from '@tiptap/vue-2';
import { __ } from '~/locale';
import Audio from '../../extensions/audio';
import Image from '../../extensions/image';
import Video from '../../extensions/video';
import EditorStateObserver from '../editor_state_observer.vue';
import { acceptedMimes } from '../../services/upload_helpers';
import BubbleMenu from './bubble_menu.vue';
const MEDIA_TYPES = [Audio.name, Image.name, Video.name];
@ -189,9 +189,8 @@ export default {
<bubble-menu
data-testid="media-bubble-menu"
class="gl-shadow gl-rounded-base gl-bg-white"
:editor="tiptapEditor"
plugin-key="bubbleMenuMedia"
:should-show="() => shouldShow()"
:should-show="shouldShow"
>
<editor-state-observer @transaction="updateMediaInfoToState">
<gl-button-group v-if="!isEditing" class="gl-display-flex gl-align-items-center">

View File

@ -4,7 +4,6 @@ import BlobForkSuggestion from '~/blob/blob_fork_suggestion';
import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater';
import LineHighlighter from '~/blob/line_highlighter';
import initBlobBundle from '~/blob_edit/blob_bundle';
import addBlobLinksTracking from '~/blob/blob_links_tracking';
export default () => {
new LineHighlighter(); // eslint-disable-line no-new
@ -16,12 +15,6 @@ export default () => {
document.querySelectorAll('.js-data-file-blob-permalink-url, .js-blob-blame-link'),
);
const eventsToTrack = [
{ selector: '.file-line-blame', property: 'blame' },
{ selector: '.file-line-num', property: 'link' },
];
addBlobLinksTracking('#blob-content-holder', eventsToTrack);
const fileBlobPermalinkUrlElement = document.querySelector('.js-data-file-blob-permalink-url');
const fileBlobPermalinkUrl =
fileBlobPermalinkUrlElement && fileBlobPermalinkUrlElement.getAttribute('href');

View File

@ -13,6 +13,7 @@ import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
import CodeIntelligence from '~/code_navigation/components/app.vue';
import LineHighlighter from '~/blob/line_highlighter';
import addBlameLink from '~/blob/blob_blame_link';
import getRefMixin from '../mixins/get_ref';
import blobInfoQuery from '../queries/blob_info.query.graphql';
import userInfoQuery from '../queries/user_info.query.graphql';
@ -242,6 +243,7 @@ export default {
if (type === SIMPLE_BLOB_VIEWER) {
new LineHighlighter(); // eslint-disable-line no-new
addBlameLink('.file-holder', 'js-line-links');
}
});

View File

@ -344,6 +344,7 @@ export default {
>
<gl-link
v-gl-tooltip="tooltipText"
class="gl-reset-color gl-hover-text-blue-800"
:href="attributeUrl"
:data-qa-selector="`${formatIssuableAttribute.snake}_link`"
>

View File

@ -91,6 +91,12 @@ export default {
fastForwardMergeText() {
return __('Merge blocked: the source branch must be rebased onto the target branch.');
},
showRebaseWithoutPipeline() {
return (
!this.mr.onlyAllowMergeIfPipelineSucceeds ||
(this.mr.onlyAllowMergeIfPipelineSucceeds && this.mr.allowMergeOnSkippedPipeline)
);
},
},
methods: {
rebase({ skipCi = false } = {}) {
@ -192,6 +198,7 @@ export default {
</template>
<template v-if="!isLoading" #actions>
<gl-button
v-if="showRebaseWithoutPipeline"
:loading="isMakingRequest"
variant="confirm"
size="small"

View File

@ -3,6 +3,7 @@ query getState($projectPath: ID!, $iid: String!) {
id
archived
onlyAllowMergeIfPipelineSucceeds
allowMergeOnSkippedPipeline
mergeRequest(iid: $iid) {
id
autoMergeEnabled

View File

@ -168,6 +168,7 @@ export default class MergeRequestStore {
this.mergeError = data.merge_error;
this.mergeStatus = data.merge_status;
this.onlyAllowMergeIfPipelineSucceeds = data.only_allow_merge_if_pipeline_succeeds || false;
this.allowMergeOnSkippedPipeline = data.allow_merge_on_skipped_pipeline || false;
this.projectArchived = data.project_archived;
this.isSHAMismatch = this.sha !== data.diff_head_sha;
this.shouldBeRebased = Boolean(data.should_be_rebased);
@ -195,6 +196,7 @@ export default class MergeRequestStore {
this.projectArchived = project.archived;
this.onlyAllowMergeIfPipelineSucceeds = project.onlyAllowMergeIfPipelineSucceeds;
this.allowMergeOnSkippedPipeline = project.allowMergeOnSkippedPipeline;
this.autoMergeEnabled = mergeRequest.autoMergeEnabled;
this.canBeMerged = mergeRequest.mergeStatus === 'can_be_merged';

View File

@ -3,6 +3,7 @@ import { GlSafeHtmlDirective, GlLoadingIcon } from '@gitlab/ui';
import LineHighlighter from '~/blob/line_highlighter';
import eventHub from '~/notes/event_hub';
import languageLoader from '~/content_editor/services/highlight_js_language_loader';
import addBlobLinksTracking from '~/blob/blob_links_tracking';
import Tracking from '~/tracking';
import {
EVENT_ACTION,
@ -66,6 +67,7 @@ export default {
},
},
async created() {
addBlobLinksTracking();
this.trackEvent(EVENT_LABEL_VIEWER);
if (this.unsupportedLanguage) {

View File

@ -5,16 +5,14 @@ import { helpPagePath } from '~/helpers/help_page_helper';
export default {
i18n: {
learnTasksButtonText: s__('WorkItem|Learn about tasks'),
workItemsText: s__('WorkItem|work items'),
learnTasksLinkText: s__('WorkItem|Learn about tasks.'),
tasksInformationTitle: s__('WorkItem|Introducing tasks'),
tasksInformationBody: s__(
'WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon.',
'WorkItem|Use tasks to break down your work in an issue into smaller pieces. %{learnMoreLink}',
),
},
helpPageLinks: {
tasksDocLinkPath: helpPagePath('user/tasks'),
workItemsLinkPath: helpPagePath(`development/work_items`),
},
components: {
GlAlert,
@ -38,16 +36,14 @@ export default {
v-if="showInfoBanner"
variant="tip"
:title="$options.i18n.tasksInformationTitle"
:primary-button-link="$options.helpPageLinks.tasksDocLinkPath"
:primary-button-text="$options.i18n.learnTasksButtonText"
data-testid="work-item-information"
class="gl-mt-3"
@dismiss="$emit('work-item-banner-dismissed')"
>
<gl-sprintf :message="$options.i18n.tasksInformationBody">
<template #workItemsLink>
<gl-link :href="$options.helpPageLinks.workItemsLinkPath">{{
$options.i18n.workItemsText
<template #learnMoreLink>
<gl-link :href="$options.helpPageLinks.tasksDocLinkPath">{{
$options.i18n.learnTasksLinkText
}}</gl-link>
</template>
></gl-sprintf

View File

@ -95,23 +95,14 @@ td.line-numbers {
.blob-viewer {
.line-numbers {
min-width: 6rem;
// for server-side-rendering
.line-links {
@include gl-display-flex;
&:first-child {
margin-top: 10px;
}
&:last-child {
margin-bottom: 10px;
}
}
// for client
&.line-links {
min-width: 6rem;
border-bottom-left-radius: 0;
+ pre {
@ -120,15 +111,15 @@ td.line-numbers {
}
}
.line-links {
&:hover a::before,
&:focus-within a::before {
@include gl-visibility-visible;
}
.line-numbers:not(.line-links) a:hover::before,
.line-numbers:not(.line-links) a:focus-within::before,
.line-links:hover a::before,
.line-links:focus-within a::before {
@include gl-visibility-visible;
}
.file-line-num {
min-width: 4.5rem;
@include gl-justify-content-end;
@include gl-flex-grow-1;
@include gl-pr-3;

View File

@ -28,7 +28,7 @@ class Projects::IncidentsController < Projects::ApplicationController
.inc_relations_for_view
.iid_in(params[:id])
.without_order
.first
.take # rubocop:disable CodeReuse/ActiveRecord
end
end

View File

@ -17,14 +17,15 @@ module SearchArguments
def ready?(**args)
validate_search_in_params!(args)
validate_anonymous_search_access!
validate_anonymous_search_access!(args)
super
end
private
def validate_anonymous_search_access!
def validate_anonymous_search_access!(args)
return unless args[:search].present?
return if current_user.present? || Feature.disabled?(:disable_anonymous_search, type: :ops)
raise ::Gitlab::Graphql::Errors::ArgumentError,

View File

@ -36,10 +36,5 @@ module AlertManagement
)
end
end
override :resolving_alert?
def resolving_alert?
incoming_payload.resolved?
end
end
end

View File

@ -113,7 +113,7 @@ module AlertManagement
end
def resolving_alert?
incoming_payload.ends_at.present?
incoming_payload.resolved?
end
def notifying_alert?
@ -121,7 +121,7 @@ module AlertManagement
end
def alert_source
incoming_payload.monitoring_tool
incoming_payload.source
end
def logger

View File

@ -35,11 +35,6 @@ module Projects
Gitlab::Utils::DeepSize.new(params).valid?
end
override :alert_source
def alert_source
super || integration&.name || 'Generic Alert Endpoint'
end
def active_integration?
integration&.active?
end

View File

@ -1,17 +1,14 @@
#blob-content.file-content.code.js-syntax-highlight
- offset = defined?(first_line_number) ? first_line_number : 1
.line-numbers{ class: "gl-p-0\!" }
- blame_path = project_blame_path(@project, tree_join(@ref, blob.path))
.line-numbers{ class: "gl-px-0!", data: { blame_path: blame_path } }
- if blob.data.present?
- link = blob_link if defined?(blob_link)
- blame_link = project_blame_path(@project, tree_join(@ref, blob.path))
- blob.data.each_line.each_with_index do |_, index|
- i = index + offset
-# We're not using `link_to` because it is too slow once we get to thousands of lines.
.line-links.diff-line-num
- if Feature.enabled?(:file_line_blame)
%a.file-line-blame{ href: "#{blame_link}#L#{i}" }
%a.file-line-num{ href: "#{link}#L#{i}", id: "L#{i}", 'data-line-number' => i }
= i
%a.file-line-num.diff-line-num{ class: ("js-line-links" if Feature.enabled?(:file_line_blame)), href: "#{link}#L#{i}", id: "L#{i}", 'data-line-number' => i }
= i
- highlight = defined?(highlight_line) && highlight_line ? highlight_line - offset : nil
.blob-content{ data: { blob_id: blob.id, path: blob.path, highlight_line: highlight, qa_selector: 'file_content' } }
%pre.code.highlight

View File

@ -1,8 +1,8 @@
- name: "SaaS certificate-based integration with Kubernetes"
announcement_milestone: "14.5"
announcement_date: "2021-11-15"
removal_milestone: "15.6"
removal_date: "2022-11-22" # the date of the milestone release when this feature is planned to be removed
removal_milestone: "15.9"
removal_date: "2023-02-22" # the date of the milestone release when this feature is planned to be removed
breaking_change: true
body: |
The certificate-based integration with Kubernetes will be [deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). As a GitLab SaaS customer, on new namespaces, you will no longer be able to integrate GitLab and your cluster using the certificate-based approach as of GitLab 15.0. The integration for current users will be enabled per namespace. The integrations are expected to be switched off completely on GitLab SaaS around 2022 November 22.

View File

@ -31,7 +31,7 @@ Configure your load balancers to pass connections on port 443 as 'TCP' rather
than 'HTTP(S)' protocol. This passes the connection to the application nodes
NGINX service untouched. NGINX has the SSL certificate and listen on port 443.
See [NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
See the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html)
for details on managing SSL certificates and configuring NGINX.
### Load Balancers terminate SSL without backend SSL
@ -41,8 +41,8 @@ The load balancers is be responsible for managing SSL certificates and
terminating SSL.
Because communication between the load balancers and GitLab isn't secure,
there is some additional configuration needed. See
[NGINX Proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl)
there is some additional configuration needed. See the
[proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/ssl.html#configure-a-reverse-proxy-or-load-balancer-ssl-termination)
for details.
### Load Balancers terminate SSL with backend SSL
@ -55,7 +55,7 @@ Traffic is secure between the load balancers and NGINX in this
scenario. There is no need to add configuration for proxied SSL because the
connection is secure all the way. However, configuration must be
added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html)
for details on managing SSL certificates and configuring NGINX.
## Ports
@ -128,5 +128,5 @@ The default ciphers for a GitLab version can be
viewed in the [`files/gitlab-cookbooks/gitlab/attributes/default.rb`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/master/files/gitlab-cookbooks/gitlab/attributes/default.rb)
file and selecting the Git tag that correlates with your target GitLab version
(for example `15.0.5+ee.0`). If required by your load balancer, you can then define
[custom SSL ciphers](https://docs.gitlab.com/omnibus/settings/nginx.html#using-custom-ssl-ciphers)
[custom SSL ciphers](https://docs.gitlab.com/omnibus/settings/ssl.html#use-custom-ssl-ciphers)
for NGINX.

View File

@ -23,7 +23,7 @@ may or may not be available by default.
The Container Registry is automatically enabled and available on your GitLab domain, port 5050 if:
- You're using the built-in [Let's Encrypt integration](https://docs.gitlab.com/omnibus/settings/ssl.html#lets-encrypt-integration), and
- You're using the built-in [Let's Encrypt integration](https://docs.gitlab.com/omnibus/settings/ssl.html#enable-the-lets-encrypt-integration), and
- You're using GitLab 12.5 or later.
Otherwise, the Container Registry is not enabled. To enable it:
@ -199,7 +199,7 @@ a wildcard certificate if hosted under a subdomain of your existing GitLab
domain, for example, `registry.gitlab.example.com`.
As well as manually generated SSL certificates (explained here), certificates automatically
generated by Let's Encrypt are also [supported in Omnibus installs](https://docs.gitlab.com/omnibus/settings/ssl.html#host-services).
generated by Let's Encrypt are also [supported in Omnibus installs](https://docs.gitlab.com/omnibus/settings/ssl.html).
Let's assume that you want the container Registry to be accessible at
`https://registry.gitlab.example.com`.

View File

@ -523,7 +523,7 @@ For Omnibus, this is fixed by [installing a custom CA in Omnibus GitLab](https:/
> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/548) in GitLab 14.8.
If GitLab has been [configured to require mutual TLS](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-2-way-ssl-client-authentication), you need to add the client certificates to Pages:
If GitLab has been [configured to require mutual TLS](https://docs.gitlab.com/omnibus/settings/ssl.html#enable-2-way-ssl-client-authentication), you need to add the client certificates to Pages:
1. Configure in `/etc/gitlab/gitlab.rb`:

View File

@ -261,7 +261,7 @@ Configure your load balancer to pass connections on port 443 as `TCP` rather
than `HTTP(S)` protocol. This will pass the connection to the application node's
NGINX service untouched. NGINX will have the SSL certificate and listen on port 443.
See the [NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
See the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html)
for details on managing SSL certificates and configuring NGINX.
### Load balancer terminates SSL without backend SSL
@ -272,7 +272,7 @@ terminating SSL.
Since communication between the load balancer and GitLab will not be secure,
there is some additional configuration needed. See the
[NGINX proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl)
[proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/ssl.html#configure-a-reverse-proxy-or-load-balancer-ssl-termination)
for details.
### Load balancer terminates SSL with backend SSL
@ -285,7 +285,7 @@ Traffic will also be secure between the load balancers and NGINX in this
scenario. There is no need to add configuration for proxied SSL since the
connection will be secure all the way. However, configuration will need to be
added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html)
for details on managing SSL certificates and configuring NGINX.
### Readiness checks
@ -2071,7 +2071,7 @@ On each node perform the following:
When you specify `https` in the `external_url`, as in the previous example,
GitLab expects that the SSL certificates are in `/etc/gitlab/ssl/`. If the
certificates aren't present, NGINX will fail to start. For more information, see
the [NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https).
the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html).
### GitLab Rails post-configuration

View File

@ -264,7 +264,7 @@ Configure your load balancer to pass connections on port 443 as `TCP` rather
than `HTTP(S)` protocol. This will pass the connection to the application node's
NGINX service untouched. NGINX will have the SSL certificate and listen on port 443.
See the [NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
See the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html)
for details on managing SSL certificates and configuring NGINX.
### Load balancer terminates SSL without backend SSL
@ -275,7 +275,7 @@ terminating SSL.
Since communication between the load balancer and GitLab will not be secure,
there is some additional configuration needed. See the
[NGINX proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl)
[proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/ssl.html#configure-a-reverse-proxy-or-load-balancer-ssl-termination)
for details.
### Load balancer terminates SSL with backend SSL
@ -287,8 +287,8 @@ end users will see.
Traffic will also be secure between the load balancers and NGINX in this
scenario. There is no need to add configuration for proxied SSL since the
connection will be secure all the way. However, configuration will need to be
added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
added to GitLab to configure SSL certificates. See the
[HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html)
for details on managing SSL certificates and configuring NGINX.
### Readiness checks
@ -2076,7 +2076,7 @@ On each node perform the following:
When you specify `https` in the `external_url`, as in the previous example,
GitLab expects that the SSL certificates are in `/etc/gitlab/ssl/`. If the
certificates aren't present, NGINX will fail to start. For more information, see
the [NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https).
the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html).
### GitLab Rails post-configuration

View File

@ -149,7 +149,7 @@ of `HTTP(S)`. This will pass the connection unaltered to the application node's
NGINX service, which has the SSL certificate and listens to port 443.
For details about managing SSL certificates and configuring NGINX, see the
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https).
[HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html)
### Load balancer terminates SSL without backend SSL
@ -159,7 +159,7 @@ terminating SSL.
Due to communication between the load balancer and GitLab not being secure,
you'll need to complete some additional configuration. For details, see the
[NGINX proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl).
[proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/ssl.html#configure-a-reverse-proxy-or-load-balancer-ssl-termination).
### Load balancer terminates SSL with backend SSL
@ -171,7 +171,7 @@ Traffic will be secure between the load balancers and NGINX in this scenario,
and there's no need to add a configuration for proxied SSL. However, you'll
need to add a configuration to GitLab to configure SSL certificates. For
details about managing SSL certificates and configuring NGINX, see the
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https).
[HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html).
### Readiness checks
@ -752,7 +752,7 @@ On each node perform the following:
When you specify `https` in the `external_url`, as in the previous example,
GitLab expects that the SSL certificates are in `/etc/gitlab/ssl/`. If the
certificates aren't present, NGINX will fail to start. For more information, see
the [NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https).
the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html).
### GitLab Rails post-configuration

View File

@ -265,7 +265,7 @@ Configure your load balancer to pass connections on port 443 as `TCP` rather
than `HTTP(S)` protocol. This will pass the connection to the application node's
NGINX service untouched. NGINX will have the SSL certificate and listen on port 443.
See the [NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
See the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html)
for details on managing SSL certificates and configuring NGINX.
### Load balancer terminates SSL without backend SSL
@ -276,7 +276,7 @@ terminating SSL.
Since communication between the load balancer and GitLab will not be secure,
there is some additional configuration needed. See the
[NGINX proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl)
[proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/ssl.html#configure-a-reverse-proxy-or-load-balancer-ssl-termination)
for details.
### Load balancer terminates SSL with backend SSL
@ -288,8 +288,8 @@ end users will see.
Traffic will also be secure between the load balancers and NGINX in this
scenario. There is no need to add configuration for proxied SSL since the
connection will be secure all the way. However, configuration will need to be
added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
added to GitLab to configure SSL certificates. See the
[HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html)
for details on managing SSL certificates and configuring NGINX.
### Readiness checks
@ -2007,7 +2007,7 @@ On each node perform the following:
When you specify `https` in the `external_url`, as in the previous example,
GitLab expects that the SSL certificates are in `/etc/gitlab/ssl/`. If the
certificates aren't present, NGINX will fail to start. For more information, see
the [NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https).
the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html).
### GitLab Rails post-configuration

View File

@ -270,7 +270,7 @@ Configure your load balancer to pass connections on port 443 as `TCP` rather
than `HTTP(S)` protocol. This will pass the connection to the application node's
NGINX service untouched. NGINX will have the SSL certificate and listen on port 443.
See the [NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
See the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html)
for details on managing SSL certificates and configuring NGINX.
### Load balancer terminates SSL without backend SSL
@ -281,7 +281,7 @@ terminating SSL.
Since communication between the load balancer and GitLab will not be secure,
there is some additional configuration needed. See the
[NGINX proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl)
[proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/ssl.html#configure-a-reverse-proxy-or-load-balancer-ssl-termination)
for details.
### Load balancer terminates SSL with backend SSL
@ -293,8 +293,8 @@ end users will see.
Traffic will also be secure between the load balancers and NGINX in this
scenario. There is no need to add configuration for proxied SSL since the
connection will be secure all the way. However, configuration will need to be
added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
added to GitLab to configure SSL certificates. See the
[HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html)
for details on managing SSL certificates and configuring NGINX.
### Readiness checks
@ -2092,7 +2092,7 @@ On each node perform the following:
When you specify `https` in the `external_url`, as in the previous example,
GitLab expects that the SSL certificates are in `/etc/gitlab/ssl/`. If the
certificates aren't present, NGINX will fail to start. For more information, see
the [NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https).
the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html).
### GitLab Rails post-configuration

View File

@ -263,7 +263,7 @@ Configure your load balancer to pass connections on port 443 as `TCP` rather
than `HTTP(S)` protocol. This passes the connection to the application node's
NGINX service untouched. NGINX has the SSL certificate and listen on port 443.
See the [NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
See the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html)
for details on managing SSL certificates and configuring NGINX.
### Load balancer terminates SSL without backend SSL
@ -274,7 +274,7 @@ terminating SSL.
Since communication between the load balancer and GitLab is not secure,
there is some additional configuration needed. See the
[NGINX proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl)
[proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/ssl.html#configure-a-reverse-proxy-or-load-balancer-ssl-termination)
for details.
### Load balancer terminates SSL with backend SSL
@ -286,8 +286,8 @@ end users see.
Traffic is also secure between the load balancers and NGINX in this
scenario. There is no need to add configuration for proxied SSL since the
connection is secure all the way. However, configuration needs to be
added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
added to GitLab to configure SSL certificates. See the
[HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html)
for details on managing SSL certificates and configuring NGINX.
### Readiness checks
@ -2007,7 +2007,7 @@ On each node perform the following:
When you specify `https` in the `external_url`, as in the previous example,
GitLab expects that the SSL certificates are in `/etc/gitlab/ssl/`. If the
certificates aren't present, NGINX fails to start. For more information, see
the [NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https).
the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl.html).
### GitLab Rails post-configuration

View File

@ -13,7 +13,7 @@ main SSL documentation:
- [Omnibus SSL Configuration](https://docs.gitlab.com/omnibus/settings/ssl.html).
- [Self-signed certificates or custom Certification Authorities for GitLab Runner](https://docs.gitlab.com/runner/configuration/tls-self-signed.html).
- [Manually configuring HTTPS](https://docs.gitlab.com/omnibus/settings/nginx.html#manually-configuring-https).
- [Configure HTTPS manually](https://docs.gitlab.com/omnibus/settings/ssl.html#configure-https-manually).
## Using an internal CA certificate with GitLab

View File

@ -80,6 +80,11 @@ Example response:
}
```
## Container Registry pagination
By default, `GET` requests return 20 results at a time because the API results
are [paginated](index.md#pagination).
## List registry repositories
### Within a project

View File

@ -289,6 +289,34 @@ preserving deployment keys and other credentials from being unintentionally
accessed. To ensure that jobs intended to be executed on protected
runners do not use regular runners, they must be tagged accordingly.
## Trigger a pipeline when an upstream project is rebuilt **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9045) in GitLab 12.8.
You can trigger a pipeline in your project whenever a pipeline finishes for a new
tag in a different project.
Prerequisites:
- The upstream project must be [public](../../user/public_access.md).
- The user must have the Developer role
in the upstream project.
To trigger the pipeline when the upstream project is rebuilt:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **Pipeline subscriptions**.
1. Enter the project you want to subscribe to, in the format `<namespace>/<project>`.
For example, if the project is `https://gitlab.com/gitlab-org/gitlab`, use `gitlab-org/gitlab`.
1. Select **Subscribe**.
Any pipelines that complete successfully for new tags in the subscribed project
now trigger a pipeline on the current project's default branch. The maximum
number of upstream pipeline subscriptions is 2 by default, for both the upstream and
downstream projects. On self-managed instances, an administrator can change this
[limit](../../administration/instance_limits.md#number-of-cicd-subscriptions-to-a-project).
### How pipeline duration is calculated
Total running time for a given pipeline excludes retries and pending

View File

@ -244,34 +244,6 @@ When using:
- [`only/except`](../yaml/index.md#only--except) to control job behavior, use the
`pipelines` keyword.
### Trigger a pipeline when an upstream project is rebuilt **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9045) in GitLab 12.8.
You can trigger a pipeline in your project whenever a pipeline finishes for a new
tag in a different project.
Prerequisites:
- The upstream project must be [public](../../user/public_access.md).
- The user must have the Developer role
in the upstream project.
To trigger the pipeline when the upstream project is rebuilt:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **Pipeline subscriptions**.
1. Enter the project you want to subscribe to, in the format `<namespace>/<project>`.
For example, if the project is `https://gitlab.com/gitlab-org/gitlab`, use `gitlab-org/gitlab`.
1. Select **Subscribe**.
Any pipelines that complete successfully for new tags in the subscribed project
now trigger a pipeline on the current project's default branch. The maximum
number of upstream pipeline subscriptions is 2 by default, for both the upstream and
downstream projects. On self-managed instances, an administrator can change this
[limit](../../administration/instance_limits.md#number-of-cicd-subscriptions-to-a-project).
## Multi-project pipeline visualization **(PREMIUM)**
When your pipeline triggers a downstream pipeline, the downstream pipeline displays

View File

@ -37,7 +37,7 @@ On the left side we have the events that can trigger a pipeline based on various
- When a [merge request is created or updated](../../ci/pipelines/merge_request_pipelines.md).
- When an MR is added to a [Merge Train](../../ci/pipelines/merge_trains.md#merge-trains).
- A [scheduled pipeline](../../ci/pipelines/schedules.md).
- When project is [subscribed to an upstream project](../../ci/pipelines/multi_project_pipelines.md#trigger-a-pipeline-when-an-upstream-project-is-rebuilt).
- When project is [subscribed to an upstream project](../../ci/pipelines/index.md#trigger-a-pipeline-when-an-upstream-project-is-rebuilt).
- When [Auto DevOps](../../topics/autodevops/index.md) is enabled.
- When GitHub integration is used with [external pull requests](../../ci/ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests).
- When an upstream pipeline contains a [bridge job](../../ci/yaml/index.md#trigger) which triggers a downstream pipeline.

View File

@ -355,18 +355,6 @@ as a reviewer, it is recommended that they are not also picked as the maintainer
Maintainers should check before merging if the merge request is approved by the
required approvers. If still awaiting further approvals from others, remove yourself as a reviewer then `@` mention the author and explain why in a comment. Stay as reviewer if you're merging the code.
Maintainers must check before merging if the merge request is introducing new
vulnerabilities, by inspecting the list in the merge request
[Security Widget](../user/application_security/index.md).
When in doubt, a [Security Engineer](https://about.gitlab.com/company/team/) can be involved. The list of detected
vulnerabilities must be either empty or containing:
- dismissed vulnerabilities in case of false positives
- vulnerabilities converted to issues
Maintainers should **never** dismiss vulnerabilities to "empty" the list,
without duly verifying them.
Note that certain merge requests may target a stable branch. These are rare
events. These types of merge requests cannot be merged by the Maintainer.
Instead, these should be sent to the [Release Manager](https://about.gitlab.com/community/release-managers/).

View File

@ -10,6 +10,8 @@ The DeclarativePolicy framework is designed to assist in performance of policy c
The policy used is based on the subject's class name - so `Ability.allowed?(user, :some_ability, project)` creates a `ProjectPolicy` and check permissions on that.
The Ruby gem source is available in the [declarative-policy](https://gitlab.com/gitlab-org/ruby/gems/declarative-policy) GitLab project.
## Managing Permission Rules
Permissions are broken into two parts: `conditions` and `rules`. Conditions are boolean expressions that can access the database and the environment, while rules are statically configured combinations of expressions and other rules that enable or prevent certain abilities. For an ability to be allowed, it must be enabled by at least one rule, and not prevented by any.

View File

@ -204,3 +204,33 @@ provide a smooth migration path of epics to WIT with minimal disruption to user
We will move towards work items, work item types, and custom widgets (CW) in an iterative process.
For a rough outline of the work ahead of us, see [epic 6033](https://gitlab.com/groups/gitlab-org/-/epics/6033).
## Redis HLL Counter Schema
We need a more scalable Redis counter schema for work items that is inclusive of Plan xMAU, Project Management xMAU, Certify xMAU, and
Product Planning xMAU. We cannot aggregate and dedupe events across features within a group or at the stage level with
our current Redis slot schema.
All three Plan product groups will be using the same base object (`work item`). Each product group still needs to
track MAU.
### Proposed aggregate counter schema
```mermaid
graph TD
Event[Specific Interaction Counter] --> AC[Aggregate Counters]
AC --> Plan[Plan xMAU]
AC --> PM[Project Management xMAU]
AC --> PP[Product Planning xMAU]
AC --> Cer[Certify xMAU]
AC --> WI[Work Items Users]
```
### Implementation
The new aggregate schema is already implemented and we are already tracking work item unique actions
in [GitLab.com](https://gitlab.com).
For implementation details, this [MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93231) can be used
as a reference. The MR covers the definition of new unique actions, event tracking in the code and also
adding the new unique actions to the required aggregate counters.

View File

@ -483,7 +483,7 @@ Connect to your GitLab instance via **Bastion Host A** using [SSH Agent Forwardi
#### Disable Let's Encrypt
Because we're adding our SSL certificate at the load balancer, we do not need the GitLab built-in support for Let's Encrypt. Let's Encrypt [is enabled by default](https://docs.gitlab.com/omnibus/settings/ssl.html#lets-encrypt-integration) when using an `https` domain in GitLab 10.7 and later, so we must explicitly disable it:
Because we're adding our SSL certificate at the load balancer, we do not need the GitLab built-in support for Let's Encrypt. Let's Encrypt [is enabled by default](https://docs.gitlab.com/omnibus/settings/ssl.html#enable-the-lets-encrypt-integration) when using an `https` domain in GitLab 10.7 and later, so we must explicitly disable it:
1. Open `/etc/gitlab/gitlab.rb` and disable it:
@ -605,7 +605,7 @@ Now that we have our EC2 instance ready, follow the [documentation to install Gi
#### Add Support for Proxied SSL
As we are terminating SSL at our [load balancer](#load-balancer), follow the steps at [Supporting proxied SSL](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl) to configure this in `/etc/gitlab/gitlab.rb`.
As we are terminating SSL at our [load balancer](#load-balancer), follow the steps at [Supporting proxied SSL](https://docs.gitlab.com/omnibus/settings/ssl.html#configure-a-reverse-proxy-or-load-balancer-ssl-termination) to configure this in `/etc/gitlab/gitlab.rb`.
Remember to run `sudo gitlab-ctl reconfigure` after saving the changes to the `gitlab.rb` file.

View File

@ -301,7 +301,7 @@ point to a valid URL.
To receive e-mails from GitLab you have to configure the
[SMTP settings](https://docs.gitlab.com/omnibus/settings/smtp.html) because the GitLab Docker image doesn't
have an SMTP server installed. You may also be interested in
[enabling HTTPS](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https).
[enabling HTTPS](https://docs.gitlab.com/omnibus/settings/ssl.html).
After you make all the changes you want, you will need to restart the container
in order to reconfigure GitLab:

View File

@ -117,8 +117,8 @@ here's how you configure GitLab to be aware of the change:
### Configuring HTTPS with the domain name
Although not needed, it's strongly recommended to secure GitLab with a TLS
certificate. Follow the steps in the [Omnibus documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https).
Although not needed, it's strongly recommended to secure GitLab with a
[TLS certificate](https://docs.gitlab.com/omnibus/settings/ssl.html).
### Configuring the email SMTP settings

View File

@ -58,8 +58,9 @@ There are a couple of ways to achieve that:
::Gitlab::CurrentSettings.elasticsearch_limit_indexing? # Whether or not Elasticsearch is limited only to certain projects/namespaces
```
- Confirm searches use Elasticsearch by accessing the [rails console]
(../../administration/operations/rails_console.md) and running the following commands:
- Confirm searches use Elasticsearch by accessing the
[rails console](../../administration/operations/rails_console.md) and running the following
commands:
```rails
u = User.find_by_email('email_of_user_doing_search')

View File

@ -174,7 +174,7 @@ Error obtaining access token. Cannot access https://gitlab.example.com from Jira
- The [GitLab Jira integration](index.md) requires
GitLab to connect to Jira. Any TLS issues that arise from a private certificate
authority or self-signed certificate are resolved
[on the GitLab server](https://docs.gitlab.com/omnibus/settings/ssl.html#other-certificate-authorities),
[on the GitLab server](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates),
as GitLab is the TLS client.
- The Jira Development panel integration requires Jira to connect to GitLab, which
causes Jira to be the TLS client. If your GitLab server's certificate is not

View File

@ -71,7 +71,7 @@ sudo EXTERNAL_URL="http://my-host.internal" dpkg -i <gitlab_package_name>.deb
## Enabling SSL
Follow these steps to enable SSL for your fresh instance. These steps reflect those for
[manually configuring SSL in Omnibus's NGINX configuration](https://docs.gitlab.com/omnibus/settings/nginx.html#manually-configuring-https):
[manually configuring SSL in Omnibus's NGINX configuration](https://docs.gitlab.com/omnibus/settings/ssl.html#configure-https-manually):
1. Make the following changes to `/etc/gitlab/gitlab.rb`:

View File

@ -1749,11 +1749,11 @@ When checking if a runner is `paused`, API users are advised to check the boolea
</div>
<div class="deprecation removal-156 breaking-change">
<div class="deprecation removal-159 breaking-change">
### SaaS certificate-based integration with Kubernetes
Planned removal: GitLab <span class="removal-milestone">15.6</span> (2022-11-22)
Planned removal: GitLab <span class="removal-milestone">15.9</span> (2023-02-22)
WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).

View File

@ -30,7 +30,7 @@ Prerequisites:
You can set the issue weight when you create or edit an issue.
You must use whole numbers (like 0, 1, 2). Negative numbers or fractions are not accepted.
You must enter whole, positive numbers.
When you change the weight of an issue, the new value overwrites the previous value.

View File

@ -57,8 +57,6 @@ switch between ascending or descending order, select **Sort order**.
## Create a release
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32812) in GitLab 12.9. Releases can be created directly in the GitLab UI.
You can create a release:
- [Using a job in your CI/CD pipeline](#creating-a-release-by-using-a-cicd-job).
@ -68,13 +66,13 @@ You can create a release:
We recommend creating a release as one of the last steps in your CI/CD pipeline.
### Create a release in the Releases page
Prerequisites:
- You must have at least the Developer role for a project. For more information, read
[Release permissions](#release-permissions).
### Create a release in the Releases page
To create a release in the Releases page:
1. On the top bar, select **Menu > Projects** and find your project.
@ -124,8 +122,11 @@ You can create a release directly as part of the GitLab CI/CD pipeline by using
The release is created only if the job processes without error. If the API returns an error during
release creation, the release job fails.
For examples of how you can create a release of your application in the CI/CD pipeline,
see [Release CI/CD examples](release_cicd_examples.md).
Methods for creating a release using a CI/CD job include:
- [Create a release when a Git tag is created](release_cicd_examples.md#create-a-release-when-a-git-tag-is-created).
- [Create a release when a commit is merged to the default branch](release_cicd_examples.md#create-a-release-when-a-commit-is-merged-to-the-default-branch).
- [Create release metadata in a custom script](release_cicd_examples.md#create-release-metadata-in-a-custom-script).
### Use a custom SSL CA certificate authority

View File

@ -12,9 +12,13 @@ CI/CD pipeline.
## Create a release when a Git tag is created
In this CI/CD example, pushing a Git tag to the repository, or creating a Git tag in the UI triggers
the release. You can use this method if you prefer to create the Git tag manually, and create a
release as a result.
In this CI/CD example, the release is triggered by one of the following events:
- Pushing a Git tag to the repository.
- Creating a Git tag in the UI.
You can use this method if you prefer to create the Git tag manually, and create a release as a
result.
NOTE:
Do not provide Release notes when you create the Git tag in the UI. Providing release notes
@ -40,8 +44,8 @@ release_job:
## Create a release when a commit is merged to the default branch
In this CI/CD example, merging a commit to the default branch triggers the pipeline. You can use
this method if your release workflow does not create a tag manually.
In this CI/CD example, the release is triggered when you merge a commit to the default branch. You
can use this method if your release workflow does not create a tag manually.
Key points in the following _extract_ of an example `.gitlab-ci.yml` file:
@ -69,16 +73,75 @@ Environment variables set in `before_script` or `script` are not available for e
in the same job. Read more about
[potentially making variables available for expanding](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6400).
## Create release metadata in a custom script
In this CI/CD example the release preparation is split into separate jobs for greater flexibility:
- The `prepare_job` job generates the release metadata. Any image can be used to run the job,
including a custom image. The generated metadata is stored in the variable file `variables.env`.
This metadata is [passed to the downstream job](../../../ci/variables/index.md#pass-an-environment-variable-to-another-job).
- The `release_job` uses the content from the variables file to create a release, using the
metadata passed to it in the variables file. This job must use the
`registry.gitlab.com/gitlab-org/release-cli:latest` image because it contains the release CLI.
```yaml
prepare_job:
stage: prepare # This stage must run before the release stage
rules:
- if: $CI_COMMIT_TAG
when: never # Do not run this job when a tag is created manually
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
script:
- echo "EXTRA_DESCRIPTION=some message" >> variables.env # Generate the EXTRA_DESCRIPTION and TAG environment variables
- echo "TAG=v$(cat VERSION)" >> variables.env # and append to the variables.env file
artifacts:
reports:
dotenv: variables.env # Use artifacts:reports:dotenv to expose the variables to other jobs
release_job:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
needs:
- job: prepare_job
artifacts: true
rules:
- if: $CI_COMMIT_TAG
when: never # Do not run this job when a tag is created manually
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
script:
- echo "running release_job for $TAG"
release:
name: 'Release $TAG'
description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION and the $TAG
tag_name: '$TAG' # variables must be defined elsewhere
ref: '$CI_COMMIT_SHA' # in the pipeline. For example, in the
milestones: # prepare_job
- 'm1'
- 'm2'
- 'm3'
released_at: '2020-07-15T08:00:00Z' # Optional, is auto generated if not defined, or can use a variable.
assets:
links:
- name: 'asset1'
url: 'https://example.com/assets/1'
- name: 'asset2'
url: 'https://example.com/assets/2'
filepath: '/pretty/url/1' # optional
link_type: 'other' # optional
```
## Skip multiple pipelines when creating a release
Creating a release using a CI/CD job could potentially trigger multiple pipelines if the associated tag does not exist already. To understand how this might happen, consider the following workflows:
- Tag first, release second:
1. A tag is created via UI or pushed.
1. A tag pipeline is triggered, and runs `release` job.
1. A release is created.
- Release first, tag second:
1. A pipeline is triggered when commits are pushed or merged to default branch. The pipeline runs `release` job.
1. A release is created.
1. A tag is created.

View File

@ -420,7 +420,7 @@ to move any project to any namespace.
When you transfer a project from a namespace licensed for GitLab SaaS Premium or Ultimate to GitLab Free, the following paid feature data is deleted:
- [Project access tokens](../../../user/project/settings/project_access_tokens.md) are revoked
- [Pipeline subscriptions](../../../ci/pipelines/multi_project_pipelines.md#trigger-a-pipeline-when-an-upstream-project-is-rebuilt)
- [Pipeline subscriptions](../../../ci/pipelines/index.md#trigger-a-pipeline-when-an-upstream-project-is-rebuilt)
and [test cases](../../../ci/test_cases/index.md) are deleted.
## Delete a project

View File

@ -99,3 +99,21 @@ To delete a task:
1. In the issue description, in the **Tasks** section, select the task you want to edit.
1. In the task window, in the options menu (**{ellipsis_v}**), select **Delete task**.
1. Select **OK**.
## Set task weight **PREMIUM**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/362550) in GitLab 15.3.
Prerequisites:
- You must have at least the Reporter role for the project.
You can set weight on each task to show how much work it needs.
This value is visible only when you view a task.
To set issue weight of a task:
1. In the issue description, in the **Tasks** section, select the title of the task you want to edit.
The task window opens.
1. Next to **Weight**, enter a whole, positive number.
1. Select the close icon (**{close}**).

View File

@ -146,7 +146,8 @@ module API
branch = find_branch!(params[:branch])
protected_branch = user_project.protected_branches.find_by(name: branch.name)
protected_branch&.destroy
::ProtectedBranches::DestroyService.new(user_project, current_user).execute(protected_branch) if protected_branch
present branch, with: Entities::Branch, current_user: current_user, project: user_project
end

View File

@ -149,6 +149,10 @@ module Gitlab
severity_mapping.fetch(severity_raw.to_s.downcase, UNMAPPED_SEVERITY)
end
def source
monitoring_tool || integration&.name
end
private
def plain_gitlab_fingerprint

View File

@ -6,6 +6,7 @@ module Gitlab
module Payload
class Generic < Base
DEFAULT_TITLE = 'New: Alert'
DEFAULT_SOURCE = 'Generic Alert Endpoint'
attribute :description, paths: 'description'
attribute :ends_at, paths: 'end_time', type: :time
@ -22,6 +23,14 @@ module Gitlab
attribute :plain_gitlab_fingerprint, paths: 'fingerprint'
private :plain_gitlab_fingerprint
def resolved?
ends_at.present?
end
def source
super || DEFAULT_SOURCE
end
end
end
end

View File

@ -44414,9 +44414,6 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
msgid "WorkItem|Add"
msgstr ""
@ -44476,7 +44473,7 @@ msgstr ""
msgid "WorkItem|Issue"
msgstr ""
msgid "WorkItem|Learn about tasks"
msgid "WorkItem|Learn about tasks."
msgstr ""
msgid "WorkItem|No tasks are currently assigned. Use tasks to break down this issue into smaller parts."
@ -44554,15 +44551,15 @@ msgstr ""
msgid "WorkItem|Undo"
msgstr ""
msgid "WorkItem|Use tasks to break down your work in an issue into smaller pieces. %{learnMoreLink}"
msgstr ""
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
msgid "WorkItem|work items"
msgstr ""
msgid "Would you like to create a new branch?"
msgstr ""

View File

@ -62,6 +62,7 @@
"@tiptap/core": "^2.0.0-beta.182",
"@tiptap/extension-blockquote": "^2.0.0-beta.29",
"@tiptap/extension-bold": "^2.0.0-beta.28",
"@tiptap/extension-bubble-menu": "^2.0.0-beta.61",
"@tiptap/extension-bullet-list": "^2.0.0-beta.29",
"@tiptap/extension-code": "^2.0.0-beta.28",
"@tiptap/extension-code-block-lowlight": "2.0.0-beta.73",

View File

@ -51,7 +51,8 @@ RSpec.describe "Help Dropdown", :js do
visit root_path
end
it 'renders correct version badge variant' do
it 'renders correct version badge variant',
quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/369850' do
page.within '.header-help' do
find('.header-help-dropdown-toggle').click

View File

@ -0,0 +1,47 @@
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import addBlameLink from '~/blob/blob_blame_link';
describe('Blob links', () => {
const mouseoverEvent = new MouseEvent('mouseover', {
view: window,
bubbles: true,
cancelable: true,
});
beforeEach(() => {
setHTMLFixture(`
<div id="blob-content-holder">
<div class="line-numbers" data-blame-path="/blamePath">
<a id="L5" href="#L5" data-line-number="5" class="file-line-num js-line-links">5</a>
</div>
<pre id="LC5">Line 5 content</pre>
</div>
`);
addBlameLink('#blob-content-holder', 'js-line-links');
document.querySelector('.file-line-num').dispatchEvent(mouseoverEvent);
});
afterEach(() => {
resetHTMLFixture();
});
it('adds wrapper elements with correct classes', () => {
const wrapper = document.querySelector('.line-links');
expect(wrapper).toBeTruthy();
expect(wrapper.classList).toContain('diff-line-num');
});
it('adds blame link with correct classes and path', () => {
const blameLink = document.querySelector('.file-line-blame');
expect(blameLink).toBeTruthy();
expect(blameLink.getAttribute('href')).toBe('/blamePath#L5');
});
it('adds line link within wraper with correct classes and path', () => {
const lineLink = document.querySelector('.file-line-num');
expect(lineLink).toBeTruthy();
expect(lineLink.getAttribute('href')).toBe('#L5');
});
});

View File

@ -15,7 +15,7 @@ describe('Blob links Tracking', () => {
beforeEach(() => {
setHTMLFixture(`
<div id="blob-content-holder">
<div class="file-holder">
<div class="line-links diff-line-num">
<a href="#L5" class="file-line-blame"></a>
<a id="L5" href="#L5" data-line-number="5" class="file-line-num">5</a>
@ -23,7 +23,7 @@ describe('Blob links Tracking', () => {
<pre id="LC5">Line 5 content</pre>
</div>
`);
addBlobLinksTracking('#blob-content-holder', eventsToTrack);
addBlobLinksTracking();
jest.spyOn(Tracking, 'event');
});

View File

@ -4,8 +4,7 @@ import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_position.vue';
import { createStore } from '~/boards/stores';
import { mockList, mockIssue2 } from 'jest/boards/mock_data';
import { mockList, mockIssue2, mockIssue, mockIssue3, mockIssue4 } from 'jest/boards/mock_data';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
Vue.use(Vuex);
@ -21,7 +20,26 @@ describe('Board Card Move to position', () => {
let store;
let dispatch;
store = new Vuex.Store();
const createStoreOptions = () => {
const state = {
pageInfoByListId: {
'gid://gitlab/List/1': {},
'gid://gitlab/List/2': { hasNextPage: true },
},
};
const getters = {
getBoardItemsByList: () => () => [mockIssue, mockIssue2, mockIssue3, mockIssue4],
};
const actions = {
moveItem: jest.fn(),
};
return {
state,
getters,
actions,
};
};
const createComponent = (propsData) => {
wrapper = shallowMountExtended(BoardCardMoveToPosition, {
@ -40,7 +58,7 @@ describe('Board Card Move to position', () => {
};
beforeEach(() => {
store = createStore();
store = new Vuex.Store(createStoreOptions());
createComponent();
});
@ -62,13 +80,26 @@ describe('Board Card Move to position', () => {
it('is opened on the click of vertical ellipsis and has 2 dropdown items when number of list items < 10', () => {
findMoveToPositionDropdown().vm.$emit('click');
expect(findDropdownItems()).toHaveLength(dropdownOptions.length);
});
it('is opened on the click of vertical ellipsis and has 1 dropdown items when number of list items > 10', () => {
wrapper.destroy();
createComponent({
list: {
...mockList,
id: 'gid://gitlab/List/2',
},
});
findMoveToPositionDropdown().vm.$emit('click');
expect(findDropdownItems()).toHaveLength(1);
});
});
describe('Dropdown options', () => {
beforeEach(() => {
createComponent({ index: 1 });
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
dispatch = jest.spyOn(store, 'dispatch').mockImplementation(() => {});
});
@ -78,12 +109,12 @@ describe('Board Card Move to position', () => {
});
it.each`
dropdownIndex | dropdownLabel | startActionCalledTimes | trackLabel
${0} | ${BoardCardMoveToPosition.i18n.moveToStartText} | ${0} | ${'move_to_start'}
${1} | ${BoardCardMoveToPosition.i18n.moveToEndText} | ${1} | ${'move_to_end'}
dropdownIndex | dropdownLabel | trackLabel | moveAfterId | moveBeforeId
${0} | ${BoardCardMoveToPosition.i18n.moveToStartText} | ${'move_to_start'} | ${mockIssue.id} | ${undefined}
${1} | ${BoardCardMoveToPosition.i18n.moveToEndText} | ${'move_to_end'} | ${undefined} | ${mockIssue4.id}
`(
'on click of dropdown index $dropdownIndex with label $dropdownLabel should call moveItem action with tracking label $trackLabel',
async ({ dropdownIndex, startActionCalledTimes, dropdownLabel, trackLabel }) => {
async ({ dropdownIndex, dropdownLabel, trackLabel, moveAfterId, moveBeforeId }) => {
await findEllipsesButton().vm.$emit('click');
expect(findDropdownItemAtIndex(dropdownIndex).text()).toBe(dropdownLabel);
@ -98,18 +129,15 @@ describe('Board Card Move to position', () => {
label: trackLabel,
property: 'type_card',
});
expect(dispatch).toHaveBeenCalledTimes(startActionCalledTimes);
if (startActionCalledTimes) {
expect(dispatch).toHaveBeenCalledWith('moveItem', {
fromListId: mockList.id,
itemId: mockIssue2.id,
itemIid: mockIssue2.iid,
itemPath: mockIssue2.referencePath,
moveBeforeId: undefined,
moveAfterId: undefined,
toListId: mockList.id,
});
}
expect(dispatch).toHaveBeenCalledWith('moveItem', {
fromListId: mockList.id,
itemId: mockIssue2.id,
itemIid: mockIssue2.iid,
itemPath: mockIssue2.referencePath,
moveBeforeId,
moveAfterId,
toListId: mockList.id,
});
},
);
});

View File

@ -0,0 +1,126 @@
import { BubbleMenuPlugin } from '@tiptap/extension-bubble-menu';
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import BubbleMenu from '~/content_editor/components/bubble_menus/bubble_menu.vue';
import { createTestEditor } from '../../test_utils';
jest.mock('@tiptap/extension-bubble-menu');
describe('content_editor/components/bubble_menus/bubble_menu', () => {
let wrapper;
let tiptapEditor;
const pluginKey = 'key';
const shouldShow = jest.fn();
const tippyOptions = { placement: 'bottom' };
const pluginInitializationResult = {};
const buildEditor = () => {
tiptapEditor = createTestEditor();
};
const createWrapper = (propsData = {}) => {
wrapper = shallowMountExtended(BubbleMenu, {
provide: {
tiptapEditor,
},
propsData: {
pluginKey,
shouldShow,
tippyOptions,
...propsData,
},
slots: {
default: '<div>menu content</div>',
},
});
};
const setupMocks = () => {
BubbleMenuPlugin.mockReturnValueOnce(pluginInitializationResult);
jest.spyOn(tiptapEditor, 'registerPlugin').mockImplementationOnce(() => true);
};
const invokeTippyEvent = (eventName, eventArgs) => {
const pluginConfig = BubbleMenuPlugin.mock.calls[0][0];
pluginConfig.tippyOptions[eventName](eventArgs);
};
beforeEach(() => {
buildEditor();
setupMocks();
});
afterEach(() => {
wrapper.destroy();
});
it('initializes BubbleMenuPlugin', async () => {
createWrapper({});
await nextTick();
expect(BubbleMenuPlugin).toHaveBeenCalledWith({
pluginKey,
editor: tiptapEditor,
shouldShow,
element: wrapper.vm.$el,
tippyOptions: expect.objectContaining({
onHidden: expect.any(Function),
onShow: expect.any(Function),
...tippyOptions,
}),
});
expect(tiptapEditor.registerPlugin).toHaveBeenCalledWith(pluginInitializationResult);
});
it('does not render default slot by default', async () => {
createWrapper({});
await nextTick();
expect(wrapper.text()).not.toContain('menu content');
});
describe('when onShow event handler is invoked', () => {
const onShowArgs = {};
beforeEach(async () => {
createWrapper({});
await nextTick();
invokeTippyEvent('onShow', onShowArgs);
});
it('displays the menu content', () => {
expect(wrapper.text()).toContain('menu content');
});
it('emits show event', () => {
expect(wrapper.emitted('show')).toEqual([[onShowArgs]]);
});
});
describe('when onHidden event handler is invoked', () => {
const onHiddenArgs = {};
beforeEach(async () => {
createWrapper({});
await nextTick();
invokeTippyEvent('onShow', onHiddenArgs);
invokeTippyEvent('onHidden', onHiddenArgs);
});
it('displays the menu content', () => {
expect(wrapper.text()).not.toContain('menu content');
});
it('emits show event', () => {
expect(wrapper.emitted('hidden')).toEqual([[onHiddenArgs]]);
});
});
});

View File

@ -1,4 +1,3 @@
import { BubbleMenu } from '@tiptap/vue-2';
import {
GlDropdown,
GlDropdownForm,
@ -11,6 +10,7 @@ import { mountExtended } from 'helpers/vue_test_utils_helper';
import { stubComponent } from 'helpers/stub_component';
import CodeBlockBubbleMenu from '~/content_editor/components/bubble_menus/code_block_bubble_menu.vue';
import eventHubFactory from '~/helpers/event_hub_factory';
import BubbleMenu from '~/content_editor/components/bubble_menus/bubble_menu.vue';
import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight';
import Diagram from '~/content_editor/extensions/diagram';
import codeBlockLanguageLoader from '~/content_editor/services/code_block_language_loader';
@ -40,6 +40,7 @@ describe('content_editor/components/bubble_menus/code_block_bubble_menu', () =>
},
stubs: {
GlDropdownItem: stubComponent(GlDropdownItem),
BubbleMenu: stubComponent(BubbleMenu),
},
});
};
@ -73,7 +74,6 @@ describe('content_editor/components/bubble_menus/code_block_bubble_menu', () =>
await emitEditorEvent({ event: 'transaction', tiptapEditor });
expect(bubbleMenu.props('editor')).toBe(tiptapEditor);
expect(bubbleMenu.classes()).toEqual(['gl-shadow', 'gl-rounded-base', 'gl-bg-white']);
});

View File

@ -1,7 +1,8 @@
import { BubbleMenu } from '@tiptap/vue-2';
import { mockTracking } from 'helpers/tracking_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import FormattingBubbleMenu from '~/content_editor/components/bubble_menus/formatting_bubble_menu.vue';
import BubbleMenu from '~/content_editor/components/bubble_menus/bubble_menu.vue';
import { stubComponent } from 'helpers/stub_component';
import {
BUBBLE_MENU_TRACKING_ACTION,
@ -25,6 +26,9 @@ describe('content_editor/components/bubble_menus/formatting_bubble_menu', () =>
provide: {
tiptapEditor,
},
stubs: {
BubbleMenu: stubComponent(BubbleMenu),
},
});
};
@ -41,7 +45,6 @@ describe('content_editor/components/bubble_menus/formatting_bubble_menu', () =>
buildWrapper();
const bubbleMenu = wrapper.findComponent(BubbleMenu);
expect(bubbleMenu.props().editor).toBe(tiptapEditor);
expect(bubbleMenu.classes()).toEqual(['gl-shadow', 'gl-rounded-base', 'gl-bg-white']);
});

View File

@ -1,8 +1,9 @@
import { GlLink, GlForm } from '@gitlab/ui';
import { BubbleMenu } from '@tiptap/vue-2';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import LinkBubbleMenu from '~/content_editor/components/bubble_menus/link_bubble_menu.vue';
import eventHubFactory from '~/helpers/event_hub_factory';
import BubbleMenu from '~/content_editor/components/bubble_menus/bubble_menu.vue';
import { stubComponent } from 'helpers/stub_component';
import Link from '~/content_editor/extensions/link';
import { createTestEditor, emitEditorEvent } from '../../test_utils';
@ -28,6 +29,9 @@ describe('content_editor/components/bubble_menus/link_bubble_menu', () => {
contentEditor,
eventHub,
},
stubs: {
BubbleMenu: stubComponent(BubbleMenu),
},
});
};
@ -60,7 +64,6 @@ describe('content_editor/components/bubble_menus/link_bubble_menu', () => {
});
it('renders bubble menu component', async () => {
expect(bubbleMenu.props('editor')).toBe(tiptapEditor);
expect(bubbleMenu.classes()).toEqual(['gl-shadow', 'gl-rounded-base', 'gl-bg-white']);
});
@ -157,19 +160,6 @@ describe('content_editor/components/bubble_menus/link_bubble_menu', () => {
expect(to).toBe(18);
});
it('shows the copy/edit/remove link buttons again if selection changes to another non-link and then back again to a link', async () => {
expectLinkButtonsToExist(false);
tiptapEditor.commands.setTextSelection(3);
await emitEditorEvent({ event: 'transaction', tiptapEditor });
tiptapEditor.commands.setTextSelection(14);
await emitEditorEvent({ event: 'transaction', tiptapEditor });
expectLinkButtonsToExist(true);
expect(wrapper.findComponent(GlForm).exists()).toBe(false);
});
describe('after making changes in the form and clicking apply', () => {
beforeEach(async () => {
linkHrefInput.setValue('https://google.com');

View File

@ -1,7 +1,8 @@
import { GlLink, GlForm } from '@gitlab/ui';
import { BubbleMenu } from '@tiptap/vue-2';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import BubbleMenu from '~/content_editor/components/bubble_menus/bubble_menu.vue';
import MediaBubbleMenu from '~/content_editor/components/bubble_menus/media_bubble_menu.vue';
import { stubComponent } from 'helpers/stub_component';
import eventHubFactory from '~/helpers/event_hub_factory';
import Image from '~/content_editor/extensions/image';
import Audio from '~/content_editor/extensions/audio';
@ -54,6 +55,9 @@ describe.each`
contentEditor,
eventHub,
},
stubs: {
BubbleMenu: stubComponent(BubbleMenu),
},
});
};
@ -94,7 +98,6 @@ describe.each`
});
it('renders bubble menu component', async () => {
expect(bubbleMenu.props('editor')).toBe(tiptapEditor);
expect(bubbleMenu.classes()).toEqual(['gl-shadow', 'gl-rounded-base', 'gl-bg-white']);
});

View File

@ -110,7 +110,7 @@ describe('Merge request widget rebase component', () => {
expect(findRebaseMessageText()).toContain('Something went wrong!');
});
describe('Rebase buttons with', () => {
describe('Rebase buttons', () => {
beforeEach(() => {
createWrapper(
{
@ -148,6 +148,79 @@ describe('Merge request widget rebase component', () => {
expect(rebaseMock).toHaveBeenCalledWith({ skipCi: true });
});
});
describe('Rebase when pipelines must succeed is enabled', () => {
beforeEach(() => {
createWrapper(
{
mr: {
rebaseInProgress: false,
canPushToSourceBranch: true,
onlyAllowMergeIfPipelineSucceeds: true,
},
service: {
rebase: rebaseMock,
poll: pollMock,
},
},
mergeRequestWidgetGraphql,
);
});
it('renders only the rebase button', () => {
expect(findRebaseWithoutCiButton().exists()).toBe(false);
expect(findStandardRebaseButton().exists()).toBe(true);
});
it('starts the rebase when clicking', async () => {
findStandardRebaseButton().vm.$emit('click');
await nextTick();
expect(rebaseMock).toHaveBeenCalledWith({ skipCi: false });
});
});
describe('Rebase when pipelines must succeed and skipped pipelines are considered successful are enabled', () => {
beforeEach(() => {
createWrapper(
{
mr: {
rebaseInProgress: false,
canPushToSourceBranch: true,
onlyAllowMergeIfPipelineSucceeds: true,
allowMergeOnSkippedPipeline: true,
},
service: {
rebase: rebaseMock,
poll: pollMock,
},
},
mergeRequestWidgetGraphql,
);
});
it('renders both rebase buttons', () => {
expect(findRebaseWithoutCiButton().exists()).toBe(true);
expect(findStandardRebaseButton().exists()).toBe(true);
});
it('starts the rebase when clicking', async () => {
findStandardRebaseButton().vm.$emit('click');
await nextTick();
expect(rebaseMock).toHaveBeenCalledWith({ skipCi: false });
});
it('starts the CI-skipping rebase when clicking on "Rebase without CI"', async () => {
findRebaseWithoutCiButton().vm.$emit('click');
await nextTick();
expect(rebaseMock).toHaveBeenCalledWith({ skipCi: true });
});
});
});
describe('without permissions', () => {

View File

@ -8,7 +8,6 @@ const createComponent = () => mount(WorkItemInformation);
describe('Work item information alert', () => {
let wrapper;
const tasksHelpPath = helpPagePath('user/tasks');
const workItemsHelpPath = helpPagePath('development/work_items');
const findAlert = () => wrapper.findComponent(GlAlert);
const findHelpLink = () => wrapper.findComponent(GlLink);
@ -33,16 +32,12 @@ describe('Work item information alert', () => {
expect(findAlert().props('variant')).toBe('tip');
});
it('should have the correct text for primary button and link', () => {
it('should have the correct text for title', () => {
expect(findAlert().props('title')).toBe(WorkItemInformation.i18n.tasksInformationTitle);
expect(findAlert().props('primaryButtonText')).toBe(
WorkItemInformation.i18n.learnTasksButtonText,
);
expect(findAlert().props('primaryButtonLink')).toBe(tasksHelpPath);
});
it('should have the correct link to work item link', () => {
expect(findHelpLink().exists()).toBe(true);
expect(findHelpLink().attributes('href')).toBe(workItemsHelpPath);
expect(findHelpLink().attributes('href')).toBe(tasksHelpPath);
});
});

View File

@ -347,4 +347,26 @@ RSpec.describe Gitlab::AlertManagement::Payload::Base do
it { is_expected.to be(true) }
end
describe '#source' do
subject { parsed_payload.source }
it { is_expected.to be_nil }
context 'with alerting integration provided' do
before do
parsed_payload.integration = instance_double('::AlertManagement::HttpIntegration', name: 'INTEGRATION')
end
it { is_expected.to eq('INTEGRATION') }
end
context 'with monitoring tool defined in the raw payload' do
before do
allow(parsed_payload).to receive(:monitoring_tool).and_return('TOOL')
end
it { is_expected.to eq('TOOL') }
end
end
end

View File

@ -144,4 +144,40 @@ RSpec.describe Gitlab::AlertManagement::Payload::Generic do
it { is_expected.to eq(value) }
end
end
describe '#resolved?' do
subject { parsed_payload.resolved? }
context 'without end time' do
it { is_expected.to eq(false) }
end
context 'with end time' do
let(:raw_payload) { { 'end_time' => Time.current.to_s } }
it { is_expected.to eq(true) }
end
end
describe '#source' do
subject { parsed_payload.source }
it { is_expected.to eq('Generic Alert Endpoint') }
context 'with alerting integration provided' do
before do
parsed_payload.integration = instance_double('::AlertManagement::HttpIntegration', name: 'INTEGRATION')
end
it { is_expected.to eq('INTEGRATION') }
end
context 'with monitoring tool defined in the raw payload' do
before do
allow(parsed_payload).to receive(:monitoring_tool).and_return('TOOL')
end
it { is_expected.to eq('TOOL') }
end
end
end

View File

@ -50,8 +50,8 @@ RSpec.describe Gitlab::BackgroundMigration::RenameTaskSystemNoteToChecklistItem
let(:migration) do
described_class.new(
start_id: note1.id,
end_id: note4.id,
start_id: metadata1.id,
end_id: metadata4.id,
batch_table: :system_note_metadata,
batch_column: :id,
sub_batch_size: 2,

View File

@ -586,13 +586,36 @@ RSpec.describe API::Branches do
let(:route) { "/projects/#{project_id}/repository/branches/#{branch_name}/unprotect" }
shared_examples_for 'repository unprotected branch' do
it 'unprotects a single branch' do
put api(route, current_user)
context 'when branch is protected' do
let!(:protected_branch) { create(:protected_branch, project: project, name: protected_branch_name) }
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/branch')
expect(json_response['name']).to eq(CGI.unescape(branch_name))
expect(json_response['protected']).to eq(false)
it 'unprotects a single branch' do
expect_next_instance_of(::ProtectedBranches::DestroyService, project, current_user) do |instance|
expect(instance).to receive(:execute).with(protected_branch).and_call_original
end
put api(route, current_user)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/branch')
expect(json_response['name']).to eq(CGI.unescape(branch_name))
expect(json_response['protected']).to eq(false)
expect { protected_branch.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
end
context 'when branch is not protected' do
it 'returns a single branch response' do
expect(::ProtectedBranches::DestroyService).not_to receive(:new)
put api(route, current_user)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/branch')
expect(json_response['name']).to eq(CGI.unescape(branch_name))
expect(json_response['protected']).to eq(false)
end
end
context 'when branch does not exist' do
@ -637,8 +660,34 @@ RSpec.describe API::Branches do
context 'when authenticated', 'as a maintainer' do
let(:current_user) { user }
let(:protected_branch_name) { branch_name }
it_behaves_like 'repository unprotected branch'
context 'when branch contains a dot' do
let(:branch_name) { branch_with_dot }
it_behaves_like 'repository unprotected branch'
end
context 'when branch contains a slash' do
let(:branch_name) { branch_with_slash }
it_behaves_like '404 response' do
let(:request) { put api(route, current_user) }
end
end
context 'when branch contains an escaped slash' do
let(:branch_name) { CGI.escape(branch_with_slash) }
let(:protected_branch_name) { branch_with_slash }
it_behaves_like 'repository unprotected branch'
end
context 'requesting with the escaped project full path' do
let(:project_id) { CGI.escape(project.full_path) }
context "when a protected branch doesn't already exist" do
it_behaves_like 'repository unprotected branch'
context 'when branch contains a dot' do
@ -646,32 +695,6 @@ RSpec.describe API::Branches do
it_behaves_like 'repository unprotected branch'
end
context 'when branch contains a slash' do
let(:branch_name) { branch_with_slash }
it_behaves_like '404 response' do
let(:request) { put api(route, current_user) }
end
end
context 'when branch contains an escaped slash' do
let(:branch_name) { CGI.escape(branch_with_slash) }
it_behaves_like 'repository unprotected branch'
end
context 'requesting with the escaped project full path' do
let(:project_id) { CGI.escape(project.full_path) }
it_behaves_like 'repository unprotected branch'
context 'when branch contains a dot' do
let(:branch_name) { branch_with_dot }
it_behaves_like 'repository unprotected branch'
end
end
end
end
end

View File

@ -73,6 +73,10 @@ RSpec.shared_examples 'graphql query for searching issuables' do
resolve_issuables(search: 'created')
end
end
it 'does not return error if search term is not present' do
expect(resolve_issuables).not_to be_instance_of(Gitlab::Graphql::Errors::ArgumentError)
end
end
context 'with disable_anonymous_search as `false`' do

View File

@ -23,12 +23,10 @@ RSpec.shared_examples 'creates an alert management alert or errors' do
end
context 'and fails to save' do
let(:errors) { double(messages: { hosts: ['hosts array is over 255 chars'] }, '[]': [] ) }
before do
allow(service).to receive(:alert).and_call_original
allow(service).to receive_message_chain(:alert, :save).and_return(false)
allow(service).to receive_message_chain(:alert, :errors).and_return(errors)
allow(AlertManagement::Alert).to receive(:new).and_wrap_original do |m, **args|
m.call(**args, hosts: ['a' * 256]) # hosts should be 255
end
end
it_behaves_like 'alerts service responds with an error', :bad_request