Skip to content
Snippets Groups Projects
Commit 8b614521 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent f864f8a7
No related branches found
No related tags found
No related merge requests found
Showing
with 350 additions and 46 deletions
12.6.0-pre
12.7.0-pre
Loading
Loading
@@ -14,7 +14,7 @@ module ChatMessage
obj_attr = HashWithIndifferentAccess.new(obj_attr)
@title = obj_attr[:title]
@wiki_page_url = obj_attr[:url]
@description = obj_attr[:content]
@description = obj_attr[:message]
 
@action =
case obj_attr[:action]
Loading
Loading
Loading
Loading
@@ -21,6 +21,7 @@ module ErrorTracking
:project_slug,
:short_id,
:status,
:tags,
:title,
:type,
:user_count
Loading
Loading
---
title: Add tags to sentry detailed error response
merge_request: 22068
author:
type: added
---
title: Add modsecurity_enabled setting to managed ingress
merge_request: 21968
author:
type: added
---
title: Include commit message instead of entire page content in Wiki chat notifications
merge_request: 21722
author: Ville Skyttä
type: changed
Loading
Loading
@@ -59,12 +59,6 @@ def subject_starts_with_capital?(subject)
first_char.upcase == first_char
end
 
def ce_upstream?
return unless gitlab_danger.ci?
gitlab.mr_labels.any? { |label| label == 'CE upstream' }
end
def too_many_changed_lines?(commit)
commit.diff_parent.stats[:total][:files] > 3 &&
lines_changed_in_commit(commit) >= 30
Loading
Loading
@@ -291,11 +285,11 @@ def lint_commits(commits)
end
end
 
if count_filtered_commits(git.commits) > 10 && !ce_upstream?
warn(
lint_commits(git.commits)
if count_filtered_commits(git.commits) > 10
fail(
'This merge request includes more than 10 commits. ' \
'Please rebase these commits into a smaller number of commits.'
)
else
lint_commits(git.commits)
end
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddModsecurityEnabledToIngressApplication < ActiveRecord::Migration[5.2]
DOWNTIME = false
def up
add_column :clusters_applications_ingress, :modsecurity_enabled, :boolean
end
def down
remove_column :clusters_applications_ingress, :modsecurity_enabled
end
end
Loading
Loading
@@ -1163,6 +1163,7 @@ ActiveRecord::Schema.define(version: 2019_12_18_225624) do
t.text "status_reason"
t.string "external_ip"
t.string "external_hostname"
t.boolean "modsecurity_enabled"
t.index ["cluster_id"], name: "index_clusters_applications_ingress_on_cluster_id", unique: true
end
 
Loading
Loading
Loading
Loading
@@ -31,11 +31,11 @@ export default new MyThing();
 
export default class MyThing {
constructor() {
if (!this.prototype.singleton) {
if (!MyThing.prototype.singleton) {
this.init();
this.prototype.singleton = this;
MyThing.prototype.singleton = this;
}
return this.prototype.singleton;
return MyThing.prototype.singleton;
}
 
init() {
Loading
Loading
Loading
Loading
@@ -26,6 +26,7 @@ module Gitlab
:project_slug,
:short_id,
:status,
:tags,
:title,
:type,
:user_count
Loading
Loading
Loading
Loading
@@ -36,6 +36,7 @@ module Sentry
id: issue.fetch('id'),
first_seen: issue.fetch('firstSeen', nil),
last_seen: issue.fetch('lastSeen', nil),
tags: extract_tags(issue),
title: issue.fetch('title', nil),
type: issue.fetch('type', nil),
user_count: issue.fetch('userCount', nil),
Loading
Loading
@@ -57,6 +58,13 @@ module Sentry
last_release_short_version: issue.dig('lastRelease', 'shortVersion')
)
end
def extract_tags(issue)
{
level: issue.fetch('level', nil),
logger: issue.fetch('logger', nil)
}
end
end
end
end
Loading
Loading
@@ -18,6 +18,12 @@ FactoryBot.define do
project_slug { 'project_name' }
short_id { 'ID' }
status { 'unresolved' }
tags do
{
level: 'error',
logger: 'rails'
}
end
frequency do
[
[Time.now.to_i, 10]
Loading
Loading
Loading
Loading
@@ -5,6 +5,7 @@
"external_base_url",
"last_seen",
"message",
"tags",
"type",
"title",
"project_id",
Loading
Loading
@@ -20,23 +21,38 @@
"last_release_short_version"
],
"properties" : {
"id": { "type": "string"},
"id": { "type": "string" },
"first_seen": { "type": "string", "format": "date-time" },
"last_seen": { "type": "string", "format": "date-time" },
"type": { "type": "string" },
"message": { "type": "string" },
"culprit": { "type": "string" },
"count": { "type": "integer"},
"count": { "type": "integer" },
"external_url": { "type": "string" },
"external_base_url": { "type": "string" },
"user_count": { "type": "integer"},
"title": { "type": "string"},
"project_id": { "type": "string"},
"project_name": { "type": "string"},
"project_slug": { "type": "string"},
"short_id": { "type": "string"},
"status": { "type": "string"},
"frequency": { "type": "array"},
"tags": {
"type": "object",
"required" : [
"level",
"logger"
],
"properties": {
"level": {
"type": "string"
},
"logger": {
"type": "string"
}
}
},
"title": { "type": "string" },
"project_id": { "type": "string" },
"project_name": { "type": "string" },
"project_slug": { "type": "string" },
"short_id": { "type": "string" },
"status": { "type": "string" },
"frequency": { "type": "array" },
"gitlab_issue": { "type": ["string", "null"] },
"first_release_last_commit": { "type": ["string", "null"] },
"last_release_last_commit": { "type": ["string", "null"] },
Loading
Loading
import BindInOut from '~/behaviors/bind_in_out';
import ClassSpecHelper from '../helpers/class_spec_helper';
describe('BindInOut', () => {
let testContext;
beforeEach(() => {
testContext = {};
});
describe('constructor', () => {
beforeEach(() => {
testContext.in = {};
testContext.out = {};
testContext.bindInOut = new BindInOut(testContext.in, testContext.out);
});
it('should set .in', () => {
expect(testContext.bindInOut.in).toBe(testContext.in);
});
it('should set .out', () => {
expect(testContext.bindInOut.out).toBe(testContext.out);
});
it('should set .eventWrapper', () => {
expect(testContext.bindInOut.eventWrapper).toEqual({});
});
describe('if .in is an input', () => {
beforeEach(() => {
testContext.bindInOut = new BindInOut({ tagName: 'INPUT' });
});
it('should set .eventType to keyup ', () => {
expect(testContext.bindInOut.eventType).toEqual('keyup');
});
});
describe('if .in is a textarea', () => {
beforeEach(() => {
testContext.bindInOut = new BindInOut({ tagName: 'TEXTAREA' });
});
it('should set .eventType to keyup ', () => {
expect(testContext.bindInOut.eventType).toEqual('keyup');
});
});
describe('if .in is not an input or textarea', () => {
beforeEach(() => {
testContext.bindInOut = new BindInOut({ tagName: 'SELECT' });
});
it('should set .eventType to change ', () => {
expect(testContext.bindInOut.eventType).toEqual('change');
});
});
});
describe('addEvents', () => {
beforeEach(() => {
testContext.in = {
addEventListener: jest.fn(),
};
testContext.bindInOut = new BindInOut(testContext.in);
testContext.addEvents = testContext.bindInOut.addEvents();
});
it('should set .eventWrapper.updateOut', () => {
expect(testContext.bindInOut.eventWrapper.updateOut).toEqual(expect.any(Function));
});
it('should call .addEventListener', () => {
expect(testContext.in.addEventListener).toHaveBeenCalledWith(
testContext.bindInOut.eventType,
testContext.bindInOut.eventWrapper.updateOut,
);
});
it('should return the instance', () => {
expect(testContext.addEvents).toBe(testContext.bindInOut);
});
});
describe('updateOut', () => {
beforeEach(() => {
testContext.in = { value: 'the-value' };
testContext.out = { textContent: 'not-the-value' };
testContext.bindInOut = new BindInOut(testContext.in, testContext.out);
testContext.updateOut = testContext.bindInOut.updateOut();
});
it('should set .out.textContent to .in.value', () => {
expect(testContext.out.textContent).toBe(testContext.in.value);
});
it('should return the instance', () => {
expect(testContext.updateOut).toBe(testContext.bindInOut);
});
});
describe('removeEvents', () => {
beforeEach(() => {
testContext.in = {
removeEventListener: jest.fn(),
};
testContext.updateOut = () => {};
testContext.bindInOut = new BindInOut(testContext.in);
testContext.bindInOut.eventWrapper.updateOut = testContext.updateOut;
testContext.removeEvents = testContext.bindInOut.removeEvents();
});
it('should call .removeEventListener', () => {
expect(testContext.in.removeEventListener).toHaveBeenCalledWith(
testContext.bindInOut.eventType,
testContext.updateOut,
);
});
it('should return the instance', () => {
expect(testContext.removeEvents).toBe(testContext.bindInOut);
});
});
describe('initAll', () => {
beforeEach(() => {
testContext.ins = [0, 1, 2];
testContext.instances = [];
jest.spyOn(document, 'querySelectorAll').mockReturnValue(testContext.ins);
jest.spyOn(Array.prototype, 'map');
jest.spyOn(BindInOut, 'init').mockImplementation(() => {});
testContext.initAll = BindInOut.initAll();
});
ClassSpecHelper.itShouldBeAStaticMethod(BindInOut, 'initAll');
it('should call .querySelectorAll', () => {
expect(document.querySelectorAll).toHaveBeenCalledWith('*[data-bind-in]');
});
it('should call .map', () => {
expect(Array.prototype.map).toHaveBeenCalledWith(expect.any(Function));
});
it('should call .init for each element', () => {
expect(BindInOut.init.mock.calls.length).toEqual(3);
});
it('should return an array of instances', () => {
expect(testContext.initAll).toEqual(expect.any(Array));
});
});
describe('init', () => {
beforeEach(() => {
// eslint-disable-next-line func-names
jest.spyOn(BindInOut.prototype, 'addEvents').mockImplementation(function() {
return this;
});
// eslint-disable-next-line func-names
jest.spyOn(BindInOut.prototype, 'updateOut').mockImplementation(function() {
return this;
});
testContext.init = BindInOut.init({}, {});
});
ClassSpecHelper.itShouldBeAStaticMethod(BindInOut, 'init');
it('should call .addEvents', () => {
expect(BindInOut.prototype.addEvents).toHaveBeenCalled();
});
it('should call .updateOut', () => {
expect(BindInOut.prototype.updateOut).toHaveBeenCalled();
});
describe('if no anOut is provided', () => {
beforeEach(() => {
testContext.anIn = { dataset: { bindIn: 'the-data-bind-in' } };
jest.spyOn(document, 'querySelector').mockImplementation(() => {});
BindInOut.init(testContext.anIn);
});
it('should call .querySelector', () => {
expect(document.querySelector).toHaveBeenCalledWith(
`*[data-bind-out="${testContext.anIn.dataset.bindIn}"]`,
);
});
});
});
});
import $ from 'jquery';
import '~/commons/bootstrap';
 
describe('Bootstrap jQuery extensions', function() {
describe('disable', function() {
beforeEach(function() {
return setFixtures('<input type="text" />');
describe('Bootstrap jQuery extensions', () => {
describe('disable', () => {
beforeEach(() => {
setFixtures('<input type="text" />');
});
 
it('adds the disabled attribute', function() {
it('adds the disabled attribute', () => {
const $input = $('input').first();
$input.disable();
 
expect($input).toHaveAttr('disabled', 'disabled');
});
return it('adds the disabled class', function() {
it('adds the disabled class', () => {
const $input = $('input').first();
$input.disable();
 
expect($input).toHaveClass('disabled');
});
});
return describe('enable', function() {
beforeEach(function() {
return setFixtures('<input type="text" disabled="disabled" class="disabled" />');
describe('enable', () => {
beforeEach(() => {
setFixtures('<input type="text" disabled="disabled" class="disabled" />');
});
 
it('removes the disabled attribute', function() {
it('removes the disabled attribute', () => {
const $input = $('input').first();
$input.enable();
 
expect($input).not.toHaveAttr('disabled');
});
return it('removes the disabled class', function() {
it('removes the disabled class', () => {
const $input = $('input').first();
$input.enable();
 
Loading
Loading
Loading
Loading
@@ -15,7 +15,7 @@ describe('branches delete modal', () => {
</div>
`);
$deleteButton = $('.js-delete-branch');
submitSpy = jasmine.createSpy('submit').and.callFake(event => event.preventDefault());
submitSpy = jest.fn(event => event.preventDefault());
$('#modal-delete-branch form').on('submit', submitSpy);
// eslint-disable-next-line no-new
new DeleteModal();
Loading
Loading
Loading
Loading
@@ -5,7 +5,7 @@ describe('breakpoints', () => {
const size = breakpoints[key];
 
it(`returns ${key} when larger than ${size}`, () => {
spyOn(bp, 'windowWidth').and.returnValue(size + 10);
jest.spyOn(bp, 'windowWidth').mockReturnValue(size + 10);
 
expect(bp.getBreakpointSize()).toBe(key);
});
Loading
Loading
@@ -13,13 +13,13 @@ describe('breakpoints', () => {
 
describe('isDesktop', () => {
it('returns true when screen size is medium', () => {
spyOn(bp, 'windowWidth').and.returnValue(breakpoints.md + 10);
jest.spyOn(bp, 'windowWidth').mockReturnValue(breakpoints.md + 10);
 
expect(bp.isDesktop()).toBe(true);
});
 
it('returns false when screen size is small', () => {
spyOn(bp, 'windowWidth').and.returnValue(breakpoints.sm + 10);
jest.spyOn(bp, 'windowWidth').mockReturnValue(breakpoints.sm + 10);
 
expect(bp.isDesktop()).toBe(false);
});
Loading
Loading
Loading
Loading
@@ -34,10 +34,10 @@ describe('Diff settiings dropdown component', () => {
 
beforeEach(() => {
actions = {
setInlineDiffViewType: jasmine.createSpy('setInlineDiffViewType'),
setParallelDiffViewType: jasmine.createSpy('setParallelDiffViewType'),
setRenderTreeList: jasmine.createSpy('setRenderTreeList'),
setShowWhitespace: jasmine.createSpy('setShowWhitespace'),
setInlineDiffViewType: jest.fn(),
setParallelDiffViewType: jest.fn(),
setRenderTreeList: jest.fn(),
setShowWhitespace: jest.fn(),
};
});
 
Loading
Loading
@@ -51,7 +51,7 @@ describe('Diff settiings dropdown component', () => {
 
vm.find('.js-list-view').trigger('click');
 
expect(actions.setRenderTreeList).toHaveBeenCalledWith(jasmine.anything(), false, undefined);
expect(actions.setRenderTreeList).toHaveBeenCalledWith(expect.anything(), false, undefined);
});
 
it('tree view button dispatches setRenderTreeList with true', () => {
Loading
Loading
@@ -59,7 +59,7 @@ describe('Diff settiings dropdown component', () => {
 
vm.find('.js-tree-view').trigger('click');
 
expect(actions.setRenderTreeList).toHaveBeenCalledWith(jasmine.anything(), true, undefined);
expect(actions.setRenderTreeList).toHaveBeenCalledWith(expect.anything(), true, undefined);
});
 
it('sets list button as active when renderTreeList is false', () => {
Loading
Loading
@@ -155,7 +155,7 @@ describe('Diff settiings dropdown component', () => {
checkbox.trigger('change');
 
expect(actions.setShowWhitespace).toHaveBeenCalledWith(
jasmine.anything(),
expect.anything(),
{
showWhitespace: true,
pushState: true,
Loading
Loading
import * as constants from '~/droplab/constants';
 
describe('constants', function() {
describe('DATA_TRIGGER', function() {
it('should be `data-dropdown-trigger`', function() {
describe('constants', () => {
describe('DATA_TRIGGER', () => {
it('should be `data-dropdown-trigger`', () => {
expect(constants.DATA_TRIGGER).toBe('data-dropdown-trigger');
});
});
 
describe('DATA_DROPDOWN', function() {
it('should be `data-dropdown`', function() {
describe('DATA_DROPDOWN', () => {
it('should be `data-dropdown`', () => {
expect(constants.DATA_DROPDOWN).toBe('data-dropdown');
});
});
 
describe('SELECTED_CLASS', function() {
it('should be `droplab-item-selected`', function() {
describe('SELECTED_CLASS', () => {
it('should be `droplab-item-selected`', () => {
expect(constants.SELECTED_CLASS).toBe('droplab-item-selected');
});
});
 
describe('ACTIVE_CLASS', function() {
it('should be `droplab-item-active`', function() {
describe('ACTIVE_CLASS', () => {
it('should be `droplab-item-active`', () => {
expect(constants.ACTIVE_CLASS).toBe('droplab-item-active');
});
});
 
describe('TEMPLATE_REGEX', function() {
it('should be a handlebars templating syntax regex', function() {
describe('TEMPLATE_REGEX', () => {
it('should be a handlebars templating syntax regex', () => {
expect(constants.TEMPLATE_REGEX).toEqual(/\{\{(.+?)\}\}/g);
});
});
 
describe('IGNORE_CLASS', function() {
it('should be `droplab-item-ignore`', function() {
describe('IGNORE_CLASS', () => {
it('should be `droplab-item-ignore`', () => {
expect(constants.IGNORE_CLASS).toBe('droplab-item-ignore');
});
});
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