Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
3f7e1004e7
commit
219623e82f
|
|
@ -262,12 +262,6 @@ export default {
|
|||
'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue',
|
||||
'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue',
|
||||
'app/assets/javascripts/vue_merge_request_widget/components/state_container.vue',
|
||||
'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue',
|
||||
'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue',
|
||||
'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue',
|
||||
'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue',
|
||||
'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue',
|
||||
'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue',
|
||||
'app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue',
|
||||
'app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue',
|
||||
'app/assets/javascripts/vue_merge_request_widget/widgets/accessibility/index.vue',
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
da219155e5f13896b0427c536e5ff169b95ec558
|
||||
fb8fb7e475bc3693f1e45875d266c73d450fe58f
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
import ClipboardJS from 'clipboard';
|
||||
import toast from '~/vue_shared/plugins/global_toast';
|
||||
import { getSelectedFragment } from '~/lib/utils/common_utils';
|
||||
import { isElementVisible } from '~/lib/utils/dom_utils';
|
||||
import { s__ } from '~/locale';
|
||||
import { DEBOUNCE_DROPDOWN_DELAY } from '~/sidebar/components/labels/labels_select_widget/constants';
|
||||
import { CopyAsGFM } from '../markdown/copy_as_gfm';
|
||||
import {
|
||||
ISSUE_MR_CHANGE_ASSIGNEE,
|
||||
ISSUE_MR_CHANGE_MILESTONE,
|
||||
ISSUABLE_CHANGE_LABEL,
|
||||
ISSUABLE_EDIT_DESCRIPTION,
|
||||
ISSUABLE_COPY_REF,
|
||||
ISSUABLE_COMMENT_OR_REPLY,
|
||||
WORK_ITEM_TOGGLE_SIDEBAR,
|
||||
} from './keybindings';
|
||||
|
||||
|
|
@ -33,7 +29,6 @@ export default class ShortcutsWorkItem {
|
|||
[ISSUABLE_EDIT_DESCRIPTION, ShortcutsWorkItem.editDescription],
|
||||
[WORK_ITEM_TOGGLE_SIDEBAR, ShortcutsWorkItem.toggleSidebar],
|
||||
[ISSUABLE_COPY_REF, () => this.copyReference()],
|
||||
[ISSUABLE_COMMENT_OR_REPLY, ShortcutsWorkItem.replyWithSelectedText],
|
||||
]);
|
||||
|
||||
/**
|
||||
|
|
@ -106,84 +101,4 @@ export default class ShortcutsWorkItem {
|
|||
this.refInMemoryButton.dispatchEvent(new CustomEvent('click'));
|
||||
}
|
||||
}
|
||||
|
||||
static replyWithSelectedText() {
|
||||
const gfmSelector = '.js-vue-markdown-field .js-gfm-input';
|
||||
let replyField =
|
||||
document.querySelector(`.gl-drawer ${gfmSelector}`) ||
|
||||
document.querySelector(`.modal ${gfmSelector}`) ||
|
||||
document.querySelector(gfmSelector);
|
||||
|
||||
// Ensure that markdown input is still present in the DOM
|
||||
// otherwise fall back to main comment input field.
|
||||
if (
|
||||
ShortcutsWorkItem.lastFocusedReplyField &&
|
||||
isElementVisible(ShortcutsWorkItem.lastFocusedReplyField)
|
||||
) {
|
||||
replyField = ShortcutsWorkItem.lastFocusedReplyField;
|
||||
}
|
||||
|
||||
if (!replyField || !isElementVisible(replyField)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const documentFragment = getSelectedFragment(document.querySelector('#content-body'));
|
||||
|
||||
if (!documentFragment) {
|
||||
replyField.focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sanity check: Make sure the selected text comes from a discussion : it can either contain a message...
|
||||
let foundMessage = Boolean(documentFragment.querySelector('.md'));
|
||||
|
||||
// ... Or come from a message
|
||||
if (!foundMessage) {
|
||||
if (documentFragment.originalNodes) {
|
||||
documentFragment.originalNodes.forEach((e) => {
|
||||
let node = e;
|
||||
do {
|
||||
// Text nodes don't define the `matches` method
|
||||
if (node.matches && node.matches('.md')) {
|
||||
foundMessage = true;
|
||||
}
|
||||
node = node.parentNode;
|
||||
} while (node && !foundMessage);
|
||||
});
|
||||
}
|
||||
|
||||
// If there is no message, just select the reply field
|
||||
if (!foundMessage) {
|
||||
replyField.focus();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const el = CopyAsGFM.transformGFMSelection(documentFragment.cloneNode(true));
|
||||
const blockquoteEl = document.createElement('blockquote');
|
||||
blockquoteEl.appendChild(el);
|
||||
CopyAsGFM.nodeToGFM(blockquoteEl)
|
||||
.then((text) => {
|
||||
if (text.trim() === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If replyField already has some content, add a newline before our quote
|
||||
const separator = (replyField.value.trim() !== '' && '\n\n') || '';
|
||||
replyField.value = `${replyField.value}${separator}${text}\n\n`;
|
||||
|
||||
// Trigger autosize
|
||||
const event = document.createEvent('Event');
|
||||
event.initEvent('autosize:update', true, false);
|
||||
replyField.dispatchEvent(event);
|
||||
|
||||
// Focus the input field
|
||||
replyField.focus();
|
||||
|
||||
return false;
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,6 @@ export default {
|
|||
BoldText,
|
||||
StateContainer,
|
||||
},
|
||||
props: {
|
||||
mr: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,8 @@ import { GlSkeletonLoader, GlSprintf } from '@gitlab/ui';
|
|||
import autoMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/auto_merge';
|
||||
import autoMergeEnabledQuery from 'ee_else_ce/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql';
|
||||
import { createAlert } from '~/alert';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import { fetchPolicies } from '~/lib/graphql';
|
||||
import { __ } from '~/locale';
|
||||
import { AUTO_MERGE_STRATEGIES } from '../../constants';
|
||||
import eventHub from '../../event_hub';
|
||||
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
|
||||
import MrWidgetAuthor from '../mr_widget_author.vue';
|
||||
|
|
@ -45,30 +43,12 @@ export default {
|
|||
return {
|
||||
state: null,
|
||||
isCancellingAutoMerge: false,
|
||||
isRemovingSourceBranch: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
loading() {
|
||||
return this.$apollo.queries.state.loading || !this.state;
|
||||
},
|
||||
stateRemoveSourceBranch() {
|
||||
if (!this.state.mergeRequest.shouldRemoveSourceBranch) return false;
|
||||
|
||||
return (
|
||||
this.state.mergeRequest.shouldRemoveSourceBranch ||
|
||||
this.state.mergeRequest.forceRemoveSourceBranch
|
||||
);
|
||||
},
|
||||
canRemoveSourceBranch() {
|
||||
const { currentUserId } = this.mr;
|
||||
const mergeUserId = getIdFromGraphQLId(this.state.mergeRequest.mergeUser?.id);
|
||||
const canRemoveSourceBranch = this.state.mergeRequest.userPermissions.removeSourceBranch;
|
||||
|
||||
return (
|
||||
!this.stateRemoveSourceBranch && canRemoveSourceBranch && mergeUserId === currentUserId
|
||||
);
|
||||
},
|
||||
actions() {
|
||||
const actions = [];
|
||||
|
||||
|
|
@ -105,32 +85,6 @@ export default {
|
|||
});
|
||||
});
|
||||
},
|
||||
removeSourceBranch() {
|
||||
const options = {
|
||||
sha: this.mr.sha,
|
||||
auto_merge_strategy: this.state.mergeRequest.autoMergeStrategy,
|
||||
should_remove_source_branch: true,
|
||||
};
|
||||
|
||||
this.isRemovingSourceBranch = true;
|
||||
this.service
|
||||
.merge(options)
|
||||
.then((res) => res.data)
|
||||
.then((data) => {
|
||||
if (AUTO_MERGE_STRATEGIES.includes(data.status)) {
|
||||
eventHub.$emit('MRWidgetUpdateRequested');
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
this.$apollo.queries.state.refetch();
|
||||
})
|
||||
.catch(() => {
|
||||
this.isRemovingSourceBranch = false;
|
||||
createAlert({
|
||||
message: __('Something went wrong. Please try again.'),
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ export default {
|
|||
},
|
||||
},
|
||||
props: {
|
||||
// eslint-disable-next-line vue/no-unused-properties -- `mr` is used in the `mergeRequestQueryVariables` computed property
|
||||
mr: {
|
||||
type: Object,
|
||||
required: true,
|
||||
|
|
|
|||
|
|
@ -6,12 +6,6 @@ export default {
|
|||
components: {
|
||||
StateContainer,
|
||||
},
|
||||
props: {
|
||||
mr: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -44,10 +44,6 @@ export default {
|
|||
!isRemovingSourceBranch
|
||||
);
|
||||
},
|
||||
shouldShowSourceBranchRemoving() {
|
||||
const { sourceBranchRemoved, isRemovingSourceBranch } = this.mr;
|
||||
return !sourceBranchRemoved && (isRemovingSourceBranch || this.isMakingRequest);
|
||||
},
|
||||
revertTitle() {
|
||||
return s__('mrWidget|Revert this merge request in a new merge request');
|
||||
},
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ export default {
|
|||
},
|
||||
mixins: [mergeRequestQueryVariablesMixin],
|
||||
apollo: {
|
||||
// `state` is used here to manage Apollo query result,
|
||||
state: {
|
||||
query: missingBranchQuery,
|
||||
variables() {
|
||||
|
|
@ -38,6 +39,7 @@ export default {
|
|||
},
|
||||
},
|
||||
data() {
|
||||
// eslint-disable-next-line vue/no-unused-properties -- `state` is tied to an Apollo query
|
||||
return { state: {} };
|
||||
},
|
||||
computed: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<li class="timeline-entry note-container-query-wrapper">
|
||||
<li class="js-timeline-entry timeline-entry note-container-query-wrapper">
|
||||
<div class="timeline-entry-inner"><slot></slot></div>
|
||||
</li>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -241,6 +241,12 @@ export default {
|
|||
// used to rerender work-item-comment-form so the text in the textarea is cleared
|
||||
return uniqueId(`work-item-add-note-${this.workItemId}-`);
|
||||
},
|
||||
// This method is called from parent components so we need
|
||||
// ignore linter here.
|
||||
// eslint-disable-next-line vue/no-unused-properties
|
||||
appendText(text) {
|
||||
this.$refs.commentForm.$refs.markdownEditor.append(text);
|
||||
},
|
||||
async updateWorkItem({ commentText, isNoteInternal = false }) {
|
||||
this.isSubmitting = true;
|
||||
this.$emit('replying', commentText);
|
||||
|
|
@ -378,6 +384,7 @@ export default {
|
|||
<work-item-comment-form
|
||||
v-if="isEditing"
|
||||
:key="addNoteKey"
|
||||
ref="commentForm"
|
||||
:work-item-type="workItemType"
|
||||
:aria-label="__('Add a reply')"
|
||||
:is-submitting="isSubmitting"
|
||||
|
|
|
|||
|
|
@ -365,6 +365,7 @@ export default {
|
|||
:noteable-type="workItemTypeKey"
|
||||
>
|
||||
<markdown-editor
|
||||
ref="markdownEditor"
|
||||
class="js-gfm-wrapper"
|
||||
:value="commentText"
|
||||
:render-markdown-path="markdownPreviewPath"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import { ASC } from '~/notes/constants';
|
||||
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
|
||||
import gfmEventHub from '~/vue_shared/components/markdown/eventhub';
|
||||
import toggleWorkItemNoteResolveDiscussion from '~/work_items/graphql/notes/toggle_work_item_note_resolve_discussion.mutation.graphql';
|
||||
import DiscussionNotesRepliesWrapper from '~/notes/components/discussion_notes_replies_wrapper.vue';
|
||||
import ToggleRepliesWidget from '~/notes/components/toggle_replies_widget.vue';
|
||||
|
|
@ -153,7 +154,31 @@ export default {
|
|||
deep: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
gfmEventHub.$on('quote-reply', this.handleQuoteReply);
|
||||
},
|
||||
beforeDestroy() {
|
||||
gfmEventHub.$off('quote-reply', this.handleQuoteReply);
|
||||
},
|
||||
methods: {
|
||||
handleQuoteReply({ event, discussionId, text }) {
|
||||
// Ensure we're using correct discussion block for reply form.
|
||||
if (this.note.discussion.id === discussionId) {
|
||||
// Prevent 'r' being written.
|
||||
if (event && typeof event.preventDefault === 'function') {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
// Show reply form if not open already.
|
||||
if (!this.showForm) this.showReplyForm();
|
||||
|
||||
// Wait for form rendering.
|
||||
this.$nextTick(() => {
|
||||
// We're using `append` method from ~/vue_shared/components/markdown/markdown_editor.vue
|
||||
this.$refs.addNote.appendText(text);
|
||||
});
|
||||
}
|
||||
},
|
||||
showReplyForm() {
|
||||
this.showForm = true;
|
||||
this.isExpanded = true;
|
||||
|
|
@ -340,6 +365,7 @@ export default {
|
|||
/>
|
||||
<work-item-add-note
|
||||
v-if="shouldShowReplyForm"
|
||||
ref="addNote"
|
||||
:notes-form="false"
|
||||
:autofocus="autofocus"
|
||||
:full-path="fullPath"
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ export default {
|
|||
<div
|
||||
v-else
|
||||
ref="description"
|
||||
class="work-item-description description md gl-relative gl-clearfix"
|
||||
class="js-work-item-description work-item-description description md gl-relative gl-clearfix"
|
||||
>
|
||||
<div
|
||||
ref="gfm-content"
|
||||
|
|
|
|||
|
|
@ -350,6 +350,9 @@ export default {
|
|||
hasBlockedWorkItemsFeature() {
|
||||
return this.workItem.userPermissions?.blockedWorkItems;
|
||||
},
|
||||
canCreateNote() {
|
||||
return this.workItem.userPermissions?.createNote;
|
||||
},
|
||||
isDiscussionLocked() {
|
||||
return this.workItemNotes?.discussionLocked;
|
||||
},
|
||||
|
|
@ -1255,6 +1258,7 @@ export default {
|
|||
:assignees="workItemAssignees && workItemAssignees.assignees.nodes"
|
||||
:can-set-work-item-metadata="canAssignUnassignUser"
|
||||
:can-summarize-comments="canSummarizeComments"
|
||||
:can-create-note="canCreateNote"
|
||||
:is-discussion-locked="isDiscussionLocked"
|
||||
:is-work-item-confidential="workItem.confidential"
|
||||
:new-comment-template-paths="newCommentTemplatePaths"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,11 @@ import {
|
|||
TYPENAME_NOTE,
|
||||
TYPENAME_GROUP,
|
||||
} from '~/graphql_shared/constants';
|
||||
import { Mousetrap } from '~/lib/mousetrap';
|
||||
import { ISSUABLE_COMMENT_OR_REPLY, keysFor } from '~/behaviors/shortcuts/keybindings';
|
||||
import { CopyAsGFM } from '~/behaviors/markdown/copy_as_gfm';
|
||||
import SystemNote from '~/work_items/components/notes/system_note.vue';
|
||||
import gfmEventHub from '~/vue_shared/components/markdown/eventhub';
|
||||
import WorkItemNotesLoading from '~/work_items/components/notes/work_item_notes_loading.vue';
|
||||
import WorkItemNotesActivityHeader from '~/work_items/components/notes/work_item_notes_activity_header.vue';
|
||||
import {
|
||||
|
|
@ -92,6 +96,11 @@ export default {
|
|||
required: false,
|
||||
default: false,
|
||||
},
|
||||
canCreateNote: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
isDiscussionLocked: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
|
@ -267,6 +276,14 @@ export default {
|
|||
if (this.shouldLoadPreviewNote) {
|
||||
this.cleanupScrollListener = scrollToTargetOnResize();
|
||||
}
|
||||
if (this.canCreateNote) {
|
||||
Mousetrap.bind(keysFor(ISSUABLE_COMMENT_OR_REPLY), (e) => this.quoteReply(e));
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.canCreateNote) {
|
||||
Mousetrap.unbind(keysFor(ISSUABLE_COMMENT_OR_REPLY), this.quoteReply);
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
previewNote: {
|
||||
|
|
@ -368,6 +385,39 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
getDiscussionIdFromSelection() {
|
||||
const selection = window.getSelection();
|
||||
if (selection.rangeCount <= 0) return null;
|
||||
|
||||
// Return early if selection is from description, we need to use the top-level comment field.
|
||||
if (selection.anchorNode?.parentElement?.closest('.js-work-item-description')) return null;
|
||||
|
||||
const el = selection.getRangeAt(0).startContainer;
|
||||
const node = el.nodeType === Node.TEXT_NODE ? el.parentNode : el;
|
||||
return node.closest('.js-timeline-entry').getAttribute('discussion-id');
|
||||
},
|
||||
async quoteReply(e) {
|
||||
const discussionId = this.getDiscussionIdFromSelection();
|
||||
const text = await CopyAsGFM.selectionToGfm();
|
||||
|
||||
// Check if selection is coming from an existing discussion
|
||||
if (discussionId) {
|
||||
gfmEventHub.$emit('quote-reply', {
|
||||
discussionId,
|
||||
text,
|
||||
event: e,
|
||||
});
|
||||
} else {
|
||||
// Selection is from description, append it to top-level comment form,
|
||||
this.appendText(text);
|
||||
}
|
||||
},
|
||||
appendText(text) {
|
||||
// Based on selected sort order of discussion timeline,
|
||||
// we have to choose correct <work-item-add-note/> reference.
|
||||
// We're using `append` method from ~/vue_shared/components/markdown/markdown_editor.vue
|
||||
this.$refs[this.formAtTop ? 'addNoteTop' : 'addNoteBottom'].appendText(text);
|
||||
},
|
||||
getDiscussionKey(discussion) {
|
||||
// discussion key is important like this since after first comment changes
|
||||
const discussionId = discussion.notes.nodes[0].id;
|
||||
|
|
@ -474,6 +524,7 @@ export default {
|
|||
<div v-if="formAtTop && !commentsDisabled" class="js-comment-form">
|
||||
<ul class="notes notes-form timeline">
|
||||
<work-item-add-note
|
||||
ref="addNoteTop"
|
||||
v-bind="workItemCommentFormProps"
|
||||
:hide-fullscreen-markdown-button="hideFullscreenMarkdownButton"
|
||||
:is-group-work-item="isGroupWorkItem"
|
||||
|
|
@ -495,6 +546,7 @@ export default {
|
|||
<template v-else>
|
||||
<work-item-discussion
|
||||
:key="getDiscussionKey(discussion)"
|
||||
ref="workItemDiscussion"
|
||||
:discussion="discussion.notes.nodes"
|
||||
:full-path="fullPath"
|
||||
:work-item-id="workItemId"
|
||||
|
|
@ -526,6 +578,7 @@ export default {
|
|||
<div v-if="!formAtTop && !commentsDisabled" class="js-comment-form">
|
||||
<ul class="notes notes-form timeline">
|
||||
<work-item-add-note
|
||||
ref="addNoteBottom"
|
||||
v-bind="workItemCommentFormProps"
|
||||
:hide-fullscreen-markdown-button="hideFullscreenMarkdownButton"
|
||||
:is-group-work-item="isGroupWorkItem"
|
||||
|
|
|
|||
|
|
@ -49,9 +49,10 @@ module MergeRequests
|
|||
# Deleted branch
|
||||
next if Gitlab::Git.blank_ref?(changes[:newrev])
|
||||
|
||||
# Default branch
|
||||
branch_name = Gitlab::Git.branch_name(changes[:ref])
|
||||
next if branch_name == target_project.default_branch
|
||||
|
||||
# Skip default branch only if no target branch is specified
|
||||
next if branch_name == target_project.default_branch && !push_options[:target]
|
||||
|
||||
result[branch_name] = changes
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveAdjustIndicesReservedStorageBytesEventWorker < Gitlab::Database::Migration[2.2]
|
||||
milestone '18.0'
|
||||
disable_ddl_transaction!
|
||||
DEPRECATED_JOB_CLASSES = %w[Search::Zoekt::AdjustIndicesReservedStorageBytesEventWorker]
|
||||
|
||||
def up
|
||||
sidekiq_remove_jobs(job_klasses: DEPRECATED_JOB_CLASSES)
|
||||
end
|
||||
|
||||
def down; end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
21084a617043b364cdea06a6d60690a9334c07f35af948ed392ae24d9e17ae4e
|
||||
|
|
@ -237,7 +237,7 @@ repeatedly reports that some items never reach 100%,
|
|||
the following command helps to focus on the most common errors.
|
||||
|
||||
```shell
|
||||
jq --raw-output 'select(.severity == "ERROR") | [.project_path, .class, .message, .error] | @tsv' geo.log | sort | uniq -c | sort | tail
|
||||
jq --raw-output 'select(.severity == "ERROR") | [.class, .id, .message, .error] | @tsv' geo.log | sort | uniq -c | sort -n | tail
|
||||
```
|
||||
|
||||
Refer to our [Geo troubleshooting page](../geo/replication/troubleshooting/_index.md)
|
||||
|
|
|
|||
|
|
@ -436,10 +436,10 @@ Then customize the configuration:
|
|||
|
||||
```ruby
|
||||
# Lower minimum index size to 100 MB (default is 1GB)
|
||||
ApplicationSetting.current.update!(database_reindexing: { reindexing_minimum_index_size: 100.megabytes })
|
||||
Gitlab::Database::Reindexing.minimum_index_size!(100.megabytes)
|
||||
|
||||
# Change minimum bloat threshold to 30% (default is 20%, there is no benefit from setting it lower)
|
||||
ApplicationSetting.current.update!(database_reindexing: { reindexing_minimum_relative_bloat_size: 0.3 })
|
||||
Gitlab::Database::Reindexing.minimum_relative_bloat_size!(0.3)
|
||||
```
|
||||
|
||||
### Automated reindexing
|
||||
|
|
|
|||
|
|
@ -3366,8 +3366,8 @@ build_job:
|
|||
|
||||
#### `needs:pipeline:job`
|
||||
|
||||
A [child pipeline](../pipelines/downstream_pipelines.md#parent-child-pipelines) can download artifacts from a job in
|
||||
its parent pipeline or another child pipeline in the same parent-child pipeline hierarchy.
|
||||
A [child pipeline](../pipelines/downstream_pipelines.md#parent-child-pipelines) can download artifacts from a
|
||||
successfully finished job in its parent pipeline or another child pipeline in the same parent-child pipeline hierarchy.
|
||||
|
||||
**Keyword type**: Job keyword. You can use it only as part of a job.
|
||||
|
||||
|
|
@ -3381,6 +3381,10 @@ its parent pipeline or another child pipeline in the same parent-child pipeline
|
|||
- Parent pipeline (`.gitlab-ci.yml`):
|
||||
|
||||
```yaml
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
|
||||
create-artifact:
|
||||
stage: build
|
||||
script: echo "sample artifact" > artifact.txt
|
||||
|
|
@ -3410,6 +3414,8 @@ In this example, the `create-artifact` job in the parent pipeline creates some a
|
|||
The `child-pipeline` job triggers a child pipeline, and passes the `CI_PIPELINE_ID`
|
||||
variable to the child pipeline as a new `PARENT_PIPELINE_ID` variable. The child pipeline
|
||||
can use that variable in `needs:pipeline` to download artifacts from the parent pipeline.
|
||||
Having the `create-artifact` and `child-pipeline` jobs in subsequent stages ensures that
|
||||
the `use-artifact` job only executes when `create-artifact` has successfully finished.
|
||||
|
||||
**Additional details**:
|
||||
|
||||
|
|
@ -3418,6 +3424,9 @@ can use that variable in `needs:pipeline` to download artifacts from the parent
|
|||
- You cannot use `needs:pipeline:job` in a [trigger job](#trigger), or to fetch artifacts
|
||||
from a [multi-project pipeline](../pipelines/downstream_pipelines.md#multi-project-pipelines).
|
||||
To fetch artifacts from a multi-project pipeline use [`needs:project`](#needsproject).
|
||||
- The job listed in `needs:pipeline:job` must complete with a status of `success`
|
||||
or the artifacts can't be fetched. [Issue 367229](https://gitlab.com/gitlab-org/gitlab/-/issues/367229)
|
||||
proposes to allow fetching artifacts from any job with artifacts.
|
||||
|
||||
#### `needs:optional`
|
||||
|
||||
|
|
|
|||
|
|
@ -135,8 +135,8 @@ Git push options can perform actions for merge requests while pushing changes:
|
|||
|
||||
| Push option | Description |
|
||||
|----------------------------------------------|-------------|
|
||||
| `merge_request.create` | Create a new merge request for the pushed branch. |
|
||||
| `merge_request.target=<branch_name>` | Set the target of the merge request to a particular branch, such as: `git push -o merge_request.target=branch_name`. |
|
||||
| `merge_request.create` | Create a new merge request for the pushed branch. When pushing from the default branch, you must specify a target branch using the `merge_request.target` option to create a merge request. |
|
||||
| `merge_request.target=<branch_name>` | Set the target of the merge request to a particular branch, such as: `git push -o merge_request.target=branch_name`. Required when creating a merge request from the default branch. |
|
||||
| `merge_request.target_project=<project>` | Set the target of the merge request to a particular upstream project, such as: `git push -o merge_request.target_project=path/to/project`. Introduced in [GitLab 16.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132475). |
|
||||
| `merge_request.merge_when_pipeline_succeeds` | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/185368) in GitLab 17.11 favor of the `auto_merge` option. |
|
||||
| `merge_request.auto_merge` | Set the merge request to [auto merge](../../user/project/merge_requests/auto_merge.md). |
|
||||
|
|
@ -186,6 +186,12 @@ new merge request, targets a branch (`my-target-branch`), and sets auto-merge:
|
|||
git push -o merge_request.create -o merge_request.target=my-target-branch -o merge_request.auto_merge
|
||||
```
|
||||
|
||||
To create a new merge request from the default branch targeting a different branch:
|
||||
|
||||
```shell
|
||||
git push -o merge_request.create -o merge_request.target=feature-branch
|
||||
```
|
||||
|
||||
### Create Git aliases for pushing
|
||||
|
||||
Adding push options to Git commands can create very long commands. If
|
||||
|
|
|
|||
|
|
@ -626,7 +626,7 @@ SSO enforcement for web activity has the following effects when enabled:
|
|||
group, even if the project is forked.
|
||||
- Git activity originating from CI/CD jobs do not have the SSO check enforced.
|
||||
- Credentials that are not tied to regular users (for example, project and group
|
||||
access tokens, and deploy keys) do not have the SSO check enforced.
|
||||
access tokens, service accounts, and deploy keys) do not have the SSO check enforced.
|
||||
- Users must be signed-in through SSO before they can pull images using the
|
||||
[Dependency Proxy](../../packages/dependency_proxy/_index.md).
|
||||
- When the **Enforce SSO-only authentication for Git and Dependency Proxy
|
||||
|
|
|
|||
|
|
@ -89,6 +89,22 @@ module Gitlab
|
|||
Coordinator.new(index).drop
|
||||
end
|
||||
end
|
||||
|
||||
def self.minimum_index_size!(bytes)
|
||||
update_reindexing_setting!(:reindexing_minimum_index_size, bytes)
|
||||
end
|
||||
|
||||
def self.minimum_relative_bloat_size!(threshold)
|
||||
update_reindexing_setting!(:reindexing_minimum_relative_bloat_size, threshold)
|
||||
end
|
||||
|
||||
def self.update_reindexing_setting!(key, value)
|
||||
application_settings = Gitlab::CurrentSettings.current_application_settings
|
||||
current_settings = application_settings.database_reindexing || {}
|
||||
updated_settings = current_settings.merge(key => value)
|
||||
application_settings.update!(database_reindexing: updated_settings)
|
||||
end
|
||||
private_class_method :update_reindexing_setting!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -23367,9 +23367,6 @@ msgstr ""
|
|||
msgid "Dynamic Application Security Testing (DAST)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dynamic application security testing (DAST)"
|
||||
msgstr ""
|
||||
|
||||
msgid "E-mail:"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -32259,9 +32256,6 @@ msgstr ""
|
|||
msgid "Infrastructure as Code (IaC) Scanning"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infrastructure as code scanning (IaC)"
|
||||
msgstr ""
|
||||
|
||||
msgid "InfrastructureRegistry|Copy Terraform Command"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -54160,27 +54154,54 @@ msgstr ""
|
|||
msgid "SecurityInventory|Add projects to this group to start tracking their security posture."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Basic SAST"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|CS"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Container scanning"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Container scanning (standard)"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Container scanning for registry"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|DAST"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|DS"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Dependency scanning"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Dynamic application security testing (DAST)"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|GitLab Advanced SAST"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Group vulnerabilities"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|IaC"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Infrastructure as code scanning (IaC)"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Manage security configuration"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|No projects found"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Pipeline secret detection"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Project vulnerabilities"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -54190,9 +54211,18 @@ msgstr ""
|
|||
msgid "SecurityInventory|SD"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Secret detection"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Secret push protection"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Security inventory"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Static application security testing (SAST)"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Tool coverage: %{coverage}%%"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -58533,9 +58563,6 @@ msgstr ""
|
|||
msgid "Static Application Security Testing (SAST)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Static application security testing (SAST)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Statistics"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -63197,6 +63224,9 @@ msgstr ""
|
|||
msgid "Tool Coverage"
|
||||
msgstr ""
|
||||
|
||||
msgid "ToolCoverageDetails|Manage configuration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@
|
|||
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
|
||||
"@rails/actioncable": "7.0.807",
|
||||
"@rails/ujs": "7.0.807",
|
||||
"@sentry/browser": "9.12.0",
|
||||
"@sentry/browser": "9.13.0",
|
||||
"@snowplow/browser-plugin-client-hints": "^3.24.2",
|
||||
"@snowplow/browser-plugin-form-tracking": "^3.24.2",
|
||||
"@snowplow/browser-plugin-ga-cookies": "^3.24.2",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ RSpec.describe Organizations::GroupsFinder, feature_category: :groups_and_projec
|
|||
let_it_be(:organization_user) { create(:organization_user) }
|
||||
let_it_be(:organization) { organization_user.organization }
|
||||
let_it_be(:user) { organization_user.user }
|
||||
let_it_be(:default_organization) { create(:organization, :default) }
|
||||
let_it_be(:other_organization) { create(:organization) }
|
||||
let_it_be_with_reload(:public_group) { create(:group, name: 'public-group', organization: organization) }
|
||||
let_it_be_with_reload(:outside_organization_group) do
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ describe('MRWidgetArchived', () => {
|
|||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallowMount(archivedComponent, { propsData: { mr: {} } });
|
||||
wrapper = shallowMount(archivedComponent);
|
||||
});
|
||||
|
||||
it('renders error icon', () => {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ describe('MRWidgetChecking', () => {
|
|||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallowMount(CheckingComponent, { propsData: { mr: {} } });
|
||||
wrapper = shallowMount(CheckingComponent);
|
||||
});
|
||||
|
||||
it('renders loading icon', () => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`History Item renders the correct markup 1`] = `
|
||||
<li
|
||||
class="note-container-query-wrapper note-wrapper system-note timeline-entry"
|
||||
class="js-timeline-entry note-container-query-wrapper note-wrapper system-note timeline-entry"
|
||||
>
|
||||
<div
|
||||
class="timeline-entry-inner"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
|
|||
import Vue, { nextTick } from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import gfmEventHub from '~/vue_shared/components/markdown/eventhub';
|
||||
import ToggleRepliesWidget from '~/notes/components/toggle_replies_widget.vue';
|
||||
import WorkItemDiscussion from '~/work_items/components/notes/work_item_discussion.vue';
|
||||
import WorkItemNote from '~/work_items/components/notes/work_item_note.vue';
|
||||
|
|
@ -54,10 +55,14 @@ describe('Work Item Discussion', () => {
|
|||
workItemIid: '1',
|
||||
workItemType,
|
||||
markdownPreviewPath: '/group/project/preview_markdown?target_type=WorkItem',
|
||||
uploadsPath: '/group/project/uploads',
|
||||
autocompleteDataSources: {},
|
||||
isExpandedOnLoad,
|
||||
hideFullscreenMarkdownButton,
|
||||
},
|
||||
stubs: {
|
||||
WorkItemAddNote,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -267,4 +272,37 @@ describe('Work Item Discussion', () => {
|
|||
expect(findToggleRepliesWidget().props('collapsed')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('quote-reply event', () => {
|
||||
const mockDiscussions =
|
||||
mockWorkItemNotesWidgetResponseWithComments.discussions.nodes[0].notes.nodes;
|
||||
let mockAppendTextSpy;
|
||||
|
||||
beforeEach(async () => {
|
||||
window.gon.current_user_id = 1;
|
||||
createComponent({
|
||||
discussion: mockDiscussions,
|
||||
});
|
||||
|
||||
mockAppendTextSpy = jest
|
||||
.spyOn(wrapper.vm.$refs.addNote, 'appendText')
|
||||
.mockImplementation(() => {});
|
||||
await gfmEventHub.$emit('quote-reply', {
|
||||
event: {
|
||||
preventDefault: jest.fn(),
|
||||
},
|
||||
discussionId: mockDiscussions[0].discussion.id,
|
||||
text: 'quoted text',
|
||||
});
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('shows reply input form for the discussion note', () => {
|
||||
expect(findWorkItemAddNote().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('calls appendText on work-item-add-note', () => {
|
||||
expect(mockAppendTextSpy).toHaveBeenCalledWith('quoted text');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -853,6 +853,7 @@ describe('WorkItemDetail component', () => {
|
|||
|
||||
expect(findNotesWidget().exists()).toBe(true);
|
||||
expect(findNotesWidget().props('isWorkItemConfidential')).toBe(confidential);
|
||||
expect(findNotesWidget().props('canCreateNote')).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,12 @@ import setWindowLocation from 'helpers/set_window_location_helper';
|
|||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import { stubComponent } from 'helpers/stub_component';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
||||
import { scrollToTargetOnResize } from '~/lib/utils/resize_observer';
|
||||
import { CopyAsGFM } from '~/behaviors/markdown/copy_as_gfm';
|
||||
import { Mousetrap } from '~/lib/mousetrap';
|
||||
import { ISSUABLE_COMMENT_OR_REPLY, keysFor } from '~/behaviors/shortcuts/keybindings';
|
||||
import gfmEventHub from '~/vue_shared/components/markdown/eventhub';
|
||||
import SystemNote from '~/work_items/components/notes/system_note.vue';
|
||||
import WorkItemNotes from '~/work_items/components/work_item_notes.vue';
|
||||
import WorkItemDiscussion from '~/work_items/components/notes/work_item_discussion.vue';
|
||||
|
|
@ -109,6 +114,7 @@ describe('WorkItemNotes component', () => {
|
|||
workItemIid = mockWorkItemIid,
|
||||
defaultWorkItemNotesQueryHandler = workItemNotesQueryHandler,
|
||||
deleteWINoteMutationHandler = deleteWorkItemNoteMutationSuccessHandler,
|
||||
canCreateNote = false,
|
||||
isGroup = false,
|
||||
isDrawer = false,
|
||||
isModal = false,
|
||||
|
|
@ -116,7 +122,16 @@ describe('WorkItemNotes component', () => {
|
|||
parentId = null,
|
||||
propsData = {},
|
||||
} = {}) => {
|
||||
setHTMLFixture(`
|
||||
<div class="work-item-overview">
|
||||
<div class="js-work-item-description">
|
||||
<p>Work Item Description</p>
|
||||
</div>
|
||||
<div id="root"></div>
|
||||
</div>
|
||||
`);
|
||||
wrapper = shallowMount(WorkItemNotes, {
|
||||
attachTo: '#root',
|
||||
apolloProvider: createMockApollo([
|
||||
[workItemNoteQuery, workItemNoteQueryHandler],
|
||||
[workItemNotesByIidQuery, defaultWorkItemNotesQueryHandler],
|
||||
|
|
@ -130,6 +145,7 @@ describe('WorkItemNotes component', () => {
|
|||
},
|
||||
propsData: {
|
||||
fullPath: 'test-path',
|
||||
uploadsPath: '/group/project/uploads',
|
||||
workItemId,
|
||||
workItemIid,
|
||||
workItemType: 'task',
|
||||
|
|
@ -137,6 +153,7 @@ describe('WorkItemNotes component', () => {
|
|||
isModal,
|
||||
isWorkItemConfidential,
|
||||
parentId,
|
||||
canCreateNote,
|
||||
...propsData,
|
||||
},
|
||||
stubs: {
|
||||
|
|
@ -149,6 +166,10 @@ describe('WorkItemNotes component', () => {
|
|||
createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
resetHTMLFixture();
|
||||
});
|
||||
|
||||
it('has the work item note activity header', () => {
|
||||
expect(findActivityHeader().exists()).toBe(true);
|
||||
});
|
||||
|
|
@ -596,4 +617,57 @@ describe('WorkItemNotes component', () => {
|
|||
expect(findAllWorkItemCommentNotes().at(0).props('hideFullscreenMarkdownButton')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('reply shortcut', () => {
|
||||
const triggerReplyShortcut = async () => {
|
||||
Mousetrap.trigger(keysFor(ISSUABLE_COMMENT_OR_REPLY)[0]);
|
||||
await nextTick();
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
window.gon.current_user_id = 1;
|
||||
createComponent({
|
||||
defaultWorkItemNotesQueryHandler: jest
|
||||
.fn()
|
||||
.mockResolvedValue(mockWorkItemNotesResponseWithComments()),
|
||||
canCreateNote: true,
|
||||
});
|
||||
|
||||
jest.spyOn(gfmEventHub, '$emit');
|
||||
jest.spyOn(wrapper.vm, 'appendText').mockImplementation(() => {});
|
||||
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('emits `quote-reply` event on $root when reply quotes an existing discussion', async () => {
|
||||
jest.spyOn(CopyAsGFM, 'selectionToGfm').mockReturnValueOnce('foo');
|
||||
jest.spyOn(wrapper.vm, 'getDiscussionIdFromSelection').mockReturnValue('discussion-1');
|
||||
await triggerReplyShortcut();
|
||||
|
||||
expect(gfmEventHub.$emit).toHaveBeenCalledWith('quote-reply', {
|
||||
discussionId: 'discussion-1',
|
||||
text: 'foo',
|
||||
event: expect.any(Object),
|
||||
});
|
||||
});
|
||||
|
||||
it.each`
|
||||
sortDirection | description
|
||||
${ASC} | ${'oldest-first'}
|
||||
${DESC} | ${'newest-first'}
|
||||
`(
|
||||
'calls on appendText on work-item-add-note form with discussion sort direction set to $description',
|
||||
async ({ sortDirection }) => {
|
||||
jest.spyOn(CopyAsGFM, 'selectionToGfm').mockReturnValueOnce('foo');
|
||||
|
||||
findActivityHeader().vm.$emit('changeSort', sortDirection);
|
||||
await nextTick();
|
||||
|
||||
await triggerReplyShortcut();
|
||||
|
||||
expect(gfmEventHub.$emit).not.toHaveBeenCalledWith();
|
||||
expect(wrapper.vm.appendText).toHaveBeenCalledWith('foo');
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -279,4 +279,30 @@ RSpec.describe Gitlab::Database::Reindexing, feature_category: :database, time_t
|
|||
expect(expected_queries).to eq(actual_queries)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.minimum_index_size!' do
|
||||
let(:current_application_settings) { Gitlab::CurrentSettings.current_application_settings }
|
||||
let(:bytes) { 2.gigabytes }
|
||||
|
||||
subject(:minimum_index_size) { described_class.minimum_index_size!(bytes) }
|
||||
|
||||
it 'updates reindexing minimun index size' do
|
||||
minimum_index_size
|
||||
|
||||
expect(current_application_settings.database_reindexing['reindexing_minimum_index_size']).to be(bytes)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.minimum_relative_bloat_size!' do
|
||||
let(:current_application_settings) { Gitlab::CurrentSettings.current_application_settings }
|
||||
let(:threshold) { 0.3 }
|
||||
|
||||
subject(:minimum_relative_bloat_size) { described_class.minimum_relative_bloat_size!(threshold) }
|
||||
|
||||
it 'updates minimum relative bloat size' do
|
||||
minimum_relative_bloat_size
|
||||
|
||||
expect(current_application_settings.database_reindexing['reindexing_minimum_relative_bloat_size']).to be(threshold)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -358,6 +358,23 @@ RSpec.describe MergeRequests::PushOptionsHandlerService, feature_category: :sour
|
|||
it_behaves_like 'with the project default branch'
|
||||
end
|
||||
|
||||
describe 'pushing from default branch' do
|
||||
let(:changes) { default_branch_changes }
|
||||
|
||||
context 'with target branch specified' do
|
||||
let(:push_options) { { create: true, target: target_branch } }
|
||||
|
||||
it_behaves_like 'a service that can create a merge request'
|
||||
it_behaves_like 'a service that can set the target of a merge request'
|
||||
end
|
||||
|
||||
context 'without target branch specified' do
|
||||
let(:push_options) { { create: true } }
|
||||
|
||||
it_behaves_like 'a service that does nothing'
|
||||
end
|
||||
end
|
||||
|
||||
describe '`target` push option' do
|
||||
let(:push_options) { { target: target_branch } }
|
||||
|
||||
|
|
|
|||
78
yarn.lock
78
yarn.lock
|
|
@ -1417,8 +1417,7 @@
|
|||
resolved "https://registry.yarnpkg.com/@gitlab/fonts/-/fonts-1.3.0.tgz#df89c1bb6714e4a8a5d3272568aa4de7fb337267"
|
||||
integrity sha512-DoMUIN3DqjEn7wvcxBg/b7Ite5fTdF5EmuOZoBRo2j0UBGweDXmNBi+9HrTZs4cBU660dOxcf1hATFcG3npbPg==
|
||||
|
||||
"@gitlab/noop@^1.0.1", jackspeak@^3.1.2, "jackspeak@npm:@gitlab/noop@1.0.1":
|
||||
name jackspeak
|
||||
"@gitlab/noop@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/noop/-/noop-1.0.1.tgz#71a831146ee02732b4a61d2d3c11204564753454"
|
||||
integrity sha512-s++4wjMYeDvBp9IO59DBrWjy8SE/gFkjTDO5ck2W0S6Vv7OlqgErwL7pHngAnrSmTJAzyUG8wHGqo0ViS4jn5Q==
|
||||
|
|
@ -2531,51 +2530,51 @@
|
|||
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
|
||||
integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==
|
||||
|
||||
"@sentry-internal/browser-utils@9.12.0":
|
||||
version "9.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.12.0.tgz#6efef1489cbe7cb19b5227ab4c37b015fde1fbc4"
|
||||
integrity sha512-GXuDEG2Ix8DmVtTkjsItWdusk2CvJ6EPWKYVqFKifxt+IAT3ZbhGZd99Rg3wdRmt9xhCNuS4QrDzDTPMPgfdCw==
|
||||
"@sentry-internal/browser-utils@9.13.0":
|
||||
version "9.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.13.0.tgz#886e6c1dcf706624d98166c389aadcbf9681bd71"
|
||||
integrity sha512-uZcbwcGI49oPC/YDEConJ+3xi2mu0TsVsDiMQKb6JoSc33KH37wq2IwXJb9nakzKJXxyMNemb44r8irAswjItw==
|
||||
dependencies:
|
||||
"@sentry/core" "9.12.0"
|
||||
"@sentry/core" "9.13.0"
|
||||
|
||||
"@sentry-internal/feedback@9.12.0":
|
||||
version "9.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.12.0.tgz#fc26bf1cd0abfeb249b941c1c943469775d056ad"
|
||||
integrity sha512-3+UxoT97QIXNSUQS4ATL1FFws0RkUb6PeaQN8CPndI6mFlqTW5tuVVLNg9Eo1seNg7R/dfk6WHCWrYN1NbFFKQ==
|
||||
"@sentry-internal/feedback@9.13.0":
|
||||
version "9.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.13.0.tgz#235bea4cd8c7dd4151725467a64b1c0f05b9788a"
|
||||
integrity sha512-fOhMnhEbOR5QVPtn5Gc5+UKQHjvAN/LmtYE6Qya3w2FDh3ZlnIXNFJWqwOneuICV3kCWjN4lLckwmzzwychr7A==
|
||||
dependencies:
|
||||
"@sentry/core" "9.12.0"
|
||||
"@sentry/core" "9.13.0"
|
||||
|
||||
"@sentry-internal/replay-canvas@9.12.0":
|
||||
version "9.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.12.0.tgz#41d4b0e85bad8f5491f0168a0396ae54d8128142"
|
||||
integrity sha512-p8LuKZgWT/CoQBbDOXkSGjWWnc8WsnAayWgna8M/ZFWNITCNEM2rCuqZOyWOElIlrni+M7qoEA3jS7MZe8Ejxw==
|
||||
"@sentry-internal/replay-canvas@9.13.0":
|
||||
version "9.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.13.0.tgz#1821377b9587b61f080c8a21617ebdeef26b2580"
|
||||
integrity sha512-5muW2BmEfWP1fpVWDNcIsph/WgqOqpHaXC1QMr4hk8/BWgt1/S2KPy85YiGVtM5lJJr0VhASKK8rBXG+9zm9IQ==
|
||||
dependencies:
|
||||
"@sentry-internal/replay" "9.12.0"
|
||||
"@sentry/core" "9.12.0"
|
||||
"@sentry-internal/replay" "9.13.0"
|
||||
"@sentry/core" "9.13.0"
|
||||
|
||||
"@sentry-internal/replay@9.12.0":
|
||||
version "9.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.12.0.tgz#fa20b509dc534d57a19500690c2141e9cec4c767"
|
||||
integrity sha512-njEQosFeO/UX+gG+DMRANkPUuz6OIJLb+A1GVylhq9adUgFQydQ9Ay3v7/x1gMhdfHVP6Jeb27qkti0BWYbzBQ==
|
||||
"@sentry-internal/replay@9.13.0":
|
||||
version "9.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.13.0.tgz#0266a5ff990f371f25154e85950d6a6e6da77c93"
|
||||
integrity sha512-l+Atwab/bqI1N8+PSG1WWTCVmiOl7swL85Z9ntwS39QBnd66CTyzt/+j/n/UbAs8GienJK6FIfX1dvG1WmvUhA==
|
||||
dependencies:
|
||||
"@sentry-internal/browser-utils" "9.12.0"
|
||||
"@sentry/core" "9.12.0"
|
||||
"@sentry-internal/browser-utils" "9.13.0"
|
||||
"@sentry/core" "9.13.0"
|
||||
|
||||
"@sentry/browser@9.12.0":
|
||||
version "9.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.12.0.tgz#f39c5e05ea9dd31b54ccf27a9d49f8de9d9ff7f2"
|
||||
integrity sha512-4xQYoZqi+VVhNvlhWiwRd57+SMr3Og4sLjuayAA+zIp1Wx/bDcIld697cugLwml/BR+mVJI2eokkgh1CBl6zag==
|
||||
"@sentry/browser@9.13.0":
|
||||
version "9.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.13.0.tgz#76cf662656c7c7ddfd36081b6e8ba05c385fe823"
|
||||
integrity sha512-KiC8s9/6HvdlfCRqA420YbiBiXMBif7GYESJ8VQqOKUmlPczn8V2CRrEZjMqxhlHdIGiR0PS6jb2VSgeJBchJQ==
|
||||
dependencies:
|
||||
"@sentry-internal/browser-utils" "9.12.0"
|
||||
"@sentry-internal/feedback" "9.12.0"
|
||||
"@sentry-internal/replay" "9.12.0"
|
||||
"@sentry-internal/replay-canvas" "9.12.0"
|
||||
"@sentry/core" "9.12.0"
|
||||
"@sentry-internal/browser-utils" "9.13.0"
|
||||
"@sentry-internal/feedback" "9.13.0"
|
||||
"@sentry-internal/replay" "9.13.0"
|
||||
"@sentry-internal/replay-canvas" "9.13.0"
|
||||
"@sentry/core" "9.13.0"
|
||||
|
||||
"@sentry/core@9.12.0":
|
||||
version "9.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.12.0.tgz#164a88af070cd77191ca14c88914e008c7ce7716"
|
||||
integrity sha512-jOqQK/90uzHmsBvkPTj/DAEFvA5poX4ZRyC7LE1zjg4F5jdOp3+M4W3qCy0CkSTu88Zu5VWBoppCU2Bs34XEqg==
|
||||
"@sentry/core@9.13.0":
|
||||
version "9.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.13.0.tgz#3269cab4ba34fa0928f04936ddb82182069cb568"
|
||||
integrity sha512-Zn1Qec5XNkNRE/M5QjL6YJLghETg6P188G/v2OzdHdHIRf0Y58/SnJilu3louF+ogos6kaSqqdMgzqKgZ8tCdg==
|
||||
|
||||
"@sinclair/typebox@^0.27.8":
|
||||
version "0.27.8"
|
||||
|
|
@ -9447,6 +9446,11 @@ iterall@^1.2.1:
|
|||
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
|
||||
integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
|
||||
|
||||
jackspeak@^3.1.2, "jackspeak@npm:@gitlab/noop@1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/noop/-/noop-1.0.1.tgz#71a831146ee02732b4a61d2d3c11204564753454"
|
||||
integrity sha512-s++4wjMYeDvBp9IO59DBrWjy8SE/gFkjTDO5ck2W0S6Vv7OlqgErwL7pHngAnrSmTJAzyUG8wHGqo0ViS4jn5Q==
|
||||
|
||||
jed@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/jed/-/jed-1.1.1.tgz#7a549bbd9ffe1585b0cd0a191e203055bee574b4"
|
||||
|
|
|
|||
Loading…
Reference in New Issue