Merge remote-tracking branch 'origin/master' into droplab-templating-xss-fix
This commit is contained in:
commit
6a6a672037
|
@ -49,7 +49,7 @@ eslint-report.html
|
|||
/tags
|
||||
/tmp/*
|
||||
/vendor/bundle/*
|
||||
/builds/*
|
||||
/builds*
|
||||
/shared/*
|
||||
/.gitlab_workhorse_secret
|
||||
/webpack-report/
|
||||
|
|
|
@ -59,7 +59,7 @@ stages:
|
|||
|
||||
.only-master-and-ee-or-mysql: &only-master-and-ee-or-mysql
|
||||
only:
|
||||
- /\-(?i)mysql$/
|
||||
- /mysql/
|
||||
- master@gitlab-org/gitlab-ce
|
||||
- master@gitlab/gitlabhq
|
||||
- tags@gitlab-org/gitlab-ce
|
||||
|
|
|
@ -1 +1 @@
|
|||
5.0.2
|
||||
5.0.3
|
||||
|
|
|
@ -716,7 +716,7 @@ GEM
|
|||
rack
|
||||
shoulda-matchers (2.8.0)
|
||||
activesupport (>= 3.0.0)
|
||||
sidekiq (4.2.7)
|
||||
sidekiq (4.2.10)
|
||||
concurrent-ruby (~> 1.0)
|
||||
connection_pool (~> 2.2, >= 2.2.0)
|
||||
rack-protection (>= 1.5.0)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import Cookies from 'js-cookie';
|
||||
import './breakpoints';
|
||||
import './flash';
|
||||
import BlobForkSuggestion from './blob/blob_fork_suggestion';
|
||||
|
||||
/* eslint-disable max-len */
|
||||
// MergeRequestTabs
|
||||
|
@ -266,6 +267,17 @@ import './flash';
|
|||
|
||||
new gl.Diff();
|
||||
this.scrollToElement('#diffs');
|
||||
|
||||
$('.diff-file').each((i, el) => {
|
||||
new BlobForkSuggestion({
|
||||
openButtons: $(el).find('.js-edit-blob-link-fork-toggler'),
|
||||
forkButtons: $(el).find('.js-fork-suggestion-button'),
|
||||
cancelButtons: $(el).find('.js-cancel-fork-suggestion-button'),
|
||||
suggestionSections: $(el).find('.js-file-fork-suggestion-section'),
|
||||
actionTextPieces: $(el).find('.js-file-fork-suggestion-section-action'),
|
||||
})
|
||||
.init();
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ class PrometheusGraph {
|
|||
const hasMetrics = $prometheusContainer.data('has-metrics');
|
||||
this.docLink = $prometheusContainer.data('doc-link');
|
||||
this.integrationLink = $prometheusContainer.data('prometheus-integration');
|
||||
this.state = '';
|
||||
|
||||
$(document).ajaxError(() => {});
|
||||
|
||||
|
@ -38,8 +39,9 @@ class PrometheusGraph {
|
|||
this.configureGraph();
|
||||
this.init();
|
||||
} else {
|
||||
const prevState = this.state;
|
||||
this.state = '.js-getting-started';
|
||||
this.updateState();
|
||||
this.updateState(prevState);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,26 +55,26 @@ class PrometheusGraph {
|
|||
}
|
||||
|
||||
init() {
|
||||
this.getData().then((metricsResponse) => {
|
||||
return this.getData().then((metricsResponse) => {
|
||||
let enoughData = true;
|
||||
if (typeof metricsResponse === 'undefined') {
|
||||
enoughData = false;
|
||||
} else {
|
||||
Object.keys(metricsResponse.metrics).forEach((key) => {
|
||||
let currentKey;
|
||||
if (key === 'cpu_values' || key === 'memory_values') {
|
||||
currentKey = metricsResponse.metrics[key];
|
||||
if (Object.keys(currentKey).length === 0) {
|
||||
const currentData = (metricsResponse.metrics[key])[0];
|
||||
if (currentData.values.length <= 2) {
|
||||
enoughData = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!enoughData) {
|
||||
this.state = '.js-loading';
|
||||
this.updateState();
|
||||
} else {
|
||||
}
|
||||
if (enoughData) {
|
||||
$(prometheusStatesContainer).hide();
|
||||
$(prometheusParentGraphContainer).show();
|
||||
this.transformData(metricsResponse);
|
||||
this.createGraph();
|
||||
}
|
||||
}).catch(() => {
|
||||
new Flash('An error occurred when trying to load metrics. Please try again.');
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -342,6 +344,8 @@ class PrometheusGraph {
|
|||
|
||||
getData() {
|
||||
const maxNumberOfRequests = 3;
|
||||
this.state = '.js-loading';
|
||||
this.updateState();
|
||||
return gl.utils.backOff((next, stop) => {
|
||||
$.ajax({
|
||||
url: metricsEndpoint,
|
||||
|
@ -352,12 +356,11 @@ class PrometheusGraph {
|
|||
this.backOffRequestCounter = this.backOffRequestCounter += 1;
|
||||
if (this.backOffRequestCounter < maxNumberOfRequests) {
|
||||
next();
|
||||
} else {
|
||||
stop({
|
||||
status: resp.status,
|
||||
metrics: data,
|
||||
});
|
||||
} else if (this.backOffRequestCounter >= maxNumberOfRequests) {
|
||||
stop(new Error('loading'));
|
||||
}
|
||||
} else if (!data.success) {
|
||||
stop(new Error('loading'));
|
||||
} else {
|
||||
stop({
|
||||
status: resp.status,
|
||||
|
@ -373,8 +376,9 @@ class PrometheusGraph {
|
|||
return resp.metrics;
|
||||
})
|
||||
.catch(() => {
|
||||
const prevState = this.state;
|
||||
this.state = '.js-unable-to-connect';
|
||||
this.updateState();
|
||||
this.updateState(prevState);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -382,19 +386,20 @@ class PrometheusGraph {
|
|||
Object.keys(metricsResponse.metrics).forEach((key) => {
|
||||
if (key === 'cpu_values' || key === 'memory_values') {
|
||||
const metricValues = (metricsResponse.metrics[key])[0];
|
||||
if (metricValues !== undefined) {
|
||||
this.graphSpecificProperties[key].data = metricValues.values.map(metric => ({
|
||||
time: new Date(metric[0] * 1000),
|
||||
value: metric[1],
|
||||
}));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateState() {
|
||||
updateState(prevState) {
|
||||
const $statesContainer = $(prometheusStatesContainer);
|
||||
$(prometheusParentGraphContainer).hide();
|
||||
if (prevState) {
|
||||
$(`${prevState}`, $statesContainer).addClass('hidden');
|
||||
}
|
||||
$(`${this.state}`, $statesContainer).removeClass('hidden');
|
||||
$(prometheusStatesContainer).show();
|
||||
}
|
||||
|
|
|
@ -108,8 +108,7 @@
|
|||
}
|
||||
|
||||
.award-control {
|
||||
margin: 3px 5px 3px 0;
|
||||
padding: .35em .4em;
|
||||
margin-right: 5px;
|
||||
outline: 0;
|
||||
|
||||
&.disabled {
|
||||
|
|
|
@ -70,7 +70,7 @@ pre {
|
|||
}
|
||||
|
||||
hr {
|
||||
margin: $gl-padding 0;
|
||||
margin: 24px 0;
|
||||
border-top: 1px solid darken($gray-normal, 8%);
|
||||
}
|
||||
|
||||
|
|
|
@ -73,14 +73,6 @@
|
|||
|
||||
&.wiki {
|
||||
padding: 30px $gl-padding;
|
||||
|
||||
.highlight {
|
||||
margin-bottom: 9px;
|
||||
|
||||
> pre {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.blob-no-preview {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
padding: 0;
|
||||
|
||||
.timeline-entry {
|
||||
padding: $gl-padding $gl-btn-padding 14px;
|
||||
padding: $gl-padding $gl-btn-padding 0;
|
||||
border-color: $white-normal;
|
||||
color: $gl-text-color;
|
||||
border-bottom: 1px solid $border-white-light;
|
||||
|
|
|
@ -8,6 +8,13 @@
|
|||
|
||||
img {
|
||||
max-width: 100%;
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
|
||||
p a:not(.no-attachment-icon) img {
|
||||
// Remove bottom padding because
|
||||
// <p> already has $gl-padding bottom
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
*:first-child:not(.katex-display) {
|
||||
|
@ -47,44 +54,50 @@
|
|||
h1 {
|
||||
font-size: 1.75em;
|
||||
font-weight: 600;
|
||||
margin: 16px 0 10px;
|
||||
padding: 0 0 0.3em;
|
||||
margin: 24px 0 16px;
|
||||
padding-bottom: 0.3em;
|
||||
border-bottom: 1px solid $white-dark;
|
||||
color: $gl-text-color;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.5em;
|
||||
font-weight: 600;
|
||||
margin: 16px 0 10px;
|
||||
margin: 24px 0 16px;
|
||||
padding-bottom: 0.3em;
|
||||
border-bottom: 1px solid $white-dark;
|
||||
color: $gl-text-color;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 16px 0 10px;
|
||||
margin: 24px 0 16px;
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin: 16px 0 10px;
|
||||
margin: 24px 0 16px;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
margin: 16px 0 10px;
|
||||
margin: 24px 0 16px;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
margin: 16px 0 10px;
|
||||
margin: 24px 0 16px;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
color: $gl-grayish-blue;
|
||||
font-size: inherit;
|
||||
padding: 8px 21px;
|
||||
margin: 12px 0;
|
||||
padding: 8px 24px;
|
||||
margin: 16px 0;
|
||||
border-left: 3px solid $white-dark;
|
||||
}
|
||||
|
||||
|
@ -95,19 +108,20 @@
|
|||
|
||||
blockquote p {
|
||||
color: $gl-grayish-blue !important;
|
||||
margin: 0;
|
||||
font-size: inherit;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
p {
|
||||
color: $gl-text-color;
|
||||
margin: 6px 0 0;
|
||||
margin: 0 0 16px;
|
||||
}
|
||||
|
||||
table {
|
||||
@extend .table;
|
||||
@extend .table-bordered;
|
||||
margin: 12px 0;
|
||||
margin: 16px 0;
|
||||
color: $gl-text-color;
|
||||
|
||||
th {
|
||||
|
@ -120,7 +134,7 @@
|
|||
}
|
||||
|
||||
pre {
|
||||
margin: 12px 0;
|
||||
margin-bottom: 16px;
|
||||
font-size: 13px;
|
||||
line-height: 1.6em;
|
||||
overflow-x: auto;
|
||||
|
@ -134,7 +148,7 @@
|
|||
ul,
|
||||
ol {
|
||||
padding: 0;
|
||||
margin: 3px 0 !important;
|
||||
margin: 0 0 16px !important;
|
||||
}
|
||||
|
||||
ul:dir(rtl),
|
||||
|
|
|
@ -29,11 +29,5 @@
|
|||
|
||||
.description {
|
||||
margin-top: 6px;
|
||||
|
||||
p {
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
|
||||
.title {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-bottom: 16px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
|
@ -357,6 +357,8 @@
|
|||
}
|
||||
|
||||
.detail-page-description {
|
||||
padding: 16px 0 0;
|
||||
|
||||
small {
|
||||
color: $gray-darkest;
|
||||
}
|
||||
|
@ -364,6 +366,8 @@
|
|||
|
||||
.edited-text {
|
||||
color: $gray-darkest;
|
||||
display: block;
|
||||
margin: 0 0 16px;
|
||||
|
||||
.author_link {
|
||||
color: $gray-darkest;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
.note-edit-form {
|
||||
.note-form-actions {
|
||||
position: relative;
|
||||
margin-top: $gl-padding;
|
||||
margin: $gl-padding 0;
|
||||
}
|
||||
|
||||
.note-preview-holder {
|
||||
|
|
|
@ -102,13 +102,12 @@ ul.notes {
|
|||
|
||||
.note-awards {
|
||||
.js-awards-block {
|
||||
padding: 2px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.note-header {
|
||||
padding-bottom: 3px;
|
||||
padding-bottom: 8px;
|
||||
padding-right: 20px;
|
||||
|
||||
@media (min-width: $screen-sm-min) {
|
||||
|
@ -151,6 +150,10 @@ ul.notes {
|
|||
margin-left: 65px;
|
||||
}
|
||||
|
||||
.note-header {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
&.timeline-entry::after {
|
||||
clear: none;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ class Admin::GroupsController < Admin::ApplicationController
|
|||
|
||||
if @group.save
|
||||
@group.add_owner(current_user)
|
||||
redirect_to [:admin, @group], notice: 'Group was successfully created.'
|
||||
redirect_to [:admin, @group], notice: "Group '#{@group.name}' was successfully created."
|
||||
else
|
||||
render "new"
|
||||
end
|
||||
|
|
|
@ -29,7 +29,7 @@ module BlobHelper
|
|||
link_to 'Edit', edit_path(project, ref, path, options), class: "#{common_classes} btn-sm"
|
||||
elsif current_user && can?(current_user, :fork_project, project)
|
||||
continue_params = {
|
||||
to: edit_path,
|
||||
to: edit_path(project, ref, path, options),
|
||||
notice: edit_in_new_fork_notice,
|
||||
notice_now: edit_in_new_fork_notice_now
|
||||
}
|
||||
|
|
|
@ -191,22 +191,23 @@ class MergeRequest < ActiveRecord::Base
|
|||
merge_request_diff ? merge_request_diff.raw_diffs(*args) : compare.raw_diffs(*args)
|
||||
end
|
||||
|
||||
def diffs(diff_options = nil)
|
||||
def diffs(diff_options = {})
|
||||
if compare
|
||||
compare.diffs(diff_options)
|
||||
# When saving MR diffs, `no_collapse` is implicitly added (because we need
|
||||
# to save the entire contents to the DB), so add that here for
|
||||
# consistency.
|
||||
compare.diffs(diff_options.merge(no_collapse: true))
|
||||
else
|
||||
merge_request_diff.diffs(diff_options)
|
||||
end
|
||||
end
|
||||
|
||||
def diff_size
|
||||
# The `#diffs` method ends up at an instance of a class inheriting from
|
||||
# `Gitlab::Diff::FileCollection::Base`, so use those options as defaults
|
||||
# here too, to get the same diff size without performing highlighting.
|
||||
#
|
||||
opts = Gitlab::Diff::FileCollection::Base.default_options.merge(diff_options || {})
|
||||
# Calling `merge_request_diff.diffs.real_size` will also perform
|
||||
# highlighting, which we don't need here.
|
||||
return real_size if merge_request_diff
|
||||
|
||||
raw_diffs(opts).size
|
||||
diffs.real_size
|
||||
end
|
||||
|
||||
def diff_base_commit
|
||||
|
|
|
@ -260,7 +260,7 @@ class MergeRequestDiff < ActiveRecord::Base
|
|||
new_attributes[:state] = :empty
|
||||
else
|
||||
diff_collection = compare.diffs(Commit.max_diff_options)
|
||||
new_attributes[:real_size] = compare.diffs.real_size
|
||||
new_attributes[:real_size] = diff_collection.real_size
|
||||
|
||||
if diff_collection.any?
|
||||
new_diffs = dump_diffs(diff_collection)
|
||||
|
|
|
@ -6,8 +6,8 @@ module Users
|
|||
@params = params.dup
|
||||
end
|
||||
|
||||
def execute
|
||||
raise Gitlab::Access::AccessDeniedError unless can_create_user?
|
||||
def execute(skip_authorization: false)
|
||||
raise Gitlab::Access::AccessDeniedError unless skip_authorization || can_create_user?
|
||||
|
||||
user = User.new(build_user_params)
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ module Users
|
|||
@params = params.dup
|
||||
end
|
||||
|
||||
def execute
|
||||
user = Users::BuildService.new(current_user, params).execute
|
||||
def execute(skip_authorization: false)
|
||||
user = Users::BuildService.new(current_user, params).execute(skip_authorization: skip_authorization)
|
||||
|
||||
@reset_token = user.generate_reset_token if user.recently_sent_password_reset?
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
.bs-callout.bs-callout-warning.clearfix
|
||||
%p
|
||||
User cohorts are only shown when the
|
||||
= link_to 'usage ping', help_page_path('user/admin_area/usage_statistics'), target: '_blank'
|
||||
= link_to 'usage ping', help_page_path('user/admin_area/settings/usage_statistics', anchor: 'usage-ping'), target: '_blank'
|
||||
is enabled. To enable it and see user cohorts,
|
||||
visit
|
||||
= succeed '.' do
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
Snippets
|
||||
|
||||
- if project_nav_tab? :settings
|
||||
= nav_link(path: %w[projects#edit members#show integrations#show repository#show ci_cd#show pages#show]) do
|
||||
= nav_link(path: %w[projects#edit members#show integrations#show services#edit repository#show ci_cd#show pages#show]) do
|
||||
= link_to edit_project_path(@project), title: 'Settings', class: 'shortcuts-tree' do
|
||||
%span
|
||||
Settings
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
- if current_user
|
||||
.js-file-fork-suggestion-section.file-fork-suggestion.hidden
|
||||
%span.file-fork-suggestion-note
|
||||
You're not allowed to
|
||||
%span.js-file-fork-suggestion-section-action
|
||||
edit
|
||||
files in this project directly. Please fork this project,
|
||||
make your changes there, and submit a merge request.
|
||||
= link_to 'Fork', nil, method: :post, class: 'js-fork-suggestion-button btn btn-grouped btn-inverted btn-new'
|
||||
%button.js-cancel-fork-suggestion-button.btn.btn-grouped{ type: 'button' }
|
||||
Cancel
|
|
@ -39,14 +39,4 @@
|
|||
= replace_blob_link
|
||||
= delete_blob_link
|
||||
|
||||
- if current_user
|
||||
.js-file-fork-suggestion-section.file-fork-suggestion.hidden
|
||||
%span.file-fork-suggestion-note
|
||||
You're not allowed to
|
||||
%span.js-file-fork-suggestion-section-action
|
||||
edit
|
||||
files in this project directly. Please fork this project,
|
||||
make your changes there, and submit a merge request.
|
||||
= link_to 'Fork', nil, method: :post, class: 'js-fork-suggestion-button btn btn-grouped btn-inverted btn-new'
|
||||
%button.js-cancel-fork-suggestion-button.btn.btn-grouped{ type: 'button' }
|
||||
Cancel
|
||||
= render 'projects/fork_suggestion'
|
||||
|
|
|
@ -18,4 +18,6 @@
|
|||
= view_file_button(diff_commit.id, diff_file.new_path, project)
|
||||
= view_on_environment_button(diff_commit.id, diff_file.new_path, environment) if environment
|
||||
|
||||
= render 'projects/fork_suggestion'
|
||||
|
||||
= render 'projects/diffs/content', diff_file: diff_file, diff_commit: diff_commit, blob: blob, project: project
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
= link_to 'Edit', edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: 'hidden-xs hidden-sm btn btn-grouped issuable-edit'
|
||||
|
||||
.issue-details.issuable-details
|
||||
.detail-page-description.content-block{ class: ('hide-bottom-border' unless @issue.description.present? ) }
|
||||
.detail-page-description.content-block
|
||||
.issue-title-data.hidden{ "data" => { "initial-title" => markdown_field(@issue, :title),
|
||||
"endpoint" => rendered_title_namespace_project_issue_path(@project.namespace, @project, @issue),
|
||||
} }
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
%a.btn.btn-default.btn-grouped.pull-right.visible-xs-block.js-sidebar-toggle{ href: "#" }
|
||||
= icon('angle-double-left')
|
||||
|
||||
.detail-page-description.milestone-detail{ class: ('hide-bottom-border' unless @milestone.description.present? ) }
|
||||
.detail-page-description.milestone-detail
|
||||
%h2.title
|
||||
= markdown_field(@milestone, :title)
|
||||
%div
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
- page_title @service.title, "Services"
|
||||
= render "projects/settings/head"
|
||||
= render 'form'
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
%span
|
||||
Members
|
||||
- if can_edit
|
||||
= nav_link(controller: :integrations) do
|
||||
= nav_link(controller: [:integrations, :services]) do
|
||||
= link_to project_settings_integrations_path(@project), title: 'Integrations' do
|
||||
%span
|
||||
Integrations
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Show group name on flash container when group is created from Admin area.
|
||||
merge_request: 10905
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Cleanup markdown spacing
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Don't display the is_admin flag in most API responses
|
||||
merge_request: 10846
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Add sub-nav for Project Integration Services edit page
|
||||
merge_request: 10813
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Fix OAuth, LDAP and SAML SSO when regular sign-ups are disabled
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Fix usage ping docs link from empty cohorts page
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Add index to webhooks type column
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Fixed Prometheus monitoring graphs not showing empty states in certain scenarios
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Show sizes correctly in merge requests when diffs overflow
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Upgrade Sidekiq to 4.2.10
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,15 @@
|
|||
class AddIndexToWebHooksType < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_index :web_hooks, :type
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index :web_hooks, :type
|
||||
end
|
||||
end
|
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20170423064036) do
|
||||
ActiveRecord::Schema.define(version: 20170424142900) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -1371,6 +1371,7 @@ ActiveRecord::Schema.define(version: 20170423064036) do
|
|||
end
|
||||
|
||||
add_index "web_hooks", ["project_id"], name: "index_web_hooks_on_project_id", using: :btree
|
||||
add_index "web_hooks", ["type"], name: "index_web_hooks_on_type", using: :btree
|
||||
|
||||
add_foreign_key "boards", "projects"
|
||||
add_foreign_key "chat_teams", "namespaces", on_delete: :cascade
|
||||
|
|
|
@ -48,7 +48,6 @@ Example of response
|
|||
"bio": null,
|
||||
"created_at": "2016-08-11T07:09:20.351Z",
|
||||
"id": 1,
|
||||
"is_admin": true,
|
||||
"linkedin": "",
|
||||
"location": null,
|
||||
"name": "Administrator",
|
||||
|
@ -106,7 +105,6 @@ Example of response
|
|||
"bio": null,
|
||||
"created_at": "2016-08-11T07:09:20.351Z",
|
||||
"id": 1,
|
||||
"is_admin": true,
|
||||
"linkedin": "",
|
||||
"location": null,
|
||||
"name": "Administrator",
|
||||
|
@ -195,7 +193,6 @@ Example of response
|
|||
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
|
||||
"web_url": "http://localhost:3000/root",
|
||||
"created_at": "2016-08-11T07:09:20.351Z",
|
||||
"is_admin": true,
|
||||
"bio": null,
|
||||
"location": null,
|
||||
"skype": "",
|
||||
|
|
|
@ -57,7 +57,6 @@ Example of response
|
|||
"bio": null,
|
||||
"created_at": "2015-12-21T13:14:24.077Z",
|
||||
"id": 1,
|
||||
"is_admin": true,
|
||||
"linkedin": "",
|
||||
"name": "Administrator",
|
||||
"skype": "",
|
||||
|
@ -101,7 +100,6 @@ Example of response
|
|||
"bio": null,
|
||||
"created_at": "2015-12-21T13:14:24.077Z",
|
||||
"id": 1,
|
||||
"is_admin": true,
|
||||
"linkedin": "",
|
||||
"name": "Administrator",
|
||||
"skype": "",
|
||||
|
@ -173,7 +171,6 @@ Example of response
|
|||
"bio": null,
|
||||
"created_at": "2015-12-21T13:14:24.077Z",
|
||||
"id": 1,
|
||||
"is_admin": true,
|
||||
"linkedin": "",
|
||||
"name": "Administrator",
|
||||
"skype": "",
|
||||
|
@ -217,7 +214,6 @@ Example of response
|
|||
"bio": null,
|
||||
"created_at": "2015-12-21T13:14:24.077Z",
|
||||
"id": 1,
|
||||
"is_admin": true,
|
||||
"linkedin": "",
|
||||
"name": "Administrator",
|
||||
"skype": "",
|
||||
|
@ -284,7 +280,6 @@ Example of response
|
|||
"bio": null,
|
||||
"created_at": "2015-12-21T13:14:24.077Z",
|
||||
"id": 1,
|
||||
"is_admin": true,
|
||||
"linkedin": "",
|
||||
"name": "Administrator",
|
||||
"skype": "",
|
||||
|
|
|
@ -26,7 +26,6 @@ Parameters:
|
|||
"avatar_url": "http://www.gravatar.com/avatar/cfa35b8cd2ec278026357769582fa563?s=40\u0026d=identicon",
|
||||
"web_url": "http://localhost:3000/john_smith",
|
||||
"created_at": "2015-09-03T07:24:01.670Z",
|
||||
"is_admin": false,
|
||||
"bio": null,
|
||||
"skype": "",
|
||||
"linkedin": "",
|
||||
|
|
|
@ -62,7 +62,6 @@ GET /users
|
|||
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg",
|
||||
"web_url": "http://localhost:3000/john_smith",
|
||||
"created_at": "2012-05-23T08:00:58Z",
|
||||
"is_admin": false,
|
||||
"bio": null,
|
||||
"location": null,
|
||||
"skype": "",
|
||||
|
@ -95,7 +94,6 @@ GET /users
|
|||
"avatar_url": "http://localhost:3000/uploads/user/avatar/2/index.jpg",
|
||||
"web_url": "http://localhost:3000/jack_smith",
|
||||
"created_at": "2012-05-23T08:01:01Z",
|
||||
"is_admin": false,
|
||||
"bio": null,
|
||||
"location": null,
|
||||
"skype": "",
|
||||
|
@ -169,7 +167,6 @@ Parameters:
|
|||
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg",
|
||||
"web_url": "http://localhost:3000/john_smith",
|
||||
"created_at": "2012-05-23T08:00:58Z",
|
||||
"is_admin": false,
|
||||
"bio": null,
|
||||
"location": null,
|
||||
"skype": "",
|
||||
|
@ -200,7 +197,6 @@ Parameters:
|
|||
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg",
|
||||
"web_url": "http://localhost:3000/john_smith",
|
||||
"created_at": "2012-05-23T08:00:58Z",
|
||||
"is_admin": false,
|
||||
"bio": null,
|
||||
"location": null,
|
||||
"skype": "",
|
||||
|
@ -325,7 +321,6 @@ GET /user
|
|||
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg",
|
||||
"web_url": "http://localhost:3000/john_smith",
|
||||
"created_at": "2012-05-23T08:00:58Z",
|
||||
"is_admin": false,
|
||||
"bio": null,
|
||||
"location": null,
|
||||
"skype": "",
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
## Backend howtos
|
||||
|
||||
- [Architecture](architecture.md) of GitLab
|
||||
- [CI setup](ci_setup.md) for testing GitLab
|
||||
- [Gotchas](gotchas.md) to avoid
|
||||
- [How to dump production data to staging](db_dump.md)
|
||||
- [Instrumentation](instrumentation.md)
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
# CI setup
|
||||
|
||||
This document describes what services we use for testing GitLab and GitLab CI.
|
||||
|
||||
We currently use four CI services to test GitLab:
|
||||
|
||||
1. GitLab CI on [GitHost.io](https://gitlab-ce.githost.io/projects/4/) for the [GitLab.com repo](https://gitlab.com/gitlab-org/gitlab-ce)
|
||||
2. GitLab CI at ci.gitlab.org to test the private GitLab B.V. repo at dev.gitlab.org
|
||||
3. [Semephore](https://semaphoreapp.com/gitlabhq/gitlabhq/) for [GitHub.com repo](https://github.com/gitlabhq/gitlabhq)
|
||||
4. [Mock CI Service](../user/project/integrations/mock_ci.md) for local development
|
||||
|
||||
| Software @ configuration being tested | GitLab CI (ci.gitlab.org) | GitLab CI (GitHost.io) | Semaphore |
|
||||
|---------------------------------------|---------------------------|---------------------------------------------------------------------------|-----------|
|
||||
| GitLab CE @ MySQL | ✓ | ✓ [Core team can trigger builds](https://gitlab-ce.githost.io/projects/4) | |
|
||||
| GitLab CE @ PostgreSQL | | | ✓ [Core team can trigger builds](https://semaphoreapp.com/gitlabhq/gitlabhq/branches/master) |
|
||||
| GitLab EE @ MySQL | ✓ | | |
|
||||
| GitLab CI @ MySQL | ✓ | | |
|
||||
| GitLab CI @ PostgreSQL | | | ✓ |
|
||||
| GitLab CI Runner | ✓ | | ✓ |
|
||||
| GitLab Shell | ✓ | | ✓ |
|
||||
| GitLab Shell | ✓ | | ✓ |
|
||||
|
||||
Core team has access to trigger builds if needed for GitLab CE.
|
||||
|
||||
We use [these build scripts](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml) for testing with GitLab CI.
|
||||
|
||||
# Build configuration on [Semaphore](https://semaphoreapp.com/gitlabhq/gitlabhq/) for testing the [GitHub.com repo](https://github.com/gitlabhq/gitlabhq)
|
||||
|
||||
- Language: Ruby
|
||||
- Ruby version: 2.1.8
|
||||
- database.yml: pg
|
||||
|
||||
Build commands
|
||||
|
||||
```bash
|
||||
sudo apt-get install cmake libicu-dev -y (Setup)
|
||||
bundle install --deployment --path vendor/bundle (Setup)
|
||||
cp config/gitlab.yml.example config/gitlab.yml (Setup)
|
||||
bundle exec rake db:create (Setup)
|
||||
bundle exec rake spinach (Thread #1)
|
||||
bundle exec rake spec (thread #2)
|
||||
bundle exec rake rubocop (thread #3)
|
||||
bundle exec rake brakeman (thread #4)
|
||||
bundle exec rake jasmine:ci (thread #5)
|
||||
```
|
||||
|
||||
Use rubygems mirror.
|
|
@ -448,13 +448,22 @@ is used for Spinach tests as well.
|
|||
|
||||
### Monitoring
|
||||
|
||||
The GitLab test suite is [monitored] and a [public dashboard] is available for
|
||||
everyone to see. Feel free to look at the slowest test files and try to improve
|
||||
them.
|
||||
The GitLab test suite is [monitored] for the `master` branch, and any branch
|
||||
that includes `rspec-profile` in their name.
|
||||
|
||||
A [public dashboard] is available for everyone to see. Feel free to look at the
|
||||
slowest test files and try to improve them.
|
||||
|
||||
[monitored]: ./performance.md#rspec-profiling
|
||||
[public dashboard]: https://redash.gitlab.com/public/dashboards/l1WhHXaxrCWM5Ai9D7YDqHKehq6OU3bx5gssaiWe?org_slug=default
|
||||
|
||||
## CI setup
|
||||
|
||||
- On CE, the test suite only runs against PostgreSQL by default. We additionally
|
||||
run the suite against MySQL for tags, `master`, and any branch that includes
|
||||
`mysql` in the name.
|
||||
- On EE, the test suite always runs both PostgreSQL and MySQL.
|
||||
|
||||
## Spinach (feature) tests
|
||||
|
||||
GitLab [moved from Cucumber to Spinach](https://github.com/gitlabhq/gitlabhq/pull/1426)
|
||||
|
|
|
@ -12,7 +12,7 @@ You can leave a comment in the following places:
|
|||
|
||||
The comment area supports [Markdown] and [slash commands]. One can edit their
|
||||
own comment at any time, and anyone with [Master access level][permissions] or
|
||||
higher can also a comment made by someone else.
|
||||
higher can also edit a comment made by someone else.
|
||||
|
||||
Apart from the standard comments, you also have the option to create a comment
|
||||
in the form of a resolvable or threaded discussion.
|
||||
|
|
|
@ -431,7 +431,7 @@ Emphasis, aka italics, with *asterisks* or _underscores_.
|
|||
|
||||
Strong emphasis, aka bold, with **asterisks** or __underscores__.
|
||||
|
||||
Combined emphasis with **_asterisks and underscores_**.
|
||||
Combined emphasis with **asterisks and _underscores_**.
|
||||
|
||||
Strikethrough uses two tildes. ~~Scratch this.~~
|
||||
```
|
||||
|
@ -640,10 +640,11 @@ Here's a line for us to start with.
|
|||
This line is separated from the one above by two newlines, so it will be a *separate paragraph*.
|
||||
|
||||
This line is also a separate paragraph, but...
|
||||
This line is only separated by a single newline, so it's a separate line in the *same paragraph*.
|
||||
This line is only separated by a single newline, so it *does not break* and just follows the previous line in the *same paragraph*.
|
||||
|
||||
This line is also a separate paragraph, and...
|
||||
This line is on its own line, because the previous line ends with two
|
||||
This line is *on its own line*, because the previous line ends with two spaces. (but still in the *same paragraph*)
|
||||
|
||||
spaces.
|
||||
```
|
||||
|
||||
|
@ -651,11 +652,12 @@ Here's a line for us to start with.
|
|||
|
||||
This line is separated from the one above by two newlines, so it will be a *separate paragraph*.
|
||||
|
||||
This line is also begins a separate paragraph, but...
|
||||
This line is only separated by a single newline, so it's a separate line in the *same paragraph*.
|
||||
This line is also a separate paragraph, but...
|
||||
This line is only separated by a single newline, so it *does not break* and just follows the previous line in the *same paragraph*.
|
||||
|
||||
This line is also a separate paragraph, and...
|
||||
This line is on its own line, because the previous line ends with two
|
||||
This line is *on its own line*, because the previous line ends with two spaces. (but still in the *same paragraph*)
|
||||
|
||||
spaces.
|
||||
|
||||
### Tables
|
||||
|
|
|
@ -14,7 +14,6 @@ module API
|
|||
|
||||
class User < UserBasic
|
||||
expose :created_at
|
||||
expose :admin?, as: :is_admin
|
||||
expose :bio, :location, :skype, :linkedin, :twitter, :website_url, :organization
|
||||
end
|
||||
|
||||
|
@ -41,8 +40,9 @@ module API
|
|||
expose :external
|
||||
end
|
||||
|
||||
class UserWithPrivateToken < UserPublic
|
||||
class UserWithPrivateDetails < UserPublic
|
||||
expose :private_token
|
||||
expose :admin?, as: :is_admin
|
||||
end
|
||||
|
||||
class Email < Grape::Entity
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module API
|
||||
class Session < Grape::API
|
||||
desc 'Login to get token' do
|
||||
success Entities::UserWithPrivateToken
|
||||
success Entities::UserWithPrivateDetails
|
||||
end
|
||||
params do
|
||||
optional :login, type: String, desc: 'The username'
|
||||
|
@ -14,7 +14,7 @@ module API
|
|||
|
||||
return unauthorized! unless user
|
||||
return render_api_error!('401 Unauthorized. You have 2FA enabled. Please use a personal access token to access the API', 401) if user.two_factor_enabled?
|
||||
present user, with: Entities::UserWithPrivateToken
|
||||
present user, with: Entities::UserWithPrivateDetails
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -433,7 +433,7 @@ module API
|
|||
success Entities::UserPublic
|
||||
end
|
||||
get do
|
||||
present current_user, with: sudo? ? Entities::UserWithPrivateToken : Entities::UserPublic
|
||||
present current_user, with: sudo? ? Entities::UserWithPrivateDetails : Entities::UserPublic
|
||||
end
|
||||
|
||||
desc "Get the currently authenticated user's SSH keys" do
|
||||
|
|
|
@ -15,6 +15,10 @@ module Gitlab
|
|||
super.tap { |_| store_highlight_cache }
|
||||
end
|
||||
|
||||
def real_size
|
||||
@merge_request_diff.real_size
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Extracted method to highlight in the same iteration to the diff_collection.
|
||||
|
|
|
@ -148,7 +148,7 @@ module Gitlab
|
|||
|
||||
def build_new_user
|
||||
user_params = user_attributes.merge(extern_uid: auth_hash.uid, provider: auth_hash.provider, skip_confirmation: true)
|
||||
Users::BuildService.new(nil, user_params).execute
|
||||
Users::BuildService.new(nil, user_params).execute(skip_authorization: true)
|
||||
end
|
||||
|
||||
def user_attributes
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
feature 'Diffs URL', js: true, feature: true do
|
||||
before do
|
||||
login_as :admin
|
||||
@merge_request = create(:merge_request)
|
||||
@project = @merge_request.source_project
|
||||
end
|
||||
let(:project) { create(:project, :public) }
|
||||
let(:merge_request) { create(:merge_request, source_project: project) }
|
||||
|
||||
context 'when visit with */* as accept header' do
|
||||
before(:each) do
|
||||
|
@ -13,9 +10,9 @@ feature 'Diffs URL', js: true, feature: true do
|
|||
end
|
||||
|
||||
it 'renders the notes' do
|
||||
create :note_on_merge_request, project: @project, noteable: @merge_request, note: 'Rebasing with master'
|
||||
create :note_on_merge_request, project: project, noteable: merge_request, note: 'Rebasing with master'
|
||||
|
||||
visit diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)
|
||||
visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request)
|
||||
|
||||
# Load notes and diff through AJAX
|
||||
expect(page).to have_css('.note-text', visible: false, text: 'Rebasing with master')
|
||||
|
@ -25,10 +22,9 @@ feature 'Diffs URL', js: true, feature: true do
|
|||
|
||||
context 'when merge request has overflow' do
|
||||
it 'displays warning' do
|
||||
allow_any_instance_of(MergeRequestDiff).to receive(:overflow?).and_return(true)
|
||||
allow(Commit).to receive(:max_diff_options).and_return(max_files: 20, max_lines: 20)
|
||||
allow(Commit).to receive(:max_diff_options).and_return(max_files: 3)
|
||||
|
||||
visit diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)
|
||||
visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request)
|
||||
|
||||
page.within('.alert') do
|
||||
expect(page).to have_text("Too many changes to show. Plain diff Email patch To preserve
|
||||
|
@ -36,4 +32,35 @@ feature 'Diffs URL', js: true, feature: true do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when editing file' do
|
||||
let(:author_user) { create(:user) }
|
||||
let(:user) { create(:user) }
|
||||
let(:forked_project) { Projects::ForkService.new(project, author_user).execute }
|
||||
let(:merge_request) { create(:merge_request_with_diffs, source_project: forked_project, target_project: project, author: author_user) }
|
||||
let(:changelog_id) { Digest::SHA1.hexdigest("CHANGELOG") }
|
||||
|
||||
context 'as author' do
|
||||
it 'shows direct edit link' do
|
||||
login_as(author_user)
|
||||
visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request)
|
||||
|
||||
# Throws `Capybara::Poltergeist::InvalidSelector` if we try to use `#hash` syntax
|
||||
expect(page).to have_selector("[id=\"#{changelog_id}\"] a.js-edit-blob")
|
||||
end
|
||||
end
|
||||
|
||||
context 'as user who needs to fork' do
|
||||
it 'shows fork/cancel confirmation' do
|
||||
login_as(user)
|
||||
visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request)
|
||||
|
||||
# Throws `Capybara::Poltergeist::InvalidSelector` if we try to use `#hash` syntax
|
||||
find("[id=\"#{changelog_id}\"] .js-edit-blob").click
|
||||
|
||||
expect(page).to have_selector('.js-fork-suggestion-button', count: 1)
|
||||
expect(page).to have_selector('.js-cancel-fork-suggestion-button', count: 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
"avatar_url",
|
||||
"web_url",
|
||||
"created_at",
|
||||
"is_admin",
|
||||
"bio",
|
||||
"location",
|
||||
"skype",
|
||||
|
@ -43,7 +42,6 @@
|
|||
"avatar_url": { "type": "string" },
|
||||
"web_url": { "type": "string" },
|
||||
"created_at": { "type": "date" },
|
||||
"is_admin": { "type": "boolean" },
|
||||
"bio": { "type": ["string", "null"] },
|
||||
"location": { "type": ["string", "null"] },
|
||||
"skype": { "type": "string" },
|
||||
|
|
|
@ -108,6 +108,18 @@ describe Gitlab::LDAP::User, lib: true do
|
|||
it "creates a new user if not found" do
|
||||
expect{ ldap_user.save }.to change{ User.count }.by(1)
|
||||
end
|
||||
|
||||
context 'when signup is disabled' do
|
||||
before do
|
||||
stub_application_setting signup_enabled: false
|
||||
end
|
||||
|
||||
it 'creates the user' do
|
||||
ldap_user.save
|
||||
|
||||
expect(gl_user).to be_persisted
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'updating email' do
|
||||
|
|
|
@ -40,6 +40,20 @@ describe Gitlab::OAuth::User, lib: true do
|
|||
let(:provider) { 'twitter' }
|
||||
|
||||
describe 'signup' do
|
||||
context 'when signup is disabled' do
|
||||
before do
|
||||
stub_application_setting signup_enabled: false
|
||||
end
|
||||
|
||||
it 'creates the user' do
|
||||
stub_omniauth_config(allow_single_sign_on: ['twitter'])
|
||||
|
||||
oauth_user.save
|
||||
|
||||
expect(gl_user).to be_persisted
|
||||
end
|
||||
end
|
||||
|
||||
it 'marks user as having password_automatically_set' do
|
||||
stub_omniauth_config(allow_single_sign_on: ['twitter'], external_providers: ['twitter'])
|
||||
|
||||
|
|
|
@ -211,6 +211,18 @@ describe Gitlab::Saml::User, lib: true do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when signup is disabled' do
|
||||
before do
|
||||
stub_application_setting signup_enabled: false
|
||||
end
|
||||
|
||||
it 'creates the user' do
|
||||
saml_user.save
|
||||
|
||||
expect(gl_user).to be_persisted
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'blocking' do
|
||||
|
|
|
@ -199,10 +199,10 @@ describe MergeRequest, models: true do
|
|||
end
|
||||
|
||||
context 'when there are no MR diffs' do
|
||||
it 'delegates to the compare object' do
|
||||
it 'delegates to the compare object, setting no_collapse: true' do
|
||||
merge_request.compare = double(:compare)
|
||||
|
||||
expect(merge_request.compare).to receive(:diffs).with(options)
|
||||
expect(merge_request.compare).to receive(:diffs).with(options.merge(no_collapse: true))
|
||||
|
||||
merge_request.diffs(options)
|
||||
end
|
||||
|
@ -215,15 +215,22 @@ describe MergeRequest, models: true do
|
|||
end
|
||||
|
||||
context 'when there are MR diffs' do
|
||||
before do
|
||||
it 'returns the correct count' do
|
||||
merge_request.save
|
||||
|
||||
expect(merge_request.diff_size).to eq('105')
|
||||
end
|
||||
|
||||
it 'returns the correct count' do
|
||||
expect(merge_request.diff_size).to eq(105)
|
||||
it 'returns the correct overflow count' do
|
||||
allow(Commit).to receive(:max_diff_options).and_return(max_files: 2)
|
||||
merge_request.save
|
||||
|
||||
expect(merge_request.diff_size).to eq('2+')
|
||||
end
|
||||
|
||||
it 'does not perform highlighting' do
|
||||
merge_request.save
|
||||
|
||||
expect(Gitlab::Diff::Highlight).not_to receive(:new)
|
||||
|
||||
merge_request.diff_size
|
||||
|
@ -231,7 +238,7 @@ describe MergeRequest, models: true do
|
|||
end
|
||||
|
||||
context 'when there are no MR diffs' do
|
||||
before do
|
||||
def set_compare(merge_request)
|
||||
merge_request.compare = CompareService.new(
|
||||
merge_request.source_project,
|
||||
merge_request.source_branch
|
||||
|
@ -242,10 +249,21 @@ describe MergeRequest, models: true do
|
|||
end
|
||||
|
||||
it 'returns the correct count' do
|
||||
expect(merge_request.diff_size).to eq(105)
|
||||
set_compare(merge_request)
|
||||
|
||||
expect(merge_request.diff_size).to eq('105')
|
||||
end
|
||||
|
||||
it 'returns the correct overflow count' do
|
||||
allow(Commit).to receive(:max_diff_options).and_return(max_files: 2)
|
||||
set_compare(merge_request)
|
||||
|
||||
expect(merge_request.diff_size).to eq('2+')
|
||||
end
|
||||
|
||||
it 'does not perform highlighting' do
|
||||
set_compare(merge_request)
|
||||
|
||||
expect(Gitlab::Diff::Highlight).not_to receive(:new)
|
||||
|
||||
merge_request.diff_size
|
||||
|
|
|
@ -32,6 +32,12 @@ describe API::Keys do
|
|||
expect(json_response['user']['id']).to eq(user.id)
|
||||
expect(json_response['user']['username']).to eq(user.username)
|
||||
end
|
||||
|
||||
it "does not include the user's `is_admin` flag" do
|
||||
get api("/keys/#{key.id}", admin)
|
||||
|
||||
expect(json_response['user']['is_admin']).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -135,6 +135,12 @@ describe API::Users do
|
|||
expect(json_response['username']).to eq(user.username)
|
||||
end
|
||||
|
||||
it "does not return the user's `is_admin` flag" do
|
||||
get api("/users/#{user.id}", user)
|
||||
|
||||
expect(json_response['is_admin']).to be_nil
|
||||
end
|
||||
|
||||
it "returns a 401 if unauthenticated" do
|
||||
get api("/users/9998")
|
||||
expect(response).to have_http_status(401)
|
||||
|
@ -397,7 +403,6 @@ describe API::Users do
|
|||
it "updates admin status" do
|
||||
put api("/users/#{user.id}", admin), { admin: true }
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response['is_admin']).to eq(true)
|
||||
expect(user.reload.admin).to eq(true)
|
||||
end
|
||||
|
||||
|
@ -411,7 +416,6 @@ describe API::Users do
|
|||
it "does not update admin status" do
|
||||
put api("/users/#{admin_user.id}", admin), { can_create_group: false }
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response['is_admin']).to eq(true)
|
||||
expect(admin_user.reload.admin).to eq(true)
|
||||
expect(admin_user.can_create_group).to eq(false)
|
||||
end
|
||||
|
|
|
@ -274,5 +274,11 @@ describe API::V3::Users do
|
|||
|
||||
expect(new_user).to be_confirmed
|
||||
end
|
||||
|
||||
it 'does not reveal the `is_admin` flag of the user' do
|
||||
post v3_api('/users', admin), attributes_for(:user)
|
||||
|
||||
expect(json_response['is_admin']).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue