summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md5
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_user.js5
-rw-r--r--app/assets/javascripts/labels_select.js7
-rw-r--r--app/assets/javascripts/lib/utils/animate.js49
-rw-r--r--app/assets/javascripts/main.js1
-rw-r--r--app/assets/stylesheets/framework/nav.scss2
-rw-r--r--app/assets/stylesheets/framework/variables.scss2
-rw-r--r--app/assets/stylesheets/pages/diff.scss10
-rw-r--r--app/assets/stylesheets/pages/login.scss2
-rw-r--r--app/assets/stylesheets/pages/projects.scss2
-rw-r--r--app/models/environment.rb5
-rw-r--r--app/models/repository.rb8
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml8
-rw-r--r--app/views/projects/diffs/_stats.html.haml4
-rw-r--r--app/views/projects/runners/_form.html.haml2
-rw-r--r--app/views/shared/issuable/_filter.html.haml4
-rw-r--r--changelogs/unreleased/20824-scope-users-to-members-in-group-issuable-list.yml5
-rw-r--r--changelogs/unreleased/change-dashed-border-button-color.yml5
-rw-r--r--changelogs/unreleased/ci-environment-status-performance.yml5
-rw-r--r--changelogs/unreleased/disallow-null-values-for-environments-project-id.yml5
-rw-r--r--changelogs/unreleased/refactor-animate-js.yml5
-rw-r--r--changelogs/unreleased/uipolish-fix-remember-me-checkbox.yml5
-rw-r--r--db/migrate/20170913131410_environments_project_id_not_null.rb16
-rw-r--r--db/migrate/20170914135630_add_index_for_recent_push_events.rb40
-rw-r--r--db/schema.rb6
-rw-r--r--doc/ci/environments.md5
-rw-r--r--doc/ci/img/environments_monitoring.pngbin243491 -> 76086 bytes
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress.md8
-rw-r--r--doc/user/search/index.md4
-rw-r--r--lib/gitlab/git/operation_service.rb12
-rw-r--r--lib/gitlab/git/repository.rb20
-rw-r--r--lib/gitlab/git/user.rb (renamed from lib/gitlab/git/committer.rb)10
-rw-r--r--spec/features/groups/user_sees_users_dropdowns_in_issuables_list_spec.rb22
-rw-r--r--spec/features/milestones/show_spec.rb4
-rw-r--r--spec/javascripts/filtered_search/dropdown_user_spec.js2
-rw-r--r--spec/lib/gitlab/git/hooks_service_spec.rb8
-rw-r--r--spec/lib/gitlab/git/user_spec.rb (renamed from spec/lib/gitlab/git/committer_spec.rb)2
-rw-r--r--spec/models/repository_spec.rb24
-rw-r--r--spec/requests/api/projects_spec.rb6
-rw-r--r--spec/spec_helper.rb2
-rw-r--r--spec/support/query_recorder.rb36
-rw-r--r--spec/support/shared_examples/features/issuables_user_dropdown_behaviors_shared_examples.rb21
-rw-r--r--spec/support/shared_examples/features/project_features_apply_to_issuables_shared_examples.rb (renamed from spec/support/project_features_apply_to_issuables_shared_examples.rb)0
-rw-r--r--spec/support/test_env.rb86
44 files changed, 315 insertions, 165 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1f25171e8a6..dfb2ce0099a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -286,7 +286,10 @@ might be edited to make them small and simple.
Please submit Feature Proposals using the ['Feature Proposal' issue template](.gitlab/issue_templates/Feature Proposal.md) provided on the issue tracker.
-For changes in the interface, it can be helpful to create a mockup first.
+For changes in the interface, it is helpful to include a mockup. Issues that add to, or change, the interface should
+be given the ~"UX" label. This will allow the UX team to provide input and guidance. You may
+need to ask one of the [core team] members to add the label, if you do not have permissions to do it by yourself.
+
If you want to create something yourself, consider opening an issue first to
discuss whether it is interesting to include this in GitLab.
diff --git a/app/assets/javascripts/filtered_search/dropdown_user.js b/app/assets/javascripts/filtered_search/dropdown_user.js
index 7246ccbb281..720fbc87ea0 100644
--- a/app/assets/javascripts/filtered_search/dropdown_user.js
+++ b/app/assets/javascripts/filtered_search/dropdown_user.js
@@ -15,6 +15,7 @@ class DropdownUser extends gl.FilteredSearchDropdown {
params: {
per_page: 20,
active: true,
+ group_id: this.getGroupId(),
project_id: this.getProjectId(),
current_user: true,
},
@@ -47,6 +48,10 @@ class DropdownUser extends gl.FilteredSearchDropdown {
super.renderContent(forceShowList);
}
+ getGroupId() {
+ return this.input.getAttribute('data-group-id');
+ }
+
getProjectId() {
return this.input.getAttribute('data-project-id');
}
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index 7d7f91227f9..2538d9c2093 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -127,13 +127,6 @@ import DropdownUtils from './filtered_search/dropdown_utils';
$('.has-tooltip', $value).tooltip({
container: 'body'
});
- return $value.find('a').each(function(i) {
- return setTimeout((function(_this) {
- return function() {
- return gl.animate.animate($(_this), 'pulse');
- };
- })(this), 200 * i);
- });
});
};
$dropdown.glDropdown({
diff --git a/app/assets/javascripts/lib/utils/animate.js b/app/assets/javascripts/lib/utils/animate.js
deleted file mode 100644
index d93c1d0da59..00000000000
--- a/app/assets/javascripts/lib/utils/animate.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-param-reassign, no-void, prefer-template, no-var, new-cap, prefer-arrow-callback, consistent-return, max-len */
-(function() {
- (function(w) {
- if (w.gl == null) {
- w.gl = {};
- }
- if (gl.animate == null) {
- gl.animate = {};
- }
- gl.animate.animate = function($el, animation, options, done) {
- if ((options != null ? options.cssStart : void 0) != null) {
- $el.css(options.cssStart);
- }
- $el.removeClass(animation + ' animated').addClass(animation + ' animated').one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() {
- $(this).removeClass(animation + ' animated');
- if (done != null) {
- done();
- }
- if ((options != null ? options.cssEnd : void 0) != null) {
- $el.css(options.cssEnd);
- }
- });
- };
- gl.animate.animateEach = function($els, animation, time, options, done) {
- var dfd;
- dfd = $.Deferred();
- if (!$els.length) {
- dfd.resolve();
- }
- $els.each(function(i) {
- setTimeout((function(_this) {
- return function() {
- var $this;
- $this = $(_this);
- return gl.animate.animate($this, animation, options, function() {
- if (i === $els.length - 1) {
- dfd.resolve();
- if (done != null) {
- return done();
- }
- }
- });
- };
- })(this), time * i);
- });
- return dfd.promise();
- };
- })(window);
-}).call(window);
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 0bc31a56684..0f84470828a 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -39,7 +39,6 @@ import './commit/file';
import './commit/image_file';
// lib/utils
-import './lib/utils/animate';
import './lib/utils/bootstrap_linked_tabs';
import './lib/utils/common_utils';
import './lib/utils/datetime_utility';
diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss
index 5ffa67a1220..2f7717760ec 100644
--- a/app/assets/stylesheets/framework/nav.scss
+++ b/app/assets/stylesheets/framework/nav.scss
@@ -328,7 +328,7 @@
border-bottom: 1px solid $border-color;
transition: padding $sidebar-transition-duration;
text-align: center;
- margin-top: $header-height;
+ margin-top: $new-navbar-height;
.container-fluid {
position: relative;
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 3857226cddb..a3da9fd44e8 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -13,6 +13,7 @@ $sidebar-breakpoint: 1024px;
$darken-normal-factor: 7%;
$darken-dark-factor: 10%;
$darken-border-factor: 5%;
+$darken-border-dashed-factor: 25%;
$white-light: #fff;
$white-normal: #f0f0f0;
@@ -134,6 +135,7 @@ $border-white-normal: darken($white-normal, $darken-border-factor);
$border-gray-light: darken($gray-light, $darken-border-factor);
$border-gray-normal: darken($gray-normal, $darken-border-factor);
+$border-gray-normal-dashed: darken($gray-normal, $darken-border-dashed-factor);
$border-gray-dark: darken($white-normal, $darken-border-factor);
/*
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index 54c3c0173ae..951580ea1fe 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -634,8 +634,16 @@
padding-top: 8px;
padding-bottom: 8px;
}
+
+ .diff-changed-file {
+ display: flex;
+ align-items: center;
+ }
}
.diff-file-changes-path {
- @include str-truncated(78%);
+ flex: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index d4dc43035eb..cf5f933a762 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -95,6 +95,8 @@
}
.omniauth-container {
+ font-size: 13px;
+
p {
margin: 0;
}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 94e4f4334d4..6400b72742c 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -752,7 +752,7 @@ a.deploy-project-label {
}
li.missing {
- border: 1px dashed $border-gray-normal;
+ border: 1px dashed $border-gray-normal-dashed;
border-radius: $border-radius-default;
a {
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 9b05f8b1cd5..44e39e21442 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -6,7 +6,10 @@ class Environment < ActiveRecord::Base
belongs_to :project, required: true, validate: true
- has_many :deployments, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :deployments,
+ -> (env) { where(project_id: env.project_id) },
+ dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+
has_one :last_deployment, -> { order('deployments.id DESC') }, class_name: 'Deployment'
before_validation :nullify_external_url
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 6ed33e0c268..f2b54705e7b 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -172,7 +172,7 @@ class Repository
end
def add_branch(user, branch_name, ref)
- branch = raw_repository.add_branch(branch_name, committer: user, target: ref)
+ branch = raw_repository.add_branch(branch_name, user: user, target: ref)
after_create_branch
@@ -182,7 +182,7 @@ class Repository
end
def add_tag(user, tag_name, target, message = nil)
- raw_repository.add_tag(tag_name, committer: user, target: target, message: message)
+ raw_repository.add_tag(tag_name, user: user, target: target, message: message)
rescue Gitlab::Git::Repository::InvalidRef
false
end
@@ -190,7 +190,7 @@ class Repository
def rm_branch(user, branch_name)
before_remove_branch
- raw_repository.rm_branch(branch_name, committer: user)
+ raw_repository.rm_branch(branch_name, user: user)
after_remove_branch
true
@@ -199,7 +199,7 @@ class Repository
def rm_tag(user, tag_name)
before_remove_tag
- raw_repository.rm_tag(tag_name, committer: user)
+ raw_repository.rm_tag(tag_name, user: user)
after_remove_tag
true
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index bfd7dd25a7d..546cec4d565 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -7,6 +7,8 @@
%span.light
- has_icon = provider_has_icon?(provider)
= link_to provider_image_tag(provider), omniauth_authorize_path(:user, provider), method: :post, class: 'oauth-login' + (has_icon ? ' oauth-image-link' : ' btn'), id: "oauth-login-#{provider}"
- %fieldset.prepend-top-10
- = check_box_tag :remember_me
- = label_tag :remember_me, 'Remember me'
+ %fieldset.prepend-top-10.checkbox.remember-me
+ %label
+ = check_box_tag :remember_me, nil, false, class: 'remember-me-checkbox'
+ %span
+ Remember me
diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml
index ad2d355ab4a..2de2cf9e38c 100644
--- a/app/views/projects/diffs/_stats.html.haml
+++ b/app/views/projects/diffs/_stats.html.haml
@@ -21,9 +21,9 @@
%ul
- diff_files.each do |diff_file|
%li
- %a{ href: "##{hexdigest(diff_file.file_path)}", title: diff_file.new_path }
+ %a.diff-changed-file{ href: "##{hexdigest(diff_file.file_path)}", title: diff_file.new_path }
= icon("#{diff_file_changed_icon(diff_file)} fw", class: "#{diff_file_changed_icon_color(diff_file)} append-right-5")
- %span.diff-file-changes-path= diff_file.new_path
+ %span.diff-file-changes-path.append-right-5= diff_file.new_path
.pull-right
%span.cgreen<
+#{diff_file.added_lines}
diff --git a/app/views/projects/runners/_form.html.haml b/app/views/projects/runners/_form.html.haml
index de85615c672..e660fce652f 100644
--- a/app/views/projects/runners/_form.html.haml
+++ b/app/views/projects/runners/_form.html.haml
@@ -11,7 +11,7 @@
.col-sm-10
.checkbox
= f.check_box :access_level, {}, 'ref_protected', 'not_protected'
- %span.light This runner will only run on pipelines trigged on protected branches
+ %span.light This runner will only run on pipelines triggered on protected branches
.form-group
= label :run_untagged, 'Run untagged jobs', class: 'control-label'
.col-sm-10
diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml
index c4ed7f6e750..d3f0aa2d339 100644
--- a/app/views/shared/issuable/_filter.html.haml
+++ b/app/views/shared/issuable/_filter.html.haml
@@ -11,13 +11,13 @@
- if params[:author_id].present?
= hidden_field_tag(:author_id, params[:author_id])
= dropdown_tag(user_dropdown_label(params[:author_id], "Author"), options: { toggle_class: "js-user-search js-filter-submit js-author-search", title: "Filter by author", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit",
- placeholder: "Search authors", data: { any_user: "Any Author", first_user: current_user.try(:username), current_user: true, project_id: @project.try(:id), selected: params[:author_id], field_name: "author_id", default_label: "Author" } })
+ placeholder: "Search authors", data: { any_user: "Any Author", first_user: current_user&.username, current_user: true, project_id: @project&.id, group_id: @group&.id, selected: params[:author_id], field_name: "author_id", default_label: "Author" } })
.filter-item.inline
- if params[:assignee_id].present?
= hidden_field_tag(:assignee_id, params[:assignee_id])
= dropdown_tag(user_dropdown_label(params[:assignee_id], "Assignee"), options: { toggle_class: "js-user-search js-filter-submit js-assignee-search", title: "Filter by assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee js-filter-submit",
- placeholder: "Search assignee", data: { any_user: "Any Assignee", first_user: current_user.try(:username), null_user: true, current_user: true, project_id: @project.try(:id), group_id: @group&.id, selected: params[:assignee_id], field_name: "assignee_id", default_label: "Assignee" } })
+ placeholder: "Search assignee", data: { any_user: "Any Assignee", first_user: current_user&.username, null_user: true, current_user: true, project_id: @project&.id, group_id: @group&.id, selected: params[:assignee_id], field_name: "assignee_id", default_label: "Assignee" } })
.filter-item.inline.milestone-filter
= render "shared/issuable/milestone_dropdown", selected: finder.milestones.try(:first), name: :milestone_title, show_any: true, show_upcoming: true, show_started: true
diff --git a/changelogs/unreleased/20824-scope-users-to-members-in-group-issuable-list.yml b/changelogs/unreleased/20824-scope-users-to-members-in-group-issuable-list.yml
new file mode 100644
index 00000000000..245b8129de8
--- /dev/null
+++ b/changelogs/unreleased/20824-scope-users-to-members-in-group-issuable-list.yml
@@ -0,0 +1,5 @@
+---
+title: Return only group's members in user dropdowns on issuables list pages
+merge_request: 14249
+author:
+type: changed
diff --git a/changelogs/unreleased/change-dashed-border-button-color.yml b/changelogs/unreleased/change-dashed-border-button-color.yml
new file mode 100644
index 00000000000..038bea79273
--- /dev/null
+++ b/changelogs/unreleased/change-dashed-border-button-color.yml
@@ -0,0 +1,5 @@
+---
+title: changed dashed border button color to be darker
+merge_request: !14041
+author:
+type: other
diff --git a/changelogs/unreleased/ci-environment-status-performance.yml b/changelogs/unreleased/ci-environment-status-performance.yml
new file mode 100644
index 00000000000..8812733b5a7
--- /dev/null
+++ b/changelogs/unreleased/ci-environment-status-performance.yml
@@ -0,0 +1,5 @@
+---
+title: Constrain environment deployments to project IDs
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/disallow-null-values-for-environments-project-id.yml b/changelogs/unreleased/disallow-null-values-for-environments-project-id.yml
new file mode 100644
index 00000000000..f4a956e6724
--- /dev/null
+++ b/changelogs/unreleased/disallow-null-values-for-environments-project-id.yml
@@ -0,0 +1,5 @@
+---
+title: "Disallow NULL values for environments.project_id"
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/refactor-animate-js.yml b/changelogs/unreleased/refactor-animate-js.yml
new file mode 100644
index 00000000000..ec32d68bbdd
--- /dev/null
+++ b/changelogs/unreleased/refactor-animate-js.yml
@@ -0,0 +1,5 @@
+---
+title: Remove animate.js and label animation.
+merge_request:
+author:
+type: removed
diff --git a/changelogs/unreleased/uipolish-fix-remember-me-checkbox.yml b/changelogs/unreleased/uipolish-fix-remember-me-checkbox.yml
new file mode 100644
index 00000000000..34aa3d0db6f
--- /dev/null
+++ b/changelogs/unreleased/uipolish-fix-remember-me-checkbox.yml
@@ -0,0 +1,5 @@
+---
+title: Made the "remember me" check boxes have consistent styles and alignment
+merge_request:
+author: Jedidiah Broadbent
+type: fixed
diff --git a/db/migrate/20170913131410_environments_project_id_not_null.rb b/db/migrate/20170913131410_environments_project_id_not_null.rb
new file mode 100644
index 00000000000..d5404f8ede9
--- /dev/null
+++ b/db/migrate/20170913131410_environments_project_id_not_null.rb
@@ -0,0 +1,16 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class EnvironmentsProjectIdNotNull < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ change_column_null :environments, :project_id, false
+ end
+
+ def down
+ change_column_null :environments, :project_id, true
+ end
+end
diff --git a/db/migrate/20170914135630_add_index_for_recent_push_events.rb b/db/migrate/20170914135630_add_index_for_recent_push_events.rb
new file mode 100644
index 00000000000..99f593b0465
--- /dev/null
+++ b/db/migrate/20170914135630_add_index_for_recent_push_events.rb
@@ -0,0 +1,40 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddIndexForRecentPushEvents < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index_if_not_present(
+ :merge_requests,
+ [:source_project_id, :source_branch]
+ )
+
+ remove_concurrent_index_if_present(:merge_requests, :source_project_id)
+ end
+
+ def down
+ add_concurrent_index_if_not_present(:merge_requests, :source_project_id)
+
+ remove_concurrent_index_if_present(
+ :merge_requests,
+ [:source_project_id, :source_branch]
+ )
+ end
+
+ def add_concurrent_index_if_not_present(table, columns)
+ return if index_exists?(table, columns)
+
+ add_concurrent_index(table, columns)
+ end
+
+ def remove_concurrent_index_if_present(table, columns)
+ return unless index_exists?(table, columns)
+
+ remove_concurrent_index(table, columns)
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 2149f5ad23d..2d8c33591f0 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20170905112933) do
+ActiveRecord::Schema.define(version: 20170914135630) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -520,7 +520,7 @@ ActiveRecord::Schema.define(version: 20170905112933) do
add_index "emails", ["user_id"], name: "index_emails_on_user_id", using: :btree
create_table "environments", force: :cascade do |t|
- t.integer "project_id"
+ t.integer "project_id", null: false
t.string "name", null: false
t.datetime "created_at"
t.datetime "updated_at"
@@ -892,7 +892,7 @@ ActiveRecord::Schema.define(version: 20170905112933) do
add_index "merge_requests", ["head_pipeline_id"], name: "index_merge_requests_on_head_pipeline_id", using: :btree
add_index "merge_requests", ["milestone_id"], name: "index_merge_requests_on_milestone_id", using: :btree
add_index "merge_requests", ["source_branch"], name: "index_merge_requests_on_source_branch", using: :btree
- add_index "merge_requests", ["source_project_id"], name: "index_merge_requests_on_source_project_id", using: :btree
+ add_index "merge_requests", ["source_project_id", "source_branch"], name: "index_merge_requests_on_source_project_id_and_source_branch", using: :btree
add_index "merge_requests", ["target_branch"], name: "index_merge_requests_on_target_branch", using: :btree
add_index "merge_requests", ["target_project_id", "iid"], name: "index_merge_requests_on_target_project_id_and_iid", unique: true, using: :btree
add_index "merge_requests", ["title"], name: "index_merge_requests_on_title", using: :btree
diff --git a/doc/ci/environments.md b/doc/ci/environments.md
index 5da913ca568..acd5682841a 100644
--- a/doc/ci/environments.md
+++ b/doc/ci/environments.md
@@ -562,7 +562,7 @@ exist, you should see something like:
>**Notes:**
>
-- For the monitor dashboard to appear, you need to:
+- For the monitoring dashboard to appear, you need to:
- Have enabled the [Prometheus integration][prom]
- Configured Prometheus to collect at least one [supported metric](../user/project/integrations/prometheus_library/metrics.md)
- With GitLab 9.2, all deployments to an environment are shown directly on the
@@ -572,8 +572,7 @@ If you have enabled [Prometheus for monitoring system and response metrics](http
Once configured, GitLab will attempt to retrieve [supported performance metrics](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/metrics.html) for any
environment which has had a successful deployment. If monitoring data was
-successfully retrieved, a Monitoring button will appear on the environment's
-detail page.
+successfully retrieved, a Monitoring button will appear for each environment.
![Environment Detail with Metrics](img/prometheus_environment_detail_with_metrics.png)
diff --git a/doc/ci/img/environments_monitoring.png b/doc/ci/img/environments_monitoring.png
index d9c46ea4c95..dcffdd1fdb8 100644
--- a/doc/ci/img/environments_monitoring.png
+++ b/doc/ci/img/environments_monitoring.png
Binary files differ
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress.md b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
index 2a37cbd160b..17a47cfa646 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
@@ -11,7 +11,7 @@ GitLab has support for automatically detecting and monitoring the Kubernetes NGI
| Latency (ms) | avg(nginx_upstream_response_msecs_avg{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}) |
| HTTP Error Rate (HTTP Errors / sec) | sum(rate(nginx_upstream_responses_total{status_code="5xx", upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) |
-## Configuring Prometheus to monitor for NGINX ingress metrics
+## Configuring NGINX ingress monitoring
If you have deployed with the [gitlab-omnibus](https://docs.gitlab.com/ee/install/kubernetes/gitlab_omnibus.md) Helm chart, and your application is running in the same cluster, no further action is required. The ingress metrics will be automatically enabled and annotated for Prometheus monitoring. Simply ensure Prometheus monitoring is [enabled for your project](../prometheus.md), which is on by default.
@@ -20,14 +20,14 @@ For other deployments, there is some configuration required depending on your in
* NGINX Ingress should be annotated for Prometheus monitoring
* Prometheus should be configured to monitor annotated pods
-### Configuring NGINX Ingress for Prometheus monitoring
+### Setting up NGINX Ingress for Prometheus monitoring
Version 0.9.0 and above of [NGINX ingress](https://github.com/kubernetes/ingress/tree/master/controllers/nginx) have built-in support for exporting Prometheus metrics. To enable, a ConfigMap setting must be passed: `enable-vts-status: "true"`. Once enabled, a Prometheus metrics endpoint will start running on port 10254.
-With metric data now available, Prometheus needs to be configured to collect it. The easiest way to do this is to leverage Prometheus' [built-in Kubernetes service discovery](https://prometheus.io/docs/operating/configuration/#kubernetes_sd_config), which automatically detects a variety of Kubernetes components and makes them available for monitoring. NGINX ingress metrics are exposed per pod, a sample scrape configuration [is available](https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml#L248). This configuration will detect pods and enable collection of metrics **only if** they have been specifically annotated for monitoring.
+With metric data now available, Prometheus needs to be configured to collect it. The easiest way to do this is to leverage Prometheus' [built-in Kubernetes service discovery](https://prometheus.io/docs/operating/configuration/#kubernetes_sd_config), which automatically detects a variety of Kubernetes components and makes them available for monitoring. Since NGINX ingress metrics are exposed per pod, a scrape job for Kubernetes pods is required. A sample pod scraping configuration [is available](https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml#L248). This configuration will detect pods and enable collection of metrics **only if** they have been specifically annotated for monitoring.
Depending on how NGINX ingress was deployed, typically a DaemonSet or Deployment, edit the corresponding YML spec. Two new annotations need to be added:
-* `prometheus.io/port: "true"`
+* `prometheus.io/scrape: "true"`
* `prometheus.io/port: "10254"`
Prometheus should now be collecting NGINX ingress metrics. To validate view the Prometheus Targets, available under `Status > Targets` on the Prometheus dashboard. New entries for NGINX should be listed in the kubernetes pod monitoring job, `kubernetes-pods`.
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index bcc3625f908..2b23c494dc4 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -31,8 +31,8 @@ on the search field on the top-right of your screen:
If you want to search for issues present in a specific project, navigate to
a project's **Issues** tab, and click on the field **Search or filter results...**. It will
-display a dropdown menu, from which you can add filters per author, assignee, milestone, label,
-and weight. When done, press **Enter** on your keyboard to filter the issues.
+display a dropdown menu, from which you can add filters per author, assignee, milestone,
+label, weight, and 'my-reaction' (based on your emoji votes). When done, press **Enter** on your keyboard to filter the issues.
![filter issues in a project](img/issue_search_filter.png)
diff --git a/lib/gitlab/git/operation_service.rb b/lib/gitlab/git/operation_service.rb
index 9e6fca8c80c..347e3b5165e 100644
--- a/lib/gitlab/git/operation_service.rb
+++ b/lib/gitlab/git/operation_service.rb
@@ -1,11 +1,13 @@
module Gitlab
module Git
class OperationService
- attr_reader :committer, :repository
+ attr_reader :user, :repository
- def initialize(committer, new_repository)
- committer = Gitlab::Git::Committer.from_user(committer) if committer.is_a?(User)
- @committer = committer
+ def initialize(user, new_repository)
+ if user
+ user = Gitlab::Git::User.from_gitlab(user) unless user.respond_to?(:gl_id)
+ @user = user
+ end
# Refactoring aid
unless new_repository.is_a?(Gitlab::Git::Repository)
@@ -128,7 +130,7 @@ module Gitlab
def with_hooks(ref, newrev, oldrev)
Gitlab::Git::HooksService.new.execute(
- committer,
+ user,
repository,
oldrev,
newrev,
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index efa13590a2c..32a265b15f2 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -610,43 +610,43 @@ module Gitlab
# TODO: implement this method
end
- def add_branch(branch_name, committer:, target:)
+ def add_branch(branch_name, user:, target:)
target_object = Ref.dereference_object(lookup(target))
raise InvalidRef.new("target not found: #{target}") unless target_object
- OperationService.new(committer, self).add_branch(branch_name, target_object.oid)
+ OperationService.new(user, self).add_branch(branch_name, target_object.oid)
find_branch(branch_name)
rescue Rugged::ReferenceError => ex
raise InvalidRef, ex
end
- def add_tag(tag_name, committer:, target:, message: nil)
+ def add_tag(tag_name, user:, target:, message: nil)
target_object = Ref.dereference_object(lookup(target))
raise InvalidRef.new("target not found: #{target}") unless target_object
- committer = Committer.from_user(committer) if committer.is_a?(User)
+ user = Gitlab::Git::User.from_gitlab(user) unless user.respond_to?(:gl_id)
options = nil # Use nil, not the empty hash. Rugged cares about this.
if message
options = {
message: message,
- tagger: Gitlab::Git.committer_hash(email: committer.email, name: committer.name)
+ tagger: Gitlab::Git.committer_hash(email: user.email, name: user.name)
}
end
- OperationService.new(committer, self).add_tag(tag_name, target_object.oid, options)
+ OperationService.new(user, self).add_tag(tag_name, target_object.oid, options)
find_tag(tag_name)
rescue Rugged::ReferenceError => ex
raise InvalidRef, ex
end
- def rm_branch(branch_name, committer:)
- OperationService.new(committer, self).rm_branch(find_branch(branch_name))
+ def rm_branch(branch_name, user:)
+ OperationService.new(user, self).rm_branch(find_branch(branch_name))
end
- def rm_tag(tag_name, committer:)
- OperationService.new(committer, self).rm_tag(find_tag(tag_name))
+ def rm_tag(tag_name, user:)
+ OperationService.new(user, self).rm_tag(find_tag(tag_name))
end
def find_tag(name)
diff --git a/lib/gitlab/git/committer.rb b/lib/gitlab/git/user.rb
index 1f4bcf7a3a0..ea634d39668 100644
--- a/lib/gitlab/git/committer.rb
+++ b/lib/gitlab/git/user.rb
@@ -1,10 +1,14 @@
module Gitlab
module Git
- class Committer
+ class User
attr_reader :name, :email, :gl_id
- def self.from_user(user)
- new(user.name, user.email, Gitlab::GlId.gl_id(user))
+ def self.from_gitlab(gitlab_user)
+ new(gitlab_user.name, gitlab_user.email, Gitlab::GlId.gl_id(gitlab_user))
+ end
+
+ def self.from_gitaly(gitaly_user)
+ new(gitaly_user.name, gitaly_user.email, gitaly_user.gl_id)
end
def initialize(name, email, gl_id)
diff --git a/spec/features/groups/user_sees_users_dropdowns_in_issuables_list_spec.rb b/spec/features/groups/user_sees_users_dropdowns_in_issuables_list_spec.rb
new file mode 100644
index 00000000000..5ed4f3ad2bc
--- /dev/null
+++ b/spec/features/groups/user_sees_users_dropdowns_in_issuables_list_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+feature 'Groups > User sees users dropdowns in issuables list' do
+ let(:entity) { create(:group) }
+ let(:user_in_dropdown) { create(:user) }
+ let!(:user_not_in_dropdown) { create(:user) }
+ let!(:project) { create(:project, group: entity) }
+
+ before do
+ entity.add_developer(user_in_dropdown)
+ end
+
+ it_behaves_like 'issuable user dropdown behaviors' do
+ let(:issuable) { create(:issue, project: project) }
+ let(:issuables_path) { issues_group_path(entity) }
+ end
+
+ it_behaves_like 'issuable user dropdown behaviors' do
+ let(:issuable) { create(:merge_request, source_project: project) }
+ let(:issuables_path) { merge_requests_group_path(entity) }
+ end
+end
diff --git a/spec/features/milestones/show_spec.rb b/spec/features/milestones/show_spec.rb
index 624f13922ed..50c5e0bb65f 100644
--- a/spec/features/milestones/show_spec.rb
+++ b/spec/features/milestones/show_spec.rb
@@ -18,9 +18,9 @@ describe 'Milestone show' do
it 'avoids N+1 database queries' do
create(:labeled_issue, issue_params)
- control_count = ActiveRecord::QueryRecorder.new { visit_milestone }.count
+ control = ActiveRecord::QueryRecorder.new { visit_milestone }
create_list(:labeled_issue, 10, issue_params)
- expect { visit_milestone }.not_to exceed_query_limit(control_count)
+ expect { visit_milestone }.not_to exceed_query_limit(control)
end
end
diff --git a/spec/javascripts/filtered_search/dropdown_user_spec.js b/spec/javascripts/filtered_search/dropdown_user_spec.js
index b3c9bca64cc..02415485d19 100644
--- a/spec/javascripts/filtered_search/dropdown_user_spec.js
+++ b/spec/javascripts/filtered_search/dropdown_user_spec.js
@@ -10,6 +10,7 @@ describe('Dropdown User', () => {
beforeEach(() => {
spyOn(gl.DropdownUser.prototype, 'bindEvents').and.callFake(() => {});
spyOn(gl.DropdownUser.prototype, 'getProjectId').and.callFake(() => {});
+ spyOn(gl.DropdownUser.prototype, 'getGroupId').and.callFake(() => {});
spyOn(gl.DropdownUtils, 'getSearchInput').and.callFake(() => {});
dropdownUser = new gl.DropdownUser({
@@ -38,6 +39,7 @@ describe('Dropdown User', () => {
beforeEach(() => {
spyOn(gl.DropdownUser.prototype, 'bindEvents').and.callFake(() => {});
spyOn(gl.DropdownUser.prototype, 'getProjectId').and.callFake(() => {});
+ spyOn(gl.DropdownUser.prototype, 'getGroupId').and.callFake(() => {});
});
it('should return endpoint', () => {
diff --git a/spec/lib/gitlab/git/hooks_service_spec.rb b/spec/lib/gitlab/git/hooks_service_spec.rb
index e9c0209fe3b..d4d75b66659 100644
--- a/spec/lib/gitlab/git/hooks_service_spec.rb
+++ b/spec/lib/gitlab/git/hooks_service_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Gitlab::Git::HooksService, seed_helper: true do
- let(:committer) { Gitlab::Git::Committer.new('Jane Doe', 'janedoe@example.com', 'user-456') }
+ let(:user) { Gitlab::Git::User.new('Jane Doe', 'janedoe@example.com', 'user-456') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, 'project-123') }
let(:service) { described_class.new }
@@ -18,7 +18,7 @@ describe Gitlab::Git::HooksService, seed_helper: true do
hook = double(trigger: [true, nil])
expect(Gitlab::Git::Hook).to receive(:new).exactly(3).times.and_return(hook)
- service.execute(committer, repository, @blankrev, @newrev, @ref) { }
+ service.execute(user, repository, @blankrev, @newrev, @ref) { }
end
end
@@ -28,7 +28,7 @@ describe Gitlab::Git::HooksService, seed_helper: true do
expect(service).not_to receive(:run_hook).with('post-receive')
expect do
- service.execute(committer, repository, @blankrev, @newrev, @ref)
+ service.execute(user, repository, @blankrev, @newrev, @ref)
end.to raise_error(Gitlab::Git::HooksService::PreReceiveError)
end
end
@@ -40,7 +40,7 @@ describe Gitlab::Git::HooksService, seed_helper: true do
expect(service).not_to receive(:run_hook).with('post-receive')
expect do
- service.execute(committer, repository, @blankrev, @newrev, @ref)
+ service.execute(user, repository, @blankrev, @newrev, @ref)
end.to raise_error(Gitlab::Git::HooksService::PreReceiveError)
end
end
diff --git a/spec/lib/gitlab/git/committer_spec.rb b/spec/lib/gitlab/git/user_spec.rb
index b0ddbb51449..0ebcecb26c0 100644
--- a/spec/lib/gitlab/git/committer_spec.rb
+++ b/spec/lib/gitlab/git/user_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Gitlab::Git::Committer do
+describe Gitlab::Git::User do
let(:name) { 'Jane Doe' }
let(:email) { 'janedoe@example.com' }
let(:gl_id) { 'user-123' }
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 7065d467ec0..53280f2c1cf 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -8,7 +8,7 @@ describe Repository, models: true do
let(:repository) { project.repository }
let(:broken_repository) { create(:project, :broken_storage).repository }
let(:user) { create(:user) }
- let(:committer) { Gitlab::Git::Committer.from_user(user) }
+ let(:git_user) { Gitlab::Git::User.from_gitlab(user) }
let(:commit_options) do
author = repository.user_to_committer(user)
@@ -886,7 +886,7 @@ describe Repository, models: true do
context 'when pre hooks were successful' do
it 'runs without errors' do
expect_any_instance_of(Gitlab::Git::HooksService).to receive(:execute)
- .with(committer, repository.raw_repository, old_rev, blank_sha, 'refs/heads/feature')
+ .with(git_user, repository.raw_repository, old_rev, blank_sha, 'refs/heads/feature')
expect { repository.rm_branch(user, 'feature') }.not_to raise_error
end
@@ -932,20 +932,20 @@ describe Repository, models: true do
service = Gitlab::Git::HooksService.new
expect(Gitlab::Git::HooksService).to receive(:new).and_return(service)
expect(service).to receive(:execute)
- .with(committer, target_repository.raw_repository, old_rev, new_rev, updating_ref)
+ .with(git_user, target_repository.raw_repository, old_rev, new_rev, updating_ref)
.and_yield(service).and_return(true)
end
it 'runs without errors' do
expect do
- Gitlab::Git::OperationService.new(committer, repository.raw_repository).with_branch('feature') do
+ Gitlab::Git::OperationService.new(git_user, repository.raw_repository).with_branch('feature') do
new_rev
end
end.not_to raise_error
end
it 'ensures the autocrlf Git option is set to :input' do
- service = Gitlab::Git::OperationService.new(committer, repository.raw_repository)
+ service = Gitlab::Git::OperationService.new(git_user, repository.raw_repository)
expect(service).to receive(:update_autocrlf_option)
@@ -956,7 +956,7 @@ describe Repository, models: true do
it 'updates the head' do
expect(repository.find_branch('feature').dereferenced_target.id).to eq(old_rev)
- Gitlab::Git::OperationService.new(committer, repository.raw_repository).with_branch('feature') do
+ Gitlab::Git::OperationService.new(git_user, repository.raw_repository).with_branch('feature') do
new_rev
end
@@ -974,7 +974,7 @@ describe Repository, models: true do
expect(target_project.repository.raw_repository).to receive(:fetch_ref)
.and_call_original
- Gitlab::Git::OperationService.new(committer, target_repository.raw_repository)
+ Gitlab::Git::OperationService.new(git_user, target_repository.raw_repository)
.with_branch(
'master',
start_repository: project.repository.raw_repository,
@@ -990,7 +990,7 @@ describe Repository, models: true do
it 'does not fetch_ref and just pass the commit' do
expect(target_repository).not_to receive(:fetch_ref)
- Gitlab::Git::OperationService.new(committer, target_repository.raw_repository)
+ Gitlab::Git::OperationService.new(git_user, target_repository.raw_repository)
.with_branch('feature', start_repository: project.repository.raw_repository) { new_rev }
end
end
@@ -1009,7 +1009,7 @@ describe Repository, models: true do
end
expect do
- Gitlab::Git::OperationService.new(committer, target_project.repository.raw_repository)
+ Gitlab::Git::OperationService.new(git_user, target_project.repository.raw_repository)
.with_branch('feature',
start_repository: project.repository.raw_repository,
&:itself)
@@ -1031,7 +1031,7 @@ describe Repository, models: true do
repository.add_branch(user, branch, old_rev)
expect do
- Gitlab::Git::OperationService.new(committer, repository.raw_repository).with_branch(branch) do
+ Gitlab::Git::OperationService.new(git_user, repository.raw_repository).with_branch(branch) do
new_rev
end
end.not_to raise_error
@@ -1049,7 +1049,7 @@ describe Repository, models: true do
# Updating 'master' to new_rev would lose the commits on 'master' that
# are not contained in new_rev. This should not be allowed.
expect do
- Gitlab::Git::OperationService.new(committer, repository.raw_repository).with_branch(branch) do
+ Gitlab::Git::OperationService.new(git_user, repository.raw_repository).with_branch(branch) do
new_rev
end
end.to raise_error(Gitlab::Git::CommitError)
@@ -1061,7 +1061,7 @@ describe Repository, models: true do
allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, ''])
expect do
- Gitlab::Git::OperationService.new(committer, repository.raw_repository).with_branch('feature') do
+ Gitlab::Git::OperationService.new(git_user, repository.raw_repository).with_branch('feature') do
new_rev
end
end.to raise_error(Gitlab::Git::HooksService::PreReceiveError)
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 9602584f546..92e7d797cbd 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -54,9 +54,9 @@ describe API::Projects do
shared_examples_for 'projects response without N + 1 queries' do
it 'avoids N + 1 queries' do
- control_count = ActiveRecord::QueryRecorder.new do
+ control = ActiveRecord::QueryRecorder.new do
get api('/projects', current_user)
- end.count
+ end
if defined?(additional_project)
additional_project
@@ -66,7 +66,7 @@ describe API::Projects do
expect do
get api('/projects', current_user)
- end.not_to exceed_query_limit(control_count + 8)
+ end.not_to exceed_query_limit(control).with_threshold(8)
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index ff1754fbe7e..92735336572 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,7 +1,7 @@
require './spec/simplecov_env'
SimpleCovEnv.start!
-ENV["RAILS_ENV"] ||= 'test'
+ENV["RAILS_ENV"] = 'test'
ENV["IN_MEMORY_APPLICATION_SETTINGS"] = 'true'
require File.expand_path("../../config/environment", __FILE__)
diff --git a/spec/support/query_recorder.rb b/spec/support/query_recorder.rb
index 55b531b4cf7..ba0b805caad 100644
--- a/spec/support/query_recorder.rb
+++ b/spec/support/query_recorder.rb
@@ -34,15 +34,47 @@ RSpec::Matchers.define :exceed_query_limit do |expected|
supports_block_expectations
match do |block|
- query_count(&block) > expected
+ query_count(&block) > expected_count + threshold
end
failure_message_when_negated do |actual|
- "Expected a maximum of #{expected} queries, got #{@recorder.count}:\n\n#{@recorder.log_message}"
+ threshold_message = threshold > 0 ? " (+#{@threshold})" : ''
+ counts = "#{expected_count}#{threshold_message}"
+ "Expected a maximum of #{counts} queries, got #{actual_count}:\n\n#{log_message}"
+ end
+
+ def with_threshold(threshold)
+ @threshold = threshold
+ self
+ end
+
+ def threshold
+ @threshold.to_i
+ end
+
+ def expected_count
+ if expected.is_a?(ActiveRecord::QueryRecorder)
+ expected.count
+ else
+ expected
+ end
+ end
+
+ def actual_count
+ @recorder.count
end
def query_count(&block)
@recorder = ActiveRecord::QueryRecorder.new(&block)
@recorder.count
end
+
+ def log_message
+ if expected.is_a?(ActiveRecord::QueryRecorder)
+ extra_queries = (expected.log - @recorder.log).join("\n\n")
+ "Extra queries: \n\n #{extra_queries}"
+ else
+ @recorder.log_message
+ end
+ end
end
diff --git a/spec/support/shared_examples/features/issuables_user_dropdown_behaviors_shared_examples.rb b/spec/support/shared_examples/features/issuables_user_dropdown_behaviors_shared_examples.rb
new file mode 100644
index 00000000000..c92c7f603d6
--- /dev/null
+++ b/spec/support/shared_examples/features/issuables_user_dropdown_behaviors_shared_examples.rb
@@ -0,0 +1,21 @@
+shared_examples 'issuable user dropdown behaviors' do
+ include FilteredSearchHelpers
+
+ before do
+ issuable # ensure we have at least one issuable
+ sign_in(user_in_dropdown)
+ end
+
+ %w[author assignee].each do |dropdown|
+ describe "#{dropdown} dropdown", :js do
+ it 'only includes members of the project/group' do
+ visit issuables_path
+
+ filtered_search.set("#{dropdown}:")
+
+ expect(find("#js-dropdown-#{dropdown} .filter-dropdown")).to have_content(user_in_dropdown.name)
+ expect(find("#js-dropdown-#{dropdown} .filter-dropdown")).not_to have_content(user_not_in_dropdown.name)
+ end
+ end
+ end
+end
diff --git a/spec/support/project_features_apply_to_issuables_shared_examples.rb b/spec/support/shared_examples/features/project_features_apply_to_issuables_shared_examples.rb
index 639b0924197..639b0924197 100644
--- a/spec/support/project_features_apply_to_issuables_shared_examples.rb
+++ b/spec/support/shared_examples/features/project_features_apply_to_issuables_shared_examples.rb
diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb
index 71b9deeabc3..6e5b9700b54 100644
--- a/spec/support/test_env.rb
+++ b/spec/support/test_env.rb
@@ -3,6 +3,8 @@ require 'rspec/mocks'
module TestEnv
extend self
+ ComponentFailedToInstallError = Class.new(StandardError)
+
# When developing the seed repository, comment out the branch you will modify.
BRANCH_SHA = {
'signed-commits' => '2d1096e',
@@ -63,6 +65,11 @@ module TestEnv
# See gitlab.yml.example test section for paths
#
def init(opts = {})
+ unless Rails.env.test?
+ puts "\nTestEnv.init can only be run if `RAILS_ENV` is set to 'test' not '#{Rails.env}'!\n"
+ exit 1
+ end
+
# Disable mailer for spinach tests
disable_mailer if opts[:mailer] == false
@@ -122,50 +129,23 @@ module TestEnv
end
def setup_gitlab_shell
- puts "\n==> Setting up Gitlab Shell..."
- start = Time.now
- gitlab_shell_dir = Gitlab.config.gitlab_shell.path
- shell_needs_update = component_needs_update?(gitlab_shell_dir,
- Gitlab::Shell.version_required)
-
- unless !shell_needs_update || system('rake', 'gitlab:shell:install')
- puts "\nGitLab Shell failed to install, cleaning up #{gitlab_shell_dir}!\n"
- FileUtils.rm_rf(gitlab_shell_dir)
- exit 1
- end
-
- puts " GitLab Shell setup in #{Time.now - start} seconds...\n"
+ component_timed_setup('GitLab Shell',
+ install_dir: Gitlab.config.gitlab_shell.path,
+ version: Gitlab::Shell.version_required,
+ task: 'gitlab:shell:install')
end
def setup_gitaly
- puts "\n==> Setting up Gitaly..."
- start = Time.now
socket_path = Gitlab::GitalyClient.address('default').sub(/\Aunix:/, '')
gitaly_dir = File.dirname(socket_path)
- if gitaly_dir_stale?(gitaly_dir)
- puts " Gitaly is outdated, cleaning up #{gitaly_dir}!"
- FileUtils.rm_rf(gitaly_dir)
- end
-
- gitaly_needs_update = component_needs_update?(gitaly_dir,
- Gitlab::GitalyClient.expected_server_version)
+ component_timed_setup('Gitaly',
+ install_dir: gitaly_dir,
+ version: Gitlab::GitalyClient.expected_server_version,
+ task: "gitlab:gitaly:install[#{gitaly_dir}]") do
- unless !gitaly_needs_update || system('rake', "gitlab:gitaly:install[#{gitaly_dir}]")
- puts "\nGitaly failed to install, cleaning up #{gitaly_dir}!\n"
- FileUtils.rm_rf(gitaly_dir)
- exit 1
+ start_gitaly(gitaly_dir)
end
-
- start_gitaly(gitaly_dir)
- puts " Gitaly setup in #{Time.now - start} seconds...\n"
- end
-
- def gitaly_dir_stale?(dir)
- gitaly_executable = File.join(dir, 'gitaly')
- return false unless File.exist?(gitaly_executable)
-
- File.mtime(gitaly_executable) < File.mtime(Rails.root.join('GITALY_SERVER_VERSION'))
end
def start_gitaly(gitaly_dir)
@@ -320,6 +300,40 @@ module TestEnv
end
end
+ def component_timed_setup(component, install_dir:, version:, task:)
+ puts "\n==> Setting up #{component}..."
+ start = Time.now
+
+ ensure_component_dir_name_is_correct!(component, install_dir)
+
+ if component_needs_update?(install_dir, version)
+ # Cleanup the component entirely to ensure we start fresh
+ FileUtils.rm_rf(install_dir)
+ unless system('rake', task)
+ raise ComponentFailedToInstallError
+ end
+ end
+
+ yield if block_given?
+
+ rescue ComponentFailedToInstallError
+ puts "\n#{component} failed to install, cleaning up #{install_dir}!\n"
+ FileUtils.rm_rf(install_dir)
+ exit 1
+ ensure
+ puts " #{component} setup in #{Time.now - start} seconds...\n"
+ end
+
+ def ensure_component_dir_name_is_correct!(component, path)
+ actual_component_dir_name = File.basename(path)
+ expected_component_dir_name = component.parameterize
+
+ unless actual_component_dir_name == expected_component_dir_name
+ puts " #{component} install dir should be named '#{expected_component_dir_name}', not '#{actual_component_dir_name}' (full install path given was '#{path}')!\n"
+ exit 1
+ end
+ end
+
def component_needs_update?(component_folder, expected_version)
version = File.read(File.join(component_folder, 'VERSION')).strip