Commit f680c29f authored by Phil Hughes's avatar Phil Hughes Committed by Igor Drozdov

Move the ready to merge state to GraphQL

This moves the widgets ready to merge state into GraphQL

Closes https://gitlab.com/gitlab-org/gitlab/-/issues/235716
parent f8971bea
......@@ -25,12 +25,13 @@ export default {
class="mr-commit-dropdown"
>
<gl-dropdown-item
v-for="commit in commits"
:key="commit.short_id"
v-for="(commit, index) in commits"
:key="index"
class="text-nowrap text-truncate"
@click="$emit('input', commit.message)"
>
<span class="monospace mr-2">{{ commit.short_id }}</span> {{ commit.title }}
<span class="monospace mr-2">{{ commit.shortId || commit.short_id }}</span>
{{ commit.title }}
</gl-dropdown-item>
</gl-dropdown>
</div>
......
......@@ -9,13 +9,18 @@ import {
GlSprintf,
GlLink,
GlTooltipDirective,
GlSkeletonLoader,
} from '@gitlab/ui';
import readyToMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/ready_to_merge';
import readyToMergeQuery from 'ee_else_ce/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql';
import simplePoll from '~/lib/utils/simple_poll';
import { __ } from '~/locale';
import MergeRequest from '../../../merge_request';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import { deprecatedCreateFlash as Flash } from '../../../flash';
import MergeRequestStore from '../../stores/mr_widget_store';
import statusIcon from '../mr_widget_status_icon.vue';
import eventHub from '../../event_hub';
import SquashBeforeMerge from './squash_before_merge.vue';
......@@ -35,6 +40,31 @@ const MERGE_HOOK_VALIDATION_ERROR_STATUS = 'hook_validation_error';
export default {
name: 'ReadyToMerge',
apollo: {
state: {
query: readyToMergeQuery,
skip() {
return !this.glFeatures.mergeRequestWidgetGraphql;
},
variables() {
return this.mergeRequestQueryVariables;
},
manual: true,
result({ data }) {
this.state = {
...data.project.mergeRequest,
mergeRequestsFfOnlyEnabled: data.mergeRequestsFfOnlyEnabled,
onlyAllowMergeIfPipelineSucceeds: data.onlyAllowMergeIfPipelineSucceeds,
};
this.removeSourceBranch = data.project.mergeRequest.shouldRemoveSourceBranch;
this.commitMessage = data.project.mergeRequest.defaultMergeCommitMessage;
this.squashBeforeMerge = data.project.mergeRequest.squashOnMerge;
this.isSquashReadOnly = data.project.squashReadOnly;
this.squashCommitMessage = data.project.mergeRequest.defaultSquashCommitMessage;
this.loading = false;
},
},
},
components: {
statusIcon,
SquashBeforeMerge,
......@@ -48,6 +78,7 @@ export default {
GlButtonGroup,
GlDropdown,
GlDropdownItem,
GlSkeletonLoader,
MergeTrainHelperText: () =>
import('ee_component/vue_merge_request_widget/components/merge_train_helper_text.vue'),
MergeImmediatelyConfirmationDialog: () =>
......@@ -58,13 +89,15 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [readyToMergeMixin],
mixins: [readyToMergeMixin, glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
props: {
mr: { type: Object, required: true },
service: { type: Object, required: true },
},
data() {
return {
loading: this.glFeatures.mergeRequestWidgetGraphql,
state: {},
removeSourceBranch: this.mr.shouldRemoveSourceBranch,
isMakingRequest: false,
isMergingImmediately: false,
......@@ -75,13 +108,93 @@ export default {
};
},
computed: {
stateData() {
return this.glFeatures.mergeRequestWidgetGraphql ? this.state : this.mr;
},
hasCI() {
return this.stateData.hasCI || this.stateData.hasCi;
},
isAutoMergeAvailable() {
return !isEmpty(this.mr.availableAutoMergeStrategies);
return !isEmpty(this.stateData.availableAutoMergeStrategies);
},
pipeline() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.state.pipelines?.nodes?.[0];
}
return this.mr.pipeline;
},
isPipelineFailed() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return ['FAILED', 'CANCELED'].indexOf(this.pipeline?.status) !== -1;
}
return this.mr.isPipelineFailed;
},
isMergeAllowed() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.state.mergeable || false;
}
return this.mr.isMergeAllowed;
},
canRemoveSourceBranch() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.state.userPermissions.removeSourceBranch;
}
return this.mr.canRemoveSourceBranch;
},
commits() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.state.commitsWithoutMergeCommits.nodes;
}
return this.mr.commits;
},
commitsCount() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.state.commitCount || 0;
}
return this.mr.commitsCount;
},
preferredAutoMergeStrategy() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return MergeRequestStore.getPreferredAutoMergeStrategy(
this.state.availableAutoMergeStrategies,
);
}
return this.mr.preferredAutoMergeStrategy;
},
isSHAMismatch() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.mr.sha !== this.state.diffHeadSha;
}
return this.mr.isSHAMismatch;
},
squashIsSelected() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.squashReadOnly ? this.state.squashOnMerge : this.state.squash;
}
return this.mr.squashIsSelected;
},
isPipelineActive() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.pipeline?.active || false;
}
return this.mr.isPipelineActive;
},
status() {
const { pipeline, isPipelineFailed, hasCI, ciStatus } = this.mr;
const ciStatus = this.glFeatures.mergeRequestWidgetGraphql
? this.pipeline?.status.toLowerCase()
: this.mr.ciStatus;
if ((hasCI && !ciStatus) || this.hasPipelineMustSucceedConflict) {
if ((this.hasCI && !ciStatus) || this.hasPipelineMustSucceedConflict) {
return PIPELINE_FAILED_STATE;
}
......@@ -89,7 +202,7 @@ export default {
return PIPELINE_PENDING_STATE;
}
if (pipeline && isPipelineFailed) {
if (this.pipeline && this.isPipelineFailed) {
return PIPELINE_FAILED_STATE;
}
......@@ -114,7 +227,7 @@ export default {
if (
this.status === PIPELINE_FAILED_STATE ||
!this.commitMessage.length ||
!this.mr.isMergeAllowed ||
!this.isMergeAllowed ||
this.mr.preventMerge
) {
return WARNING;
......@@ -133,27 +246,31 @@ export default {
return __('Merge');
},
hasPipelineMustSucceedConflict() {
return !this.mr.hasCI && this.mr.onlyAllowMergeIfPipelineSucceeds;
return !this.hasCI && this.stateData.onlyAllowMergeIfPipelineSucceeds;
},
isRemoveSourceBranchButtonDisabled() {
return this.isMergeButtonDisabled;
},
shouldShowSquashBeforeMerge() {
const { commitsCount, enableSquashBeforeMerge, squashIsReadonly, squashIsSelected } = this.mr;
const { enableSquashBeforeMerge } = this.mr;
if (squashIsReadonly && !squashIsSelected) {
if (this.isSquashReadOnly && !this.squashIsSelected) {
return false;
}
return enableSquashBeforeMerge && commitsCount > 1;
return enableSquashBeforeMerge && this.commitsCount > 1;
},
shouldShowMergeControls() {
return this.mr.isMergeAllowed || this.isAutoMergeAvailable;
return this.isMergeAllowed || this.isAutoMergeAvailable;
},
shouldShowSquashEdit() {
return this.squashBeforeMerge && this.shouldShowSquashBeforeMerge;
},
shouldShowMergeEdit() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return !this.state.mergeRequestsFfOnlyEnabled;
}
return !this.mr.ffOnlyEnabled;
},
shaMismatchLink() {
......@@ -162,18 +279,26 @@ export default {
},
methods: {
updateMergeCommitMessage(includeDescription) {
const { commitMessageWithDescription, commitMessage } = this.mr;
const commitMessage = this.glFeatures.mergeRequestWidgetGraphql
? this.state.defaultMergeCommitMessage
: this.mr.commitMessage;
const commitMessageWithDescription = this.glFeatures.mergeRequestWidgetGraphql
? this.state.defaultMergeCommitMessageWithDescription
: this.mr.commitMessageWithDescription;
this.commitMessage = includeDescription ? commitMessageWithDescription : commitMessage;
},
handleMergeButtonClick(useAutoMerge, mergeImmediately = false) {
if (mergeImmediately) {
this.isMergingImmediately = true;
}
const latestSha = this.glFeatures.mergeRequestWidgetGraphql
? this.state.diffHeadSha
: this.mr.latestSHA;
const options = {
sha: this.mr.latestSHA || this.mr.sha,
sha: latestSha || this.mr.sha,
commit_message: this.commitMessage,
auto_merge_strategy: useAutoMerge ? this.mr.preferredAutoMergeStrategy : undefined,
auto_merge_strategy: useAutoMerge ? this.preferredAutoMergeStrategy : undefined,
should_remove_source_branch: this.removeSourceBranch === true,
squash: this.squashBeforeMerge,
};
......@@ -294,156 +419,168 @@ export default {
<template>
<div>
<div class="mr-widget-body media" :class="{ 'gl-pb-3': shouldRenderMergeTrainHelperText }">
<status-icon :status="iconClass" />
<div class="media-body">
<div class="mr-widget-body-controls media space-children">
<gl-button-group>
<gl-button
size="medium"
category="primary"
class="qa-merge-button accept-merge-request"
:variant="mergeButtonVariant"
:disabled="isMergeButtonDisabled"
:loading="isMakingRequest"
@click="handleMergeButtonClick(isAutoMergeAvailable)"
>{{ mergeButtonText }}</gl-button
>
<gl-dropdown
v-if="shouldShowMergeImmediatelyDropdown"
v-gl-tooltip.hover.focus="__('Select merge moment')"
:disabled="isMergeButtonDisabled"
variant="info"
data-qa-selector="merge_moment_dropdown"
toggle-class="btn-icon js-merge-moment"
>
<template #button-content>
<gl-icon name="chevron-down" class="mr-0" />
<span class="sr-only">{{ __('Select merge moment') }}</span>
</template>
<gl-dropdown-item
icon-name="warning"
button-class="accept-merge-request js-merge-immediately-button"
data-qa-selector="merge_immediately_option"
@click="handleMergeImmediatelyButtonClick"
<div v-if="loading" class="mr-widget-body">
<div class="gl-w-full mr-ready-to-merge-loader">
<gl-skeleton-loader :width="418" :height="30">
<rect x="0" y="3" width="24" height="24" rx="4" />
<rect x="32" y="0" width="70" height="30" rx="4" />
<rect x="110" y="7" width="150" height="16" rx="4" />
<rect x="268" y="7" width="150" height="16" rx="4" />
</gl-skeleton-loader>
</div>
</div>
<template v-else>
<div class="mr-widget-body media" :class="{ 'gl-pb-3': shouldRenderMergeTrainHelperText }">
<status-icon :status="iconClass" />
<div class="media-body">
<div class="mr-widget-body-controls media space-children">
<gl-button-group>
<gl-button
size="medium"
category="primary"
class="qa-merge-button accept-merge-request"
:variant="mergeButtonVariant"
:disabled="isMergeButtonDisabled"
:loading="isMakingRequest"
@click="handleMergeButtonClick(isAutoMergeAvailable)"
>{{ mergeButtonText }}</gl-button
>
{{ __('Merge immediately') }}
</gl-dropdown-item>
<merge-immediately-confirmation-dialog
ref="confirmationDialog"
:docs-url="mr.mergeImmediatelyDocsPath"
@mergeImmediately="onMergeImmediatelyConfirmation"
/>
</gl-dropdown>
</gl-button-group>
<div class="media-body-wrap space-children">
<template v-if="shouldShowMergeControls">
<label v-if="mr.canRemoveSourceBranch">
<input
id="remove-source-branch-input"
v-model="removeSourceBranch"
:disabled="isRemoveSourceBranchButtonDisabled"
class="js-remove-source-branch-checkbox"
type="checkbox"
<gl-dropdown
v-if="shouldShowMergeImmediatelyDropdown"
v-gl-tooltip.hover.focus="__('Select merge moment')"
:disabled="isMergeButtonDisabled"
variant="info"
data-qa-selector="merge_moment_dropdown"
toggle-class="btn-icon js-merge-moment"
>
<template #button-content>
<gl-icon name="chevron-down" class="mr-0" />
<span class="sr-only">{{ __('Select merge moment') }}</span>
</template>
<gl-dropdown-item
icon-name="warning"
button-class="accept-merge-request js-merge-immediately-button"
data-qa-selector="merge_immediately_option"
@click="handleMergeImmediatelyButtonClick"
>
{{ __('Merge immediately') }}
</gl-dropdown-item>
<merge-immediately-confirmation-dialog
ref="confirmationDialog"
:docs-url="mr.mergeImmediatelyDocsPath"
@mergeImmediately="onMergeImmediatelyConfirmation"
/>
{{ __('Delete source branch') }}
</label>
</gl-dropdown>
</gl-button-group>
<div class="media-body-wrap space-children">
<template v-if="shouldShowMergeControls">
<label v-if="canRemoveSourceBranch">
<input
id="remove-source-branch-input"
v-model="removeSourceBranch"
:disabled="isRemoveSourceBranchButtonDisabled"
class="js-remove-source-branch-checkbox"
type="checkbox"
/>
{{ __('Delete source branch') }}
</label>
<!-- Placeholder for EE extension of this component -->
<squash-before-merge
v-if="shouldShowSquashBeforeMerge"
v-model="squashBeforeMerge"
:help-path="mr.squashBeforeMergeHelpPath"
:is-disabled="isSquashReadOnly"
/>
</template>
<template v-else>
<div class="bold js-resolve-mr-widget-items-message">
<div
v-if="hasPipelineMustSucceedConflict"
class="gl-display-flex gl-align-items-center"
data-testid="pipeline-succeed-conflict"
>
<gl-sprintf :message="pipelineMustSucceedConflictText" />
<gl-link
:href="mr.pipelineMustSucceedDocsPath"
target="_blank"
class="gl-display-flex gl-ml-2"
<!-- Placeholder for EE extension of this component -->
<squash-before-merge
v-if="shouldShowSquashBeforeMerge"
v-model="squashBeforeMerge"
:help-path="mr.squashBeforeMergeHelpPath"
:is-disabled="isSquashReadOnly"
/>
</template>
<template v-else>
<div class="bold js-resolve-mr-widget-items-message">
<div
v-if="hasPipelineMustSucceedConflict"
class="gl-display-flex gl-align-items-center"
data-testid="pipeline-succeed-conflict"
>
<gl-icon name="question" />
</gl-link>
<gl-sprintf :message="pipelineMustSucceedConflictText" />
<gl-link
:href="mr.pipelineMustSucceedDocsPath"
target="_blank"
class="gl-display-flex gl-ml-2"
>
<gl-icon name="question" />
</gl-link>
</div>
<gl-sprintf v-else :message="mergeDisabledText" />
</div>
<gl-sprintf v-else :message="mergeDisabledText" />
</div>
</template>
</div>
</div>
<div v-if="mr.isSHAMismatch" class="d-flex align-items-center mt-2 js-sha-mismatch">
<gl-icon name="warning-solid" class="text-warning mr-1" />
<span class="text-warning">
<gl-sprintf
:message="
__('New changes were added. %{linkStart}Reload the page to review them%{linkEnd}')
"
>
<template #link="{ content }">
<gl-link :href="mr.mergeRequestDiffsPath">{{ content }}</gl-link>
</template>
</gl-sprintf>
</span>
</div>
</div>
<div v-if="isSHAMismatch" class="d-flex align-items-center mt-2 js-sha-mismatch">
<gl-icon name="warning-solid" class="text-warning mr-1" />
<span class="text-warning">
<gl-sprintf
:message="
__('New changes were added. %{linkStart}Reload the page to review them%{linkEnd}')
"
>
<template #link="{ content }">
<gl-link :href="mr.mergeRequestDiffsPath">{{ content }}</gl-link>
</template>
</gl-sprintf>
</span>
</div>
</div>
</div>
</div>
<merge-train-helper-text
v-if="shouldRenderMergeTrainHelperText"
:pipeline-id="mr.pipeline.id"
:pipeline-link="mr.pipeline.path"
:merge-train-length="mr.mergeTrainsCount"
:merge-train-when-pipeline-succeeds-docs-path="mr.mergeTrainWhenPipelineSucceedsDocsPath"
/>
<template v-if="shouldShowMergeControls">
<div v-if="mr.ffOnlyEnabled" class="mr-fast-forward-message">
{{ __('Fast-forward merge without a merge commit') }}
</div>
<commits-header
v-if="shouldShowSquashEdit || shouldShowMergeEdit"
:is-squash-enabled="squashBeforeMerge"
:commits-count="mr.commitsCount"
:target-branch="mr.targetBranch"
:is-fast-forward-enabled="mr.ffOnlyEnabled"
:class="{ 'border-bottom': mr.mergeError }"
>
<ul class="border-top content-list commits-list flex-list">
<commit-edit
v-if="shouldShowSquashEdit"
v-model="squashCommitMessage"
:label="__('Squash commit message')"
input-id="squash-message-edit"
squash
>
<commit-message-dropdown
slot="header"
<merge-train-helper-text
v-if="shouldRenderMergeTrainHelperText"
:pipeline-id="pipeline.id"
:pipeline-link="pipeline.path"
:merge-train-length="stateData.mergeTrainsCount"
:merge-train-when-pipeline-succeeds-docs-path="mr.mergeTrainWhenPipelineSucceedsDocsPath"
/>
<template v-if="shouldShowMergeControls">
<div v-if="!shouldShowMergeEdit" class="mr-fast-forward-message">
{{ __('Fast-forward merge without a merge commit') }}
</div>
<commits-header
v-if="shouldShowSquashEdit || shouldShowMergeEdit"
:is-squash-enabled="squashBeforeMerge"
:commits-count="commitsCount"
:target-branch="stateData.targetBranch"
:is-fast-forward-enabled="!shouldShowMergeEdit"
:class="{ 'border-bottom': stateData.mergeError }"
>
<ul class="border-top content-list commits-list flex-list">
<commit-edit
v-if="shouldShowSquashEdit"
v-model="squashCommitMessage"
:commits="mr.commits"
/>
</commit-edit>
<commit-edit
v-if="shouldShowMergeEdit"
v-model="commitMessage"
:label="__('Merge commit message')"
input-id="merge-message-edit"
>
<label slot="checkbox">
<input
id="include-description"
type="checkbox"
@change="updateMergeCommitMessage($event.target.checked)"
:label="__('Squash commit message')"
input-id="squash-message-edit"
squash
>
<commit-message-dropdown
slot="header"
v-model="squashCommitMessage"
:commits="commits"
/>
{{ __('Include merge request description') }}
</label>
</commit-edit>
</ul>
</commits-header>
</commit-edit>
<commit-edit
v-if="shouldShowMergeEdit"
v-model="commitMessage"
:label="__('Merge commit message')"
input-id="merge-message-edit"
>
<label slot="checkbox">
<input
id="include-description"
type="checkbox"
@change="updateMergeCommitMessage($event.target.checked)"
/>
{{ __('Include merge request description') }}
</label>
</commit-edit>
</ul>
</commits-header>
</template>
</template>
</div>
</template>
......@@ -27,7 +27,7 @@ export default {
return __('Merge when pipeline succeeds');
},
shouldShowMergeImmediatelyDropdown() {
return this.mr.isPipelineActive && !this.mr.onlyAllowMergeIfPipelineSucceeds;
return this.isPipelineActive && !this.stateData.onlyAllowMergeIfPipelineSucceeds;
},
isMergeImmediatelyDangerous() {
return false;
......
fragment ReadyToMerge on Project {
onlyAllowMergeIfPipelineSucceeds
mergeRequestsFfOnlyEnabled
squashReadOnly
mergeRequest(iid: $iid) {
autoMergeEnabled
shouldRemoveSourceBranch
defaultMergeCommitMessage
defaultMergeCommitMessageWithDescription
defaultSquashCommitMessage
squash
squashOnMerge
availableAutoMergeStrategies
hasCi
mergeable
mergeWhenPipelineSucceeds
commitCount
diffHeadSha
userPermissions {
removeSourceBranch
}
targetBranch
mergeError
commitsWithoutMergeCommits {
nodes {
sha
shortId
title
message
}
}
pipelines(first: 1) {
nodes {
id
status
path
active
}
}
}
}
#import "./ready_to_merge.fragment.graphql"
query readyToMergeQuery($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
...ReadyToMerge
}
}
......@@ -167,7 +167,7 @@ export default class MergeRequestStore {
this.canBeMerged = mergeRequest.mergeStatus === 'can_be_merged';
this.canMerge = mergeRequest.userPermissions.canMerge;
this.ciStatus = pipeline?.status.toLowerCase();
this.commitsCount = mergeRequest.commitCount;
this.commitsCount = mergeRequest.commitCount || 10;
this.branchMissing = !mergeRequest.sourceBranchExists || !mergeRequest.targetBranchExists;
this.hasConflicts = mergeRequest.conflicts;
this.hasMergeableDiscussionsState = mergeRequest.mergeableDiscussionsState === false;
......
......@@ -1016,3 +1016,11 @@ $mr-widget-min-height: 69px;
vertical-align: middle;
}
}
.mr-ready-to-merge-loader {
max-width: 418px;
> svg {
vertical-align: middle;
}
}
......@@ -96,6 +96,8 @@ module Types
description: 'Default merge commit message of the merge request'
field :default_merge_commit_message_with_description, GraphQL::STRING_TYPE, null: true,
description: 'Default merge commit message of the merge request with description'
field :default_squash_commit_message, GraphQL::STRING_TYPE, null: true, calls_gitaly: true,
description: 'Default squash commit message of the merge request'
field :merge_ongoing, GraphQL::BOOLEAN_TYPE, method: :merge_ongoing?, null: false,
description: 'Indicates if a merge is currently occurring'
field :source_branch_exists, GraphQL::BOOLEAN_TYPE,
......@@ -161,6 +163,8 @@ module Types
description: 'Users who approved the merge request'
field :squash_on_merge, GraphQL::BOOLEAN_TYPE, null: false, method: :squash_on_merge?,
description: 'Indicates if squash on merge is enabled'
field :squash, GraphQL::BOOLEAN_TYPE, null: false,
description: 'Indicates if squash on merge is enabled'
field :available_auto_merge_strategies, [GraphQL::STRING_TYPE], null: true, calls_gitaly: true,
description: 'Array of available auto merge strategies'
field :has_ci, GraphQL::BOOLEAN_TYPE, null: false, method: :has_ci?,
......
......@@ -13754,6 +13754,11 @@ type MergeRequest implements CurrentUserTodos & Noteable {
"""
defaultMergeCommitMessageWithDescription: String
"""
Default squash commit message of the merge request
"""
defaultSquashCommitMessage: String
"""
Description of the merge request (Markdown rendered as HTML for caching)
"""
......@@ -14114,6 +14119,11 @@ type MergeRequest implements CurrentUserTodos & Noteable {
"""
sourceProjectId: Int
"""
Indicates if squash on merge is enabled
"""
squash: Boolean!
"""
Indicates if squash on merge is enabled
"""
......
......@@ -37758,6 +37758,20 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "defaultSquashCommitMessage",
"description": "Default squash commit message of the merge request",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "description",
"description": "Description of the merge request (Markdown rendered as HTML for caching)",
......@@ -38718,6 +38732,24 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "squash",
"description": "Indicates if squash on merge is enabled",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "squashOnMerge",
"description": "Indicates if squash on merge is enabled",
......@@ -2082,6 +2082,7 @@ Autogenerated return type of MarkAsSpamSnippet.
| `currentUserTodos` | TodoConnection! | Todos for the current user |
| `defaultMergeCommitMessage` | String | Default merge commit message of the merge request |
| `defaultMergeCommitMessageWithDescription` | String | Default merge commit message of the merge request with description |
| `defaultSquashCommitMessage` | String | Default squash commit message of the merge request |
| `description` | String | Description of the merge request (Markdown rendered as HTML for caching) |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
| `diffHeadSha` | String | Diff head SHA of the merge request |
......@@ -2125,6 +2126,7 @@ Autogenerated return type of MarkAsSpamSnippet.
| `sourceBranchProtected` | Boolean! | Indicates if the source branch is protected |
| `sourceProject` | Project | Source project of the merge request |
| `sourceProjectId` | Int | ID of the merge request source project |
| `squash` | Boolean! | Indicates if squash on merge is enabled |
| `squashOnMerge` | Boolean! | Indicates if squash on merge is enabled |
| `state` | MergeRequestState! | State of the merge request |
| `subscribed` | Boolean! | Indicates if the currently logged in user is subscribed to this merge request |
......
......@@ -36,13 +36,13 @@ export default {
return PIPELINE_MUST_SUCCEED_CONFLICT_TEXT;
},
autoMergeText() {
if (this.mr.preferredAutoMergeStrategy === MTWPS_MERGE_STRATEGY) {
if (this.mr.mergeTrainsCount === 0) {
if (this.preferredAutoMergeStrategy === MTWPS_MERGE_STRATEGY) {
if (this.stateData.mergeTrainsCount === 0) {
return __('Start merge train when pipeline succeeds');
}
return __('Add to merge train when pipeline succeeds');
} else if (this.mr.preferredAutoMergeStrategy === MT_MERGE_STRATEGY) {
if (this.mr.mergeTrainsCount === 0) {
} else if (this.preferredAutoMergeStrategy === MT_MERGE_STRATEGY) {
if (this.stateData.mergeTrainsCount === 0) {
return __('Start merge train');
}
return __('Add to merge train');
......@@ -51,22 +51,22 @@ export default {
},
shouldRenderMergeTrainHelperText() {
return (
this.mr.pipeline &&
isNumber(this.mr.pipeline.id) &&
isString(this.mr.pipeline.path) &&
this.mr.preferredAutoMergeStrategy === MTWPS_MERGE_STRATEGY &&
!this.mr.autoMergeEnabled
this.pipeline &&
isNumber(this.pipeline.id) &&
isString(this.pipeline.path) &&
this.preferredAutoMergeStrategy === MTWPS_MERGE_STRATEGY &&
!this.stateData.autoMergeEnabled
);
},
shouldShowMergeImmediatelyDropdown() {
if (this.mr.preferredAutoMergeStrategy === MT_MERGE_STRATEGY) {
if (this.preferredAutoMergeStrategy === MT_MERGE_STRATEGY) {
return true;
}
return this.mr.isPipelineActive && !this.mr.onlyAllowMergeIfPipelineSucceeds;
return this.isPipelineActive && !this.stateData.onlyAllowMergeIfPipelineSucceeds;
},
isMergeImmediatelyDangerous() {
return [MT_MERGE_STRATEGY, MTWPS_MERGE_STRATEGY].includes(this.mr.preferredAutoMergeStrategy);
return [MT_MERGE_STRATEGY, MTWPS_MERGE_STRATEGY].includes(this.preferredAutoMergeStrategy);
},
},
};
#import "~/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql"
query readyToMergeQuery($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
...ReadyToMerge
mergeRequest(iid: $iid) {
mergeTrainsCount
}
}
}
......@@ -47,7 +47,8 @@ describe('Commits message dropdown component', () => {
});
it('should have correct message for the first dropdown list element', () => {
expect(findFirstDropdownElement().text()).toBe('78d5b7 Commit 1');
expect(findFirstDropdownElement().text()).toContain('78d5b7');
expect(findFirstDropdownElement().text()).toContain('Commit 1');
});
it('should emit a commit title on selecting commit', () => {
......
......@@ -29,7 +29,7 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do
total_time_spent reference author merged_at commit_count current_user_todos
conflicts auto_merge_enabled approved_by source_branch_protected
default_merge_commit_message_with_description squash_on_merge available_auto_merge_strategies
has_ci mergeable commits_without_merge_commits security_auto_fix
has_ci mergeable commits_without_merge_commits squash security_auto_fix default_squash_commit_message
]
if Gitlab.ee?
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment