Commit 071bf3b7 authored by Alfredo Sumaran's avatar Alfredo Sumaran Committed by Felipe Artur

Merge branch '28010-mr-merge-button-default-to-danger' into 'master'

Default to dangerous MR merge button

Closes #28010

See merge request !9245
parent e2b45367
...@@ -129,8 +129,9 @@ require('./smart_interval'); ...@@ -129,8 +129,9 @@ require('./smart_interval');
}; };
MergeRequestWidget.prototype.getMergeStatus = function() { MergeRequestWidget.prototype.getMergeStatus = function() {
return $.get(this.opts.merge_check_url, function(data) { return $.get(this.opts.merge_check_url, (data) => {
var $html = $(data); var $html = $(data);
this.updateMergeButton(this.status, this.hasCi, $html);
$('.mr-widget-body').replaceWith($html.find('.mr-widget-body')); $('.mr-widget-body').replaceWith($html.find('.mr-widget-body'));
$('.mr-widget-footer').replaceWith($html.find('.mr-widget-footer')); $('.mr-widget-footer').replaceWith($html.find('.mr-widget-footer'));
}); });
...@@ -154,9 +155,9 @@ require('./smart_interval'); ...@@ -154,9 +155,9 @@ require('./smart_interval');
return $.getJSON(this.opts.ci_status_url, (function(_this) { return $.getJSON(this.opts.ci_status_url, (function(_this) {
return function(data) { return function(data) {
var message, status, title; var message, status, title;
if (!data.status) { _this.status = data.status;
return; _this.hasCi = data.has_ci;
} _this.updateMergeButton(_this.status, _this.hasCi);
if (data.environments && data.environments.length) _this.renderEnvironments(data.environments); if (data.environments && data.environments.length) _this.renderEnvironments(data.environments);
if (data.status !== _this.opts.ci_status || if (data.status !== _this.opts.ci_status ||
data.sha !== _this.opts.ci_sha || data.sha !== _this.opts.ci_sha ||
...@@ -227,42 +228,51 @@ require('./smart_interval'); ...@@ -227,42 +228,51 @@ require('./smart_interval');
}; };
MergeRequestWidget.prototype.showCIStatus = function(state) { MergeRequestWidget.prototype.showCIStatus = function(state) {
// TODO: Can this variable be removed? - Felipe Artur
var allowed_states; var allowed_states;
if (state == null) { if (state == null) {
return; return;
} }
$('.ci_widget').hide(); $('.ci_widget').hide();
allowed_states = ["failed", "canceled", "running", "pending", "success", "success_with_warnings", "skipped", "not_found"];
if (indexOf.call(allowed_states, state) >= 0) {
$('.ci_widget.ci-' + state).show(); $('.ci_widget.ci-' + state).show();
this.initMiniPipelineGraph();
};
MergeRequestWidget.prototype.showCICoverage = function(coverage) {
var text = `Coverage ${coverage}%`;
return $('.ci_widget:visible .ci-coverage').text(text);
};
MergeRequestWidget.prototype.updateMergeButton = function(state, hasCi, $html) {
const allowed_states = ["failed", "canceled", "running", "pending", "success", "success_with_warnings", "skipped", "not_found"];
let stateClass = 'btn-danger';
if (!hasCi) {
stateClass = 'btn-create';
} else if (indexOf.call(allowed_states, state) !== -1) {
switch (state) { switch (state) {
case "failed": case "failed":
case "canceled": case "canceled":
case "not_found": case "not_found":
this.setMergeButtonClass('btn-danger'); stateClass = 'btn-danger';
break; break;
case "running": case "running":
this.setMergeButtonClass('btn-info'); stateClass = 'btn-info';
break; break;
case "success": case "success":
case "success_with_warnings": case "success_with_warnings":
this.setMergeButtonClass('btn-create'); stateClass = 'btn-create';
} }
} else { } else {
$('.ci_widget.ci-error').show(); $('.ci_widget.ci-error').show();
this.setMergeButtonClass('btn-danger'); stateClass = 'btn-danger';
} }
this.initMiniPipelineGraph();
};
MergeRequestWidget.prototype.showCICoverage = function(coverage) { this.setMergeButtonClass(stateClass, $html);
var text;
text = 'Coverage ' + coverage + '%';
return $('.ci_widget:visible .ci-coverage').text(text);
}; };
MergeRequestWidget.prototype.setMergeButtonClass = function(css_class) { MergeRequestWidget.prototype.setMergeButtonClass = function(css_class, $html = $('.mr-state-widget')) {
return $('.js-merge-button,.accept-action .dropdown-toggle').removeClass('btn-danger btn-info btn-create').addClass(css_class); return $html.find('.js-merge-button').removeClass('btn-danger btn-info btn-create').addClass(css_class);
}; };
MergeRequestWidget.prototype.updatePipelineUrls = function(id) { MergeRequestWidget.prototype.updatePipelineUrls = function(id) {
......
...@@ -15,15 +15,15 @@ ...@@ -15,15 +15,15 @@
}); });
$(document) $(document)
.off('click', '.accept_merge_request') .off('click', '.accept-merge-request')
.on('click', '.accept_merge_request', () => { .on('click', '.accept-merge-request', () => {
$('.js-merge-button').html('<i class="fa fa-spinner fa-spin"></i> Merge in progress'); $('.js-merge-button, .js-merge-when-pipeline-succeeds-button').html('<i class="fa fa-spinner fa-spin"></i> Merge in progress');
}); });
$(document) $(document)
.off('click', '.merge_when_build_succeeds') .off('click', '.merge-when-pipeline-succeeds')
.on('click', '.merge_when_build_succeeds', () => { .on('click', '.merge-when-pipeline-succeeds', () => {
$('#merge_when_build_succeeds').val('1'); $('#merge_when_pipeline_succeeds').val('1');
}); });
$(document) $(document)
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
background-color: $gl-success; background-color: $gl-success;
} }
.accept_merge_request { .accept-merge-request {
&.ci-pending, &.ci-pending,
&.ci-running { &.ci-running {
@include btn-blue; @include btn-blue;
...@@ -42,6 +42,12 @@ ...@@ -42,6 +42,12 @@
@include btn-red; @include btn-red;
} }
} }
.dropdown-toggle {
.fa {
color: inherit;
}
}
} }
.accept-control { .accept-control {
......
...@@ -308,6 +308,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -308,6 +308,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def merge_check def merge_check
@merge_request.check_if_can_be_merged @merge_request.check_if_can_be_merged
@pipelines = @merge_request.all_pipelines
render partial: "projects/merge_requests/widget/show.html.haml", layout: false render partial: "projects/merge_requests/widget/show.html.haml", layout: false
end end
...@@ -426,6 +427,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -426,6 +427,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def ci_status def ci_status
pipeline = @merge_request.head_pipeline pipeline = @merge_request.head_pipeline
@pipelines = @merge_request.all_pipelines
if pipeline if pipeline
status = pipeline.status status = pipeline.status
...@@ -444,7 +446,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -444,7 +446,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
sha: (merge_request.diff_head_commit.short_id if merge_request.diff_head_sha), sha: (merge_request.diff_head_commit.short_id if merge_request.diff_head_sha),
status: status, status: status,
coverage: coverage, coverage: coverage,
pipeline: pipeline.try(:id) pipeline: pipeline.try(:id),
has_ci: @merge_request.has_ci?
} }
render json: response render json: response
......
...@@ -692,7 +692,10 @@ class MergeRequest < ActiveRecord::Base ...@@ -692,7 +692,10 @@ class MergeRequest < ActiveRecord::Base
end end
def has_ci? def has_ci?
source_project.try(:ci_service) && commits.any? has_ci_integration = source_project.try(:ci_service)
uses_gitlab_ci = all_pipelines.any?
(has_ci_integration || uses_gitlab_ci) && commits.any?
end end
def branch_missing? def branch_missing?
......
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('merge_request_widget') = page_specific_javascript_bundle_tag('merge_request_widget')
- status_class = @pipeline ? " ci-#{@pipeline.status}" : nil
= form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-quick-submit js-requires-input' } do |f| = form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-quick-submit js-requires-input' } do |f|
= hidden_field_tag :authenticity_token, form_authenticity_token = hidden_field_tag :authenticity_token, form_authenticity_token
= hidden_field_tag :sha, @merge_request.diff_head_sha = hidden_field_tag :sha, @merge_request.diff_head_sha
...@@ -11,10 +9,10 @@ ...@@ -11,10 +9,10 @@
.accept-action .accept-action
- if @pipeline && @pipeline.active? - if @pipeline && @pipeline.active?
%span.btn-group %span.btn-group
= button_tag class: "btn btn-create js-merge-button merge_when_build_succeeds" do = button_tag class: "btn btn-info js-merge-when-pipeline-succeeds-button merge-when-pipeline-succeeds" do
Merge When Pipeline Succeeds Merge When Pipeline Succeeds
- unless @project.only_allow_merge_if_build_succeeds? - unless @project.only_allow_merge_if_pipeline_succeeds?
= button_tag class: "btn btn-success dropdown-toggle", 'data-toggle' => 'dropdown' do = button_tag class: "btn btn-info dropdown-toggle", 'data-toggle' => 'dropdown' do
= icon('caret-down') = icon('caret-down')
%span.sr-only %span.sr-only
Select Merge Moment Select Merge Moment
...@@ -24,11 +22,11 @@ ...@@ -24,11 +22,11 @@
= icon('check fw') = icon('check fw')
Merge When Pipeline Succeeds Merge When Pipeline Succeeds
%li %li
= link_to "#", class: "accept_merge_request" do = link_to "#", class: "accept-merge-request" do
= icon('warning fw') = icon('warning fw')
Merge Immediately Merge Immediately
- else - else
= f.button class: "btn btn-create btn-grouped js-merge-button accept_merge_request #{status_class}" do = f.button class: "btn btn-grouped js-merge-button accept-merge-request" do
Accept Merge Request Accept Merge Request
- if @merge_request.force_remove_source_branch? - if @merge_request.force_remove_source_branch?
.accept-control .accept-control
......
---
title: Default to subtle MR mege button until CI status is available
merge_request:
author:
...@@ -34,7 +34,7 @@ feature 'Merge immediately', :feature, :js do ...@@ -34,7 +34,7 @@ feature 'Merge immediately', :feature, :js do
click_link 'Merge Immediately' click_link 'Merge Immediately'
expect(find('.js-merge-button')).to have_content('Merge in progress') expect(find('.js-merge-when-pipeline-succeeds-button')).to have_content('Merge in progress')
end end
end end
end end
......
...@@ -3,8 +3,8 @@ require 'rails_helper' ...@@ -3,8 +3,8 @@ require 'rails_helper'
describe 'Merge request', :feature, :js do describe 'Merge request', :feature, :js do
include WaitForAjax include WaitForAjax
let(:project) { create(:project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project) }
let(:merge_request) { create(:merge_request, source_project: project) } let(:merge_request) { create(:merge_request, source_project: project) }
before do before do
...@@ -31,7 +31,7 @@ describe 'Merge request', :feature, :js do ...@@ -31,7 +31,7 @@ describe 'Merge request', :feature, :js do
wait_for_ajax wait_for_ajax
expect(page).to have_selector('.accept_merge_request') expect(page).to have_selector('.accept-merge-request')
end end
end end
...@@ -51,6 +51,69 @@ describe 'Merge request', :feature, :js do ...@@ -51,6 +51,69 @@ describe 'Merge request', :feature, :js do
expect(find('.js-environment-link')[:href]).to include(environment.formatted_external_url) expect(find('.js-environment-link')[:href]).to include(environment.formatted_external_url)
end end
end end
it 'shows green accept merge request button' do
# Wait for the `ci_status` and `merge_check` requests
wait_for_ajax
expect(page).to have_selector('.accept-merge-request.btn-create')
end
end
context 'view merge request with external CI service' do
before do
create(:service, project: project,
active: true,
type: 'CiService',
category: 'ci')
visit namespace_project_merge_request_path(project.namespace, project, merge_request)
end
it 'has danger button while waiting for external CI status' do
# Wait for the `ci_status` and `merge_check` requests
wait_for_ajax
expect(page).to have_selector('.accept-merge-request.btn-danger')
end
end
context 'view merge request with failed GitLab CI pipelines' do
before do
commit_status = create(:commit_status, project: project, status: 'failed')
pipeline = create(:ci_pipeline, project: project,
sha: merge_request.diff_head_sha,
ref: merge_request.source_branch,
status: 'failed',
statuses: [commit_status])
create(:ci_build, :pending, pipeline: pipeline)
visit namespace_project_merge_request_path(project.namespace, project, merge_request)
end
it 'has danger button when not succeeded' do
# Wait for the `ci_status` and `merge_check` requests
wait_for_ajax
expect(page).to have_selector('.accept-merge-request.btn-danger')
end
end
context 'view merge request with MWBS button' do
before do
commit_status = create(:commit_status, project: project, status: 'pending')
pipeline = create(:ci_pipeline, project: project,
sha: merge_request.diff_head_sha,
ref: merge_request.source_branch,
status: 'pending',
statuses: [commit_status])
create(:ci_build, :pending, pipeline: pipeline)
visit namespace_project_merge_request_path(project.namespace, project, merge_request)
end
it 'has info button when MWBS button' do
# Wait for the `ci_status` and `merge_check` requests
wait_for_ajax
expect(page).to have_selector('.merge-when-pipeline-succeeds.btn-info')
end
end end
context 'merge error' do context 'merge error' do
......
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