summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--.scss-lint.yml6
-rw-r--r--CHANGELOG.md9
-rw-r--r--app/assets/javascripts/build.js2
-rw-r--r--app/assets/javascripts/dispatcher.js.es63
-rw-r--r--app/assets/javascripts/gl_field_errors.js.es67
-rw-r--r--app/assets/javascripts/merge_request_tabs.js1
-rw-r--r--app/assets/stylesheets/framework/animations.scss4
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss2
-rw-r--r--app/assets/stylesheets/framework/logo.scss2
-rw-r--r--app/assets/stylesheets/framework/modal.scss2
-rw-r--r--app/assets/stylesheets/framework/tw_bootstrap_variables.scss122
-rw-r--r--app/assets/stylesheets/framework/variables.scss44
-rw-r--r--app/assets/stylesheets/mailers/devise.scss10
-rw-r--r--app/assets/stylesheets/pages/cycle_analytics.scss18
-rw-r--r--app/assets/stylesheets/pages/diff.scss4
-rw-r--r--app/assets/stylesheets/pages/environments.scss8
-rw-r--r--app/assets/stylesheets/pages/events.scss2
-rw-r--r--app/assets/stylesheets/pages/login.scss2
-rw-r--r--app/assets/stylesheets/pages/merge_conflicts.scss2
-rw-r--r--app/assets/stylesheets/pages/note_form.scss2
-rw-r--r--app/assets/stylesheets/pages/notes.scss2
-rw-r--r--app/assets/stylesheets/pages/status.scss2
-rw-r--r--app/assets/stylesheets/pages/tree.scss4
-rw-r--r--app/finders/labels_finder.rb8
-rw-r--r--app/helpers/boards_helper.rb2
-rw-r--r--app/models/ci/build.rb4
-rw-r--r--app/models/ci/pipeline.rb6
-rw-r--r--app/models/ci/runner.rb6
-rw-r--r--app/models/ci/runner_project.rb4
-rw-r--r--app/models/ci/trigger.rb4
-rw-r--r--app/models/ci/trigger_request.rb6
-rw-r--r--app/models/ci/variable.rb2
-rw-r--r--app/models/commit_status.rb2
-rw-r--r--app/models/group.rb2
-rw-r--r--app/models/members/group_member.rb2
-rw-r--r--app/models/members/project_member.rb2
-rw-r--r--app/models/merge_request.rb4
-rw-r--r--app/models/merge_request_diff.rb8
-rw-r--r--app/models/project.rb8
-rw-r--r--app/models/user.rb10
-rw-r--r--app/views/devise/shared/_tabs_normal.html.haml5
-rw-r--r--app/views/projects/merge_requests/show/_commits.html.haml2
-rw-r--r--doc/administration/integration/koding.md1
-rw-r--r--doc/user/project/new_ci_build_permissions_model.md6
-rw-r--r--lib/banzai/filter/relative_link_filter.rb4
-rw-r--r--lib/gitlab/ee_compat_check.rb261
-rw-r--r--lib/tasks/ce_to_ee_merge_check.rake4
-rw-r--r--lib/tasks/ee_compat_check.rake4
-rw-r--r--lib/tasks/gitlab/dev.rake109
-rw-r--r--spec/features/boards/boards_spec.rb4
-rw-r--r--spec/features/login_spec.rb65
-rw-r--r--spec/finders/labels_finder_spec.rb32
-rw-r--r--spec/javascripts/gl_field_errors_spec.js.es64
-rw-r--r--spec/lib/banzai/filter/relative_link_filter_spec.rb40
-rw-r--r--spec/models/members/project_member_spec.rb2
-rw-r--r--spec/models/merge_request_spec.rb7
-rw-r--r--spec/models/user_spec.rb4
-rw-r--r--spec/services/issues/move_service_spec.rb43
-rw-r--r--spec/views/projects/merge_requests/_commits.html.haml_spec.rb38
60 files changed, 684 insertions, 293 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 76117a48730..9c4b4acbaf5 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -210,7 +210,7 @@ rake brakeman: *exec
rake flay: *exec
license_finder: *exec
rake downtime_check: *exec
-rake ce_to_ee_merge_check:
+rake ee_compat_check:
<<: *exec
only:
- branches
diff --git a/.scss-lint.yml b/.scss-lint.yml
index f8fc1c077b8..5c8e5ac0758 100644
--- a/.scss-lint.yml
+++ b/.scss-lint.yml
@@ -191,7 +191,7 @@ linters:
# Variables should be formatted with a single space separating the colon
# from the variable's value.
SpaceAfterVariableColon:
- enabled: false
+ enabled: true
# Variables should be formatted with no space between the name and the
# colon.
@@ -201,7 +201,7 @@ linters:
# Operators should be formatted with a single space on both sides of an
# infix operator.
SpaceAroundOperator:
- enabled: false
+ enabled: true
# Opening braces should be preceded by a single space.
SpaceBeforeBrace:
@@ -223,7 +223,7 @@ linters:
# Reports lines containing trailing whitespace.
TrailingWhitespace:
- enabled: false
+ enabled: true
# Don't write trailing zeros for numeric values with a decimal point.
TrailingZero:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0f02cc1f102..60f932e1f76 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,8 +5,10 @@ Please view this file on the master branch, on stable branches it's out of date.
- Trim leading and trailing whitespace on project_path (Linus Thiel)
- Prevent award emoji via notes for issues/MRs authored by user (barthc)
- Adds an optional path parameter to the Commits API to filter commits by path (Luis HGO)
+ - Fix extra space on Build sidebar on Firefox !7060
- Fix HipChat notifications rendering (airatshigapov, eisnerd)
- Add hover to trash icon in notes !7008 (blackst0ne)
+ - Escape ref and path for relative links !6050 (winniehell)
- Simpler arguments passed to named_route on toggle_award_url helper method
- Fix: Backup restore doesn't clear cache
- Use MergeRequestsClosingIssues cache data on Issue#closed_by_merge_requests method
@@ -15,12 +17,16 @@ Please view this file on the master branch, on stable branches it's out of date.
- Refactor email, use setter method instead AR callbacks for email attribute (Semyon Pupkov)
## 8.13.1 (unreleased)
+ - Fix bug where labels would be assigned to issues that were moved
- Fix error in generating labels
- Fix reply-by-email not working due to queue name mismatch
+ - Fixed hidden pipeline graph on commit and MR page !6895
- Expire and build repository cache after project import
- Fix 404 for group pages when GitLab setup uses relative url
- - Simpler arguments passed to named_route on toggle_award_url helper method
+ - Simpler arguments passed to named_route on toggle_award_url helper method
+ - Fix unauthorized users dragging on issue boards
- Better handle when no users were selected for adding to group or project. (Linus Thiel)
+ - Only show register tab if signup enabled.
## 8.13.0 (2016-10-22)
- Removes extra line for empty issue description. (!7045)
@@ -102,6 +108,7 @@ Please view this file on the master branch, on stable branches it's out of date.
- Add visibility level to project repository
- Fix robots.txt disallowing access to groups starting with "s" (Matt Harrison)
- Close open merge request without source project (Katarzyna Kobierska Ula Budziszewska)
+ - Fix showing commits from source project for merge request !6658
- Fix that manual jobs would no longer block jobs in the next stage. !6604
- Add configurable email subject suffix (Fu Xu)
- Use defined colour for a language when available !6748 (nilsding)
diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js
index 97462a5959c..f4c387a1a05 100644
--- a/app/assets/javascripts/build.js
+++ b/app/assets/javascripts/build.js
@@ -148,7 +148,7 @@
};
Build.prototype.translateSidebar = function(e) {
- var newPosition = this.sidebarTranslationLimits.max - document.body.scrollTop;
+ var newPosition = this.sidebarTranslationLimits.max - (document.body.scrollTop || document.documentElement.scrollTop);
if (newPosition < this.sidebarTranslationLimits.min) newPosition = this.sidebarTranslationLimits.min;
this.$sidebar.css({
top: newPosition
diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6
index afc0d6f8c62..a1fe57562fa 100644
--- a/app/assets/javascripts/dispatcher.js.es6
+++ b/app/assets/javascripts/dispatcher.js.es6
@@ -117,6 +117,9 @@
new ZenMode();
shortcut_handler = new ShortcutsNavigation();
break;
+ case 'projects:commit:builds':
+ new gl.Pipelines();
+ break;
case 'projects:commits:show':
case 'projects:activity':
shortcut_handler = new ShortcutsNavigation();
diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js.es6
index 8657e7b4abf..8e8f9f29ab3 100644
--- a/app/assets/javascripts/gl_field_errors.js.es6
+++ b/app/assets/javascripts/gl_field_errors.js.es6
@@ -137,8 +137,11 @@
}
initValidators () {
- // select all non-hidden inputs in form
- this.state.inputs = this.form.find(':input:not([type=hidden])').toArray()
+ // register selectors here as needed
+ const validateSelectors = [':text', ':password', '[type=email]']
+ .map((selector) => `input${selector}`).join(',');
+
+ this.state.inputs = this.form.find(validateSelectors).toArray()
.filter((input) => !input.classList.contains(customValidationFlag))
.map((input) => new GlFieldError({ input, formErrors: this }));
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 9f28738e06b..3dde979185b 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -282,6 +282,7 @@
document.querySelector("div#builds").innerHTML = data.html;
gl.utils.localTimeAgo($('.js-timeago', 'div#builds'));
_this.buildsLoaded = true;
+ if (!this.pipelines) this.pipelines = new gl.Pipelines();
return _this.scrollToElement("#builds");
};
})(this)
diff --git a/app/assets/stylesheets/framework/animations.scss b/app/assets/stylesheets/framework/animations.scss
index 0224cc2df21..f1d36efb3de 100644
--- a/app/assets/stylesheets/framework/animations.scss
+++ b/app/assets/stylesheets/framework/animations.scss
@@ -1,10 +1,10 @@
// This file is based off animate.css 3.5.1, available here:
// https://github.com/daneden/animate.css/blob/3.5.1/animate.css
-//
+//
// animate.css - http://daneden.me/animate
// Version - 3.5.1
// Licensed under the MIT license - http://opensource.org/licenses/MIT
-//
+//
// Copyright (c) 2016 Daniel Eden
.animated {
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index a2d0b1353da..1de246600fd 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -404,7 +404,7 @@
.dropdown-content {
max-height: 215px;
- overflow-y: scroll;
+ overflow-y: auto;
}
.dropdown-footer {
diff --git a/app/assets/stylesheets/framework/logo.scss b/app/assets/stylesheets/framework/logo.scss
index a90e45bb5f4..429cfbe7235 100644
--- a/app/assets/stylesheets/framework/logo.scss
+++ b/app/assets/stylesheets/framework/logo.scss
@@ -61,7 +61,7 @@
10%, 80% {
fill: $tanuki-red;
}
-
+
20%, 90% {
fill: lighten($tanuki-red, 25%);
}
diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss
index 8374f30d0b2..8cd49280e1c 100644
--- a/app/assets/stylesheets/framework/modal.scss
+++ b/app/assets/stylesheets/framework/modal.scss
@@ -3,7 +3,7 @@
padding: 15px;
.form-actions {
- margin: -$gl-padding+1;
+ margin: -$gl-padding + 1;
margin-top: 15px;
}
diff --git a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
index 915aa631ef8..44fe37d3a4a 100644
--- a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
+++ b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
@@ -16,21 +16,21 @@
// $gray-light: lighten($gray-base, 46.7%) // #777
// $gray-lighter: lighten($gray-base, 93.5%) // #eee
-$brand-primary: $gl-primary;
-$brand-success: $gl-success;
-$brand-info: $gl-info;
-$brand-warning: $gl-warning;
-$brand-danger: $gl-danger;
+$brand-primary: $gl-primary;
+$brand-success: $gl-success;
+$brand-info: $gl-info;
+$brand-warning: $gl-warning;
+$brand-danger: $gl-danger;
-$border-radius-base: 3px !default;
-$border-radius-large: 3px !default;
-$border-radius-small: 3px !default;
+$border-radius-base: 3px !default;
+$border-radius-large: 3px !default;
+$border-radius-small: 3px !default;
//== Scaffolding
//
-$text-color: $gl-text-color;
-$link-color: $gl-link-color;
+$text-color: $gl-text-color;
+$link-color: $gl-link-color;
//== Typography
@@ -38,112 +38,112 @@ $link-color: $gl-link-color;
//## Font, line-height, and color for body text, headings, and more.
$font-family-sans-serif: $regular_font;
-$font-family-monospace: $monospace_font;
-$font-size-base: $gl-font-size;
+$font-family-monospace: $monospace_font;
+$font-size-base: $gl-font-size;
//== Components
//
//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
-$padding-base-vertical: $gl-vert-padding;
-$padding-base-horizontal: $gl-padding;
-$component-active-color: #fff;
-$component-active-bg: $brand-info;
+$padding-base-vertical: $gl-vert-padding;
+$padding-base-horizontal: $gl-padding;
+$component-active-color: #fff;
+$component-active-bg: $brand-info;
//== Forms
//
//##
-$input-color: $text-color;
-$input-border: $border-color;
-$input-border-focus: $focus-border-color;
-$legend-color: $text-color;
+$input-color: $text-color;
+$input-border: $border-color;
+$input-border-focus: $focus-border-color;
+$legend-color: $text-color;
//== Pagination
//
//##
-$pagination-color: $gl-gray;
-$pagination-bg: #fff;
-$pagination-border: $border-color;
+$pagination-color: $gl-gray;
+$pagination-bg: #fff;
+$pagination-border: $border-color;
-$pagination-hover-color: $gl-gray;
-$pagination-hover-bg: $row-hover;
-$pagination-hover-border: $border-color;
+$pagination-hover-color: $gl-gray;
+$pagination-hover-bg: $row-hover;
+$pagination-hover-border: $border-color;
-$pagination-active-color: $blue-dark;
-$pagination-active-bg: #fff;
-$pagination-active-border: $border-color;
+$pagination-active-color: $blue-dark;
+$pagination-active-bg: #fff;
+$pagination-active-border: $border-color;
-$pagination-disabled-color: #cdcdcd;
-$pagination-disabled-bg: $background-color;
-$pagination-disabled-border: $border-color;
+$pagination-disabled-color: #cdcdcd;
+$pagination-disabled-bg: $background-color;
+$pagination-disabled-border: $border-color;
//== Form states and alerts
//
//## Define colors for form feedback states and, by default, alerts.
-$state-success-text: #fff;
-$state-success-bg: $brand-success;
-$state-success-border: $brand-success;
+$state-success-text: #fff;
+$state-success-bg: $brand-success;
+$state-success-border: $brand-success;
-$state-info-text: #fff;
-$state-info-bg: $brand-info;
-$state-info-border: $brand-info;
+$state-info-text: #fff;
+$state-info-bg: $brand-info;
+$state-info-border: $brand-info;
-$state-warning-text: #fff;
-$state-warning-bg: $brand-warning;
-$state-warning-border: $brand-warning;
+$state-warning-text: #fff;
+$state-warning-bg: $brand-warning;
+$state-warning-border: $brand-warning;
-$state-danger-text: #fff;
-$state-danger-bg: $brand-danger;
-$state-danger-border: $brand-danger;
+$state-danger-text: #fff;
+$state-danger-bg: $brand-danger;
+$state-danger-border: $brand-danger;
//== Alerts
//
//## Define alert colors, border radius, and padding.
-$alert-border-radius: 0;
+$alert-border-radius: 0;
//== Panels
//
//##
-$panel-border-radius: 2px;
-$panel-default-text: $text-color;
-$panel-default-border: $border-color;
+$panel-border-radius: 2px;
+$panel-default-text: $text-color;
+$panel-default-border: $border-color;
$panel-default-heading-bg: $background-color;
-$panel-footer-bg: $background-color;
-$panel-inner-border: $border-color;
+$panel-footer-bg: $background-color;
+$panel-inner-border: $border-color;
//== Wells
//
//##
-$well-bg: $gray-light;
-$well-border: #eee;
+$well-bg: $gray-light;
+$well-border: #eee;
//== Code
//
//##
-$code-color: #c7254e;
-$code-bg: #f9f2f4;
+$code-color: #c7254e;
+$code-bg: #f9f2f4;
-$kbd-color: #fff;
-$kbd-bg: #333;
+$kbd-color: #fff;
+$kbd-bg: #333;
//== Buttons
//
//##
-$btn-default-color: $gl-text-color;
-$btn-default-bg: #fff;
-$btn-default-border: #e7e9ed;
+$btn-default-color: $gl-text-color;
+$btn-default-bg: #fff;
+$btn-default-border: #e7e9ed;
//== Nav
//
@@ -153,8 +153,8 @@ $nav-link-padding: 13px $gl-padding;
//== Code
//
//##
-$pre-bg: $background-color !default;
-$pre-color: $gl-gray !default;
+$pre-bg: $background-color !default;
+$pre-color: $gl-gray !default;
$pre-border-color: $border-color;
$table-bg-accent: $background-color;
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index eafe84570a8..b271f8cf332 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -84,39 +84,39 @@ $warning-message-border: #f0e2bb;
/*
* UI elements
*/
-$border-color: #e5e5e5;
-$focus-border-color: #3aabf0;
-$table-border-color: #f0f0f0;
-$background-color: $gray-light;
+$border-color: #e5e5e5;
+$focus-border-color: #3aabf0;
+$table-border-color: #f0f0f0;
+$background-color: $gray-light;
$dark-background-color: #f5f5f5;
-$table-text-gray: #8f8f8f;
+$table-text-gray: #8f8f8f;
/*
* Text
*/
-$gl-font-size: 15px;
-$gl-title-color: #333;
-$gl-text-color: #5c5c5c;
-$gl-text-color-light: #8c8c8c;
-$gl-text-green: #4a2;
-$gl-text-red: #d12f19;
-$gl-text-orange: #d90;
-$gl-link-color: #3084bb;
-$gl-dark-link-color: #333;
+$gl-font-size: 15px;
+$gl-title-color: #333;
+$gl-text-color: #5c5c5c;
+$gl-text-color-light: #8c8c8c;
+$gl-text-green: #4a2;
+$gl-text-red: #d12f19;
+$gl-text-orange: #d90;
+$gl-link-color: #3084bb;
+$gl-dark-link-color: #333;
$gl-placeholder-color: #8f8f8f;
-$gl-icon-color: $gl-placeholder-color;
-$gl-grayish-blue: #7f8fa4;
-$gl-gray: $gl-text-color;
-$gl-gray-dark: #313236;
-$gl-gray-light: $gl-placeholder-color;
-$gl-header-color: #4c4e54;
+$gl-icon-color: $gl-placeholder-color;
+$gl-grayish-blue: #7f8fa4;
+$gl-gray: $gl-text-color;
+$gl-gray-dark: #313236;
+$gl-gray-light: $gl-placeholder-color;
+$gl-header-color: #4c4e54;
/*
* Lists
*/
-$list-font-size: $gl-font-size;
+$list-font-size: $gl-font-size;
$list-title-color: $gl-title-color;
-$list-text-color: $gl-text-color;
+$list-text-color: $gl-text-color;
$list-text-height: 42px;
/*
diff --git a/app/assets/stylesheets/mailers/devise.scss b/app/assets/stylesheets/mailers/devise.scss
index 9495c5b3f37..b2bce482fde 100644
--- a/app/assets/stylesheets/mailers/devise.scss
+++ b/app/assets/stylesheets/mailers/devise.scss
@@ -5,13 +5,13 @@
// Styles defined here are embedded directly into the resulting email HTML via
// the `premailer` gem.
-$body-background-color: #363636;
+$body-background-color: #363636;
$message-background-color: #fafafa;
-$header-color: #6b4fbb;
-$body-color: #444;
-$cta-color: #e14329;
-$footer-link-color: #7e7e7e;
+$header-color: #6b4fbb;
+$body-color: #444;
+$cta-color: #e14329;
+$footer-link-color: #7e7e7e;
$font-family: Helvetica, Arial, sans-serif;
diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss
index d732008de3d..572e1e7d558 100644
--- a/app/assets/stylesheets/pages/cycle_analytics.scss
+++ b/app/assets/stylesheets/pages/cycle_analytics.scss
@@ -9,15 +9,15 @@
padding: 24px 0;
border-bottom: none;
position: relative;
-
+
@media (max-width: $screen-sm-min) {
padding: 6px 0 24px;
- }
+ }
}
.column {
text-align: center;
-
+
@media (max-width: $screen-sm-min) {
padding: 15px 0;
}
@@ -36,7 +36,7 @@
&:last-child {
text-align: right;
-
+
@media (max-width: $screen-sm-min) {
text-align: center;
}
@@ -51,7 +51,7 @@
.bordered-box {
border: 1px solid $border-color;
border-radius: $border-radius-default;
-
+
}
.content-list {
@@ -73,10 +73,10 @@
font-weight: 600;
color: $gl-title-color;
}
-
+
&.text {
color: $layout-link-gray;
-
+
&.value-col {
color: $gl-title-color;
}
@@ -108,13 +108,13 @@
.svg-container {
text-align: center;
-
+
svg {
width: 136px;
height: 136px;
}
}
-
+
.inner-content {
@media (max-width: $screen-sm-min) {
padding: 0 28px;
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index 9627d1c841b..e0367d1d942 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -223,12 +223,12 @@
top: 13px;
right: 7px;
}
-
+
.frame {
top: 0;
right: 0;
position: absolute;
-
+
&.deleted {
margin: 0;
display: block;
diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss
index 12ee0a5dc3d..fc49ff780fc 100644
--- a/app/assets/stylesheets/pages/environments.scss
+++ b/app/assets/stylesheets/pages/environments.scss
@@ -37,10 +37,10 @@
.branch-name {
color: $gl-dark-link-color;
}
-
+
.stop-env-link {
color: $table-text-gray;
-
+
.stop-env-icon {
font-size: 14px;
}
@@ -48,11 +48,11 @@
.deployment {
.build-column {
-
+
.build-link {
color: $gl-dark-link-color;
}
-
+
.avatar {
float: none;
}
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index 5d9a76dac05..3004959ff7b 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -142,7 +142,7 @@
.event-last-push {
overflow: auto;
width: 100%;
-
+
.event-last-push-text {
@include str-truncated(100%);
padding: 4px 0;
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index 82e46377308..3d2b024fe5c 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -289,7 +289,7 @@
.new_user {
position: relative;
padding-bottom: 35px;
-
+
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
.forgot-password {
float: none !important;
diff --git a/app/assets/stylesheets/pages/merge_conflicts.scss b/app/assets/stylesheets/pages/merge_conflicts.scss
index aa8057e4b9d..032feae8854 100644
--- a/app/assets/stylesheets/pages/merge_conflicts.scss
+++ b/app/assets/stylesheets/pages/merge_conflicts.scss
@@ -255,7 +255,7 @@ $colors: (
border-top: solid 2px $border-green-extra-light;
}
}
-
+
.editor {
pre {
height: 350px;
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index c1a3c082cfa..16ddef481bd 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -8,7 +8,7 @@
.diff-file .diff-content {
tr.line_holder:hover > td .line_note_link {
opacity: 1.0;
- filter: alpha(opacity=100);
+ filter: alpha(opacity = 100);
}
}
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 586f21821f7..b90c91831f2 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -459,7 +459,7 @@ ul.notes {
.discussion-next-btn {
svg {
margin: 0;
-
+
path {
fill: $gray-darkest;
}
diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss
index f1d53c7b8bc..01426e28e92 100644
--- a/app/assets/stylesheets/pages/status.scss
+++ b/app/assets/stylesheets/pages/status.scss
@@ -74,7 +74,7 @@
.ci-status-icon-success_with_warning {
color: $gl-warning;
}
-
+
.ci-status-icon-running {
color: $blue-normal;
}
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index 99d53d52119..2b836fa1f4a 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -30,11 +30,11 @@
.last-commit {
@include str-truncated(506px);
-
+
@media (min-width: $screen-sm-max) and (max-width: $screen-md-max) {
@include str-truncated(450px);
}
-
+
}
.commit-history-link-spacer {
diff --git a/app/finders/labels_finder.rb b/app/finders/labels_finder.rb
index 6ace14a4bb5..95e62cdb02a 100644
--- a/app/finders/labels_finder.rb
+++ b/app/finders/labels_finder.rb
@@ -35,8 +35,10 @@ class LabelsFinder < UnionFinder
end
def with_title(items)
- items = items.where(title: title) if title
- items
+ return items if title.nil?
+ return items.none if title.blank?
+
+ items.where(title: title)
end
def group_id
@@ -52,7 +54,7 @@ class LabelsFinder < UnionFinder
end
def title
- params[:title].presence || params[:name].presence
+ params[:title] || params[:name]
end
def project
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index b7247ffa8b2..38c586ccd31 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -5,7 +5,7 @@ module BoardsHelper
{
endpoint: namespace_project_boards_path(@project.namespace, @project),
board_id: board.id,
- disabled: !can?(current_user, :admin_list, @project),
+ disabled: "#{!can?(current_user, :admin_list, @project)}",
issue_link_base: namespace_project_issues_path(@project.namespace, @project)
}
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index a6b606d13de..bf5f92f8462 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -3,8 +3,8 @@ module Ci
include TokenAuthenticatable
include AfterCommitQueue
- belongs_to :runner, class_name: 'Ci::Runner'
- belongs_to :trigger_request, class_name: 'Ci::TriggerRequest'
+ belongs_to :runner
+ belongs_to :trigger_request
belongs_to :erased_by, class_name: 'User'
serialize :options
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index d5c1e03b461..adda3b8f40c 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -7,12 +7,12 @@ module Ci
self.table_name = 'ci_commits'
- belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
+ belongs_to :project, foreign_key: :gl_project_id
belongs_to :user
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id
- has_many :builds, class_name: 'Ci::Build', foreign_key: :commit_id
- has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest', foreign_key: :commit_id
+ has_many :builds, foreign_key: :commit_id
+ has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id
validates_presence_of :sha, unless: :importing?
validates_presence_of :ref, unless: :importing?
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 44cb19ece3b..123930273e0 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -6,9 +6,9 @@ module Ci
AVAILABLE_SCOPES = %w[specific shared active paused online]
FORM_EDITABLE = %i[description tag_list active run_untagged locked]
- has_many :builds, class_name: 'Ci::Build'
- has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject'
- has_many :projects, through: :runner_projects, class_name: '::Project', foreign_key: :gl_project_id
+ has_many :builds
+ has_many :runner_projects, dependent: :destroy
+ has_many :projects, through: :runner_projects, foreign_key: :gl_project_id
has_one :last_build, ->() { order('id DESC') }, class_name: 'Ci::Build'
diff --git a/app/models/ci/runner_project.rb b/app/models/ci/runner_project.rb
index 4b44ffa886e..1f9baeca5b1 100644
--- a/app/models/ci/runner_project.rb
+++ b/app/models/ci/runner_project.rb
@@ -2,8 +2,8 @@ module Ci
class RunnerProject < ActiveRecord::Base
extend Ci::Model
- belongs_to :runner, class_name: 'Ci::Runner'
- belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
+ belongs_to :runner
+ belongs_to :project, foreign_key: :gl_project_id
validates_uniqueness_of :runner_id, scope: :gl_project_id
end
diff --git a/app/models/ci/trigger.rb b/app/models/ci/trigger.rb
index a0b19b51a12..62889fe80d8 100644
--- a/app/models/ci/trigger.rb
+++ b/app/models/ci/trigger.rb
@@ -4,8 +4,8 @@ module Ci
acts_as_paranoid
- belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
- has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest'
+ belongs_to :project, foreign_key: :gl_project_id
+ has_many :trigger_requests, dependent: :destroy
validates_presence_of :token
validates_uniqueness_of :token
diff --git a/app/models/ci/trigger_request.rb b/app/models/ci/trigger_request.rb
index fc674871743..2b807731d0d 100644
--- a/app/models/ci/trigger_request.rb
+++ b/app/models/ci/trigger_request.rb
@@ -2,9 +2,9 @@ module Ci
class TriggerRequest < ActiveRecord::Base
extend Ci::Model
- belongs_to :trigger, class_name: 'Ci::Trigger'
- belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id
- has_many :builds, class_name: 'Ci::Build'
+ belongs_to :trigger
+ belongs_to :pipeline, foreign_key: :commit_id
+ has_many :builds
serialize :variables
diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb
index 6959223aed9..94d9e2b3208 100644
--- a/app/models/ci/variable.rb
+++ b/app/models/ci/variable.rb
@@ -2,7 +2,7 @@ module Ci
class Variable < ActiveRecord::Base
extend Ci::Model
- belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
+ belongs_to :project, foreign_key: :gl_project_id
validates_uniqueness_of :key, scope: :gl_project_id
validates :key,
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 7b554be4f9a..4cb3a69416e 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -5,7 +5,7 @@ class CommitStatus < ActiveRecord::Base
self.table_name = 'ci_builds'
- belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
+ belongs_to :project, foreign_key: :gl_project_id
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id
belongs_to :user
diff --git a/app/models/group.rb b/app/models/group.rb
index 00a595d2705..552e1154df6 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -6,7 +6,7 @@ class Group < Namespace
include AccessRequestable
include Referable
- has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'GroupMember'
+ has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source
alias_method :members, :group_members
has_many :users, through: :group_members
has_many :owners,
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index 1b54a85d064..204f34f0269 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -1,7 +1,7 @@
class GroupMember < Member
SOURCE_TYPE = 'Namespace'
- belongs_to :group, class_name: 'Group', foreign_key: 'source_id'
+ belongs_to :group, foreign_key: 'source_id'
# Make sure group member points only to group as it source
default_value_for :source_type, SOURCE_TYPE
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index e4880973117..008fff0857c 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -3,7 +3,7 @@ class ProjectMember < Member
include Gitlab::ShellAdapter
- belongs_to :project, class_name: 'Project', foreign_key: 'source_id'
+ belongs_to :project, foreign_key: 'source_id'
# Make sure project member points only to project as it source
default_value_for :source_type, SOURCE_TYPE
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index c476a3bb14e..4872f8b8649 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -6,8 +6,8 @@ class MergeRequest < ActiveRecord::Base
include Taskable
include Importable
- belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project"
- belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project"
+ belongs_to :target_project, class_name: "Project"
+ belongs_to :source_project, class_name: "Project"
belongs_to :merge_user, class_name: "User"
has_many :merge_request_diffs, dependent: :destroy
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index b8a10b7968e..dd65a9a8b86 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -299,8 +299,10 @@ class MergeRequestDiff < ActiveRecord::Base
end
def keep_around_commits
- repository.keep_around(start_commit_sha)
- repository.keep_around(head_commit_sha)
- repository.keep_around(base_commit_sha)
+ [repository, merge_request.source_project.repository].each do |repo|
+ repo.keep_around(start_commit_sha)
+ repo.keep_around(head_commit_sha)
+ repo.keep_around(base_commit_sha)
+ end
end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index af117f0acb0..fbf7012972e 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -63,11 +63,11 @@ class Project < ActiveRecord::Base
alias_attribute :title, :name
# Relations
- belongs_to :creator, foreign_key: 'creator_id', class_name: 'User'
+ belongs_to :creator, class_name: 'User'
belongs_to :group, -> { where(type: 'Group') }, foreign_key: 'namespace_id'
belongs_to :namespace
- has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id'
+ has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event'
has_many :boards, before_add: :validate_board_limit, dependent: :destroy
# Project services
@@ -116,7 +116,7 @@ class Project < ActiveRecord::Base
has_many :hooks, dependent: :destroy, class_name: 'ProjectHook'
has_many :protected_branches, dependent: :destroy
- has_many :project_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'ProjectMember'
+ has_many :project_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source
alias_method :members, :project_members
has_many :users, through: :project_members
@@ -137,7 +137,7 @@ class Project < ActiveRecord::Base
has_one :import_data, dependent: :destroy, class_name: "ProjectImportData"
has_one :project_feature, dependent: :destroy
- has_many :commit_statuses, dependent: :destroy, class_name: 'CommitStatus', foreign_key: :gl_project_id
+ has_many :commit_statuses, dependent: :destroy, foreign_key: :gl_project_id
has_many :pipelines, dependent: :destroy, class_name: 'Ci::Pipeline', foreign_key: :gl_project_id
has_many :builds, class_name: 'Ci::Build', foreign_key: :gl_project_id # the builds are created from the commit_statuses
has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject', foreign_key: :gl_project_id
diff --git a/app/models/user.rb b/app/models/user.rb
index f367f4616fb..9e76df63d31 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -47,7 +47,7 @@ class User < ActiveRecord::Base
#
# Namespace for personal projects
- has_one :namespace, -> { where type: nil }, dependent: :destroy, foreign_key: :owner_id, class_name: "Namespace"
+ has_one :namespace, -> { where type: nil }, dependent: :destroy, foreign_key: :owner_id
# Profile
has_many :keys, dependent: :destroy
@@ -66,17 +66,17 @@ class User < ActiveRecord::Base
# Projects
has_many :groups_projects, through: :groups, source: :projects
has_many :personal_projects, through: :namespace, source: :projects
- has_many :project_members, -> { where(requested_at: nil) }, dependent: :destroy, class_name: 'ProjectMember'
+ has_many :project_members, -> { where(requested_at: nil) }, dependent: :destroy
has_many :projects, through: :project_members
has_many :created_projects, foreign_key: :creator_id, class_name: 'Project'
has_many :users_star_projects, dependent: :destroy
has_many :starred_projects, through: :users_star_projects, source: :project
- has_many :snippets, dependent: :destroy, foreign_key: :author_id, class_name: "Snippet"
+ has_many :snippets, dependent: :destroy, foreign_key: :author_id
has_many :issues, dependent: :destroy, foreign_key: :author_id
has_many :notes, dependent: :destroy, foreign_key: :author_id
has_many :merge_requests, dependent: :destroy, foreign_key: :author_id
- has_many :events, dependent: :destroy, foreign_key: :author_id, class_name: "Event"
+ has_many :events, dependent: :destroy, foreign_key: :author_id
has_many :subscriptions, dependent: :destroy
has_many :recent_events, -> { order "id DESC" }, foreign_key: :author_id, class_name: "Event"
has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue"
@@ -309,7 +309,7 @@ class User < ActiveRecord::Base
username
end
- def to_reference(_from_project = nil)
+ def to_reference(_from_project = nil, _target_project = nil)
"#{self.class.reference_prefix}#{username}"
end
diff --git a/app/views/devise/shared/_tabs_normal.html.haml b/app/views/devise/shared/_tabs_normal.html.haml
index 79b1d447a92..05246303fb6 100644
--- a/app/views/devise/shared/_tabs_normal.html.haml
+++ b/app/views/devise/shared/_tabs_normal.html.haml
@@ -1,5 +1,6 @@
%ul.nav-links.new-session-tabs.nav-tabs{ role: 'tablist'}
%li.active{ role: 'presentation' }
%a{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab'} Sign in
- %li{ role: 'presentation'}
- %a{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab'} Register
+ - if signin_enabled? && signup_enabled?
+ %li{ role: 'presentation'}
+ %a{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab'} Register
diff --git a/app/views/projects/merge_requests/show/_commits.html.haml b/app/views/projects/merge_requests/show/_commits.html.haml
index 0b05785430b..61020516bcf 100644
--- a/app/views/projects/merge_requests/show/_commits.html.haml
+++ b/app/views/projects/merge_requests/show/_commits.html.haml
@@ -3,4 +3,4 @@
Most recent commits displayed first
%ol#commits-list.list-unstyled
- = render "projects/commits/commits", project: @merge_request.project
+ = render "projects/commits/commits", project: @merge_request.source_project
diff --git a/doc/administration/integration/koding.md b/doc/administration/integration/koding.md
index a2c358af095..b95c425842c 100644
--- a/doc/administration/integration/koding.md
+++ b/doc/administration/integration/koding.md
@@ -61,6 +61,7 @@ executing commands in the following snippet.
```bash
git clone https://github.com/koding/koding.git
cd koding
+docker-compose -f docker-compose-init.yml run init
docker-compose up
```
diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md
index 8827b501901..60b7bec2ba7 100644
--- a/doc/user/project/new_ci_build_permissions_model.md
+++ b/doc/user/project/new_ci_build_permissions_model.md
@@ -254,6 +254,12 @@ test:
This will make GitLab CI initialize (fetch) and update (checkout) all your
submodules recursively.
+If Git does not use the newly added relative URLs but still uses your old URLs,
+you might need to add `git submodule sync --recursive` to your `.gitlab-ci.yml`,
+prior to running `git submodule update --init --recursive`. This transfers the
+changes from your `.gitmodules` file into the `.git` folder, which is kept by
+runners between runs.
+
In case your environment or your Docker image doesn't have Git installed,
you have to either ask your Administrator or install the missing dependency
yourself:
diff --git a/lib/banzai/filter/relative_link_filter.rb b/lib/banzai/filter/relative_link_filter.rb
index 4fa8d05481f..f09d78be0ce 100644
--- a/lib/banzai/filter/relative_link_filter.rb
+++ b/lib/banzai/filter/relative_link_filter.rb
@@ -52,8 +52,8 @@ module Banzai
relative_url_root,
context[:project].path_with_namespace,
uri_type(file_path),
- ref,
- file_path
+ Addressable::URI.escape(ref),
+ Addressable::URI.escape(file_path)
].compact.join('/').squeeze('/').chomp('/')
uri
diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb
new file mode 100644
index 00000000000..b1a6d5fe0f6
--- /dev/null
+++ b/lib/gitlab/ee_compat_check.rb
@@ -0,0 +1,261 @@
+# rubocop: disable Rails/Output
+module Gitlab
+ # Checks if a set of migrations requires downtime or not.
+ class EeCompatCheck
+ EE_REPO = 'https://gitlab.com/gitlab-org/gitlab-ee.git'.freeze
+
+ attr_reader :ce_branch, :check_dir, :ce_repo
+
+ def initialize(branch:, check_dir:, ce_repo: nil)
+ @ce_branch = branch
+ @check_dir = check_dir
+ @ce_repo = ce_repo || 'https://gitlab.com/gitlab-org/gitlab-ce.git'
+ end
+
+ def check
+ ensure_ee_repo
+ delete_patches
+
+ generate_patch(ce_branch, ce_patch_full_path)
+
+ Dir.chdir(check_dir) do
+ step("In the #{check_dir} directory")
+
+ step("Pulling latest master", %w[git pull --ff-only origin master])
+
+ status = catch(:halt_check) do
+ ce_branch_compat_check!
+
+ delete_ee_branch_locally
+
+ ee_branch_presence_check!
+
+ ee_branch_compat_check!
+ end
+
+ delete_ee_branch_locally
+ delete_patches
+
+ if status.nil?
+ true
+ else
+ false
+ end
+ end
+ end
+
+ private
+
+ def ensure_ee_repo
+ if Dir.exist?(check_dir)
+ step("#{check_dir} already exists")
+ else
+ cmd = %W[git clone --branch master --single-branch --depth 1 #{EE_REPO} #{check_dir}]
+ step("Cloning #{EE_REPO} into #{check_dir}", cmd)
+ end
+ end
+
+ def ce_branch_compat_check!
+ cmd = %W[git apply --check #{ce_patch_full_path}]
+ status = step("Checking if #{ce_patch_name} applies cleanly to EE/master", cmd)
+
+ if status.zero?
+ puts ce_applies_cleanly_msg(ce_branch)
+ throw(:halt_check)
+ end
+ end
+
+ def ee_branch_presence_check!
+ status = step("Fetching origin/#{ee_branch}", %W[git fetch origin #{ee_branch}])
+
+ unless status.zero?
+ puts
+ puts ce_branch_doesnt_apply_cleanly_and_no_ee_branch_msg
+
+ throw(:halt_check, :ko)
+ end
+ end
+
+ def ee_branch_compat_check!
+ step("Checking out origin/#{ee_branch}", %W[git checkout -b #{ee_branch} FETCH_HEAD])
+
+ generate_patch(ee_branch, ee_patch_full_path)
+ cmd = %W[git apply --check #{ee_patch_full_path}]
+ status = step("Checking if #{ee_patch_name} applies cleanly to EE/master", cmd)
+
+ unless status.zero?
+ puts
+ puts ee_branch_doesnt_apply_cleanly_msg
+
+ throw(:halt_check, :ko)
+ end
+
+ puts
+ puts ee_applies_cleanly_msg
+ end
+
+ def generate_patch(branch, filepath)
+ FileUtils.rm(filepath, force: true)
+
+ depth = 0
+ loop do
+ depth += 10
+ step("Fetching origin/master", %W[git fetch origin master --depth=#{depth}])
+ status = step("Finding merge base with master", %W[git merge-base FETCH_HEAD #{branch}])
+
+ break if status.zero? || depth > 500
+ end
+
+ raise "#{branch} is too far behind master, please rebase it!" if depth > 500
+
+ step("Generating the patch against master")
+ output, status = Gitlab::Popen.popen(%w[git format-patch FETCH_HEAD --stdout])
+ throw(:halt_check, :ko) unless status.zero?
+
+ File.write(filepath, output)
+ throw(:halt_check, :ko) unless File.exist?(filepath)
+ end
+
+ def delete_ee_branch_locally
+ command(%w[git checkout master])
+ step("Deleting the local #{ee_branch} branch", %W[git branch -D #{ee_branch}])
+ end
+
+ def delete_patches
+ step("Deleting #{ce_patch_full_path}")
+ FileUtils.rm(ce_patch_full_path, force: true)
+
+ step("Deleting #{ee_patch_full_path}")
+ FileUtils.rm(ee_patch_full_path, force: true)
+ end
+
+ def ce_patch_name
+ @ce_patch_name ||= "#{ce_branch}.patch"
+ end
+
+ def ce_patch_full_path
+ @ce_patch_full_path ||= File.expand_path(ce_patch_name, check_dir)
+ end
+
+ def ee_branch
+ @ee_branch ||= "#{ce_branch}-ee"
+ end
+
+ def ee_patch_name
+ @ee_patch_name ||= "#{ee_branch}.patch"
+ end
+
+ def ee_patch_full_path
+ @ee_patch_full_path ||= File.expand_path(ee_patch_name, check_dir)
+ end
+
+ def step(desc, cmd = nil)
+ puts "\n=> #{desc}\n"
+
+ if cmd
+ puts "\n$ #{cmd.join(' ')}"
+ command(cmd)
+ end
+ end
+
+ def command(cmd)
+ output, status = Gitlab::Popen.popen(cmd)
+ puts output
+
+ status
+ end
+
+ def ce_applies_cleanly_msg(ce_branch)
+ <<-MSG.strip_heredoc
+ =================================================================
+ 🎉 Congratulations!! 🎉
+
+ The #{ce_branch} branch applies cleanly to EE/master!
+
+ Much ❤️!!
+ =================================================================\n
+ MSG
+ end
+
+ def ce_branch_doesnt_apply_cleanly_and_no_ee_branch_msg
+ <<-MSG.strip_heredoc
+ =================================================================
+ 💥 Oh no! 💥
+
+ The #{ce_branch} branch does not apply cleanly to the current
+ EE/master, and no #{ee_branch} branch was found in the EE repository.
+
+ Please create a #{ee_branch} branch that includes changes from
+ #{ce_branch} but also specific changes than can be applied cleanly
+ to EE/master.
+
+ There are different ways to create such branch:
+
+ 1. Create a new branch based on the CE branch and rebase it on top of EE/master
+
+ # In the EE repo
+ $ git fetch #{ce_repo} #{ce_branch}
+ $ git checkout -b #{ee_branch} FETCH_HEAD
+
+ # You can squash the #{ce_branch} commits into a single "Port of #{ce_branch} to EE" commit
+ # before rebasing to limit the conflicts-resolving steps during the rebase
+ $ git fetch origin
+ $ git rebase origin/master
+
+ At this point you will likely have conflicts.
+ Solve them, and continue/finish the rebase.
+
+ You can squash the #{ce_branch} commits into a single "Port of #{ce_branch} to EE".
+
+ 2. Create a new branch from master and cherry-pick your CE commits
+
+ # In the EE repo
+ $ git fetch origin
+ $ git checkout -b #{ee_branch} FETCH_HEAD
+ $ git fetch #{ce_repo} #{ce_branch}
+ $ git cherry-pick SHA # Repeat for all the commits you want to pick
+
+ You can squash the #{ce_branch} commits into a single "Port of #{ce_branch} to EE" commit.
+
+ Don't forget to push your branch to #{EE_REPO}:
+
+ # In the EE repo
+ $ git push origin #{ee_branch}
+
+ You can then retry this failed build, and hopefully it should pass.
+
+ Stay 💪 !
+ =================================================================\n
+ MSG
+ end
+
+ def ee_branch_doesnt_apply_cleanly_msg
+ <<-MSG.strip_heredoc
+ =================================================================
+ 💥 Oh no! 💥
+
+ The #{ce_branch} does not apply cleanly to the current
+ EE/master, and even though a #{ee_branch} branch exists in the EE
+ repository, it does not apply cleanly either to EE/master!
+
+ Please update the #{ee_branch}, push it again to #{EE_REPO}, and
+ retry this build.
+
+ Stay 💪 !
+ =================================================================\n
+ MSG
+ end
+
+ def ee_applies_cleanly_msg
+ <<-MSG.strip_heredoc
+ =================================================================
+ 🎉 Congratulations!! 🎉
+
+ The #{ee_branch} branch applies cleanly to EE/master!
+
+ Much ❤️!!
+ =================================================================\n
+ MSG
+ end
+ end
+end
diff --git a/lib/tasks/ce_to_ee_merge_check.rake b/lib/tasks/ce_to_ee_merge_check.rake
deleted file mode 100644
index 424e7883060..00000000000
--- a/lib/tasks/ce_to_ee_merge_check.rake
+++ /dev/null
@@ -1,4 +0,0 @@
-desc 'Checks if the branch would apply cleanly to EE'
-task ce_to_ee_merge_check: :environment do
- Rake::Task['gitlab:dev:ce_to_ee_merge_check'].invoke
-end
diff --git a/lib/tasks/ee_compat_check.rake b/lib/tasks/ee_compat_check.rake
new file mode 100644
index 00000000000..f494fa5c5c2
--- /dev/null
+++ b/lib/tasks/ee_compat_check.rake
@@ -0,0 +1,4 @@
+desc 'Checks if the branch would apply cleanly to EE'
+task ee_compat_check: :environment do
+ Rake::Task['gitlab:dev:ee_compat_check'].invoke
+end
diff --git a/lib/tasks/gitlab/dev.rake b/lib/tasks/gitlab/dev.rake
index 47bdb2d32d2..5ee99dfc810 100644
--- a/lib/tasks/gitlab/dev.rake
+++ b/lib/tasks/gitlab/dev.rake
@@ -1,106 +1,21 @@
namespace :gitlab do
namespace :dev do
desc 'Checks if the branch would apply cleanly to EE'
- task ce_to_ee_merge_check: :environment do
+ task ee_compat_check: :environment do
return if defined?(Gitlab::License)
return unless ENV['CI']
- ce_repo = ENV['CI_BUILD_REPO']
- ce_branch = ENV['CI_BUILD_REF_NAME']
-
- ee_repo = 'https://gitlab.com/gitlab-org/gitlab-ee.git'
- ee_branch = "#{ce_branch}-ee"
- ee_dir = 'gitlab-ee-merge-check'
-
- puts "\n=> Cloning #{ee_repo} into #{ee_dir}\n"
- `git clone #{ee_repo} #{ee_dir} --depth 1`
- Dir.chdir(ee_dir) do
- puts "\n => Fetching #{ce_repo}/#{ce_branch}\n"
- `git fetch #{ce_repo} #{ce_branch} --depth 1`
-
- # Try to merge the current tested branch to EE/master...
- puts "\n => Merging #{ce_repo}/#{ce_branch} into #{ee_repo}/master\n"
- `git merge FETCH_HEAD`
-
- exit 0 if $?.success?
-
- # Check if the <branch>-ee branch exists...
- puts "\n => Check if #{ee_repo}/#{ee_branch} exists\n"
- `git rev-parse --verify #{ee_branch}`
-
- # The <branch>-ee doesn't exist
- unless $?.success?
- puts
- puts <<-MSG.strip_heredoc
- =================================================================
- The #{ce_branch} branch cannot be merged without conflicts to the
- current EE/master, and no #{ee_branch} branch was detected in
- the EE repository.
-
- Please create a #{ee_branch} branch that includes changes from
- #{ce_branch} but also specific changes than can be applied cleanly
- to EE/master.
-
- You can create this branch as follows:
-
- 1. In the EE repo:
- $ git fetch origin
- $ git fetch #{ce_repo} #{ce_branch}
- $ git checkout -b #{ee_branch} FETCH_HEAD
- $ git rebase origin/master
- 2. At this point you will likely have conflicts, solve them, and
- continue/finish the rebase. Note: You can squash the CE commits
- before rebasing.
- 3. You can squash all the original #{ce_branch} commits into a
- single "Port of #{ce_branch} to EE".
- 4. Push your branch to #{ee_repo}:
- $ git push origin #{ee_branch}
- =================================================================\n
- MSG
-
- exit 1
- end
-
- # Try to merge the <branch>-ee branch to EE/master...
- puts "\n => Merging #{ee_repo}/#{ee_branch} into #{ee_repo}/master\n"
- `git merge #{ee_branch} master`
-
- # The <branch>-ee cannot be merged cleanly to EE/master...
- unless $?.success?
- puts
- puts <<-MSG.strip_heredoc
- =================================================================
- The #{ce_branch} branch cannot be merged without conflicts to
- EE/master, and even though the #{ee_branch} branch exists in the EE
- repository, it cannot be merged without conflicts to EE/master.
-
- Please update the #{ee_branch}, push it again to #{ee_repo}, and
- retry this job.
- =================================================================\n
- MSG
-
- exit 2
- end
-
- puts "\n => Merging #{ce_repo}/#{ce_branch} into #{ee_repo}/master\n"
- `git merge FETCH_HEAD`
- exit 0 if $?.success?
-
- # The <branch>-ee can be merged cleanly to EE/master, but <branch> still
- # cannot be merged cleanly to EE/master...
- puts
- puts <<-MSG.strip_heredoc
- =================================================================
- The #{ce_branch} branch cannot be merged without conflicts to EE, and
- even though the #{ee_branch} branch exists in the EE repository and
- applies cleanly to EE/master, it doesn't prevent conflicts when
- merging #{ce_branch} into EE.
-
- We may be in a complex situation here.
- =================================================================\n
- MSG
-
- exit 3
+ success =
+ Gitlab::EeCompatCheck.new(
+ branch: ENV['CI_BUILD_REF_NAME'],
+ check_dir: File.expand_path('ee-compat-check', __dir__),
+ ce_repo: ENV['CI_BUILD_REPO']
+ ).check
+
+ if success
+ exit 0
+ else
+ exit 1
end
end
end
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index 0fb1608a0a3..c533ce1d87f 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -624,6 +624,10 @@ describe 'Issue Boards', feature: true, js: true do
it 'does not show create new list' do
expect(page).not_to have_selector('.js-new-board-list')
end
+
+ it 'does not allow dragging' do
+ expect(page).not_to have_selector('.user-can-drag')
+ end
end
context 'as guest user' do
diff --git a/spec/features/login_spec.rb b/spec/features/login_spec.rb
index 996f39ea06d..76bcfbe523a 100644
--- a/spec/features/login_spec.rb
+++ b/spec/features/login_spec.rb
@@ -215,4 +215,69 @@ feature 'Login', feature: true do
end
end
end
+
+ describe 'UI tabs and panes' do
+ context 'when no defaults are changed' do
+ it 'correctly renders tabs and panes' do
+ ensure_tab_pane_correctness
+ end
+ end
+
+ context 'when signup is disabled' do
+ before do
+ stub_application_setting(signup_enabled: false)
+ end
+
+ it 'correctly renders tabs and panes' do
+ ensure_tab_pane_correctness
+ end
+ end
+
+ context 'when ldap is enabled' do
+ before do
+ visit new_user_session_path
+ allow(page).to receive(:form_based_providers).and_return([:ldapmain])
+ allow(page).to receive(:ldap_enabled).and_return(true)
+ end
+
+ it 'correctly renders tabs and panes' do
+ ensure_tab_pane_correctness(false)
+ end
+ end
+
+ context 'when crowd is enabled' do
+ before do
+ visit new_user_session_path
+ allow(page).to receive(:form_based_providers).and_return([:crowd])
+ allow(page).to receive(:crowd_enabled?).and_return(true)
+ end
+
+ it 'correctly renders tabs and panes' do
+ ensure_tab_pane_correctness(false)
+ end
+ end
+
+ def ensure_tab_pane_correctness(visit_path = true)
+ if visit_path
+ visit new_user_session_path
+ end
+
+ ensure_tab_pane_counts
+ ensure_one_active_tab
+ ensure_one_active_pane
+ end
+
+ def ensure_tab_pane_counts
+ tabs_count = page.all('[role="tab"]').size
+ expect(page).to have_selector('[role="tabpanel"]', count: tabs_count)
+ end
+
+ def ensure_one_active_tab
+ expect(page).to have_selector('.nav-tabs > li.active', count: 1)
+ end
+
+ def ensure_one_active_pane
+ expect(page).to have_selector('.tab-pane.active', count: 1)
+ end
+ end
end
diff --git a/spec/finders/labels_finder_spec.rb b/spec/finders/labels_finder_spec.rb
index 27acc464ea2..10cfb66ec1c 100644
--- a/spec/finders/labels_finder_spec.rb
+++ b/spec/finders/labels_finder_spec.rb
@@ -38,6 +38,14 @@ describe LabelsFinder do
expect(finder.execute).to eq [group_label_2, group_label_3, project_label_1, group_label_1, project_label_2, project_label_4]
end
+
+ it 'returns labels available if nil title is supplied' do
+ group_2.add_developer(user)
+ # params[:title] will return `nil` regardless whether it is specified
+ finder = described_class.new(user, title: nil)
+
+ expect(finder.execute).to eq [group_label_2, group_label_3, project_label_1, group_label_1, project_label_2, project_label_4]
+ end
end
context 'filtering by group_id' do
@@ -64,6 +72,30 @@ describe LabelsFinder do
expect(finder.execute).to eq [group_label_2]
end
+
+ it 'returns label with title alias' do
+ finder = described_class.new(user, name: 'Group Label 2')
+
+ expect(finder.execute).to eq [group_label_2]
+ end
+
+ it 'returns no labels if empty title is supplied' do
+ finder = described_class.new(user, title: [])
+
+ expect(finder.execute).to be_empty
+ end
+
+ it 'returns no labels if blank title is supplied' do
+ finder = described_class.new(user, title: '')
+
+ expect(finder.execute).to be_empty
+ end
+
+ it 'returns no labels if empty name is supplied' do
+ finder = described_class.new(user, name: [])
+
+ expect(finder.execute).to be_empty
+ end
end
end
end
diff --git a/spec/javascripts/gl_field_errors_spec.js.es6 b/spec/javascripts/gl_field_errors_spec.js.es6
index 36feb2b2aa5..da9259edd78 100644
--- a/spec/javascripts/gl_field_errors_spec.js.es6
+++ b/spec/javascripts/gl_field_errors_spec.js.es6
@@ -11,12 +11,12 @@
this.fieldErrors = new global.GlFieldErrors($form);
});
- it('should properly initialize the form', function() {
+ it('should select the correct input elements', function() {
expect(this.$form).toBeDefined();
expect(this.$form.length).toBe(1);
expect(this.fieldErrors).toBeDefined();
const inputs = this.fieldErrors.state.inputs;
- expect(inputs.length).toBe(5);
+ expect(inputs.length).toBe(4);
});
it('should ignore elements with custom error handling', function() {
diff --git a/spec/lib/banzai/filter/relative_link_filter_spec.rb b/spec/lib/banzai/filter/relative_link_filter_spec.rb
index 6b58f3e43ee..2bfa51deb20 100644
--- a/spec/lib/banzai/filter/relative_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/relative_link_filter_spec.rb
@@ -50,14 +50,6 @@ describe Banzai::Filter::RelativeLinkFilter, lib: true do
end
end
- shared_examples :relative_to_requested do
- it 'rebuilds URL relative to the requested path' do
- doc = filter(link('users.md'))
- expect(doc.at_css('a')['href']).
- to eq "/#{project_path}/blob/#{ref}/doc/api/users.md"
- end
- end
-
context 'with a project_wiki' do
let(:project_wiki) { double('ProjectWiki') }
include_examples :preserve_unchanged
@@ -188,12 +180,38 @@ describe Banzai::Filter::RelativeLinkFilter, lib: true do
context 'when requested path is a file in the repo' do
let(:requested_path) { 'doc/api/README.md' }
- include_examples :relative_to_requested
+ it 'rebuilds URL relative to the containing directory' do
+ doc = filter(link('users.md'))
+ expect(doc.at_css('a')['href']).to eq "/#{project_path}/blob/#{Addressable::URI.escape(ref)}/doc/api/users.md"
+ end
end
context 'when requested path is a directory in the repo' do
- let(:requested_path) { 'doc/api' }
- include_examples :relative_to_requested
+ let(:requested_path) { 'doc/api/' }
+ it 'rebuilds URL relative to the directory' do
+ doc = filter(link('users.md'))
+ expect(doc.at_css('a')['href']).to eq "/#{project_path}/blob/#{Addressable::URI.escape(ref)}/doc/api/users.md"
+ end
+ end
+
+ context 'when ref name contains percent sign' do
+ let(:ref) { '100%branch' }
+ let(:commit) { project.commit('1b12f15a11fc6e62177bef08f47bc7b5ce50b141') }
+ let(:requested_path) { 'foo/bar/' }
+ it 'correctly escapes the ref' do
+ doc = filter(link('.gitkeep'))
+ expect(doc.at_css('a')['href']).to eq "/#{project_path}/blob/#{Addressable::URI.escape(ref)}/foo/bar/.gitkeep"
+ end
+ end
+
+ context 'when requested path is a directory with space in the repo' do
+ let(:ref) { 'master' }
+ let(:commit) { project.commit('38008cb17ce1466d8fec2dfa6f6ab8dcfe5cf49e') }
+ let(:requested_path) { 'with space/' }
+ it 'does not escape the space twice' do
+ doc = filter(link('README.md'))
+ expect(doc.at_css('a')['href']).to eq "/#{project_path}/blob/#{Addressable::URI.escape(ref)}/with%20space/README.md"
+ end
end
end
diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb
index b2fe96e2e02..f6b2ec5ae31 100644
--- a/spec/models/members/project_member_spec.rb
+++ b/spec/models/members/project_member_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe ProjectMember, models: true do
describe 'associations' do
- it { is_expected.to belong_to(:project).class_name('Project').with_foreign_key(:source_id) }
+ it { is_expected.to belong_to(:project).with_foreign_key(:source_id) }
end
describe 'validations' do
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 6e5137602aa..1067ff7bb4d 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -6,8 +6,8 @@ describe MergeRequest, models: true do
subject { create(:merge_request) }
describe 'associations' do
- it { is_expected.to belong_to(:target_project).with_foreign_key(:target_project_id).class_name('Project') }
- it { is_expected.to belong_to(:source_project).with_foreign_key(:source_project_id).class_name('Project') }
+ it { is_expected.to belong_to(:target_project).class_name('Project') }
+ it { is_expected.to belong_to(:source_project).class_name('Project') }
it { is_expected.to belong_to(:merge_user).class_name("User") }
it { is_expected.to have_many(:merge_request_diffs).dependent(:destroy) }
end
@@ -1286,7 +1286,8 @@ describe MergeRequest, models: true do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:fork_project) { create(:project, forked_from_project: project, namespace: user.namespace) }
- let(:merge_request) do
+
+ let!(:merge_request) do
create(:closed_merge_request,
source_project: fork_project,
target_project: project)
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 65b2896930a..10c39b90212 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -15,11 +15,11 @@ describe User, models: true do
describe 'associations' do
it { is_expected.to have_one(:namespace) }
- it { is_expected.to have_many(:snippets).class_name('Snippet').dependent(:destroy) }
+ it { is_expected.to have_many(:snippets).dependent(:destroy) }
it { is_expected.to have_many(:project_members).dependent(:destroy) }
it { is_expected.to have_many(:groups) }
it { is_expected.to have_many(:keys).dependent(:destroy) }
- it { is_expected.to have_many(:events).class_name('Event').dependent(:destroy) }
+ it { is_expected.to have_many(:events).dependent(:destroy) }
it { is_expected.to have_many(:recent_events).class_name('Event') }
it { is_expected.to have_many(:issues).dependent(:destroy) }
it { is_expected.to have_many(:notes).dependent(:destroy) }
diff --git a/spec/services/issues/move_service_spec.rb b/spec/services/issues/move_service_spec.rb
index 93bf0f64963..f0ded06b785 100644
--- a/spec/services/issues/move_service_spec.rb
+++ b/spec/services/issues/move_service_spec.rb
@@ -23,14 +23,15 @@ describe Issues::MoveService, services: true do
old_project.team << [user, :reporter]
new_project.team << [user, :reporter]
- ['label1', 'label2'].each do |label|
+ labels = Array.new(2) { |x| "label%d" % (x + 1) }
+
+ labels.each do |label|
old_issue.labels << create(:label,
project_id: old_project.id,
title: label)
- end
- new_project.labels << create(:label, title: 'label1')
- new_project.labels << create(:label, title: 'label2')
+ new_project.labels << create(:label, title: label)
+ end
end
end
@@ -207,10 +208,10 @@ describe Issues::MoveService, services: true do
end
end
- describe 'rewritting references' do
+ describe 'rewriting references' do
include_context 'issue move executed'
- context 'issue reference' do
+ context 'issue references' do
let(:another_issue) { create(:issue, project: old_project) }
let(:description) { "Some description #{another_issue.to_reference}" }
@@ -219,6 +220,16 @@ describe Issues::MoveService, services: true do
.to eq "Some description #{old_project.to_reference}#{another_issue.to_reference}"
end
end
+
+ context "user references" do
+ let(:another_issue) { create(:issue, project: old_project) }
+ let(:description) { "Some description #{user.to_reference}" }
+
+ it "doesn't throw any errors for issues containing user references" do
+ expect(new_issue.description)
+ .to eq "Some description #{user.to_reference}"
+ end
+ end
end
context 'moving to same project' do
@@ -277,5 +288,25 @@ describe Issues::MoveService, services: true do
it { expect { move }.to raise_error(StandardError, /permissions/) }
end
end
+
+ context 'movable issue with no assigned labels' do
+ before do
+ old_project.team << [user, :reporter]
+ new_project.team << [user, :reporter]
+
+ labels = Array.new(2) { |x| "label%d" % (x + 1) }
+
+ labels.each do |label|
+ new_project.labels << create(:label, title: label)
+ end
+ end
+
+ include_context 'issue move executed'
+
+ it 'does not assign labels to new issue' do
+ expected_label_titles = new_issue.reload.labels.map(&:title)
+ expect(expected_label_titles.size).to eq 0
+ end
+ end
end
end
diff --git a/spec/views/projects/merge_requests/_commits.html.haml_spec.rb b/spec/views/projects/merge_requests/_commits.html.haml_spec.rb
new file mode 100644
index 00000000000..6f70b3daf8e
--- /dev/null
+++ b/spec/views/projects/merge_requests/_commits.html.haml_spec.rb
@@ -0,0 +1,38 @@
+require 'spec_helper'
+
+describe 'projects/merge_requests/show/_commits.html.haml' do
+ include Devise::Test::ControllerHelpers
+
+ let(:user) { create(:user) }
+ let(:target_project) { create(:project) }
+
+ let(:source_project) do
+ create(:project, forked_from_project: target_project)
+ end
+
+ let(:merge_request) do
+ create(:merge_request, :simple,
+ source_project: source_project,
+ target_project: target_project,
+ author: user)
+ end
+
+ before do
+ controller.prepend_view_path('app/views/projects')
+
+ assign(:merge_request, merge_request)
+ assign(:commits, merge_request.commits)
+ end
+
+ it 'shows commits from source project' do
+ render
+
+ commit = source_project.commit(merge_request.source_branch)
+ href = namespace_project_commit_path(
+ source_project.namespace,
+ source_project,
+ commit)
+
+ expect(rendered).to have_link(Commit.truncate_sha(commit.sha), href: href)
+ end
+end