Commit 6a6a6720 authored by Luke "Jared" Bennett's avatar Luke "Jared" Bennett

Merge remote-tracking branch 'origin/master' into droplab-templating-xss-fix

parents 597c5c76 3c6fad64
......@@ -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
......
......@@ -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;
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) {
enoughData = false;
}
}
});
if (!enoughData) {
this.state = '.js-loading';
this.updateState();
if (typeof metricsResponse === 'undefined') {
enoughData = false;
} else {
Object.keys(metricsResponse.metrics).forEach((key) => {
if (key === 'cpu_values' || key === 'memory_values') {
const currentData = (metricsResponse.metrics[key])[0];
if (currentData.values.length <= 2) {
enoughData = false;
}
}
});
}
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],
}));
}
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
......
- 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
......
- 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
......
---
title: Show group name on flash container when group is created from Admin area.
merge_request: 10905
author:
---
title: Cleanup markdown spacing
merge_request:
author:
---
title: Don't display the is_admin flag in most API responses
merge_request: 10846
author:
---
title: Add sub-nav for Project Integration Services edit page
merge_request: 10813
author:
---
title: Fix OAuth, LDAP and SAML SSO when regular sign-ups are disabled
merge_request:
author:
---
title: Fix usage ping docs link from empty cohorts page
merge_request:
author:
---
title: Add index to webhooks type column
merge_request:
author:
---
title: Fixed Prometheus monitoring graphs not showing empty states in certain scenarios
merge_request:
author:
---
title: Show sizes correctly in merge requests when diffs overflow
merge_request:
author:
---
title: Upgrade Sidekiq to 4.2.10
merge_request:
author:
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)
......
# 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 spaces. (but still 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
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 spaces. (but still 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
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
......
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
......
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
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