summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Greiling <mike@pixelcog.com>2017-01-28 11:25:15 -0600
committerMike Greiling <mike@pixelcog.com>2017-01-28 11:25:15 -0600
commitc454dec170da32fc83b8d78c61c3f452c819f0ed (patch)
treedf05c491f06e845a0e8266afcb23962e95160a4a
parenta5f7934420e1d26682700e02aa8fc9333e808f47 (diff)
parentb78d06b78143b16dccc5d5afaa8796473b68bea1 (diff)
downloadgitlab-ce-c454dec170da32fc83b8d78c61c3f452c819f0ed.tar.gz
Merge branch 'master' into go-go-gadget-webpack
* master: (33 commits) Improved code style on the issue_sidebar_spec.rb add CHAGELOG.md entry for !8831 remove assets:compile step from relative_url docs update scripts and docs to reference the newly namespaced rake task namespace assets rake tasks to gitlab:assets:* correct gzip files if they exist as well automatically correct CSS urls on assets:precompile remove hard-coded assets path for ace editor modules Fixed cancel button in the services form not redirecting back to the integrations settings view Fix search bar search param encoding Fix a transient failure in the `Explore::ProjectsController` spec Fix filtering with multiple words Fix project name label's for reference in project settings Fixed merge request tabs extra margin Don't call `#uniq` on a relation Move Gitlab::Shell and Gitlab::ShellAdapter files to lib/ Move ApplicationSetting DEFAULTS to `.defaults` instead Move a begin/rescue clause to ApplicationSetting.expire Use badge partial as single source of truth instead of having 2 partials doing the same Changes after review ...
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock7
-rw-r--r--app/assets/javascripts/application.js9
-rw-r--r--app/assets/javascripts/commits.js8
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_utils.js.es610
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js.es63
-rw-r--r--app/assets/javascripts/issuable_context.js9
-rw-r--r--app/assets/javascripts/lib/ace.js3
-rw-r--r--app/assets/javascripts/lib/ace/ace_config_paths.js.erb25
-rw-r--r--app/assets/javascripts/users/calendar.js2
-rw-r--r--app/assets/stylesheets/framework/calendar.scss1
-rw-r--r--app/assets/stylesheets/framework/header.scss2
-rw-r--r--app/assets/stylesheets/framework/variables.scss2
-rw-r--r--app/assets/stylesheets/pages/issuable.scss4
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss26
-rw-r--r--app/assets/stylesheets/pages/projects.scss4
-rw-r--r--app/controllers/autocomplete_controller.rb5
-rw-r--r--app/models/application_setting.rb95
-rw-r--r--app/views/ci/status/_badge.html.haml3
-rw-r--r--app/views/projects/builds/_header.html.haml4
-rw-r--r--app/views/projects/edit.html.haml2
-rw-r--r--app/views/projects/issues/index.html.haml4
-rw-r--r--app/views/projects/merge_requests/_show.html.haml2
-rw-r--r--app/views/projects/services/_form.html.haml2
-rw-r--r--changelogs/unreleased/26947-build-status-self-link.yml4
-rw-r--r--changelogs/unreleased/27248-filtered-search-does-not-allow-filtering-labels-with-multiple-words.yml4
-rw-r--r--changelogs/unreleased/27259-label-for-references-the-wrong-associated-text-input.yml4
-rw-r--r--changelogs/unreleased/contribution-calendar-scroll.yml4
-rw-r--r--changelogs/unreleased/fix-cancel-integration-settings.yml4
-rw-r--r--changelogs/unreleased/fix-search-bar-search-param.yml4
-rw-r--r--changelogs/unreleased/issuable-sidebar-bug.yml4
-rw-r--r--changelogs/unreleased/mr-tabs-container-offset.yml4
-rw-r--r--changelogs/unreleased/relative-url-assets.yml4
-rw-r--r--config/initializers/1_settings.rb8
-rw-r--r--config/initializers/5_backend.rb6
-rw-r--r--config/initializers/rspec_profiling.rb14
-rw-r--r--doc/administration/raketasks/maintenance.md4
-rw-r--r--doc/api/commits.md2
-rw-r--r--doc/development/performance.md35
-rw-r--r--doc/install/installation.md2
-rw-r--r--doc/install/relative_url.md8
-rw-r--r--doc/update/patch_versions.md2
-rw-r--r--lib/gitlab/current_settings.rb4
-rw-r--r--lib/gitlab/shell.rb (renamed from lib/gitlab/backend/shell.rb)0
-rw-r--r--lib/gitlab/shell_adapter.rb (renamed from lib/gitlab/backend/shell_adapter.rb)0
-rw-r--r--lib/gitlab/upgrader.rb2
-rwxr-xr-xlib/support/deploy/deploy.sh4
-rw-r--r--lib/tasks/gitlab/assets.rake47
-rw-r--r--spec/controllers/explore/projects_controller_spec.rb25
-rw-r--r--spec/features/issues/filtered_search/filter_issues_spec.rb2
-rw-r--r--spec/features/issues/issue_sidebar_spec.rb25
-rw-r--r--spec/features/projects/project_settings_spec.rb4
-rw-r--r--spec/javascripts/commits_spec.js.es650
-rw-r--r--spec/javascripts/filtered_search/dropdown_utils_spec.js.es6156
-rw-r--r--spec/javascripts/filtered_search/filtered_search_manager_spec.js.es668
-rw-r--r--spec/spec_helper.rb4
-rw-r--r--spec/support/mobile_helpers.rb13
-rw-r--r--spec/views/projects/builds/show.html.haml_spec.rb30
59 files changed, 651 insertions, 135 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6976f24c391..588f5b59e4c 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -109,7 +109,7 @@ setup-test-env:
script:
- npm install
- bundle exec rake webpack:compile
- - bundle exec rake assets:precompile 2>/dev/null
+ - bundle exec rake gitlab:assets:compile 2>/dev/null
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
artifacts:
expire_in: 7d
diff --git a/Gemfile b/Gemfile
index e38dcae70ce..726d4484dc0 100644
--- a/Gemfile
+++ b/Gemfile
@@ -280,6 +280,7 @@ group :development, :test do
gem 'rspec-retry', '~> 0.4.5'
gem 'spinach-rails', '~> 0.2.1'
gem 'spinach-rerun-reporter', '~> 0.0.2'
+ gem 'rspec_profiling'
# Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826)
gem 'minitest', '~> 5.7.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index b1ef956c32c..b4d03eaddc2 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -638,6 +638,11 @@ GEM
rspec-retry (0.4.5)
rspec-core
rspec-support (3.5.0)
+ rspec_profiling (0.0.4)
+ activerecord
+ pg
+ rails
+ sqlite3
rubocop (0.46.0)
parser (>= 2.3.1.1, < 3.0)
powerpack (~> 0.1)
@@ -733,6 +738,7 @@ GEM
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
+ sqlite3 (1.3.11)
stackprof (0.2.10)
state_machines (0.4.0)
state_machines-activemodel (0.4.0)
@@ -953,6 +959,7 @@ DEPENDENCIES
rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.5.0)
rspec-retry (~> 0.4.5)
+ rspec_profiling
rubocop (~> 0.46.0)
rubocop-rspec (~> 1.9.1)
ruby-fogbugz (~> 0.2.1)
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 98042106111..ae81eecfe6a 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -81,7 +81,6 @@ window.ES6Promise.polyfill();
var $sidebarGutterToggle = $('.js-sidebar-toggle');
var $flash = $('.flash-container');
var bootstrapBreakpoint = bp.getBreakpointSize();
- var checkInitialSidebarSize;
var fitSidebarForSize;
// Set the default path for all cookies to GitLab's root directory
@@ -243,19 +242,11 @@ window.ES6Promise.polyfill();
return $document.trigger('breakpoint:change', [bootstrapBreakpoint]);
}
};
- checkInitialSidebarSize = function () {
- bootstrapBreakpoint = bp.getBreakpointSize();
- if (bootstrapBreakpoint === 'xs' || 'sm') {
- return $document.trigger('breakpoint:change', [bootstrapBreakpoint]);
- }
- };
$window.off('resize.app').on('resize.app', function () {
return fitSidebarForSize();
});
gl.awardsHandler = new AwardsHandler();
- checkInitialSidebarSize();
new Aside();
-
// bind sidebar events
new gl.Sidebar();
});
diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js
index cabeae74ae3..c6fdfbcaa10 100644
--- a/app/assets/javascripts/commits.js
+++ b/app/assets/javascripts/commits.js
@@ -3,7 +3,7 @@
(function() {
this.CommitsList = (function() {
- function CommitsList() {}
+ var CommitsList = {};
CommitsList.timer = null;
@@ -20,6 +20,7 @@
});
this.content = $("#commits-list");
this.searchField = $("#commits-search");
+ this.lastSearch = this.searchField.val();
return this.initSearch();
};
@@ -37,6 +38,7 @@
var commitsUrl, form, search;
form = $(".commits-search-form");
search = CommitsList.searchField.val();
+ if (search === CommitsList.lastSearch) return;
commitsUrl = form.attr("action") + '?' + form.serialize();
CommitsList.content.fadeTo('fast', 0.5);
return $.ajax({
@@ -47,12 +49,16 @@
return CommitsList.content.fadeTo('fast', 1.0);
},
success: function(data) {
+ CommitsList.lastSearch = search;
CommitsList.content.html(data.html);
return history.replaceState({
page: commitsUrl
// Change url so if user reload a page - search results are saved
}, document.title, commitsUrl);
},
+ error: function() {
+ CommitsList.lastSearch = null;
+ },
dataType: "json"
});
};
diff --git a/app/assets/javascripts/filtered_search/dropdown_utils.js.es6 b/app/assets/javascripts/filtered_search/dropdown_utils.js.es6
index eeab10fba17..de3fa116717 100644
--- a/app/assets/javascripts/filtered_search/dropdown_utils.js.es6
+++ b/app/assets/javascripts/filtered_search/dropdown_utils.js.es6
@@ -28,7 +28,12 @@
if (lastToken !== searchToken) {
const title = updatedItem.title.toLowerCase();
let value = lastToken.value.toLowerCase();
- value = value.replace(/"(.*?)"/g, str => str.slice(1).slice(0, -1));
+
+ // Removes the first character if it is a quotation so that we can search
+ // with multiple words
+ if ((value[0] === '"' || value[0] === '\'') && title.indexOf(' ') !== -1) {
+ value = value.slice(1);
+ }
// Eg. filterSymbol = ~ for labels
const matchWithoutSymbol = lastToken.symbol === filterSymbol && title.indexOf(value) !== -1;
@@ -83,8 +88,9 @@
const selectionStart = input.selectionStart;
let inputValue = input.value;
// Replace all spaces inside quote marks with underscores
+ // (will continue to match entire string until an end quote is found if any)
// This helps with matching the beginning & end of a token:key
- inputValue = inputValue.replace(/("(.*?)"|:\s+)/g, str => str.replace(/\s/g, '_'));
+ inputValue = inputValue.replace(/(('[^']*'{0,1})|("[^"]*"{0,1})|:\s+)/g, str => str.replace(/\s/g, '_'));
// Get the right position for the word selected
// Regex matches first space
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6
index 8d62324b79f..029564ffc61 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6
@@ -196,7 +196,8 @@
});
if (searchToken) {
- paths.push(`search=${encodeURIComponent(searchToken)}`);
+ const sanitized = searchToken.split(' ').map(t => encodeURIComponent(t)).join('+');
+ paths.push(`search=${sanitized}`);
}
Turbolinks.visit(`?scope=all&utf8=✓&${paths.join('&')}`);
diff --git a/app/assets/javascripts/issuable_context.js b/app/assets/javascripts/issuable_context.js
index 9c53cdee58e..c77fbb6a1c7 100644
--- a/app/assets/javascripts/issuable_context.js
+++ b/app/assets/javascripts/issuable_context.js
@@ -1,5 +1,7 @@
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-new, comma-dangle, quotes, prefer-arrow-callback, consistent-return, one-var, no-var, one-var-declaration-per-line, no-underscore-dangle, max-len */
/* global UsersSelect */
+/* global Cookies */
+/* global bp */
(function() {
this.IssuableContext = (function() {
@@ -37,6 +39,13 @@
}, 0);
}
});
+ window.addEventListener('beforeunload', function() {
+ // collapsed_gutter cookie hides the sidebar
+ var bpBreakpoint = bp.getBreakpointSize();
+ if (bpBreakpoint === 'xs' || bpBreakpoint === 'sm') {
+ Cookies.set('collapsed_gutter', true);
+ }
+ });
$(".right-sidebar").niceScroll();
}
diff --git a/app/assets/javascripts/lib/ace.js b/app/assets/javascripts/lib/ace.js
index 4cdf99cae72..9cdc0309503 100644
--- a/app/assets/javascripts/lib/ace.js
+++ b/app/assets/javascripts/lib/ace.js
@@ -1,2 +1,3 @@
-/*= require ace-rails-ap */
+/*= require ace/ace */
/*= require ace/ext-searchbox */
+/*= require ./ace/ace_config_paths */
diff --git a/app/assets/javascripts/lib/ace/ace_config_paths.js.erb b/app/assets/javascripts/lib/ace/ace_config_paths.js.erb
new file mode 100644
index 00000000000..25e623f0fdc
--- /dev/null
+++ b/app/assets/javascripts/lib/ace/ace_config_paths.js.erb
@@ -0,0 +1,25 @@
+<%
+ace_gem_path = Bundler.rubygems.find_name('ace-rails-ap').first.full_gem_path
+ace_workers = Dir[ace_gem_path + '/vendor/assets/javascripts/ace/worker-*.js'].sort.map do |file|
+ File.basename(file, '.js').sub(/^worker-/, '')
+end
+ace_modes = Dir[ace_gem_path + '/vendor/assets/javascripts/ace/mode-*.js'].sort.map do |file|
+ File.basename(file, '.js').sub(/^mode-/, '')
+end
+%>
+
+(function() {
+ window.gon = window.gon || {};
+ var basePath = (window.gon.relative_url_root || '').replace(/\/$/, '') + '/assets/ace';
+ ace.config.set('basePath', basePath);
+
+ // configure paths for all worker modules
+<% ace_workers.each do |worker| %>
+ ace.config.setModuleUrl('ace/mode/<%= worker %>_worker', basePath + '/worker-<%= worker %>.js');
+<% end %>
+
+ // configure paths for all mode modules
+<% ace_modes.each do |mode| %>
+ ace.config.setModuleUrl('ace/mode/<%= mode %>', basePath + '/mode-<%= mode %>.js');
+<% end %>
+})();
diff --git a/app/assets/javascripts/users/calendar.js b/app/assets/javascripts/users/calendar.js
index 5e07359b51b..e0e40ad3adb 100644
--- a/app/assets/javascripts/users/calendar.js
+++ b/app/assets/javascripts/users/calendar.js
@@ -158,7 +158,7 @@
};
Calendar.prototype.renderMonths = function() {
- return this.svg.append('g').selectAll('text').data(this.months).enter().append('text').attr('x', function(date) {
+ return this.svg.append('g').attr('direction', 'ltr').selectAll('text').data(this.months).enter().append('text').attr('x', function(date) {
return date.x;
}).attr('y', 10).attr('class', 'user-contrib-text').text((function(_this) {
return function(date) {
diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
index ef921a8c6a9..1d2d1bfc0d7 100644
--- a/app/assets/stylesheets/framework/calendar.scss
+++ b/app/assets/stylesheets/framework/calendar.scss
@@ -1,6 +1,7 @@
.calender-block {
padding-left: 0;
padding-right: 0;
+ direction: rtl;
@media (min-width: $screen-sm-min) and (max-width: $screen-md-max) {
overflow-x: scroll;
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 24a1ce2b84d..2a01bc4d44d 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -71,7 +71,7 @@ header {
&:focus,
&:active {
background-color: $gray-light;
- color: darken($gl-text-color-secondary, 30%);
+ color: $gl-text-color;
.todos-pending-count {
background: darken($todo-alert-blue, 10%);
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 07cb669a46e..7809d4866f1 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -178,7 +178,7 @@ $count-arrow-border: #dce0e5;
$save-project-loader-color: #555;
$divergence-graph-bar-bg: #ccc;
$divergence-graph-separator-bg: #ccc;
-$general-hover-transition-duration: 150ms;
+$general-hover-transition-duration: 100ms;
$general-hover-transition-curve: linear;
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 93cc5a8cf0a..4ef95d27f4f 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -26,10 +26,6 @@
border: 0;
}
}
-
- .container-fluid {
- @extend .fixed-width-container;
- }
}
}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 45ff9f7ff5f..ab68b360f93 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -420,10 +420,6 @@
.merge-request-tabs-holder {
background-color: $white-light;
- .container-limited {
- max-width: $limited-layout-width;
- }
-
&.affix {
top: 100px;
left: 0;
@@ -433,10 +429,26 @@
@media (max-width: $screen-xs-max) {
right: 0;
}
+
+ .merge-request-tabs-container {
+ padding-left: $gl-padding;
+ padding-right: $gl-padding;
+ }
}
+}
- &:not(.affix) .container-fluid {
- padding-left: 0;
- padding-right: 0;
+.limit-container-width {
+ .merge-request-tabs-container {
+ max-width: $limited-layout-width;
+ margin-left: auto;
+ margin-right: auto;
+ }
+}
+
+.limit-container-width:not(.container-limited) {
+ .merge-request-tabs-holder:not(.affix) {
+ .merge-request-tabs-container {
+ max-width: $limited-layout-width - ($gl-padding * 2);
+ }
}
}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 1b0bf4554e6..8b59c20cb65 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -198,7 +198,7 @@
margin: 15px 5px 0 0;
input {
- height: 27px;
+ height: 28px;
}
}
@@ -523,7 +523,7 @@ a.deploy-project-label {
&:hover,
&:focus {
- color: darken($notes-light-color, 15%);
+ color: $gl-text-color;
}
}
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 6db4e1dc1bc..d7a45bacd35 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -18,15 +18,14 @@ class AutocompleteController < ApplicationController
if params[:search].blank?
# Include current user if available to filter by "Me"
if params[:current_user].present? && current_user
+ @users = @users.where.not(id: current_user.id)
@users = [current_user, *@users]
end
if params[:author_id].present?
author = User.find_by_id(params[:author_id])
- @users = [author, *@users] if author
+ @users = [author, *@users].uniq if author
end
-
- @users.uniq!
end
render json: @users, only: [:name, :username, :id], methods: [:avatar_url]
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index e33a58d3771..2df8b071e13 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -13,49 +13,6 @@ class ApplicationSetting < ActiveRecord::Base
[\r\n] # any number of newline characters
}x
- DEFAULTS_CE = {
- after_sign_up_text: nil,
- akismet_enabled: false,
- container_registry_token_expire_delay: 5,
- default_branch_protection: Settings.gitlab['default_branch_protection'],
- default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
- default_projects_limit: Settings.gitlab['default_projects_limit'],
- default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'],
- disabled_oauth_sign_in_sources: [],
- domain_whitelist: Settings.gitlab['domain_whitelist'],
- gravatar_enabled: Settings.gravatar['enabled'],
- help_page_text: nil,
- housekeeping_bitmaps_enabled: true,
- housekeeping_enabled: true,
- housekeeping_full_repack_period: 50,
- housekeeping_gc_period: 200,
- housekeeping_incremental_repack_period: 10,
- import_sources: Gitlab::ImportSources.values,
- koding_enabled: false,
- koding_url: nil,
- max_artifacts_size: Settings.artifacts['max_size'],
- max_attachment_size: Settings.gitlab['max_attachment_size'],
- plantuml_enabled: false,
- plantuml_url: nil,
- recaptcha_enabled: false,
- repository_checks_enabled: true,
- repository_storages: ['default'],
- require_two_factor_authentication: false,
- restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels'],
- session_expire_delay: Settings.gitlab['session_expire_delay'],
- send_user_confirmation_email: false,
- shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'],
- shared_runners_text: nil,
- sidekiq_throttling_enabled: false,
- sign_in_text: nil,
- signin_enabled: Settings.gitlab['signin_enabled'],
- signup_enabled: Settings.gitlab['signup_enabled'],
- two_factor_grace_period: 48,
- user_default_external: false
- }
-
- DEFAULTS = DEFAULTS_CE
-
serialize :restricted_visibility_levels
serialize :import_sources
serialize :disabled_oauth_sign_in_sources, Array
@@ -199,14 +156,64 @@ class ApplicationSetting < ActiveRecord::Base
def self.expire
Rails.cache.delete(CACHE_KEY)
+ rescue
+ # Gracefully handle when Redis is not available. For example,
+ # omnibus may fail here during gitlab:assets:compile.
end
def self.cached
Rails.cache.fetch(CACHE_KEY)
end
+ def self.defaults_ce
+ {
+ after_sign_up_text: nil,
+ akismet_enabled: false,
+ container_registry_token_expire_delay: 5,
+ default_branch_protection: Settings.gitlab['default_branch_protection'],
+ default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
+ default_projects_limit: Settings.gitlab['default_projects_limit'],
+ default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'],
+ disabled_oauth_sign_in_sources: [],
+ domain_whitelist: Settings.gitlab['domain_whitelist'],
+ gravatar_enabled: Settings.gravatar['enabled'],
+ help_page_text: nil,
+ housekeeping_bitmaps_enabled: true,
+ housekeeping_enabled: true,
+ housekeeping_full_repack_period: 50,
+ housekeeping_gc_period: 200,
+ housekeeping_incremental_repack_period: 10,
+ import_sources: Gitlab::ImportSources.values,
+ koding_enabled: false,
+ koding_url: nil,
+ max_artifacts_size: Settings.artifacts['max_size'],
+ max_attachment_size: Settings.gitlab['max_attachment_size'],
+ plantuml_enabled: false,
+ plantuml_url: nil,
+ recaptcha_enabled: false,
+ repository_checks_enabled: true,
+ repository_storages: ['default'],
+ require_two_factor_authentication: false,
+ restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels'],
+ session_expire_delay: Settings.gitlab['session_expire_delay'],
+ send_user_confirmation_email: false,
+ shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'],
+ shared_runners_text: nil,
+ sidekiq_throttling_enabled: false,
+ sign_in_text: nil,
+ signin_enabled: Settings.gitlab['signin_enabled'],
+ signup_enabled: Settings.gitlab['signup_enabled'],
+ two_factor_grace_period: 48,
+ user_default_external: false
+ }
+ end
+
+ def self.defaults
+ defaults_ce
+ end
+
def self.create_from_defaults
- create(DEFAULTS)
+ create(defaults)
end
def home_page_url_column_exist
diff --git a/app/views/ci/status/_badge.html.haml b/app/views/ci/status/_badge.html.haml
index 601fb7f0f3f..c00c7f7407e 100644
--- a/app/views/ci/status/_badge.html.haml
+++ b/app/views/ci/status/_badge.html.haml
@@ -1,7 +1,8 @@
- status = local_assigns.fetch(:status)
+- link = local_assigns.fetch(:link, true)
- css_classes = "ci-status ci-#{status.group}"
-- if status.has_details?
+- if link && status.has_details?
= link_to status.details_path, class: css_classes do
= custom_icon(status.icon)
= status.text
diff --git a/app/views/projects/builds/_header.html.haml b/app/views/projects/builds/_header.html.haml
index b15be0d861d..736b485bf06 100644
--- a/app/views/projects/builds/_header.html.haml
+++ b/app/views/projects/builds/_header.html.haml
@@ -1,8 +1,8 @@
.content-block.build-header
.header-content
- = render 'ci/status/badge', status: @build.detailed_status(current_user)
+ = render 'ci/status/badge', status: @build.detailed_status(current_user), link: false
Build
- %strong ##{@build.id}
+ %strong.js-build-id ##{@build.id}
in pipeline
= link_to pipeline_path(@build.pipeline) do
%strong ##{@build.pipeline.id}
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 114865935d6..84787155168 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -9,7 +9,7 @@
%fieldset.append-bottom-0
.row
.form-group.col-md-9
- = f.label :name, class: 'label-light' do
+ = f.label :name, class: 'label-light', for: 'project_name_edit' do
Project name
= f.text_field :name, class: "form-control", id: "project_name_edit"
diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml
index 2d1671a89df..8ea1a3a45e1 100644
--- a/app/views/projects/issues/index.html.haml
+++ b/app/views/projects/issues/index.html.haml
@@ -19,10 +19,8 @@
= render 'shared/issuable/nav', type: :issues
.nav-controls
- if current_user
- = link_to url_for(params.merge(format: :atom, private_token: current_user.private_token)), class: 'btn append-right-10' do
+ = link_to url_for(params.merge(format: :atom, private_token: current_user.private_token)), class: 'btn append-right-10 has-tooltip', title: 'Subscribe' do
= icon('rss')
- %span.icon-label
- Subscribe
- if can? current_user, :create_issue, @project
= link_to new_namespace_project_issue_path(@project.namespace,
@project,
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index 4a24ec32454..2884f5942f4 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -52,7 +52,7 @@
= render 'award_emoji/awards_block', awardable: @merge_request, inline: true
.merge-request-tabs-holder{ class: ("js-tabs-affix" unless ENV['RAILS_ENV'] == 'test') }
- %div{ class: container_class }
+ .merge-request-tabs-container
%ul.merge-request-tabs.nav-links.no-top.no-bottom
%li.notes-tab
= link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#notes', action: 'notes', toggle: 'tab' } do
diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml
index fc338dcf887..f1a80f1d5e1 100644
--- a/app/views/projects/services/_form.html.haml
+++ b/app/views/projects/services/_form.html.haml
@@ -17,4 +17,4 @@
- disabled_title = @service.disabled_title
= link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service), class: "btn #{disabled_class}", title: disabled_title
- = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel"
+ = link_to "Cancel", namespace_project_settings_integrations_path(@project.namespace, @project), class: "btn btn-cancel"
diff --git a/changelogs/unreleased/26947-build-status-self-link.yml b/changelogs/unreleased/26947-build-status-self-link.yml
new file mode 100644
index 00000000000..15c5821874e
--- /dev/null
+++ b/changelogs/unreleased/26947-build-status-self-link.yml
@@ -0,0 +1,4 @@
+---
+title: Add link verification to badge partial in order to render a badge without a link
+merge_request: 8740
+author:
diff --git a/changelogs/unreleased/27248-filtered-search-does-not-allow-filtering-labels-with-multiple-words.yml b/changelogs/unreleased/27248-filtered-search-does-not-allow-filtering-labels-with-multiple-words.yml
new file mode 100644
index 00000000000..6e036923158
--- /dev/null
+++ b/changelogs/unreleased/27248-filtered-search-does-not-allow-filtering-labels-with-multiple-words.yml
@@ -0,0 +1,4 @@
+---
+title: Fix filtering with multiple words
+merge_request: 8830
+author:
diff --git a/changelogs/unreleased/27259-label-for-references-the-wrong-associated-text-input.yml b/changelogs/unreleased/27259-label-for-references-the-wrong-associated-text-input.yml
new file mode 100644
index 00000000000..2591f161bc5
--- /dev/null
+++ b/changelogs/unreleased/27259-label-for-references-the-wrong-associated-text-input.yml
@@ -0,0 +1,4 @@
+---
+title: Fix project name label's for reference in project settings
+merge_request: 8795
+author:
diff --git a/changelogs/unreleased/contribution-calendar-scroll.yml b/changelogs/unreleased/contribution-calendar-scroll.yml
new file mode 100644
index 00000000000..a504d59e61c
--- /dev/null
+++ b/changelogs/unreleased/contribution-calendar-scroll.yml
@@ -0,0 +1,4 @@
+---
+title: contribution calendar scrolls from right to left
+merge_request:
+author:
diff --git a/changelogs/unreleased/fix-cancel-integration-settings.yml b/changelogs/unreleased/fix-cancel-integration-settings.yml
new file mode 100644
index 00000000000..294b0aa5db9
--- /dev/null
+++ b/changelogs/unreleased/fix-cancel-integration-settings.yml
@@ -0,0 +1,4 @@
+---
+title: Fixed services form cancel not redirecting back the integrations settings view
+merge_request: 8843
+author:
diff --git a/changelogs/unreleased/fix-search-bar-search-param.yml b/changelogs/unreleased/fix-search-bar-search-param.yml
new file mode 100644
index 00000000000..4df14d3bf13
--- /dev/null
+++ b/changelogs/unreleased/fix-search-bar-search-param.yml
@@ -0,0 +1,4 @@
+---
+title: Fix search bar search param encoding
+merge_request: 8753
+author:
diff --git a/changelogs/unreleased/issuable-sidebar-bug.yml b/changelogs/unreleased/issuable-sidebar-bug.yml
new file mode 100644
index 00000000000..4086292eb89
--- /dev/null
+++ b/changelogs/unreleased/issuable-sidebar-bug.yml
@@ -0,0 +1,4 @@
+---
+title: Fixed Issuable sidebar not closing on smaller/mobile sized screens
+merge_request:
+author:
diff --git a/changelogs/unreleased/mr-tabs-container-offset.yml b/changelogs/unreleased/mr-tabs-container-offset.yml
new file mode 100644
index 00000000000..c5df8abfcf2
--- /dev/null
+++ b/changelogs/unreleased/mr-tabs-container-offset.yml
@@ -0,0 +1,4 @@
+---
+title: Fixed merge requests tab extra margin when fixed to window
+merge_request:
+author:
diff --git a/changelogs/unreleased/relative-url-assets.yml b/changelogs/unreleased/relative-url-assets.yml
new file mode 100644
index 00000000000..0877664aca4
--- /dev/null
+++ b/changelogs/unreleased/relative-url-assets.yml
@@ -0,0 +1,4 @@
+---
+title: allow relative url change without recompiling frontend assets
+merge_request: 8831
+author:
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 906ec11f012..4f33aad8693 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -419,10 +419,4 @@ if Rails.env.test?
end
# Force a refresh of application settings at startup
-begin
- ApplicationSetting.expire
- Ci::ApplicationSetting.expire
-rescue
- # Gracefully handle when Redis is not available. For example,
- # omnibus may fail here during assets:precompile.
-end
+ApplicationSetting.expire
diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb
index ed88c8ee1b8..2bd159ca7f1 100644
--- a/config/initializers/5_backend.rb
+++ b/config/initializers/5_backend.rb
@@ -1,9 +1,3 @@
-# GIT over SSH
-require_dependency Rails.root.join('lib/gitlab/backend/shell')
-
-# GitLab shell adapter
-require_dependency Rails.root.join('lib/gitlab/backend/shell_adapter')
-
required_version = Gitlab::VersionInfo.parse(Gitlab::Shell.version_required)
current_version = Gitlab::VersionInfo.parse(Gitlab::Shell.new.version)
diff --git a/config/initializers/rspec_profiling.rb b/config/initializers/rspec_profiling.rb
new file mode 100644
index 00000000000..f462e654b2c
--- /dev/null
+++ b/config/initializers/rspec_profiling.rb
@@ -0,0 +1,14 @@
+module RspecProfilingConnection
+ def establish_connection
+ ::RspecProfiling::Collectors::PSQL::Result.establish_connection(ENV['RSPEC_PROFILING_POSTGRES_URL'])
+ end
+end
+
+if Rails.env.test?
+ RspecProfiling.configure do |config|
+ if ENV['RSPEC_PROFILING_POSTGRES_URL']
+ RspecProfiling::Collectors::PSQL.prepend(RspecProfilingConnection)
+ config.collector = RspecProfiling::Collectors::PSQL
+ end
+ end
+end
diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md
index 33b9b28433a..5b6ee354887 100644
--- a/doc/administration/raketasks/maintenance.md
+++ b/doc/administration/raketasks/maintenance.md
@@ -172,14 +172,14 @@ Omnibus packages.
```
cd /home/git/gitlab
-sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
+sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production
```
For omnibus versions, the unoptimized assets (JavaScript, CSS) are frozen at
the release of upstream GitLab. The omnibus version includes optimized versions
of those assets. Unless you are modifying the JavaScript / CSS code on your
production machine after installing the package, there should be no reason to redo
-rake assets:precompile on the production machine. If you suspect that assets
+rake gitlab:assets:compile on the production machine. If you suspect that assets
have been corrupted, you should reinstall the omnibus package.
## Tracking Deployments
diff --git a/doc/api/commits.md b/doc/api/commits.md
index 5c11d0f83bb..53ce381c8ae 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -245,7 +245,7 @@ Example response:
```json
[
{
- "diff": "--- a/doc/update/5.4-to-6.0.md\n+++ b/doc/update/5.4-to-6.0.md\n@@ -71,6 +71,8 @@\n sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production\n sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production\n \n+sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production\n+\n ```\n \n ### 6. Update config files",
+ "diff": "--- a/doc/update/5.4-to-6.0.md\n+++ b/doc/update/5.4-to-6.0.md\n@@ -71,6 +71,8 @@\n sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production\n sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production\n \n+sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production\n+\n ```\n \n ### 6. Update config files",
"new_path": "doc/update/5.4-to-6.0.md",
"old_path": "doc/update/5.4-to-6.0.md",
"a_mode": null,
diff --git a/doc/development/performance.md b/doc/development/performance.md
index f936a49a2aa..c1f129e576c 100644
--- a/doc/development/performance.md
+++ b/doc/development/performance.md
@@ -211,6 +211,41 @@ suite first. See the
[StackProf documentation](https://github.com/tmm1/stackprof/blob/master/README.md)
for details.
+## RSpec profiling
+
+GitLab's development environment also includes the
+[rspec_profiling](https://github.com/foraker/rspec_profiling) gem, which is used
+to collect data on spec execution times. This is useful for analyzing the
+performance of the test suite itself, or seeing how the performance of a spec
+may have changed over time.
+
+To activate profiling in your local environment, run the following:
+
+```
+$ export RSPEC_PROFILING=yes
+$ rake rspec_profiling:install
+```
+
+This creates an SQLite3 database in `tmp/rspec_profiling`, into which statistics
+are saved every time you run specs with the `RSPEC_PROFILING` environment
+variable set.
+
+Ad-hoc investigation of the collected results can be performed in an interactive
+shell:
+
+```
+$ rake rspec_profiling:console
+irb(main):001:0> results.count
+=> 231
+irb(main):002:0> results.last.attributes.keys
+=> ["id", "commit", "date", "file", "line_number", "description", "time", "status", "exception", "query_count", "query_time", "request_count", "request_time", "created_at", "updated_at"]
+irb(main):003:0> results.where(status: "passed").average(:time).to_s
+=> "0.211340155844156"
+```
+These results can also be placed into a PostgreSQL database by setting the
+`RSPEC_PROFILING_POSTGRES_URL` variable. This is used to profile the test suite
+when running in the CI environment.
+
## Importance of Changes
When working on performance improvements, it's important to always ask yourself
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 3e7674e13ab..425c5d93efb 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -448,7 +448,7 @@ Check if GitLab and its environment are configured correctly:
### Compile Assets
- sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
+ sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production
### Start Your GitLab Instance
diff --git a/doc/install/relative_url.md b/doc/install/relative_url.md
index 44d2a14f366..713d11b75e4 100644
--- a/doc/install/relative_url.md
+++ b/doc/install/relative_url.md
@@ -113,14 +113,6 @@ Make sure to follow all steps below:
If you are using a custom init script, make sure to edit the above
gitlab-workhorse setting as needed.
-1. After all the above changes recompile the assets. This is an important task
- and will take some time to complete depending on the server resources:
-
- ```
- cd /home/git/gitlab
- sudo -u git -H bundle exec rake assets:clean assets:precompile RAILS_ENV=production
- ```
-
1. [Restart GitLab][] for the changes to take effect.
### Disable relative URL in GitLab
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index 54d523b59fd..154a0f817da 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -57,7 +57,7 @@ sudo -u git -H bundle clean
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
# Clean up assets and cache
-sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
+sudo -u git -H bundle exec rake gitlab:assets:clean gitlab:assets:compile cache:clear RAILS_ENV=production
```
### 4. Update gitlab-workhorse to the corresponding version
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 4ebd48a3fc7..e20f5f6f514 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -30,7 +30,7 @@ module Gitlab
end
def in_memory_application_settings
- @in_memory_application_settings ||= ::ApplicationSetting.new(::ApplicationSetting::DEFAULTS)
+ @in_memory_application_settings ||= ::ApplicationSetting.new(::ApplicationSetting.defaults)
# In case migrations the application_settings table is not created yet,
# we fallback to a simple OpenStruct
rescue ActiveRecord::StatementInvalid, ActiveRecord::UnknownAttributeError
@@ -38,7 +38,7 @@ module Gitlab
end
def fake_application_settings
- OpenStruct.new(::ApplicationSetting::DEFAULTS)
+ OpenStruct.new(::ApplicationSetting.defaults)
end
private
diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/shell.rb
index 82e194c1af1..82e194c1af1 100644
--- a/lib/gitlab/backend/shell.rb
+++ b/lib/gitlab/shell.rb
diff --git a/lib/gitlab/backend/shell_adapter.rb b/lib/gitlab/shell_adapter.rb
index fbe2a7a0d72..fbe2a7a0d72 100644
--- a/lib/gitlab/backend/shell_adapter.rb
+++ b/lib/gitlab/shell_adapter.rb
diff --git a/lib/gitlab/upgrader.rb b/lib/gitlab/upgrader.rb
index f3567f3ef85..e78d0c34a02 100644
--- a/lib/gitlab/upgrader.rb
+++ b/lib/gitlab/upgrader.rb
@@ -61,7 +61,7 @@ module Gitlab
"Switch to new version" => %W(#{Gitlab.config.git.bin_path} checkout v#{latest_version}),
"Install gems" => %W(bundle),
"Migrate DB" => %W(bundle exec rake db:migrate),
- "Recompile assets" => %W(bundle exec rake assets:clean assets:precompile),
+ "Recompile assets" => %W(bundle exec rake gitlab:assets:clean gitlab:assets:compile),
"Clear cache" => %W(bundle exec rake cache:clear)
}
end
diff --git a/lib/support/deploy/deploy.sh b/lib/support/deploy/deploy.sh
index adea4c7a747..ab46c47d8f5 100755
--- a/lib/support/deploy/deploy.sh
+++ b/lib/support/deploy/deploy.sh
@@ -31,8 +31,8 @@ echo 'Deploy: Bundle and migrate'
sudo -u git -H bundle --without aws development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production
-sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
+sudo -u git -H bundle exec rake gitlab:assets:clean RAILS_ENV=production
+sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production
sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
# return stashed changes (if necessary)
diff --git a/lib/tasks/gitlab/assets.rake b/lib/tasks/gitlab/assets.rake
new file mode 100644
index 00000000000..5d884bf9f66
--- /dev/null
+++ b/lib/tasks/gitlab/assets.rake
@@ -0,0 +1,47 @@
+namespace :gitlab do
+ namespace :assets do
+ desc 'GitLab | Assets | Compile all frontend assets'
+ task :compile do
+ Rake::Task['assets:precompile'].invoke
+ Rake::Task['gitlab:assets:fix_urls'].invoke
+ end
+
+ desc 'GitLab | Assets | Clean up old compiled frontend assets'
+ task :clean do
+ Rake::Task['assets:clean'].invoke
+ end
+
+ desc 'GitLab | Assets | Remove all compiled frontend assets'
+ task :purge do
+ Rake::Task['assets:clobber'].invoke
+ end
+
+ desc 'GitLab | Assets | Fix all absolute url references in CSS'
+ task :fix_urls do
+ css_files = Dir['public/assets/*.css']
+ css_files.each do | file |
+ # replace url(/assets/*) with url(./*)
+ puts "Fixing #{file}"
+ system "sed", "-i", "-e", 's/url(\([\"\']\?\)\/assets\//url(\1.\//g', file
+
+ # rewrite the corresponding gzip file (if it exists)
+ gzip = "#{file}.gz"
+ if File.exist?(gzip)
+ puts "Fixing #{gzip}"
+
+ FileUtils.rm(gzip)
+ mtime = File.stat(file).mtime
+
+ File.open(gzip, 'wb+') do |f|
+ gz = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
+ gz.mtime = mtime
+ gz.write IO.binread(file)
+ gz.close
+
+ File.utime(mtime, mtime, f.path)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/explore/projects_controller_spec.rb b/spec/controllers/explore/projects_controller_spec.rb
index 6128091f543..9dceeca168d 100644
--- a/spec/controllers/explore/projects_controller_spec.rb
+++ b/spec/controllers/explore/projects_controller_spec.rb
@@ -1,29 +1,26 @@
require 'spec_helper'
describe Explore::ProjectsController do
- let(:user) { create(:user) }
- let(:visibility) { :public }
-
describe 'GET #trending' do
- let!(:project_1) { create(:project, visibility, ci_id: 1) }
- let!(:project_2) { create(:project, visibility, ci_id: 2) }
-
- let!(:trending_project_1) { create(:trending_project, project: project_1) }
- let!(:trending_project_2) { create(:trending_project, project: project_2) }
+ context 'sorting by update date' do
+ let(:project1) { create(:empty_project, :public, updated_at: 3.days.ago) }
+ let(:project2) { create(:empty_project, :public, updated_at: 1.day.ago) }
- before do
- sign_in(user)
- end
+ before do
+ create(:trending_project, project: project1)
+ create(:trending_project, project: project2)
+ end
- context 'sorting by update date' do
it 'sorts by last updated' do
get :trending, sort: 'updated_desc'
- expect(assigns(:projects)).to eq [project_2, project_1]
+
+ expect(assigns(:projects)).to eq [project2, project1]
end
it 'sorts by oldest updated' do
get :trending, sort: 'updated_asc'
- expect(assigns(:projects)).to eq [project_1, project_2]
+
+ expect(assigns(:projects)).to eq [project1, project2]
end
end
end
diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb
index f48a0193545..3f70a6aa75f 100644
--- a/spec/features/issues/filtered_search/filter_issues_spec.rb
+++ b/spec/features/issues/filtered_search/filter_issues_spec.rb
@@ -773,7 +773,7 @@ describe 'Filter issues', js: true, feature: true do
describe 'RSS feeds' do
it 'updates atom feed link for project issues' do
visit namespace_project_issues_path(project.namespace, project, milestone_title: milestone.title, assignee_id: user.id)
- link = find('.nav-controls a', text: 'Subscribe')
+ link = find_link('Subscribe')
params = CGI.parse(URI.parse(link[:href]).query)
auto_discovery_link = find('link[type="application/atom+xml"]', visible: false)
auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query)
diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb
index bc068b5e7e0..1eb981942ea 100644
--- a/spec/features/issues/issue_sidebar_spec.rb
+++ b/spec/features/issues/issue_sidebar_spec.rb
@@ -2,6 +2,7 @@ require 'rails_helper'
feature 'Issue Sidebar', feature: true do
include WaitForAjax
+ include MobileHelpers
let(:project) { create(:project, :public) }
let(:issue) { create(:issue, project: project) }
@@ -59,6 +60,23 @@ feature 'Issue Sidebar', feature: true do
end
end
+ context 'sidebar', js: true do
+ it 'changes size when the screen size is smaller' do
+ sidebar_selector = 'aside.right-sidebar.right-sidebar-collapsed'
+ # Resize the window
+ resize_screen_sm
+ # Make sure the sidebar is collapsed
+ expect(page).to have_css(sidebar_selector)
+ # Once is collapsed let's open the sidebard and reload
+ open_issue_sidebar
+ refresh
+ expect(page).to have_css(sidebar_selector)
+ # Restore the window size as it was including the sidebar
+ restore_window_size
+ open_issue_sidebar
+ end
+ end
+
context 'creating a new label', js: true do
it 'shows option to crate a new label is present' do
page.within('.block.labels') do
@@ -109,4 +127,11 @@ feature 'Issue Sidebar', feature: true do
def visit_issue(project, issue)
visit namespace_project_issue_path(project.namespace, project, issue)
end
+
+ def open_issue_sidebar
+ page.within('aside.right-sidebar.right-sidebar-collapsed') do
+ find('.js-sidebar-toggle').click
+ sleep 1
+ end
+ end
end
diff --git a/spec/features/projects/project_settings_spec.rb b/spec/features/projects/project_settings_spec.rb
index 55d5d082c6e..5d0314d5c09 100644
--- a/spec/features/projects/project_settings_spec.rb
+++ b/spec/features/projects/project_settings_spec.rb
@@ -37,7 +37,7 @@ describe 'Edit Project Settings', feature: true do
it 'shows errors for invalid project path/name' do
visit edit_namespace_project_path(project.namespace, project)
- fill_in 'Project name', with: 'foo&bar'
+ fill_in 'project_name', with: 'foo&bar'
fill_in 'Path', with: 'foo&bar'
click_button 'Rename project'
@@ -53,7 +53,7 @@ describe 'Edit Project Settings', feature: true do
it 'shows error for invalid project name' do
visit edit_namespace_project_path(project.namespace, project)
- fill_in 'Project name', with: '🚀 foo bar ☁️'
+ fill_in 'project_name', with: '🚀 foo bar ☁️'
click_button 'Rename project'
diff --git a/spec/javascripts/commits_spec.js.es6 b/spec/javascripts/commits_spec.js.es6
new file mode 100644
index 00000000000..bb9a9072f3a
--- /dev/null
+++ b/spec/javascripts/commits_spec.js.es6
@@ -0,0 +1,50 @@
+/* global CommitsList */
+
+//= require jquery.endless-scroll
+//= require pager
+//= require commits
+
+(() => {
+ describe('Commits List', () => {
+ beforeEach(() => {
+ setFixtures(`
+ <form class="commits-search-form" action="/h5bp/html5-boilerplate/commits/master">
+ <input id="commits-search">
+ </form>
+ <ol id="commits-list"></ol>
+ `);
+ });
+
+ it('should be defined', () => {
+ expect(CommitsList).toBeDefined();
+ });
+
+ describe('on entering input', () => {
+ let ajaxSpy;
+
+ beforeEach(() => {
+ CommitsList.init(25);
+ CommitsList.searchField.val('');
+ spyOn(history, 'replaceState').and.stub();
+ ajaxSpy = spyOn(jQuery, 'ajax').and.callFake((req) => {
+ req.success({
+ data: '<li>Result</li>',
+ });
+ });
+ });
+
+ it('should save the last search string', () => {
+ CommitsList.searchField.val('GitLab');
+ CommitsList.filterResults();
+ expect(ajaxSpy).toHaveBeenCalled();
+ expect(CommitsList.lastSearch).toEqual('GitLab');
+ });
+
+ it('should not make ajax call if the input does not change', () => {
+ CommitsList.filterResults();
+ expect(ajaxSpy).not.toHaveBeenCalled();
+ expect(CommitsList.lastSearch).toEqual('');
+ });
+ });
+ });
+})();
diff --git a/spec/javascripts/filtered_search/dropdown_utils_spec.js.es6 b/spec/javascripts/filtered_search/dropdown_utils_spec.js.es6
index 074a46349ab..1e2d7582d5b 100644
--- a/spec/javascripts/filtered_search/dropdown_utils_spec.js.es6
+++ b/spec/javascripts/filtered_search/dropdown_utils_spec.js.es6
@@ -64,6 +64,68 @@ require('~/filtered_search/filtered_search_dropdown_manager');
const updatedItem = gl.DropdownUtils.filterWithSymbol('@', input, item);
expect(updatedItem.droplab_hidden).toBe(false);
});
+
+ describe('filters multiple word title', () => {
+ const multipleWordItem = {
+ title: 'Community Contributions',
+ };
+
+ it('should filter with double quote', () => {
+ input.value = 'label:"';
+
+ const updatedItem = gl.DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+ expect(updatedItem.droplab_hidden).toBe(false);
+ });
+
+ it('should filter with double quote and symbol', () => {
+ input.value = 'label:~"';
+
+ const updatedItem = gl.DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+ expect(updatedItem.droplab_hidden).toBe(false);
+ });
+
+ it('should filter with double quote and multiple words', () => {
+ input.value = 'label:"community con';
+
+ const updatedItem = gl.DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+ expect(updatedItem.droplab_hidden).toBe(false);
+ });
+
+ it('should filter with double quote, symbol and multiple words', () => {
+ input.value = 'label:~"community con';
+
+ const updatedItem = gl.DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+ expect(updatedItem.droplab_hidden).toBe(false);
+ });
+
+ it('should filter with single quote', () => {
+ input.value = 'label:\'';
+
+ const updatedItem = gl.DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+ expect(updatedItem.droplab_hidden).toBe(false);
+ });
+
+ it('should filter with single quote and symbol', () => {
+ input.value = 'label:~\'';
+
+ const updatedItem = gl.DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+ expect(updatedItem.droplab_hidden).toBe(false);
+ });
+
+ it('should filter with single quote and multiple words', () => {
+ input.value = 'label:\'community con';
+
+ const updatedItem = gl.DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+ expect(updatedItem.droplab_hidden).toBe(false);
+ });
+
+ it('should filter with single quote, symbol and multiple words', () => {
+ input.value = 'label:~\'community con';
+
+ const updatedItem = gl.DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+ expect(updatedItem.droplab_hidden).toBe(false);
+ });
+ });
});
describe('filterHint', () => {
@@ -130,5 +192,99 @@ require('~/filtered_search/filtered_search_dropdown_manager');
expect(result).toBe(false);
});
});
+
+ describe('getInputSelectionPosition', () => {
+ describe('word with trailing spaces', () => {
+ const value = 'label:none ';
+
+ it('should return selectionStart when cursor is at the trailing space', () => {
+ const { left, right } = gl.DropdownUtils.getInputSelectionPosition({
+ selectionStart: 11,
+ value,
+ });
+
+ expect(left).toBe(11);
+ expect(right).toBe(11);
+ });
+
+ it('should return input when cursor is at the start of input', () => {
+ const { left, right } = gl.DropdownUtils.getInputSelectionPosition({
+ selectionStart: 0,
+ value,
+ });
+
+ expect(left).toBe(0);
+ expect(right).toBe(10);
+ });
+
+ it('should return input when cursor is at the middle of input', () => {
+ const { left, right } = gl.DropdownUtils.getInputSelectionPosition({
+ selectionStart: 7,
+ value,
+ });
+
+ expect(left).toBe(0);
+ expect(right).toBe(10);
+ });
+
+ it('should return input when cursor is at the end of input', () => {
+ const { left, right } = gl.DropdownUtils.getInputSelectionPosition({
+ selectionStart: 10,
+ value,
+ });
+
+ expect(left).toBe(0);
+ expect(right).toBe(10);
+ });
+ });
+
+ describe('multiple words', () => {
+ const value = 'label:~"Community Contribution"';
+
+ it('should return input when cursor is after the first word', () => {
+ const { left, right } = gl.DropdownUtils.getInputSelectionPosition({
+ selectionStart: 17,
+ value,
+ });
+
+ expect(left).toBe(0);
+ expect(right).toBe(31);
+ });
+
+ it('should return input when cursor is before the second word', () => {
+ const { left, right } = gl.DropdownUtils.getInputSelectionPosition({
+ selectionStart: 18,
+ value,
+ });
+
+ expect(left).toBe(0);
+ expect(right).toBe(31);
+ });
+ });
+
+ describe('incomplete multiple words', () => {
+ const value = 'label:~"Community Contribution';
+
+ it('should return entire input when cursor is at the start of input', () => {
+ const { left, right } = gl.DropdownUtils.getInputSelectionPosition({
+ selectionStart: 0,
+ value,
+ });
+
+ expect(left).toBe(0);
+ expect(right).toBe(30);
+ });
+
+ it('should return entire input when cursor is at the end of input', () => {
+ const { left, right } = gl.DropdownUtils.getInputSelectionPosition({
+ selectionStart: 30,
+ value,
+ });
+
+ expect(left).toBe(0);
+ expect(right).toBe(30);
+ });
+ });
+ });
});
})();
diff --git a/spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6 b/spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6
new file mode 100644
index 00000000000..c8b5c2b36ad
--- /dev/null
+++ b/spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6
@@ -0,0 +1,68 @@
+/* global Turbolinks */
+
+//= require turbolinks
+//= require lib/utils/common_utils
+//= require filtered_search/filtered_search_token_keys
+//= require filtered_search/filtered_search_tokenizer
+//= require filtered_search/filtered_search_dropdown_manager
+//= require filtered_search/filtered_search_manager
+
+(() => {
+ describe('Filtered Search Manager', () => {
+ describe('search', () => {
+ let manager;
+ const defaultParams = '?scope=all&utf8=✓&state=opened';
+
+ function getInput() {
+ return document.querySelector('.filtered-search');
+ }
+
+ beforeEach(() => {
+ setFixtures(`
+ <input type='text' class='filtered-search' />
+ `);
+
+ spyOn(gl.FilteredSearchManager.prototype, 'bindEvents').and.callFake(() => {});
+ spyOn(gl.FilteredSearchManager.prototype, 'loadSearchParamsFromURL').and.callFake(() => {});
+ spyOn(gl.FilteredSearchDropdownManager.prototype, 'setDropdown').and.callFake(() => {});
+ spyOn(gl.utils, 'getParameterByName').and.returnValue(null);
+
+ manager = new gl.FilteredSearchManager();
+ });
+
+ afterEach(() => {
+ getInput().outerHTML = '';
+ });
+
+ it('should search with a single word', () => {
+ getInput().value = 'searchTerm';
+
+ spyOn(Turbolinks, 'visit').and.callFake((url) => {
+ expect(url).toEqual(`${defaultParams}&search=searchTerm`);
+ });
+
+ manager.search();
+ });
+
+ it('should search with multiple words', () => {
+ getInput().value = 'awesome search terms';
+
+ spyOn(Turbolinks, 'visit').and.callFake((url) => {
+ expect(url).toEqual(`${defaultParams}&search=awesome+search+terms`);
+ });
+
+ manager.search();
+ });
+
+ it('should search with special characters', () => {
+ getInput().value = '~!@#$%^&*()_+{}:<>,.?/';
+
+ spyOn(Turbolinks, 'visit').and.callFake((url) => {
+ expect(url).toEqual(`${defaultParams}&search=~!%40%23%24%25%5E%26*()_%2B%7B%7D%3A%3C%3E%2C.%3F%2F`);
+ });
+
+ manager.search();
+ });
+ });
+ });
+})();
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index e160c11111b..ab38dac65c5 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -9,6 +9,10 @@ require 'rspec/rails'
require 'shoulda/matchers'
require 'rspec/retry'
+if ENV['RSPEC_PROFILING_POSTGRES_URL'] || ENV['RSPEC_PROFILING']
+ require 'rspec_profiling/rspec'
+end
+
if ENV['CI'] && !ENV['NO_KNAPSACK']
require 'knapsack'
Knapsack::Adapters::RSpecAdapter.bind
diff --git a/spec/support/mobile_helpers.rb b/spec/support/mobile_helpers.rb
new file mode 100644
index 00000000000..20d5849bcab
--- /dev/null
+++ b/spec/support/mobile_helpers.rb
@@ -0,0 +1,13 @@
+module MobileHelpers
+ def resize_screen_sm
+ resize_window(900, 768)
+ end
+
+ def restore_window_size
+ resize_window(1366, 768)
+ end
+
+ def resize_window(width, height)
+ page.driver.resize_window width, height
+ end
+end
diff --git a/spec/views/projects/builds/show.html.haml_spec.rb b/spec/views/projects/builds/show.html.haml_spec.rb
index 745d0c745bd..44870cfcfb3 100644
--- a/spec/views/projects/builds/show.html.haml_spec.rb
+++ b/spec/views/projects/builds/show.html.haml_spec.rb
@@ -15,6 +15,36 @@ describe 'projects/builds/show', :view do
allow(view).to receive(:can?).and_return(true)
end
+ describe 'build information in header' do
+ let(:build) do
+ create(:ci_build, :success, environment: 'staging')
+ end
+
+ before do
+ render
+ end
+
+ it 'shows status name' do
+ expect(rendered).to have_css('.ci-status.ci-success', text: 'passed')
+ end
+
+ it 'does not render a link to the build' do
+ expect(rendered).not_to have_link('passed')
+ end
+
+ it 'shows build id' do
+ expect(rendered).to have_css('.js-build-id', text: build.id)
+ end
+
+ it 'shows a link to the pipeline' do
+ expect(rendered).to have_link(build.pipeline.id)
+ end
+
+ it 'shows a link to the commit' do
+ expect(rendered).to have_link(build.pipeline.short_sha)
+ end
+ end
+
describe 'environment info in build view' do
context 'build with latest deployment' do
let(:build) do