Skip to content
Snippets Groups Projects
Commit 83ab2898 authored by John Jarvis's avatar John Jarvis
Browse files

Merge branch 'master' into 11-10-stable

parents bfec819f a6e9175f
No related branches found
No related tags found
No related merge requests found
Showing
with 139 additions and 76 deletions
Loading
Loading
@@ -1018,10 +1018,8 @@ schedule:review-build-cng:
 
.review-deploy-base: &review-deploy-base
<<: *review-base
retry: 2
allow_failure: true
variables:
GIT_DEPTH: "1"
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
GITLAB_HELM_CHART_REF: "master"
Loading
Loading
# Backend Maintainers are the default for all ruby files
*.rb @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @nick.thomas @rspeicher @rymai @smcgivern
*.rake @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @nick.thomas @rspeicher @rymai @smcgivern
*.rb @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @mkozono @nick.thomas @rspeicher @rymai @smcgivern
*.rake @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @mkozono @nick.thomas @rspeicher @rymai @smcgivern
 
# Technical writing team are the default reviewers for everything in `doc/`
/doc/ @axil @marcia
Loading
Loading
Loading
Loading
@@ -2,6 +2,19 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
 
## 11.9.5 (2019-04-03)
### Fixed (3 changes)
- Force to recreate all MR diffs on import. !26480
- Fix API /project/:id/branches not returning correct merge status. !26785
- Avoid excessive recursive calls with Rugged TreeEntries. !26813
### Performance (1 change)
- Force a full GC after importing a project. !26803
## 11.9.3 (2019-03-27)
 
### Security (8 changes)
Loading
Loading
Loading
Loading
@@ -13,3 +13,4 @@ danger.import_dangerfile(path: 'danger/prettier')
danger.import_dangerfile(path: 'danger/eslint')
danger.import_dangerfile(path: 'danger/roulette')
danger.import_dangerfile(path: 'danger/single_codebase')
danger.import_dangerfile(path: 'danger/gitlab_ui_wg')
Loading
Loading
@@ -54,7 +54,10 @@ export default Vue.extend({
return `${n__('%d issue', '%d issues', issuesSize)}`;
},
isNewIssueShown() {
return this.list.type === 'backlog' || (!this.disabled && this.list.type !== 'closed');
return (
this.list.type === 'backlog' ||
(!this.disabled && this.list.type !== 'closed' && this.list.type !== 'blank')
);
},
},
watch: {
Loading
Loading
Loading
Loading
@@ -40,6 +40,12 @@ export default class VariableList {
// converted. we need the value as a string.
default: $('.js-ci-variable-input-protected').attr('data-default'),
},
masked: {
selector: '.js-ci-variable-input-masked',
// use `attr` instead of `data` as we don't want the value to be
// converted. we need the value as a string.
default: $('.js-ci-variable-input-masked').attr('data-default'),
},
environment_scope: {
// We can't use a `.js-` class here because
// gl_dropdown replaces the <input> and doesn't copy over the class
Loading
Loading
@@ -88,13 +94,16 @@ export default class VariableList {
}
});
 
// Always make sure there is an empty last row
this.$container.on('input trigger-change', inputSelector, () => {
this.$container.on('input trigger-change', inputSelector, e => {
// Always make sure there is an empty last row
const $lastRow = this.$container.find('.js-row').last();
 
if (this.checkIfRowTouched($lastRow)) {
this.insertRow($lastRow);
}
// If masked, validate value against regex
this.validateMaskability($(e.currentTarget).closest('.js-row'));
});
}
 
Loading
Loading
@@ -171,12 +180,33 @@ export default class VariableList {
 
checkIfRowTouched($row) {
return Object.keys(this.inputMap).some(name => {
// Row should not qualify as touched if only switches have been touched
if (['protected', 'masked'].includes(name)) return false;
const entry = this.inputMap[name];
const $el = $row.find(entry.selector);
return $el.length && $el.val() !== entry.default;
});
}
 
validateMaskability($row) {
const invalidInputClass = 'gl-field-error-outline';
const maskableRegex = /^\w{8,}$/; // Eight or more alphanumeric characters plus underscores
const variableValue = $row.find(this.inputMap.secret_value.selector).val();
const isValueMaskable = maskableRegex.test(variableValue) || variableValue === '';
const isMaskedChecked = $row.find(this.inputMap.masked.selector).val() === 'true';
// Show a validation error if the user wants to mask an unmaskable variable value
$row
.find(this.inputMap.secret_value.selector)
.toggleClass(invalidInputClass, isMaskedChecked && !isValueMaskable);
$row
.find('.js-secret-value-placeholder')
.toggleClass(invalidInputClass, isMaskedChecked && !isValueMaskable);
$row.find('.masking-validation-error').toggle(isMaskedChecked && !isValueMaskable);
}
toggleEnableRow(isEnabled = true) {
this.$container.find(this.inputMap.key.selector).attr('disabled', !isEnabled);
this.$container.find('.js-row-remove-button').attr('disabled', !isEnabled);
Loading
Loading
Loading
Loading
@@ -188,10 +188,6 @@ export default {
/>
</div>
</template>
<div v-if="isFileTooLarge" class="nothing-here-block diff-collapsed js-too-large-diff">
{{ __('This source diff could not be displayed because it is too large.') }}
<span v-html="viewBlobLink"></span>
</div>
</div>
</template>
 
Loading
Loading
import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
import { decorateData, sortTree } from '../stores/utils';
 
export const escapeFileUrl = fileUrl => encodeURIComponent(fileUrl).replace(/%2F/g, '/');
export const splitParent = path => {
const idx = path.lastIndexOf('/');
 
Loading
Loading
@@ -45,7 +47,7 @@ export const decorateFiles = ({
id: path,
name,
path,
url: `/${projectId}/tree/${branchId}/-/${path}/`,
url: `/${projectId}/tree/${branchId}/-/${escapeFileUrl(path)}/`,
type: 'tree',
parentTreeUrl: parentFolder ? parentFolder.url : `/${projectId}/tree/${branchId}/`,
tempFile,
Loading
Loading
@@ -81,7 +83,7 @@ export const decorateFiles = ({
id: path,
name,
path,
url: `/${projectId}/blob/${branchId}/-/${path}`,
url: `/${projectId}/blob/${branchId}/-/${escapeFileUrl(path)}`,
type: 'blob',
parentTreeUrl: fileFolder ? fileFolder.url : `/${projectId}/blob/${branchId}`,
tempFile,
Loading
Loading
Loading
Loading
@@ -92,7 +92,7 @@ export const getTimeago = () => {
 
const timeAgoLocaleRemaining = [
() => [s__('Timeago|just now'), s__('Timeago|right now')],
() => [s__('Timeago|%s seconds ago'), s__('Timeago|%s seconds remaining')],
() => [s__('Timeago|just now'), s__('Timeago|%s seconds remaining')],
() => [s__('Timeago|1 minute ago'), s__('Timeago|1 minute remaining')],
() => [s__('Timeago|%s minutes ago'), s__('Timeago|%s minutes remaining')],
() => [s__('Timeago|1 hour ago'), s__('Timeago|1 hour remaining')],
Loading
Loading
@@ -121,7 +121,7 @@ export const getTimeago = () => {
 
const timeAgoLocale = [
() => [s__('Timeago|just now'), s__('Timeago|right now')],
() => [s__('Timeago|%s seconds ago'), s__('Timeago|in %s seconds')],
() => [s__('Timeago|just now'), s__('Timeago|in %s seconds')],
() => [s__('Timeago|1 minute ago'), s__('Timeago|in 1 minute')],
() => [s__('Timeago|%s minutes ago'), s__('Timeago|in %s minutes')],
() => [s__('Timeago|1 hour ago'), s__('Timeago|in 1 hour')],
Loading
Loading
@@ -160,7 +160,11 @@ export const getTimeago = () => {
* @param {Boolean} setTimeago
*/
export const localTimeAgo = ($timeagoEls, setTimeago = true) => {
getTimeago().render($timeagoEls, timeagoLanguageCode);
getTimeago();
$timeagoEls.each((i, el) => {
$(el).text(timeagoInstance.format($(el).attr('datetime'), timeagoLanguageCode));
});
 
if (!setTimeago) {
return;
Loading
Loading
Loading
Loading
@@ -86,9 +86,6 @@ export default {
},
computed: {
...mapGetters(['getUserDataByProp']),
showReplyButton() {
return gon.features && gon.features.replyToIndividualNotes && this.showReply;
},
shouldShowActionsDropdown() {
return this.currentUserId && (this.canEdit || this.canReportAsAbuse);
},
Loading
Loading
@@ -167,7 +164,7 @@ export default {
</a>
</div>
<reply-button
v-if="showReplyButton"
v-if="showReply"
ref="replyButton"
class="js-reply-button"
@startReplying="$emit('startReplying')"
Loading
Loading
Loading
Loading
@@ -96,7 +96,7 @@ export default {
return '';
}
 
// We need to do this to ensure we have the currect sentence order
// We need to do this to ensure we have the correct sentence order
// when translating this as the sentence order may change from one
// language to the next. See:
// https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24427#note_133713771
Loading
Loading
import $ from 'jquery';
import Flash from './flash';
import { __ } from '~/locale';
 
export default function notificationsDropdown() {
$(document).on('click', '.update-notification', function updateNotificationCallback(e) {
Loading
Loading
@@ -27,7 +28,7 @@ export default function notificationsDropdown() {
.closest('.js-notification-dropdown')
.replaceWith(data.html);
} else {
Flash('Failed to save new settings', 'alert');
Flash(__('Failed to save new settings'), 'alert');
}
});
}
/* eslint-disable class-methods-use-this */
const defaultTimezone = 'UTC';
export const formatUtcOffset = offset => {
const parsed = parseInt(offset, 10);
if (Number.isNaN(parsed) || parsed === 0) {
return `0`;
}
const prefix = offset > 0 ? '+' : '-';
return `${prefix} ${Math.abs(offset / 3600)}`;
};
 
import $ from 'jquery';
export const formatTimezone = item => `[UTC ${formatUtcOffset(item.offset)}] ${item.name}`;
 
const defaultTimezone = 'UTC';
const defaults = {
$inputEl: null,
$dropdownEl: null,
onSelectTimezone: null,
};
 
export default class TimezoneDropdown {
constructor() {
this.$dropdown = $('.js-timezone-dropdown');
constructor({ $dropdownEl, $inputEl, onSelectTimezone } = defaults) {
this.$dropdown = $dropdownEl;
this.$dropdownToggle = this.$dropdown.find('.dropdown-toggle-text');
this.$input = $('#schedule_cron_timezone');
this.$input = $inputEl;
this.timezoneData = this.$dropdown.data('data');
this.initDefaultTimezone();
this.initDropdown();
this.onSelectTimezone = onSelectTimezone;
}
 
initDropdown() {
Loading
Loading
@@ -24,28 +40,12 @@ export default class TimezoneDropdown {
fields: ['name'],
},
clicked: cfg => this.updateInputValue(cfg),
text: item => this.formatTimezone(item),
text: item => formatTimezone(item),
});
 
this.setDropdownToggle();
}
 
formatUtcOffset(offset) {
let prefix = '';
if (offset > 0) {
prefix = '+';
} else if (offset < 0) {
prefix = '-';
}
return `${prefix} ${Math.abs(offset / 3600)}`;
}
formatTimezone(item) {
return `[UTC ${this.formatUtcOffset(item.offset)}] ${item.name}`;
}
initDefaultTimezone() {
const initialValue = this.$input.val();
 
Loading
Loading
@@ -56,13 +56,14 @@ export default class TimezoneDropdown {
 
setDropdownToggle() {
const initialValue = this.$input.val();
this.$dropdownToggle.text(initialValue);
}
 
updateInputValue({ selectedObj, e }) {
e.preventDefault();
this.$input.val(selectedObj.identifier);
gl.pipelineScheduleFieldErrors.updateFormValidityState();
if (this.onSelectTimezone) {
this.onSelectTimezone({ selectedObj, e });
}
}
}
Loading
Loading
@@ -41,7 +41,13 @@ export default () => {
 
const formElement = document.getElementById('new-pipeline-schedule-form');
 
gl.timezoneDropdown = new TimezoneDropdown();
gl.timezoneDropdown = new TimezoneDropdown({
$dropdownEl: $('.js-timezone-dropdown'),
$inputEl: $('#schedule_cron_timezone'),
onSelectTimezone: () => {
gl.pipelineScheduleFieldErrors.updateFormValidityState();
},
});
gl.targetBranchDropdown = new TargetBranchDropdown();
gl.pipelineScheduleFieldErrors = new GlFieldErrors(formElement);
 
Loading
Loading
Loading
Loading
@@ -50,6 +50,9 @@ export default {
buttonLabel() {
return this.isTodo ? MARK_TEXT : TODO_TEXT;
},
buttonTooltip() {
return !this.collapsed ? undefined : this.buttonLabel;
},
collapsedButtonIconClasses() {
return this.isTodo ? 'todo-undone' : '';
},
Loading
Loading
@@ -69,7 +72,7 @@ export default {
<button
v-tooltip
:class="buttonClasses"
:title="buttonLabel"
:title="buttonTooltip"
:aria-label="buttonLabel"
:data-issuable-id="issuableId"
:data-issuable-type="issuableType"
Loading
Loading
Loading
Loading
@@ -109,29 +109,31 @@ export default {
></div>
</div>
 
<div v-if="mr.isOpen" class="branch-actions d-flex">
<a
v-if="!mr.sourceBranchRemoved"
v-tooltip
:href="webIdePath"
:title="ideButtonTitle"
:class="{ disabled: !mr.canPushToSourceBranch }"
class="btn btn-default js-web-ide d-none d-md-inline-block append-right-8"
data-placement="bottom"
tabindex="0"
role="button"
>
{{ s__('mrWidget|Open in Web IDE') }}
</a>
<button
:disabled="mr.sourceBranchRemoved"
data-target="#modal_merge_info"
data-toggle="modal"
class="btn btn-default js-check-out-branch append-right-default"
type="button"
>
{{ s__('mrWidget|Check out branch') }}
</button>
<div class="branch-actions d-flex">
<template v-if="mr.isOpen">
<a
v-if="!mr.sourceBranchRemoved"
v-tooltip
:href="webIdePath"
:title="ideButtonTitle"
:class="{ disabled: !mr.canPushToSourceBranch }"
class="btn btn-default js-web-ide d-none d-md-inline-block append-right-8"
data-placement="bottom"
tabindex="0"
role="button"
>
{{ s__('mrWidget|Open in Web IDE') }}
</a>
<button
:disabled="mr.sourceBranchRemoved"
data-target="#modal_merge_info"
data-toggle="modal"
class="btn btn-default js-check-out-branch append-right-default"
type="button"
>
{{ s__('mrWidget|Check out branch') }}
</button>
</template>
<span class="dropdown">
<button
type="button"
Loading
Loading
Loading
Loading
@@ -102,7 +102,7 @@ export default {
:style="{
width: onionMaxPixelWidth,
height: onionMaxPixelHeight,
'user-select': dragging === true ? 'none' : '',
'user-select': dragging ? 'none' : null,
}"
class="onion-skin-frame"
>
Loading
Loading
Loading
Loading
@@ -68,12 +68,10 @@ export default {
},
startDrag() {
this.dragging = true;
document.body.style.userSelect = 'none';
document.body.addEventListener('mousemove', this.dragMove);
},
stopDrag() {
this.dragging = false;
document.body.style.userSelect = '';
document.body.removeEventListener('mousemove', this.dragMove);
},
prepareSwipe() {
Loading
Loading
@@ -104,7 +102,13 @@ export default {
 
<template>
<div class="swipe view">
<div ref="swipeFrame" class="swipe-frame">
<div
ref="swipeFrame"
:style="{
'user-select': dragging ? 'none' : null,
}"
class="swipe-frame"
>
<image-viewer
key="swipeOldImg"
ref="swipeOldImg"
Loading
Loading
Loading
Loading
@@ -66,6 +66,7 @@
}
}
 
.ci-variable-masked-item,
.ci-variable-protected-item {
flex: 0 1 auto;
display: flex;
Loading
Loading
Loading
Loading
@@ -14,6 +14,7 @@
@include str-truncated(100%);
margin-top: -1px;
margin-bottom: 0;
font-size: $gl-font-size-small;
}
}
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment