Commit 821d053d authored by Igor Drozdov's avatar Igor Drozdov

Merge branch 'ph/235716/readyToMergeGraphql' into 'master'

Move the ready to merge state to GraphQL

See merge request gitlab-org/gitlab!49948
parents d4ed85ad f680c29f
......@@ -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