summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml126
-rw-r--r--app/assets/stylesheets/framework/blank.scss91
-rw-r--r--app/assets/stylesheets/framework/variables.scss1
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss2
-rw-r--r--app/controllers/concerns/requires_health_token.rb25
-rw-r--r--app/controllers/concerns/requires_whitelisted_monitoring_client.rb33
-rw-r--r--app/controllers/health_check_controller.rb2
-rw-r--r--app/controllers/health_controller.rb2
-rw-r--r--app/controllers/metrics_controller.rb4
-rw-r--r--app/services/milestones/destroy_service.rb6
-rw-r--r--app/views/dashboard/projects/_blank_state_admin_welcome.html.haml18
-rw-r--r--app/views/dashboard/projects/_blank_state_welcome.html.haml18
-rw-r--r--app/views/dashboard/projects/_zero_authorized_projects.html.haml4
-rw-r--r--changelogs/unreleased/33949-deprecate-healthcheck-access-token.yml4
-rw-r--r--changelogs/unreleased/fix-n-plus-one-in-url-builder.yml4
-rw-r--r--config/database.yml.mysql1
-rw-r--r--config/database.yml.postgresql1
-rw-r--r--config/gitlab.yml.example9
-rw-r--r--config/initializers/1_settings.rb7
-rw-r--r--config/initializers/8_metrics.rb2
-rw-r--r--doc/install/installation.md10
-rw-r--r--doc/update/9.3-to-9.4.md45
-rw-r--r--doc/user/admin_area/monitoring/health_check.md26
-rw-r--r--lib/api/merge_requests.rb8
-rw-r--r--lib/gitlab/current_settings.rb2
-rw-r--r--lib/gitlab/url_builder.rb8
-rw-r--r--spec/controllers/health_check_controller_spec.rb75
-rw-r--r--spec/controllers/health_controller_spec.rb95
-rw-r--r--spec/controllers/metrics_controller_spec.rb34
-rw-r--r--spec/helpers/award_emoji_helper_spec.rb4
-rw-r--r--spec/services/milestones/destroy_service_spec.rb51
-rw-r--r--spec/support/test_env.rb1
-rw-r--r--vendor/gitlab-ci-yml/Docker.gitlab-ci.yml19
-rw-r--r--vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml8
-rw-r--r--vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml6
-rw-r--r--vendor/gitlab-ci-yml/autodeploy/OpenShift.gitlab-ci.yml12
36 files changed, 470 insertions, 294 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f7ab0259448..a54b38d284d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -203,69 +203,69 @@ setup-test-env:
- public/assets
- tmp/tests
-rspec-pg 0 20: *rspec-knapsack-pg
-rspec-pg 1 20: *rspec-knapsack-pg
-rspec-pg 2 20: *rspec-knapsack-pg
-rspec-pg 3 20: *rspec-knapsack-pg
-rspec-pg 4 20: *rspec-knapsack-pg
-rspec-pg 5 20: *rspec-knapsack-pg
-rspec-pg 6 20: *rspec-knapsack-pg
-rspec-pg 7 20: *rspec-knapsack-pg
-rspec-pg 8 20: *rspec-knapsack-pg
-rspec-pg 9 20: *rspec-knapsack-pg
-rspec-pg 10 20: *rspec-knapsack-pg
-rspec-pg 11 20: *rspec-knapsack-pg
-rspec-pg 12 20: *rspec-knapsack-pg
-rspec-pg 13 20: *rspec-knapsack-pg
-rspec-pg 14 20: *rspec-knapsack-pg
-rspec-pg 15 20: *rspec-knapsack-pg
-rspec-pg 16 20: *rspec-knapsack-pg
-rspec-pg 17 20: *rspec-knapsack-pg
-rspec-pg 18 20: *rspec-knapsack-pg
-rspec-pg 19 20: *rspec-knapsack-pg
-
-rspec-mysql 0 20: *rspec-knapsack-mysql
-rspec-mysql 1 20: *rspec-knapsack-mysql
-rspec-mysql 2 20: *rspec-knapsack-mysql
-rspec-mysql 3 20: *rspec-knapsack-mysql
-rspec-mysql 4 20: *rspec-knapsack-mysql
-rspec-mysql 5 20: *rspec-knapsack-mysql
-rspec-mysql 6 20: *rspec-knapsack-mysql
-rspec-mysql 7 20: *rspec-knapsack-mysql
-rspec-mysql 8 20: *rspec-knapsack-mysql
-rspec-mysql 9 20: *rspec-knapsack-mysql
-rspec-mysql 10 20: *rspec-knapsack-mysql
-rspec-mysql 11 20: *rspec-knapsack-mysql
-rspec-mysql 12 20: *rspec-knapsack-mysql
-rspec-mysql 13 20: *rspec-knapsack-mysql
-rspec-mysql 14 20: *rspec-knapsack-mysql
-rspec-mysql 15 20: *rspec-knapsack-mysql
-rspec-mysql 16 20: *rspec-knapsack-mysql
-rspec-mysql 17 20: *rspec-knapsack-mysql
-rspec-mysql 18 20: *rspec-knapsack-mysql
-rspec-mysql 19 20: *rspec-knapsack-mysql
-
-spinach-pg 0 10: *spinach-knapsack-pg
-spinach-pg 1 10: *spinach-knapsack-pg
-spinach-pg 2 10: *spinach-knapsack-pg
-spinach-pg 3 10: *spinach-knapsack-pg
-spinach-pg 4 10: *spinach-knapsack-pg
-spinach-pg 5 10: *spinach-knapsack-pg
-spinach-pg 6 10: *spinach-knapsack-pg
-spinach-pg 7 10: *spinach-knapsack-pg
-spinach-pg 8 10: *spinach-knapsack-pg
-spinach-pg 9 10: *spinach-knapsack-pg
-
-spinach-mysql 0 10: *spinach-knapsack-mysql
-spinach-mysql 1 10: *spinach-knapsack-mysql
-spinach-mysql 2 10: *spinach-knapsack-mysql
-spinach-mysql 3 10: *spinach-knapsack-mysql
-spinach-mysql 4 10: *spinach-knapsack-mysql
-spinach-mysql 5 10: *spinach-knapsack-mysql
-spinach-mysql 6 10: *spinach-knapsack-mysql
-spinach-mysql 7 10: *spinach-knapsack-mysql
-spinach-mysql 8 10: *spinach-knapsack-mysql
-spinach-mysql 9 10: *spinach-knapsack-mysql
+rspec-pg 0 25: *rspec-knapsack-pg
+rspec-pg 1 25: *rspec-knapsack-pg
+rspec-pg 2 25: *rspec-knapsack-pg
+rspec-pg 3 25: *rspec-knapsack-pg
+rspec-pg 4 25: *rspec-knapsack-pg
+rspec-pg 5 25: *rspec-knapsack-pg
+rspec-pg 6 25: *rspec-knapsack-pg
+rspec-pg 7 25: *rspec-knapsack-pg
+rspec-pg 8 25: *rspec-knapsack-pg
+rspec-pg 9 25: *rspec-knapsack-pg
+rspec-pg 10 25: *rspec-knapsack-pg
+rspec-pg 11 25: *rspec-knapsack-pg
+rspec-pg 12 25: *rspec-knapsack-pg
+rspec-pg 13 25: *rspec-knapsack-pg
+rspec-pg 14 25: *rspec-knapsack-pg
+rspec-pg 15 25: *rspec-knapsack-pg
+rspec-pg 16 25: *rspec-knapsack-pg
+rspec-pg 17 25: *rspec-knapsack-pg
+rspec-pg 18 25: *rspec-knapsack-pg
+rspec-pg 19 25: *rspec-knapsack-pg
+rspec-pg 20 25: *rspec-knapsack-pg
+rspec-pg 21 25: *rspec-knapsack-pg
+rspec-pg 22 25: *rspec-knapsack-pg
+rspec-pg 23 25: *rspec-knapsack-pg
+rspec-pg 24 25: *rspec-knapsack-pg
+
+rspec-mysql 0 25: *rspec-knapsack-mysql
+rspec-mysql 1 25: *rspec-knapsack-mysql
+rspec-mysql 2 25: *rspec-knapsack-mysql
+rspec-mysql 3 25: *rspec-knapsack-mysql
+rspec-mysql 4 25: *rspec-knapsack-mysql
+rspec-mysql 5 25: *rspec-knapsack-mysql
+rspec-mysql 6 25: *rspec-knapsack-mysql
+rspec-mysql 7 25: *rspec-knapsack-mysql
+rspec-mysql 8 25: *rspec-knapsack-mysql
+rspec-mysql 9 25: *rspec-knapsack-mysql
+rspec-mysql 10 25: *rspec-knapsack-mysql
+rspec-mysql 11 25: *rspec-knapsack-mysql
+rspec-mysql 12 25: *rspec-knapsack-mysql
+rspec-mysql 13 25: *rspec-knapsack-mysql
+rspec-mysql 14 25: *rspec-knapsack-mysql
+rspec-mysql 15 25: *rspec-knapsack-mysql
+rspec-mysql 16 25: *rspec-knapsack-mysql
+rspec-mysql 17 25: *rspec-knapsack-mysql
+rspec-mysql 18 25: *rspec-knapsack-mysql
+rspec-mysql 19 25: *rspec-knapsack-mysql
+rspec-mysql 20 25: *rspec-knapsack-mysql
+rspec-mysql 21 25: *rspec-knapsack-mysql
+rspec-mysql 22 25: *rspec-knapsack-mysql
+rspec-mysql 23 25: *rspec-knapsack-mysql
+rspec-mysql 24 25: *rspec-knapsack-mysql
+
+spinach-pg 0 5: *spinach-knapsack-pg
+spinach-pg 1 5: *spinach-knapsack-pg
+spinach-pg 2 5: *spinach-knapsack-pg
+spinach-pg 3 5: *spinach-knapsack-pg
+spinach-pg 4 5: *spinach-knapsack-pg
+
+spinach-mysql 0 5: *spinach-knapsack-mysql
+spinach-mysql 1 5: *spinach-knapsack-mysql
+spinach-mysql 2 5: *spinach-knapsack-mysql
+spinach-mysql 3 5: *spinach-knapsack-mysql
+spinach-mysql 4 5: *spinach-knapsack-mysql
# Static analysis jobs
.ruby-static-analysis: &ruby-static-analysis
diff --git a/app/assets/stylesheets/framework/blank.scss b/app/assets/stylesheets/framework/blank.scss
index c0224d3bfa9..6bb096fc5bd 100644
--- a/app/assets/stylesheets/framework/blank.scss
+++ b/app/assets/stylesheets/framework/blank.scss
@@ -1,9 +1,5 @@
.blank-state-parent-container {
- display: flex;
-
.section-container {
- display: flex;
- flex: 1;
padding: 10px;
}
@@ -13,91 +9,42 @@
padding-bottom: 25px;
border: 1px solid $border-color;
border-radius: $border-radius-default;
-
- &.section-ee-trial {
- display: flex;
- align-items: center;
- justify-content: center;
- }
- }
-}
-
-.blank-state-welcome {
- text-align: center;
-
- .blank-state-text {
- margin-bottom: 0;
}
}
.blank-state {
padding-top: 20px;
padding-bottom: 20px;
-}
-
-.blank-state.ee-trial {
- padding: 20px;
text-align: center;
-}
-
-.blank-state-no-icon {
- padding-top: 40px;
- padding-bottom: 40px;
-}
-
-.blank-state-icon {
- padding-bottom: 20px;
- font-size: 56px;
- svg {
- display: block;
- margin: auto;
- }
-}
-
-@media (min-width: $screen-sm-max) {
- .section-welcome .blank-state-icon svg {
- width: 130%;
- }
-}
-
-.blank-state-title {
- margin-top: 0;
- margin-bottom: 10px;
- font-size: 18px;
-}
-
-.blank-state-text {
- margin-top: 0;
- margin-bottom: $gl-padding;
- font-size: 14px;
+ &.blank-state-welcome {
+ .blank-state-welcome-title {
+ font-size: 24px;
+ }
- > strong {
- font-weight: 600;
+ .blank-state-text {
+ margin-bottom: 0;
+ }
}
-}
-.blank-state-welcome-title {
- font-size: 24px;
-}
+ .blank-state-icon {
+ padding-bottom: 20px;
-@media (max-width: $screen-md-min) {
- .blank-state-parent-container {
- &,
- .section-container {
+ svg {
display: block;
+ margin: auto;
}
}
- .blank-state {
- text-align: center;
+ .blank-state-title {
+ margin-top: 0;
+ margin-bottom: 10px;
+ font-size: 18px;
}
- .blank-state-icon {
- padding-bottom: 0;
- }
-
- .blank-state-body {
- margin-top: 15px;
+ .blank-state-text {
+ max-width: $container-text-max-width;
+ margin: 0 auto $gl-padding;
+ font-size: 14px;
}
}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 3f032776d82..52519b1149c 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -176,6 +176,7 @@ $header-height: 50px;
$fixed-layout-width: 1280px;
$limited-layout-width: 990px;
$limited-layout-width-sm: 790px;
+$container-text-max-width: 540px;
$gl-avatar-size: 40px;
$error-exclamation-point: $red-500;
$border-radius-default: 3px;
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 7adf17dddb8..d48dec8fe7a 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -125,7 +125,7 @@
.dropdown-menu {
margin-top: 11px;
- z-index: 200;
+ z-index: 300;
}
.ci-action-icon-wrapper {
diff --git a/app/controllers/concerns/requires_health_token.rb b/app/controllers/concerns/requires_health_token.rb
deleted file mode 100644
index 34ab1a97649..00000000000
--- a/app/controllers/concerns/requires_health_token.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-module RequiresHealthToken
- extend ActiveSupport::Concern
- included do
- before_action :validate_health_check_access!
- end
-
- private
-
- def validate_health_check_access!
- render_404 unless token_valid?
- end
-
- def token_valid?
- token = params[:token].presence || request.headers['TOKEN']
- token.present? &&
- ActiveSupport::SecurityUtils.variable_size_secure_compare(
- token,
- current_application_settings.health_check_access_token
- )
- end
-
- def render_404
- render file: Rails.root.join('public', '404'), layout: false, status: '404'
- end
-end
diff --git a/app/controllers/concerns/requires_whitelisted_monitoring_client.rb b/app/controllers/concerns/requires_whitelisted_monitoring_client.rb
new file mode 100644
index 00000000000..ad2f4bbc486
--- /dev/null
+++ b/app/controllers/concerns/requires_whitelisted_monitoring_client.rb
@@ -0,0 +1,33 @@
+module RequiresWhitelistedMonitoringClient
+ extend ActiveSupport::Concern
+ included do
+ before_action :validate_ip_whitelisted_or_valid_token!
+ end
+
+ private
+
+ def validate_ip_whitelisted_or_valid_token!
+ render_404 unless client_ip_whitelisted? || valid_token?
+ end
+
+ def client_ip_whitelisted?
+ ip_whitelist.any? { |e| e.include?(Gitlab::RequestContext.client_ip) }
+ end
+
+ def ip_whitelist
+ @ip_whitelist ||= Settings.monitoring.ip_whitelist.map(&IPAddr.method(:new))
+ end
+
+ def valid_token?
+ token = params[:token].presence || request.headers['TOKEN']
+ token.present? &&
+ ActiveSupport::SecurityUtils.variable_size_secure_compare(
+ token,
+ current_application_settings.health_check_access_token
+ )
+ end
+
+ def render_404
+ render file: Rails.root.join('public', '404'), layout: false, status: '404'
+ end
+end
diff --git a/app/controllers/health_check_controller.rb b/app/controllers/health_check_controller.rb
index 5d3109b7187..c3d18991fd4 100644
--- a/app/controllers/health_check_controller.rb
+++ b/app/controllers/health_check_controller.rb
@@ -1,3 +1,3 @@
class HealthCheckController < HealthCheck::HealthCheckController
- include RequiresHealthToken
+ include RequiresWhitelistedMonitoringClient
end
diff --git a/app/controllers/health_controller.rb b/app/controllers/health_controller.rb
index 3dbacbbc897..98c2aaa3526 100644
--- a/app/controllers/health_controller.rb
+++ b/app/controllers/health_controller.rb
@@ -1,6 +1,6 @@
class HealthController < ActionController::Base
protect_from_forgery with: :exception
- include RequiresHealthToken
+ include RequiresWhitelistedMonitoringClient
CHECKS = [
Gitlab::HealthChecks::DbCheck,
diff --git a/app/controllers/metrics_controller.rb b/app/controllers/metrics_controller.rb
index 0e9a19c0b6f..37587a52eaf 100644
--- a/app/controllers/metrics_controller.rb
+++ b/app/controllers/metrics_controller.rb
@@ -1,12 +1,12 @@
class MetricsController < ActionController::Base
- include RequiresHealthToken
+ include RequiresWhitelistedMonitoringClient
protect_from_forgery with: :exception
before_action :validate_prometheus_metrics
def index
- render text: metrics_service.metrics_text, content_type: 'text/plain; verssion=0.0.4'
+ render text: metrics_service.metrics_text, content_type: 'text/plain; version=0.0.4'
end
private
diff --git a/app/services/milestones/destroy_service.rb b/app/services/milestones/destroy_service.rb
index e457212508f..600ebcfbecb 100644
--- a/app/services/milestones/destroy_service.rb
+++ b/app/services/milestones/destroy_service.rb
@@ -1,15 +1,17 @@
module Milestones
class DestroyService < Milestones::BaseService
def execute(milestone)
+ return unless milestone.is_project_milestone?
+
Milestone.transaction do
update_params = { milestone: nil }
milestone.issues.each do |issue|
- Issues::UpdateService.new(project, current_user, update_params).execute(issue)
+ Issues::UpdateService.new(parent, current_user, update_params).execute(issue)
end
milestone.merge_requests.each do |merge_request|
- MergeRequests::UpdateService.new(project, current_user, update_params).execute(merge_request)
+ MergeRequests::UpdateService.new(parent, current_user, update_params).execute(merge_request)
end
event_service.destroy_milestone(milestone, current_user)
diff --git a/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml b/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
index 0319838bdb4..209afd4aab4 100644
--- a/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
+++ b/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
@@ -1,7 +1,7 @@
-.row.blank-state.clearfix
- .col-md-1.col-md-offset-3.blank-state-icon
+.blank-state
+ .blank-state-icon
= custom_icon("add_new_user", size: 50)
- .col-md-5.blank-state-body
+ .blank-state-body
%h3.blank-state-title
Add user
%p.blank-state-text
@@ -9,10 +9,10 @@
= link_to new_admin_user_path, class: "btn btn-new" do
New user
-.row.blank-state.clearfix
- .col-md-1.col-md-offset-3.blank-state-icon
+.blank-state
+ .blank-state-icon
= custom_icon("configure_server", size: 50)
- .col-md-5.blank-state-body
+ .blank-state-body
%h3.blank-state-title
Configure GitLab
%p.blank-state-text
@@ -21,10 +21,10 @@
Configure
- if current_user.can_create_group?
- .row.blank-state.clearfix
- .col-md-1.col-md-offset-3.blank-state-icon
+ .blank-state
+ .blank-state-icon
= custom_icon("add_new_group", size: 50)
- .col-md-5.blank-state-body
+ .blank-state-body
%h3.blank-state-title
Create a group
%p.blank-state-text
diff --git a/app/views/dashboard/projects/_blank_state_welcome.html.haml b/app/views/dashboard/projects/_blank_state_welcome.html.haml
index a079f0ac1a4..a93a3415ee1 100644
--- a/app/views/dashboard/projects/_blank_state_welcome.html.haml
+++ b/app/views/dashboard/projects/_blank_state_welcome.html.haml
@@ -1,10 +1,10 @@
- public_project_count = ProjectsFinder.new(current_user: current_user).execute.count
- if current_user.can_create_group?
- .row.blank-state.clearfix
- .col-md-1.col-md-offset-3.blank-state-icon
+ .blank-state
+ .blank-state-icon
= custom_icon("add_new_group", size: 50)
- .col-md-5.blank-state-body
+ .blank-state-body
%h3.blank-state-title
Create a group for several dependent projects.
%p.blank-state-text
@@ -12,10 +12,10 @@
= link_to new_group_path, class: "btn btn-new" do
New group
-.row.blank-state.clearfix
- .col-md-1.col-md-offset-3.blank-state-icon
+.blank-state
+ .blank-state-icon
= custom_icon("add_new_project", size: 50)
- .col-md-5.blank-state-body
+ .blank-state-body
%h3.blank-state-title
Create a project
%p.blank-state-text
@@ -32,10 +32,10 @@
New project
- if public_project_count > 0
- .row.blank-state.clearfix
- .col-md-1.col-md-offset-3.blank-state-icon
+ .blank-state
+ .blank-state-icon
= custom_icon("globe", size: 50)
- .col-md-5.blank-state-body
+ .blank-state-body
%h3.blank-state-title
Explore public projects
%p.blank-state-text
diff --git a/app/views/dashboard/projects/_zero_authorized_projects.html.haml b/app/views/dashboard/projects/_zero_authorized_projects.html.haml
index 94af033c1e3..ad3fac6d164 100644
--- a/app/views/dashboard/projects/_zero_authorized_projects.html.haml
+++ b/app/views/dashboard/projects/_zero_authorized_projects.html.haml
@@ -1,6 +1,6 @@
.row.blank-state-parent-container
- .section-container
- .container.section-body.section-welcome{ class: "#{ 'section-admin-welcome' if current_user.admin? }" }
+ .section-container.section-welcome{ class: "#{ 'section-admin-welcome' if current_user.admin? }" }
+ .container.section-body
.blank-state.blank-state-welcome
%h2.blank-state-welcome-title
Welcome to GitLab
diff --git a/changelogs/unreleased/33949-deprecate-healthcheck-access-token.yml b/changelogs/unreleased/33949-deprecate-healthcheck-access-token.yml
new file mode 100644
index 00000000000..a08795e1a26
--- /dev/null
+++ b/changelogs/unreleased/33949-deprecate-healthcheck-access-token.yml
@@ -0,0 +1,4 @@
+---
+title: Deprecate Healthcheck Access Token in favor of IP whitelist
+merge_request:
+author:
diff --git a/changelogs/unreleased/fix-n-plus-one-in-url-builder.yml b/changelogs/unreleased/fix-n-plus-one-in-url-builder.yml
new file mode 100644
index 00000000000..5781316cfd9
--- /dev/null
+++ b/changelogs/unreleased/fix-n-plus-one-in-url-builder.yml
@@ -0,0 +1,4 @@
+---
+title: Improve issue rendering performance with lots of notes from other users
+merge_request:
+author:
diff --git a/config/database.yml.mysql b/config/database.yml.mysql
index db1b712d3bc..eb71d3f5fe1 100644
--- a/config/database.yml.mysql
+++ b/config/database.yml.mysql
@@ -42,3 +42,4 @@ test: &test
password:
# host: localhost
# socket: /tmp/mysql.sock
+ prepared_statements: false
diff --git a/config/database.yml.postgresql b/config/database.yml.postgresql
index c517a4c0cb8..4b30982fe82 100644
--- a/config/database.yml.postgresql
+++ b/config/database.yml.postgresql
@@ -46,3 +46,4 @@ test: &test
username: postgres
password:
# host: localhost
+ prepared_statements: false
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 221e3d6e03b..d0ab2dab0af 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -539,10 +539,15 @@ production: &base
# enabled: true
# host: localhost
# port: 3808
- prometheus:
+
+ ## Monitoring
+ # Built in monitoring settings
+ monitoring:
# Time between sampling of unicorn socket metrics, in seconds
# unicorn_sampler_interval: 10
-
+ # IP whitelist to access monitoring endpoints
+ ip_whitelist:
+ - 127.0.0.0/8
#
# 5. Extra customization
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index fa33e602e93..eb4a1e390a9 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -494,10 +494,11 @@ Settings.webpack.dev_server['host'] ||= 'localhost'
Settings.webpack.dev_server['port'] ||= 3808
#
-# Prometheus metrics settings
+# Monitoring settings
#
-Settings['prometheus'] ||= Settingslogic.new({})
-Settings.prometheus['unicorn_sampler_interval'] ||= 10
+Settings['monitoring'] ||= Settingslogic.new({})
+Settings.monitoring['ip_whitelist'] ||= ['127.0.0.1/8']
+Settings.monitoring['unicorn_sampler_interval'] ||= 10
#
# Testing settings
diff --git a/config/initializers/8_metrics.rb b/config/initializers/8_metrics.rb
index d56fd7a6cfa..5e34aac6527 100644
--- a/config/initializers/8_metrics.rb
+++ b/config/initializers/8_metrics.rb
@@ -119,7 +119,7 @@ def instrument_classes(instrumentation)
end
# rubocop:enable Metrics/AbcSize
-Gitlab::Metrics::UnicornSampler.initialize_instance(Settings.prometheus.unicorn_sampler_interval).start
+Gitlab::Metrics::UnicornSampler.initialize_instance(Settings.monitoring.unicorn_sampler_interval).start
Gitlab::Application.configure do |config|
# 0 should be Sentry to catch errors in this middleware
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 992ff162efb..5e981b0b3e7 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -294,9 +294,9 @@ sudo usermod -aG redis git
### Clone the Source
# Clone GitLab repository
- sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 9-3-stable gitlab
+ sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 9-4-stable gitlab
-**Note:** You can change `9-3-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
+**Note:** You can change `9-4-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It
@@ -420,6 +420,12 @@ GitLab Shell is an SSH access and repository management software developed speci
**Note:** Make sure your hostname can be resolved on the machine itself by either a proper DNS record or an additional line in /etc/hosts ("127.0.0.1 hostname"). This might be necessary for example if you set up GitLab behind a reverse proxy. If the hostname cannot be resolved, the final installation check will fail with "Check GitLab API access: FAILED. code: 401" and pushing commits will be rejected with "[remote rejected] master -> master (hook declined)".
+**Note:** GitLab Shell application startup time can be greatly reduced by disabling RubyGems. This can be done in several manners:
+
+* Export `RUBYOPT=--disable-gems` environment variable for the processes
+* Compile Ruby with `configure --disable-rubygems` to disable RubyGems by default. Not recommened for system-wide Ruby.
+* Omnibus GitLab [replaces the *shebang* line of the `gitlab-shell/bin/*` scripts](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/1707)
+
### Install gitlab-workhorse
GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/). The
diff --git a/doc/update/9.3-to-9.4.md b/doc/update/9.3-to-9.4.md
index bbb7f4a8d48..6962d124c80 100644
--- a/doc/update/9.3-to-9.4.md
+++ b/doc/update/9.3-to-9.4.md
@@ -72,8 +72,8 @@ More information can be found on the [yarn website](https://yarnpkg.com/en/docs/
### 5. Update Go
-NOTE: GitLab 9.4 and higher only supports Go 1.8.3 and dropped support for Go 1.5.x through 1.7.x. Be
-sure to upgrade your installation if necessary
+NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
+1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
You can check which version you are running with `go version`.
@@ -117,7 +117,7 @@ cd /home/git/gitlab
sudo -u git -H git checkout 9-4-stable-ee
```
-### 5. Update gitlab-shell
+### 7. Update gitlab-shell
```bash
cd /home/git/gitlab-shell
@@ -127,11 +127,10 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
sudo -u git -H bin/compile
```
-### 6. Update gitlab-workhorse
+### 8. Update gitlab-workhorse
-Install and compile gitlab-workhorse. This requires
-[Go 1.8](https://golang.org/dl) which should already be on your system from
-GitLab 8.1. GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/).
+Install and compile gitlab-workhorse. GitLab-Workhorse uses
+[GNU Make](https://www.gnu.org/software/make/).
If you are not using Linux you may have to run `gmake` instead of
`make` below.
@@ -143,7 +142,7 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
sudo -u git -H make
```
-### 7. Update Gitaly
+### 9. Update Gitaly
If you have not yet set up Gitaly then follow [Gitaly section of the installation
guide](../install/installation.md#install-gitaly).
@@ -171,7 +170,29 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
sudo -u git -H make
```
-### 10. Update configuration files
+### 10. Update MySQL permissions
+
+If you are using MySQL you need to grant the GitLab user the necessary
+permissions on the database:
+
+```bash
+mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
+```
+
+If you use MySQL with replication, or just have MySQL configured with binary logging,
+you will need to also run the following on all of your MySQL servers:
+
+```bash
+mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
+```
+
+You can make this setting permanent by adding it to your `my.cnf`:
+
+```
+log_bin_trust_function_creators=1
+```
+
+### 11. Update configuration files
#### New configuration options for `gitlab.yml`
@@ -245,7 +266,7 @@ For Ubuntu 16.04.1 LTS:
sudo systemctl daemon-reload
```
-### 11. Install libs, migrations, etc.
+### 12. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
@@ -271,14 +292,14 @@ sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-### 12. Start application
+### 13. Start application
```bash
sudo service gitlab start
sudo service nginx restart
```
-### 13. Check application status
+### 14. Check application status
Check if GitLab and its environment are configured correctly:
diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md
index a954840b8a6..69a9dfc3500 100644
--- a/doc/user/admin_area/monitoring/health_check.md
+++ b/doc/user/admin_area/monitoring/health_check.md
@@ -5,6 +5,8 @@
- The `health_check` endpoint was [introduced][ce-3888] in GitLab 8.8 and will
be deprecated in GitLab 9.1. Read more in the [old behavior](#old-behavior)
section.
+ - [Access token](#access-token) has been deprecated in GitLab 9.4
+ in favor of [IP Whitelist](#ip-whitelist)
GitLab provides liveness and readiness probes to indicate service health and
reachability to required services. These probes report on the status of the
@@ -12,7 +14,19 @@ database connection, Redis connection, and access to the filesystem. These
endpoints [can be provided to schedulers like Kubernetes][kubernetes] to hold
traffic until the system is ready or restart the container as needed.
-## Access Token
+## IP Whitelist
+
+To access monitoring resources the client IP needs to be included in the whitelist.
+To add or remove hosts or IP ranges from the list you can edit `gitlab.rb` or `gitlab.yml`.
+
+Example whitelist configuration:
+```yaml
+monitoring:
+ ip_whitelist:
+ - 127.0.0.0/8 # by default only local IPs are allowed to access monitoring resources
+```
+
+## Access Token (Deprecated)
An access token needs to be provided while accessing the probe endpoints. The current
accepted token can be found under the **Admin area ➔ Monitoring ➔ Health check**
@@ -47,10 +61,10 @@ which will then provide a report of system health in JSON format:
## Using the Endpoint
-Once you have the access token, the probes can be accessed:
+With default whitelist settings, the probes can be accessed from localhost:
-- `https://gitlab.example.com/-/readiness?token=ACCESS_TOKEN`
-- `https://gitlab.example.com/-/liveness?token=ACCESS_TOKEN`
+- `http://localhost/-/readiness`
+- `http://localhost/-/liveness`
## Status
@@ -71,8 +85,8 @@ the database connection, the state of the database migrations, and the ability t
and access the cache. This endpoint can be provided to uptime monitoring services like
[Pingdom][pingdom], [Nagios][nagios-health], and [NewRelic][newrelic-health].
-Once you have the [access token](#access-token), health information can be
-retrieved as plain text, JSON, or XML using the `health_check` endpoint:
+Once you have the [access token](#access-token) or your client IP is [whitelisted](#ip-whitelist),
+health information can be retrieved as plain text, JSON, or XML using the `health_check` endpoint:
- `https://gitlab.example.com/health_check?token=ACCESS_TOKEN`
- `https://gitlab.example.com/health_check.json?token=ACCESS_TOKEN`
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 4ad1eef4ff1..1a3fdb66f3f 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -44,9 +44,9 @@ module API
args[:label_name] = args.delete(:labels)
merge_requests = MergeRequestsFinder.new(current_user, args).execute
- .preload(:notes, :target_project, :author, :assignee, :milestone, :merge_request_diff, :labels)
-
- merge_requests.reorder(args[:order_by] => args[:sort])
+ merge_requests = merge_requests.reorder(args[:order_by] => args[:sort])
+ paginate(merge_requests)
+ .preload(:notes, :target_project, :author, :assignee, :milestone, :merge_request_diff, :labels)
end
params :optional_params_ce do
@@ -85,7 +85,7 @@ module API
merge_requests = find_merge_requests(project_id: user_project.id)
issuable_metadata = issuable_meta_data(merge_requests, 'MergeRequest')
- present paginate(merge_requests), with: Entities::MergeRequestBasic, current_user: current_user, project: user_project, issuable_metadata: issuable_metadata
+ present merge_requests, with: Entities::MergeRequestBasic, current_user: current_user, project: user_project, issuable_metadata: issuable_metadata
end
desc 'Create a merge request' do
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 791a3c36476..7fa02f3d7b3 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -25,7 +25,7 @@ module Gitlab
def cached_application_settings
begin
::ApplicationSetting.cached
- rescue ::Redis::BaseError, ::Errno::ENOENT
+ rescue ::Redis::BaseError, ::Errno::ENOENT, ::Errno::EADDRNOTAVAIL
# In case Redis isn't running or the Redis UNIX socket file is not available
end
end
diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb
index 35792d2d67f..824e2d7251f 100644
--- a/lib/gitlab/url_builder.rb
+++ b/lib/gitlab/url_builder.rb
@@ -52,15 +52,13 @@ module Gitlab
commit_url(id: object.commit_id, anchor: dom_id(object))
elsif object.for_issue?
- issue = Issue.find(object.noteable_id)
- issue_url(issue, anchor: dom_id(object))
+ issue_url(object.noteable, anchor: dom_id(object))
elsif object.for_merge_request?
- merge_request = MergeRequest.find(object.noteable_id)
- merge_request_url(merge_request, anchor: dom_id(object))
+ merge_request_url(object.noteable, anchor: dom_id(object))
elsif object.for_snippet?
- snippet = Snippet.find(object.noteable_id)
+ snippet = object.noteable
if snippet.is_a?(PersonalSnippet)
snippet_url(snippet, anchor: dom_id(object))
diff --git a/spec/controllers/health_check_controller_spec.rb b/spec/controllers/health_check_controller_spec.rb
index 58c16cc57e6..03da6287774 100644
--- a/spec/controllers/health_check_controller_spec.rb
+++ b/spec/controllers/health_check_controller_spec.rb
@@ -3,52 +3,79 @@ require 'spec_helper'
describe HealthCheckController do
include StubENV
- let(:token) { current_application_settings.health_check_access_token }
let(:json_response) { JSON.parse(response.body) }
let(:xml_response) { Hash.from_xml(response.body)['hash'] }
+ let(:token) { current_application_settings.health_check_access_token }
+ let(:whitelisted_ip) { '127.0.0.1' }
+ let(:not_whitelisted_ip) { '127.0.0.2' }
before do
+ allow(Settings.monitoring).to receive(:ip_whitelist).and_return([whitelisted_ip])
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
end
describe 'GET #index' do
- context 'when services are up but NO access token' do
+ context 'when services are up but accessed from outside whitelisted ips' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(not_whitelisted_ip)
+ end
+
it 'returns a not found page' do
get :index
+
expect(response).to be_not_found
end
+
+ context 'when services are accessed with token' do
+ it 'supports passing the token in the header' do
+ request.headers['TOKEN'] = token
+
+ get :index
+
+ expect(response).to be_success
+ expect(response.content_type).to eq 'text/plain'
+ end
+
+ it 'supports passing the token in query params' do
+ get :index, token: token
+
+ expect(response).to be_success
+ expect(response.content_type).to eq 'text/plain'
+ end
+ end
end
- context 'when services are up and an access token is provided' do
- it 'supports passing the token in the header' do
- request.headers['TOKEN'] = token
- get :index
- expect(response).to be_success
- expect(response.content_type).to eq 'text/plain'
+ context 'when services are up and accessed from whitelisted ips' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(whitelisted_ip)
end
- it 'supports successful plaintest response' do
- get :index, token: token
+ it 'supports successful plaintext response' do
+ get :index
+
expect(response).to be_success
expect(response.content_type).to eq 'text/plain'
end
it 'supports successful json response' do
- get :index, token: token, format: :json
+ get :index, format: :json
+
expect(response).to be_success
expect(response.content_type).to eq 'application/json'
expect(json_response['healthy']).to be true
end
it 'supports successful xml response' do
- get :index, token: token, format: :xml
+ get :index, format: :xml
+
expect(response).to be_success
expect(response.content_type).to eq 'application/xml'
expect(xml_response['healthy']).to be true
end
it 'supports successful responses for specific checks' do
- get :index, token: token, checks: 'email', format: :json
+ get :index, checks: 'email', format: :json
+
expect(response).to be_success
expect(response.content_type).to eq 'application/json'
expect(json_response['healthy']).to be true
@@ -58,33 +85,29 @@ describe HealthCheckController do
context 'when a service is down but NO access token' do
it 'returns a not found page' do
get :index
+
expect(response).to be_not_found
end
end
- context 'when a service is down and an access token is provided' do
+ context 'when a service is down and an endpoint is accessed from whitelisted ip' do
before do
allow(HealthCheck::Utils).to receive(:process_checks).with(['standard']).and_return('The server is on fire')
allow(HealthCheck::Utils).to receive(:process_checks).with(['email']).and_return('Email is on fire')
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(whitelisted_ip)
end
- it 'supports passing the token in the header' do
- request.headers['TOKEN'] = token
+ it 'supports failure plaintext response' do
get :index
- expect(response).to have_http_status(500)
- expect(response.content_type).to eq 'text/plain'
- expect(response.body).to include('The server is on fire')
- end
- it 'supports failure plaintest response' do
- get :index, token: token
expect(response).to have_http_status(500)
expect(response.content_type).to eq 'text/plain'
expect(response.body).to include('The server is on fire')
end
it 'supports failure json response' do
- get :index, token: token, format: :json
+ get :index, format: :json
+
expect(response).to have_http_status(500)
expect(response.content_type).to eq 'application/json'
expect(json_response['healthy']).to be false
@@ -92,7 +115,8 @@ describe HealthCheckController do
end
it 'supports failure xml response' do
- get :index, token: token, format: :xml
+ get :index, format: :xml
+
expect(response).to have_http_status(500)
expect(response.content_type).to eq 'application/xml'
expect(xml_response['healthy']).to be false
@@ -100,7 +124,8 @@ describe HealthCheckController do
end
it 'supports failure responses for specific checks' do
- get :index, token: token, checks: 'email', format: :json
+ get :index, checks: 'email', format: :json
+
expect(response).to have_http_status(500)
expect(response.content_type).to eq 'application/json'
expect(json_response['healthy']).to be false
diff --git a/spec/controllers/health_controller_spec.rb b/spec/controllers/health_controller_spec.rb
index 241c36620d1..cc389e554ad 100644
--- a/spec/controllers/health_controller_spec.rb
+++ b/spec/controllers/health_controller_spec.rb
@@ -3,21 +3,25 @@ require 'spec_helper'
describe HealthController do
include StubENV
- let(:token) { current_application_settings.health_check_access_token }
let(:json_response) { JSON.parse(response.body) }
+ let(:token) { current_application_settings.health_check_access_token }
+ let(:whitelisted_ip) { '127.0.0.1' }
+ let(:not_whitelisted_ip) { '127.0.0.2' }
before do
+ allow(Settings.monitoring).to receive(:ip_whitelist).and_return([whitelisted_ip])
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
end
describe '#readiness' do
- context 'authorization token provided' do
- before do
- request.headers['TOKEN'] = token
- end
+ shared_context 'endpoint responding with readiness data' do
+ let(:request_params) { {} }
+
+ subject { get :readiness, request_params }
+
+ it 'responds with readiness checks data' do
+ subject
- it 'returns proper response' do
- get :readiness
expect(json_response['db_check']['status']).to eq('ok')
expect(json_response['cache_check']['status']).to eq('ok')
expect(json_response['queues_check']['status']).to eq('ok')
@@ -27,22 +31,50 @@ describe HealthController do
end
end
- context 'without authorization token' do
- it 'returns proper response' do
+ context 'accessed from whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(whitelisted_ip)
+ end
+
+ it_behaves_like 'endpoint responding with readiness data'
+ end
+
+ context 'accessed from not whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(not_whitelisted_ip)
+ end
+
+ it 'responds with resource not found' do
get :readiness
+
expect(response.status).to eq(404)
end
+
+ context 'accessed with valid token' do
+ context 'token passed in request header' do
+ before do
+ request.headers['TOKEN'] = token
+ end
+
+ it_behaves_like 'endpoint responding with readiness data'
+ end
+ end
+
+ context 'token passed as URL param' do
+ it_behaves_like 'endpoint responding with readiness data' do
+ let(:request_params) { { token: token } }
+ end
+ end
end
end
describe '#liveness' do
- context 'authorization token provided' do
- before do
- request.headers['TOKEN'] = token
- end
+ shared_context 'endpoint responding with liveness data' do
+ subject { get :liveness }
+
+ it 'responds with liveness checks data' do
+ subject
- it 'returns proper response' do
- get :liveness
expect(json_response['db_check']['status']).to eq('ok')
expect(json_response['cache_check']['status']).to eq('ok')
expect(json_response['queues_check']['status']).to eq('ok')
@@ -51,11 +83,40 @@ describe HealthController do
end
end
- context 'without authorization token' do
- it 'returns proper response' do
+ context 'accessed from whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(whitelisted_ip)
+ end
+
+ it_behaves_like 'endpoint responding with liveness data'
+ end
+
+ context 'accessed from not whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(not_whitelisted_ip)
+ end
+
+ it 'responds with resource not found' do
get :liveness
+
expect(response.status).to eq(404)
end
+
+ context 'accessed with valid token' do
+ context 'token passed in request header' do
+ before do
+ request.headers['TOKEN'] = token
+ end
+
+ it_behaves_like 'endpoint responding with liveness data'
+ end
+
+ context 'token passed as URL param' do
+ it_behaves_like 'endpoint responding with liveness data' do
+ subject { get :liveness, token: token }
+ end
+ end
+ end
end
end
end
diff --git a/spec/controllers/metrics_controller_spec.rb b/spec/controllers/metrics_controller_spec.rb
index c46dd92b454..86847c07c09 100644
--- a/spec/controllers/metrics_controller_spec.rb
+++ b/spec/controllers/metrics_controller_spec.rb
@@ -3,22 +3,22 @@ require 'spec_helper'
describe MetricsController do
include StubENV
- let(:token) { current_application_settings.health_check_access_token }
let(:json_response) { JSON.parse(response.body) }
let(:metrics_multiproc_dir) { Dir.mktmpdir }
+ let(:whitelisted_ip) { '127.0.0.1' }
+ let(:whitelisted_ip_range) { '10.0.0.0/24' }
+ let(:ip_in_whitelisted_range) { '10.0.0.1' }
+ let(:not_whitelisted_ip) { '10.0.1.1' }
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
stub_env('prometheus_multiproc_dir', metrics_multiproc_dir)
allow(Gitlab::Metrics).to receive(:prometheus_metrics_enabled?).and_return(true)
+ allow(Settings.monitoring).to receive(:ip_whitelist).and_return([whitelisted_ip, whitelisted_ip_range])
end
describe '#index' do
- context 'authorization token provided' do
- before do
- request.headers['TOKEN'] = token
- end
-
+ shared_examples_for 'endpoint providing metrics' do
it 'returns DB ping metrics' do
get :index
@@ -83,7 +83,27 @@ describe MetricsController do
end
end
- context 'without authorization token' do
+ context 'accessed from whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(whitelisted_ip)
+ end
+
+ it_behaves_like 'endpoint providing metrics'
+ end
+
+ context 'accessed from ip in whitelisted range' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(ip_in_whitelisted_range)
+ end
+
+ it_behaves_like 'endpoint providing metrics'
+ end
+
+ context 'accessed from not whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(not_whitelisted_ip)
+ end
+
it 'returns proper response' do
get :index
diff --git a/spec/helpers/award_emoji_helper_spec.rb b/spec/helpers/award_emoji_helper_spec.rb
index 7dfd6a3f6b4..035960ed96e 100644
--- a/spec/helpers/award_emoji_helper_spec.rb
+++ b/spec/helpers/award_emoji_helper_spec.rb
@@ -40,7 +40,7 @@ describe AwardEmojiHelper do
it 'returns correct url' do
@project = merge_request.project
- expected_url = "/#{@project.namespace.path}/#{@project.path}/merge_requests/#{merge_request.id}/toggle_award_emoji"
+ expected_url = "/#{@project.namespace.path}/#{@project.path}/merge_requests/#{merge_request.iid}/toggle_award_emoji"
expect(helper.toggle_award_url(merge_request)).to eq(expected_url)
end
@@ -52,7 +52,7 @@ describe AwardEmojiHelper do
it 'returns correct url' do
@project = issue.project
- expected_url = "/#{@project.namespace.path}/#{@project.path}/issues/#{issue.id}/toggle_award_emoji"
+ expected_url = "/#{@project.namespace.path}/#{@project.path}/issues/#{issue.iid}/toggle_award_emoji"
expect(helper.toggle_award_url(issue)).to eq(expected_url)
end
diff --git a/spec/services/milestones/destroy_service_spec.rb b/spec/services/milestones/destroy_service_spec.rb
new file mode 100644
index 00000000000..8d1fe3ae2c1
--- /dev/null
+++ b/spec/services/milestones/destroy_service_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+
+describe Milestones::DestroyService, services: true do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+ let(:milestone) { create(:milestone, title: 'Milestone v1.0', project: project) }
+ let(:issue) { create(:issue, project: project, milestone: milestone) }
+ let(:merge_request) { create(:merge_request, source_project: project, milestone: milestone) }
+
+ before do
+ project.team << [user, :master]
+ end
+
+ def service
+ described_class.new(project, user, {})
+ end
+
+ describe '#execute' do
+ it 'deletes milestone' do
+ service.execute(milestone)
+
+ expect { milestone.reload }.to raise_error ActiveRecord::RecordNotFound
+ end
+
+ it 'deletes milestone id from issuables' do
+ service.execute(milestone)
+
+ expect(issue.reload.milestone).to be_nil
+ expect(merge_request.reload.milestone).to be_nil
+ end
+
+ context 'group milestones' do
+ let(:group) { create(:group) }
+ let(:group_milestone) { create(:milestone, group: group) }
+
+ before do
+ project.update(namespace: group)
+ group.add_developer(user)
+ end
+
+ it { expect(service.execute(group_milestone)).to be_nil }
+
+ it 'does not update milestone issuables' do
+ expect(MergeRequests::UpdateService).not_to receive(:new)
+ expect(Issues::UpdateService).not_to receive(:new)
+
+ service.execute(group_milestone)
+ end
+ end
+ end
+end
diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb
index 0cae5620920..0a194ca4c90 100644
--- a/spec/support/test_env.rb
+++ b/spec/support/test_env.rb
@@ -206,6 +206,7 @@ module TestEnv
# Otherwise they'd be created by the first test, often timing out and
# causing a transient test failure
def eager_load_driver_server
+ return unless ENV['CI']
return unless defined?(Capybara)
puts "Starting the Capybara driver server..."
diff --git a/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml b/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml
index 5b6af7be8c4..eeefadaa019 100644
--- a/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml
@@ -4,10 +4,21 @@ image: docker:latest
services:
- docker:dind
+before_script:
+ - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+
+build-master:
+ stage: build
+ script:
+ - docker build --pull -t "$CI_REGISTRY_IMAGE" .
+ - docker push "$CI_REGISTRY_IMAGE"
+ only:
+ - master
+
build:
stage: build
- before_script:
- - docker login -u "$CI_REGISTRY_USER" -p "CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- - docker build --pull -t "$CI_REGISTRY_IMAGE:CI_COMMIT_REF_SLUG" .
- - docker push "$CI_REGISTRY_IMAGE:CI_COMMIT_REF_SLUG"
+ - docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" .
+ - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
+ except:
+ - master
diff --git a/vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml b/vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml
index 555a51d35b9..06b0c84e516 100644
--- a/vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml
@@ -28,7 +28,7 @@ canary:
- command canary
environment:
name: production
- url: http://$CI_PROJECT_NAME.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_DOMAIN
when: manual
only:
- master
@@ -39,7 +39,7 @@ production:
- command deploy
environment:
name: production
- url: http://$CI_PROJECT_NAME.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_DOMAIN
when: manual
only:
- master
@@ -50,7 +50,7 @@ staging:
- command deploy
environment:
name: staging
- url: http://$CI_PROJECT_NAME-staging.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_DOMAIN
only:
- master
@@ -60,7 +60,7 @@ review:
- command deploy
environment:
name: review/$CI_COMMIT_REF_NAME
- url: http://$CI_PROJECT_NAME-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
on_stop: stop_review
only:
- branches
diff --git a/vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml b/vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml
index ee830ec2eb0..722934b7981 100644
--- a/vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml
@@ -27,7 +27,7 @@ production:
- command deploy
environment:
name: production
- url: http://$CI_PROJECT_NAME.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_DOMAIN
when: manual
only:
- master
@@ -38,7 +38,7 @@ staging:
- command deploy
environment:
name: staging
- url: http://$CI_PROJECT_NAME-staging.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_DOMAIN
only:
- master
@@ -48,7 +48,7 @@ review:
- command deploy
environment:
name: review/$CI_COMMIT_REF_NAME
- url: http://$CI_PROJECT_NAME-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
on_stop: stop_review
only:
- branches
diff --git a/vendor/gitlab-ci-yml/autodeploy/OpenShift.gitlab-ci.yml b/vendor/gitlab-ci-yml/autodeploy/OpenShift.gitlab-ci.yml
index 27c9107e0d7..acba718ebe4 100644
--- a/vendor/gitlab-ci-yml/autodeploy/OpenShift.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/autodeploy/OpenShift.gitlab-ci.yml
@@ -23,38 +23,32 @@ build:
production:
stage: production
- variables:
- CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME.$KUBE_DOMAIN
script:
- command deploy
environment:
name: production
- url: http://$CI_PROJECT_NAME.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_DOMAIN
when: manual
only:
- master
staging:
stage: staging
- variables:
- CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME-staging.$KUBE_DOMAIN
script:
- command deploy
environment:
name: staging
- url: http://$CI_PROJECT_NAME-staging.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_DOMAIN
only:
- master
review:
stage: review
- variables:
- CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
script:
- command deploy
environment:
name: review/$CI_COMMIT_REF_NAME
- url: http://$CI_PROJECT_NAME-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
on_stop: stop_review
only:
- branches