Commit 17b577ad authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-03-20

parents bd861eb0 38bc4acb
...@@ -2,7 +2,7 @@ import $ from 'jquery'; ...@@ -2,7 +2,7 @@ import $ from 'jquery';
import autosize from 'autosize'; import autosize from 'autosize';
import GfmAutoComplete from './gfm_auto_complete'; import GfmAutoComplete from './gfm_auto_complete';
import dropzoneInput from './dropzone_input'; import dropzoneInput from './dropzone_input';
import textUtils from './lib/utils/text_markdown'; import { addMarkdownListeners, removeMarkdownListeners } from './lib/utils/text_markdown';
export default class GLForm { export default class GLForm {
constructor(form, enableGFM = false) { constructor(form, enableGFM = false) {
...@@ -47,7 +47,7 @@ export default class GLForm { ...@@ -47,7 +47,7 @@ export default class GLForm {
} }
// form and textarea event listeners // form and textarea event listeners
this.addEventListeners(); this.addEventListeners();
textUtils.init(this.form); addMarkdownListeners(this.form);
// hide discard button // hide discard button
this.form.find('.js-note-discard').hide(); this.form.find('.js-note-discard').hide();
this.form.show(); this.form.show();
...@@ -86,7 +86,7 @@ export default class GLForm { ...@@ -86,7 +86,7 @@ export default class GLForm {
clearEventListeners() { clearEventListeners() {
this.textarea.off('focus'); this.textarea.off('focus');
this.textarea.off('blur'); this.textarea.off('blur');
textUtils.removeListeners(this.form); removeMarkdownListeners(this.form);
} }
addEventListeners() { addEventListeners() {
......
/* eslint-disable import/prefer-default-export, func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, quotes, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, no-empty, max-len, consistent-return, no-unused-vars, no-return-assign, max-len, vars-on-top */ /* eslint-disable import/prefer-default-export, func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, quotes, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, no-empty, max-len, consistent-return, no-unused-vars, no-return-assign, max-len, vars-on-top */
import $ from 'jquery'; import $ from 'jquery';
import { insertText } from '~/lib/utils/common_utils';
const textUtils = {}; function selectedText(text, textarea) {
textUtils.selectedText = function(text, textarea) {
return text.substring(textarea.selectionStart, textarea.selectionEnd); return text.substring(textarea.selectionStart, textarea.selectionEnd);
}; }
textUtils.lineBefore = function(text, textarea) { function lineBefore(text, textarea) {
var split; var split;
split = text.substring(0, textarea.selectionStart).trim().split('\n'); split = text.substring(0, textarea.selectionStart).trim().split('\n');
return split[split.length - 1]; return split[split.length - 1];
}; }
textUtils.lineAfter = function(text, textarea) { function lineAfter(text, textarea) {
return text.substring(textarea.selectionEnd).trim().split('\n')[0]; return text.substring(textarea.selectionEnd).trim().split('\n')[0];
}; }
textUtils.blockTagText = function(text, textArea, blockTag, selected) { function blockTagText(text, textArea, blockTag, selected) {
var lineAfter, lineBefore; const before = lineBefore(text, textArea);
lineBefore = this.lineBefore(text, textArea); const after = lineAfter(text, textArea);
lineAfter = this.lineAfter(text, textArea); if (before === blockTag && after === blockTag) {
if (lineBefore === blockTag && lineAfter === blockTag) {
// To remove the block tag we have to select the line before & after // To remove the block tag we have to select the line before & after
if (blockTag != null) { if (blockTag != null) {
textArea.selectionStart = textArea.selectionStart - (blockTag.length + 1); textArea.selectionStart = textArea.selectionStart - (blockTag.length + 1);
...@@ -32,10 +29,30 @@ textUtils.blockTagText = function(text, textArea, blockTag, selected) { ...@@ -32,10 +29,30 @@ textUtils.blockTagText = function(text, textArea, blockTag, selected) {
} else { } else {
return blockTag + "\n" + selected + "\n" + blockTag; return blockTag + "\n" + selected + "\n" + blockTag;
} }
}; }
textUtils.insertText = function(textArea, text, tag, blockTag, selected, wrap) { function moveCursor(textArea, tag, wrapped, removedLastNewLine) {
var insertText, inserted, selectedSplit, startChar, removedLastNewLine, removedFirstNewLine, currentLineEmpty, lastNewLine; var pos;
if (!textArea.setSelectionRange) {
return;
}
if (textArea.selectionStart === textArea.selectionEnd) {
if (wrapped) {
pos = textArea.selectionStart - tag.length;
} else {
pos = textArea.selectionStart;
}
if (removedLastNewLine) {
pos -= 1;
}
return textArea.setSelectionRange(pos, pos);
}
}
export function insertMarkdownText(textArea, text, tag, blockTag, selected, wrap) {
var textToInsert, inserted, selectedSplit, startChar, removedLastNewLine, removedFirstNewLine, currentLineEmpty, lastNewLine;
removedLastNewLine = false; removedLastNewLine = false;
removedFirstNewLine = false; removedFirstNewLine = false;
currentLineEmpty = false; currentLineEmpty = false;
...@@ -67,9 +84,9 @@ textUtils.insertText = function(textArea, text, tag, blockTag, selected, wrap) { ...@@ -67,9 +84,9 @@ textUtils.insertText = function(textArea, text, tag, blockTag, selected, wrap) {
if (selectedSplit.length > 1 && (!wrap || (blockTag != null && blockTag !== ''))) { if (selectedSplit.length > 1 && (!wrap || (blockTag != null && blockTag !== ''))) {
if (blockTag != null && blockTag !== '') { if (blockTag != null && blockTag !== '') {
insertText = this.blockTagText(text, textArea, blockTag, selected); textToInsert = blockTagText(text, textArea, blockTag, selected);
} else { } else {
insertText = selectedSplit.map(function(val) { textToInsert = selectedSplit.map(function(val) {
if (val.indexOf(tag) === 0) { if (val.indexOf(tag) === 0) {
return "" + (val.replace(tag, '')); return "" + (val.replace(tag, ''));
} else { } else {
...@@ -78,78 +95,42 @@ textUtils.insertText = function(textArea, text, tag, blockTag, selected, wrap) { ...@@ -78,78 +95,42 @@ textUtils.insertText = function(textArea, text, tag, blockTag, selected, wrap) {
}).join('\n'); }).join('\n');
} }
} else { } else {
insertText = "" + startChar + tag + selected + (wrap ? tag : ' '); textToInsert = "" + startChar + tag + selected + (wrap ? tag : ' ');
} }
if (removedFirstNewLine) { if (removedFirstNewLine) {
insertText = '\n' + insertText; textToInsert = '\n' + textToInsert;
} }
if (removedLastNewLine) { if (removedLastNewLine) {
insertText += '\n'; textToInsert += '\n';
} }
if (document.queryCommandSupported('insertText')) { insertText(textArea, textToInsert);
inserted = document.execCommand('insertText', false, insertText); return moveCursor(textArea, tag, wrap, removedLastNewLine);
} }
if (!inserted) {
try {
document.execCommand("ms-beginUndoUnit");
} catch (error) {}
textArea.value = this.replaceRange(text, textArea.selectionStart, textArea.selectionEnd, insertText);
try {
document.execCommand("ms-endUndoUnit");
} catch (error) {}
}
return this.moveCursor(textArea, tag, wrap, removedLastNewLine);
};
textUtils.moveCursor = function(textArea, tag, wrapped, removedLastNewLine) { function updateText(textArea, tag, blockTag, wrap) {
var pos;
if (!textArea.setSelectionRange) {
return;
}
if (textArea.selectionStart === textArea.selectionEnd) {
if (wrapped) {
pos = textArea.selectionStart - tag.length;
} else {
pos = textArea.selectionStart;
}
if (removedLastNewLine) {
pos -= 1;
}
return textArea.setSelectionRange(pos, pos);
}
};
textUtils.updateText = function(textArea, tag, blockTag, wrap) {
var $textArea, selected, text; var $textArea, selected, text;
$textArea = $(textArea); $textArea = $(textArea);
textArea = $textArea.get(0); textArea = $textArea.get(0);
text = $textArea.val(); text = $textArea.val();
selected = this.selectedText(text, textArea); selected = selectedText(text, textArea);
$textArea.focus(); $textArea.focus();
return this.insertText(textArea, text, tag, blockTag, selected, wrap); return insertMarkdownText(textArea, text, tag, blockTag, selected, wrap);
}; }
textUtils.init = function(form) { function replaceRange(s, start, end, substitute) {
var self; return s.substring(0, start) + substitute + s.substring(end);
self = this; }
export function addMarkdownListeners(form) {
return $('.js-md', form).off('click').on('click', function() { return $('.js-md', form).off('click').on('click', function() {
var $this; const $this = $(this);
$this = $(this); return updateText($this.closest('.md-area').find('textarea'), $this.data('mdTag'), $this.data('mdBlock'), !$this.data('mdPrepend'));
return self.updateText($this.closest('.md-area').find('textarea'), $this.data('mdTag'), $this.data('mdBlock'), !$this.data('mdPrepend'));
}); });
}; }
textUtils.removeListeners = function(form) { export function removeMarkdownListeners(form) {
return $('.js-md', form).off('click'); return $('.js-md', form).off('click');
}; }
textUtils.replaceRange = function(s, start, end, substitute) {
return s.substring(0, start) + substitute + s.substring(end);
};
export default textUtils;
...@@ -143,7 +143,11 @@ module Ci ...@@ -143,7 +143,11 @@ module Ci
next if build.retries_max.zero? next if build.retries_max.zero?
if build.retries_count < build.retries_max if build.retries_count < build.retries_max
Ci::Build.retry(build, build.user) begin
Ci::Build.retry(build, build.user)
rescue Gitlab::Access::AccessDeniedError => ex
Rails.logger.error "Unable to auto-retry job #{build.id}: #{ex}"
end
end end
end end
......
---
title: Fix Firefox stealing formatting characters on issue notes
merge_request:
author:
type: fixed
---
title: Prevent auto-retry AccessDenied error from stopping transition to failed
merge_request: 17862
author:
type: fixed
...@@ -6,6 +6,7 @@ module QA ...@@ -6,6 +6,7 @@ module QA
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js' do view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js' do
element :merge_button element :merge_button
element :fast_forward_message, 'Fast-forward merge without a merge commit'
end end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do
...@@ -14,19 +15,19 @@ module QA ...@@ -14,19 +15,19 @@ module QA
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue' do view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue' do
element :mr_rebase_button element :mr_rebase_button
element :fast_forward_nessage, "Fast-forward merge is not possible" element :no_fast_forward_message, 'Fast-forward merge is not possible'
end end
def rebase! def rebase!
wait(reload: false) do click_element :mr_rebase_button
click_element :mr_rebase_button
has_text?("The source branch HEAD has recently changed.") wait(reload: false) do
has_text?('Fast-forward merge without a merge commit')
end end
end end
def fast_forward_possible? def fast_forward_possible?
!has_text?("Fast-forward merge is not possible") !has_text?('Fast-forward merge is not possible')
end end
def has_merge_button? def has_merge_button?
...@@ -36,10 +37,10 @@ module QA ...@@ -36,10 +37,10 @@ module QA
end end
def merge! def merge!
wait(reload: false) do click_element :merge_button
click_element :merge_button
has_text?("The changes were merged into") wait(reload: false) do
has_text?('The changes were merged into')
end end
end end
end end
......
import textUtils from '~/lib/utils/text_markdown'; import { insertMarkdownText } from '~/lib/utils/text_markdown';
describe('init markdown', () => { describe('init markdown', () => {
let textArea; let textArea;
...@@ -21,7 +21,7 @@ describe('init markdown', () => { ...@@ -21,7 +21,7 @@ describe('init markdown', () => {
textArea.selectionStart = 0; textArea.selectionStart = 0;
textArea.selectionEnd = 0; textArea.selectionEnd = 0;
textUtils.insertText(textArea, textArea.value, '*', null, '', false); insertMarkdownText(textArea, textArea.value, '*', null, '', false);
expect(textArea.value).toEqual(`${initialValue}* `); expect(textArea.value).toEqual(`${initialValue}* `);
}); });
...@@ -32,7 +32,7 @@ describe('init markdown', () => { ...@@ -32,7 +32,7 @@ describe('init markdown', () => {
textArea.value = initialValue; textArea.value = initialValue;
textArea.setSelectionRange(initialValue.length, initialValue.length); textArea.setSelectionRange(initialValue.length, initialValue.length);
textUtils.insertText(textArea, textArea.value, '*', null, '', false); insertMarkdownText(textArea, textArea.value, '*', null, '', false);
expect(textArea.value).toEqual(`${initialValue}\n* `); expect(textArea.value).toEqual(`${initialValue}\n* `);
}); });
...@@ -43,7 +43,7 @@ describe('init markdown', () => { ...@@ -43,7 +43,7 @@ describe('init markdown', () => {
textArea.value = initialValue; textArea.value = initialValue;
textArea.setSelectionRange(initialValue.length, initialValue.length); textArea.setSelectionRange(initialValue.length, initialValue.length);
textUtils.insertText(textArea, textArea.value, '*', null, '', false); insertMarkdownText(textArea, textArea.value, '*', null, '', false);
expect(textArea.value).toEqual(`${initialValue}* `); expect(textArea.value).toEqual(`${initialValue}* `);
}); });
...@@ -54,7 +54,7 @@ describe('init markdown', () => { ...@@ -54,7 +54,7 @@ describe('init markdown', () => {
textArea.value = initialValue; textArea.value = initialValue;
textArea.setSelectionRange(initialValue.length, initialValue.length); textArea.setSelectionRange(initialValue.length, initialValue.length);
textUtils.insertText(textArea, textArea.value, '*', null, '', false); insertMarkdownText(textArea, textArea.value, '*', null, '', false);
expect(textArea.value).toEqual(`${initialValue}* `); expect(textArea.value).toEqual(`${initialValue}* `);
}); });
......
...@@ -2121,6 +2121,35 @@ describe Ci::Build do ...@@ -2121,6 +2121,35 @@ describe Ci::Build do
subject.drop! subject.drop!
end end
context 'when retry service raises Gitlab::Access::AccessDeniedError exception' do
let(:retry_service) { Ci::RetryBuildService.new(subject.project, subject.user) }
before do
allow_any_instance_of(Ci::RetryBuildService)
.to receive(:execute)
.with(subject)
.and_raise(Gitlab::Access::AccessDeniedError)
allow(Rails.logger).to receive(:error)
end
it 'handles raised exception' do
expect { subject.drop! }.not_to raise_exception(Gitlab::Access::AccessDeniedError)
end
it 'logs the error' do
subject.drop!
expect(Rails.logger)
.to have_received(:error)
.with(a_string_matching("Unable to auto-retry job #{subject.id}"))
end
it 'fails the job' do
subject.drop!
expect(subject.failed?).to be_truthy
end
end
end end
context 'when build is not configured to be retried' do context 'when build is not configured to be retried' 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