Merge branch '32178-prevent-merge-on-sha-change' into 'master'
Add "SHA mismatch" state to the MR widget Closes #32178 See merge request !11316
This commit is contained in:
commit
2a8686353a
10 changed files with 69 additions and 0 deletions
|
@ -0,0 +1,16 @@
|
|||
export default {
|
||||
name: 'MRWidgetSHAMismatch',
|
||||
template: `
|
||||
<div class="mr-widget-body">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-success btn-small"
|
||||
disabled="true">
|
||||
Merge
|
||||
</button>
|
||||
<span class="bold">
|
||||
The source branch HEAD has recently changed. Please reload the page and review the changes before merging.
|
||||
</span>
|
||||
</div>
|
||||
`,
|
||||
};
|
|
@ -27,6 +27,7 @@ export { default as NothingToMergeState } from './components/states/mr_widget_no
|
|||
export { default as MissingBranchState } from './components/states/mr_widget_missing_branch';
|
||||
export { default as NotAllowedState } from './components/states/mr_widget_not_allowed';
|
||||
export { default as ReadyToMergeState } from './components/states/mr_widget_ready_to_merge';
|
||||
export { default as SHAMismatchState } from './components/states/mr_widget_sha_mismatch';
|
||||
export { default as UnresolvedDiscussionsState } from './components/states/mr_widget_unresolved_discussions';
|
||||
export { default as PipelineBlockedState } from './components/states/mr_widget_pipeline_blocked';
|
||||
export { default as PipelineFailedState } from './components/states/mr_widget_pipeline_failed';
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
MissingBranchState,
|
||||
NotAllowedState,
|
||||
ReadyToMergeState,
|
||||
SHAMismatchState,
|
||||
UnresolvedDiscussionsState,
|
||||
PipelineBlockedState,
|
||||
PipelineFailedState,
|
||||
|
@ -203,6 +204,7 @@ export default {
|
|||
'mr-widget-not-allowed': NotAllowedState,
|
||||
'mr-widget-missing-branch': MissingBranchState,
|
||||
'mr-widget-ready-to-merge': ReadyToMergeState,
|
||||
'mr-widget-sha-mismatch': SHAMismatchState,
|
||||
'mr-widget-squash-before-merge': SquashBeforeMerge,
|
||||
'mr-widget-checking': CheckingState,
|
||||
'mr-widget-unresolved-discussions': UnresolvedDiscussionsState,
|
||||
|
|
|
@ -21,6 +21,8 @@ export default function deviseState(data) {
|
|||
return 'unresolvedDiscussions';
|
||||
} else if (this.isPipelineBlocked) {
|
||||
return 'pipelineBlocked';
|
||||
} else if (this.hasSHAChanged) {
|
||||
return 'shaMismatch';
|
||||
} else if (this.canBeMerged) {
|
||||
return 'readyToMerge';
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import { getStateKey } from '../dependencies';
|
|||
export default class MergeRequestStore {
|
||||
|
||||
constructor(data) {
|
||||
this.startingSha = data.diff_head_sha;
|
||||
this.setData(data);
|
||||
}
|
||||
|
||||
|
@ -67,6 +68,7 @@ export default class MergeRequestStore {
|
|||
this.canMerge = !!data.merge_path;
|
||||
this.canCreateIssue = currentUser.can_create_issue || false;
|
||||
this.canCancelAutomaticMerge = !!data.cancel_merge_when_pipeline_succeeds_path;
|
||||
this.hasSHAChanged = this.sha !== this.startingSha;
|
||||
this.canBeMerged = data.can_be_merged || false;
|
||||
|
||||
// Cherry-pick and Revert actions related
|
||||
|
|
|
@ -16,6 +16,7 @@ const stateToComponentMap = {
|
|||
mergeWhenPipelineSucceeds: 'mr-widget-merge-when-pipeline-succeeds',
|
||||
failedToMerge: 'mr-widget-failed-to-merge',
|
||||
autoMergeFailed: 'mr-widget-auto-merge-failed',
|
||||
shaMismatch: 'mr-widget-sha-mismatch',
|
||||
};
|
||||
|
||||
const statesToShowHelpWidget = [
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Add state to MR widget that prevent merges when branch changes after page load
|
||||
merge_request: 11316
|
||||
author:
|
|
@ -0,0 +1,16 @@
|
|||
import Vue from 'vue';
|
||||
import shaMismatchComponent from '~/vue_merge_request_widget/components/states/mr_widget_sha_mismatch';
|
||||
|
||||
describe('MRWidgetSHAMismatch', () => {
|
||||
describe('template', () => {
|
||||
const Component = Vue.extend(shaMismatchComponent);
|
||||
const vm = new Component({
|
||||
el: document.createElement('div'),
|
||||
});
|
||||
it('should have correct elements', () => {
|
||||
expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
|
||||
expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy();
|
||||
expect(vm.$el.innerText).toContain('The source branch HEAD has recently changed. Please reload the page and review the changes before merging.');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -25,6 +25,9 @@ describe('getStateKey', () => {
|
|||
context.canBeMerged = true;
|
||||
expect(bound()).toEqual('readyToMerge');
|
||||
|
||||
context.hasSHAChanged = true;
|
||||
expect(bound()).toEqual('shaMismatch');
|
||||
|
||||
context.isPipelineBlocked = true;
|
||||
expect(bound()).toEqual('pipelineBlocked');
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import MergeRequestStore from '~/vue_merge_request_widget/stores/mr_widget_store';
|
||||
import mockData from '../mock_data';
|
||||
|
||||
describe('MergeRequestStore', () => {
|
||||
describe('setData', () => {
|
||||
let store;
|
||||
|
||||
beforeEach(() => {
|
||||
store = new MergeRequestStore(mockData);
|
||||
});
|
||||
|
||||
it('should set hasSHAChanged when the diff SHA changes', () => {
|
||||
store.setData({ ...mockData, diff_head_sha: 'a-different-string' });
|
||||
expect(store.hasSHAChanged).toBe(true);
|
||||
});
|
||||
|
||||
it('should not set hasSHAChanged when other data changes', () => {
|
||||
store.setData({ ...mockData, work_in_progress: !mockData.work_in_progress });
|
||||
expect(store.hasSHAChanged).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue