summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-30 15:07:51 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-30 15:07:51 +0000
commit4e9acbfba3682c552b3de707c535e6257ef41054 (patch)
tree8b1fd5f89ad3f1be68d8944815b13bb7d498e4a6
parent506d6dcd7c787ba71a8a53102f3d4fdb6adcfa5e (diff)
downloadgitlab-ce-4e9acbfba3682c552b3de707c535e6257ef41054.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/mirrors/mirror_repos.js13
-rw-r--r--app/controllers/projects/mirrors_controller.rb1
-rw-r--r--app/models/audit_event.rb16
-rw-r--r--app/models/user.rb2
-rw-r--r--app/presenters/pages_domain_presenter.rb18
-rw-r--r--app/services/audit_event_service.rb10
-rw-r--r--app/services/metrics/dashboard/clone_dashboard_service.rb99
-rw-r--r--app/views/projects/mirrors/_mirror_repos_push.html.haml7
-rw-r--r--app/views/projects/pages/_list.html.haml14
-rw-r--r--changelogs/unreleased/dz-scope-some-global-routes.yml5
-rw-r--r--config/routes.rb55
-rw-r--r--db/migrate/20180102220145_add_pages_https_only_to_projects.rb2
-rw-r--r--db/migrate/20180228172924_add_include_private_contributions_to_users.rb2
-rw-r--r--db/migrate/20180503141722_add_remote_mirror_available_overridden_to_projects.rb2
-rw-r--r--db/migrate/20180722103201_add_private_profile_to_users.rb2
-rw-r--r--db/migrate/20180814153625_add_commit_email_to_users.rb6
-rw-r--r--db/migrate/20180924190739_add_scheduled_at_to_ci_builds.rb2
-rw-r--r--db/migrate/20181019032408_add_repositories_table.rb2
-rw-r--r--db/migrate/20181116141504_add_encrypted_runners_token_to_projects.rb6
-rw-r--r--db/migrate/20181129104854_add_token_encrypted_to_ci_builds.rb6
-rw-r--r--db/migrate/20181203002526_add_project_bfg_object_map_column.rb6
-rw-r--r--db/migrate/20190312071108_add_detected_repository_languages_to_projects.rb2
-rw-r--r--db/migrate/20190419121952_add_bridged_pipeline_id_to_bridges.rb2
-rw-r--r--db/migrate/20190715215532_add_project_emails_disabled.rb2
-rw-r--r--db/migrate/20190722104947_add_static_object_token_to_users.rb2
-rw-r--r--db/migrate/20190820163320_add_first_last_name_to_user.rb2
-rw-r--r--db/migrate/20190911115056_add_projects_max_pages_size.rb2
-rw-r--r--db/migrate/20190911115207_add_projects_max_artifacts_size.rb2
-rw-r--r--db/migrate/20190912223232_add_role_to_users.rb2
-rw-r--r--db/migrate/20190924124627_add_pull_mirror_branch_prefix_to_projects.rb2
-rw-r--r--db/migrate/20191003161031_add_mark_for_deletion_to_projects.rb2
-rw-r--r--db/migrate/20191017094449_add_remove_source_branch_after_merge_to_projects.rb2
-rw-r--r--db/migrate/20191115114032_add_processed_to_ci_builds.rb2
-rw-r--r--db/migrate/20191129144630_add_resource_group_id_to_ci_builds.rb2
-rw-r--r--db/migrate/20191208110214_add_suggestion_commit_message_to_projects.rb2
-rw-r--r--db/migrate/20191223124940_add_scheduling_type_to_ci_builds.rb2
-rw-r--r--db/migrate/20200103195205_add_autoclose_referenced_issues_to_projects.rb2
-rw-r--r--db/migrate/20200304085423_add_user_type.rb2
-rw-r--r--db/post_migrate/20190424134256_drop_projects_ci_id.rb2
-rw-r--r--db/post_migrate/20190511144331_remove_users_support_type.rb2
-rw-r--r--db/post_migrate/20191015154408_drop_merge_requests_require_code_owner_approval_from_projects.rb2
-rw-r--r--doc/administration/troubleshooting/log_parsing.md152
-rw-r--r--doc/install/aws/index.md12
-rw-r--r--doc/user/project/integrations/img/prometheus_dashboard_bar_chart_panel_type_v12.10.pngbin0 -> 4761 bytes
-rw-r--r--doc/user/project/integrations/prometheus.md29
-rw-r--r--locale/gitlab.pot5
-rw-r--r--package.json2
-rw-r--r--rubocop/cop/migration/add_columns_to_wide_tables.rb47
-rw-r--r--rubocop/migration_helpers.rb11
-rw-r--r--spec/features/projects/settings/repository_settings_spec.rb29
-rw-r--r--spec/models/user_spec.rb2
-rw-r--r--spec/presenters/pages_domain_presenter_spec.rb73
-rw-r--r--spec/routing/routing_spec.rb31
-rw-r--r--spec/rubocop/cop/migration/add_columns_to_wide_tables_spec.rb92
-rw-r--r--spec/services/metrics/dashboard/clone_dashboard_service_spec.rb14
-rw-r--r--spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb11
-rw-r--r--spec/views/projects/pages/show.html.haml_spec.rb72
-rw-r--r--yarn.lock8
58 files changed, 773 insertions, 133 deletions
diff --git a/app/assets/javascripts/mirrors/mirror_repos.js b/app/assets/javascripts/mirrors/mirror_repos.js
index e5acaaf9366..5401fb7b6ec 100644
--- a/app/assets/javascripts/mirrors/mirror_repos.js
+++ b/app/assets/javascripts/mirrors/mirror_repos.js
@@ -22,15 +22,18 @@ export default class MirrorRepos {
}
initMirrorPush() {
+ this.$keepDivergentRefsInput = $('.js-mirror-keep-divergent-refs', this.$form);
this.$passwordGroup = $('.js-password-group', this.$container);
this.$password = $('.js-password', this.$passwordGroup);
this.$authMethod = $('.js-auth-method', this.$form);
+ this.$keepDivergentRefsInput.on('change', () => this.updateKeepDivergentRefs());
this.$authMethod.on('change', () => this.togglePassword());
this.$password.on('input.updateUrl', () => this.debouncedUpdateUrl());
this.initMirrorSSH();
this.updateProtectedBranches();
+ this.updateKeepDivergentRefs();
}
initMirrorSSH() {
@@ -61,6 +64,16 @@ export default class MirrorRepos {
$('.js-mirror-protected-hidden', this.$form).val(val);
}
+ updateKeepDivergentRefs() {
+ const field = this.$keepDivergentRefsInput.get(0);
+
+ // This field only exists after the form is switched to 'Push' mode
+ if (field) {
+ const val = field.checked ? this.$keepDivergentRefsInput.val() : '0';
+ $('.js-mirror-keep-divergent-refs-hidden', this.$form).val(val);
+ }
+ }
+
registerUpdateListeners() {
this.debouncedUpdateUrl = debounce(() => this.updateUrl(), 200);
this.$urlInput.on('input', () => this.debouncedUpdateUrl());
diff --git a/app/controllers/projects/mirrors_controller.rb b/app/controllers/projects/mirrors_controller.rb
index 936f89e58e7..518e6a92afa 100644
--- a/app/controllers/projects/mirrors_controller.rb
+++ b/app/controllers/projects/mirrors_controller.rb
@@ -77,6 +77,7 @@ class Projects::MirrorsController < Projects::ApplicationController
id
enabled
only_protected_branches
+ keep_divergent_refs
auth_method
password
ssh_known_hosts
diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb
index 7ff0076c3e3..03841917bbf 100644
--- a/app/models/audit_event.rb
+++ b/app/models/audit_event.rb
@@ -30,26 +30,12 @@ class AuditEvent < ApplicationRecord
end
def author_name
- lazy_author.name
+ self.user.name
end
def formatted_details
details.merge(details.slice(:from, :to).transform_values(&:to_s))
end
-
- def lazy_author
- BatchLoader.for(author_id).batch(default_value: default_author_value) do |author_ids, loader|
- User.where(id: author_ids).find_each do |user|
- loader.call(user.id, user)
- end
- end
- end
-
- private
-
- def default_author_value
- ::Gitlab::Audit::NullAuthor.for(author_id, details[:author_name])
- end
end
AuditEvent.prepend_if_ee('EE::AuditEvent')
diff --git a/app/models/user.rb b/app/models/user.rb
index 8709bfb18fd..b147c7d4d48 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1825,7 +1825,7 @@ class User < ApplicationRecord
return if restrictions.blank?
if Gitlab::UntrustedRegexp.new(restrictions).match?(email)
- errors.add(:email, _('is not allowed for sign-up'))
+ errors.add(:email, _('is not allowed. Try again with a different email address, or contact your GitLab admin.'))
end
end
diff --git a/app/presenters/pages_domain_presenter.rb b/app/presenters/pages_domain_presenter.rb
new file mode 100644
index 00000000000..6b74983d932
--- /dev/null
+++ b/app/presenters/pages_domain_presenter.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class PagesDomainPresenter < Gitlab::View::Presenter::Delegated
+ presents :pages_domain
+
+ def needs_verification?
+ Gitlab::CurrentSettings.pages_domain_verification_enabled? && unverified?
+ end
+
+ def show_auto_ssl_failed_warning?
+ return false unless Feature.enabled?(:pages_letsencrypt_errors, pages_domain.project)
+
+ # validations prevents auto ssl from working, so there is no need to show that warning until
+ return false if needs_verification?
+
+ ::Gitlab::LetsEncrypt.enabled? && auto_ssl_failed
+ end
+end
diff --git a/app/services/audit_event_service.rb b/app/services/audit_event_service.rb
index d9e40c456aa..42ed5f17d8d 100644
--- a/app/services/audit_event_service.rb
+++ b/app/services/audit_event_service.rb
@@ -13,7 +13,7 @@ class AuditEventService
#
# @return [AuditEventService]
def initialize(author, entity, details = {})
- @author = build_author(author)
+ @author = author
@entity = entity
@details = details
end
@@ -49,14 +49,6 @@ class AuditEventService
private
- def build_author(author)
- if author.is_a?(User)
- author
- else
- Gitlab::Audit::UnauthenticatedAuthor.new(name: author)
- end
- end
-
def base_payload
{
author_id: @author.id,
diff --git a/app/services/metrics/dashboard/clone_dashboard_service.rb b/app/services/metrics/dashboard/clone_dashboard_service.rb
index ee5b50aefc3..3ca25b3bd9b 100644
--- a/app/services/metrics/dashboard/clone_dashboard_service.rb
+++ b/app/services/metrics/dashboard/clone_dashboard_service.rb
@@ -5,9 +5,18 @@
module Metrics
module Dashboard
class CloneDashboardService < ::BaseService
+ include Stepable
+
ALLOWED_FILE_TYPE = '.yml'
USER_DASHBOARDS_DIR = ::Metrics::Dashboard::CustomDashboardService::DASHBOARD_ROOT
+ steps :check_push_authorized,
+ :check_branch_name,
+ :check_file_type,
+ :check_dashboard_template,
+ :create_file,
+ :refresh_repository_method_caches
+
class << self
def allowed_dashboard_templates
@allowed_dashboard_templates ||= Set[::Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH].freeze
@@ -22,21 +31,52 @@ module Metrics
end
end
- # rubocop:disable Cop/BanCatchThrow
def execute
- catch(:error) do
- throw(:error, error(_(%q(You are not allowed to push into this branch. Create another branch or open a merge request.)), :forbidden)) unless push_authorized?
+ execute_steps
+ end
+
+ private
+
+ def check_push_authorized(result)
+ return error(_('You are not allowed to push into this branch. Create another branch or open a merge request.'), :forbidden) unless push_authorized?
+
+ success(result)
+ end
+
+ def check_branch_name(result)
+ return error(_('There was an error creating the dashboard, branch name is invalid.'), :bad_request) unless valid_branch_name?
+ return error(_('There was an error creating the dashboard, branch named: %{branch} already exists.') % { branch: params[:branch] }, :bad_request) unless new_or_default_branch?
+
+ success(result)
+ end
- result = ::Files::CreateService.new(project, current_user, dashboard_attrs).execute
- throw(:error, wrap_error(result)) unless result[:status] == :success
+ def check_file_type(result)
+ return error(_('The file name should have a .yml extension'), :bad_request) unless target_file_type_valid?
- repository.refresh_method_caches([:metrics_dashboard])
- success(result.merge(http_status: :created, dashboard: dashboard_details))
+ success(result)
+ end
+
+ def check_dashboard_template(result)
+ return error(_('Not found.'), :not_found) unless self.class.allowed_dashboard_templates.include?(params[:dashboard])
+
+ success(result)
+ end
+
+ def create_file(result)
+ create_file_response = ::Files::CreateService.new(project, current_user, dashboard_attrs).execute
+
+ if create_file_response[:status] == :success
+ success(result.merge(create_file_response))
+ else
+ wrap_error(create_file_response)
end
end
- # rubocop:enable Cop/BanCatchThrow
- private
+ def refresh_repository_method_caches(result)
+ repository.refresh_method_caches([:metrics_dashboard])
+
+ success(result.merge(http_status: :created, dashboard: dashboard_details))
+ end
def dashboard_attrs
{
@@ -62,26 +102,13 @@ module Metrics
Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(branch)
end
- # rubocop:disable Cop/BanCatchThrow
def dashboard_template
- @dashboard_template ||= begin
- throw(:error, error(_('Not found.'), :not_found)) unless self.class.allowed_dashboard_templates.include?(params[:dashboard])
-
- params[:dashboard]
- end
+ @dashboard_template ||= params[:dashboard]
end
- # rubocop:enable Cop/BanCatchThrow
- # rubocop:disable Cop/BanCatchThrow
def branch
- @branch ||= begin
- throw(:error, error(_('There was an error creating the dashboard, branch name is invalid.'), :bad_request)) unless valid_branch_name?
- throw(:error, error(_('There was an error creating the dashboard, branch named: %{branch} already exists.') % { branch: params[:branch] }, :bad_request)) unless new_or_default_branch? # temporary validation for first UI iteration
-
- params[:branch]
- end
+ @branch ||= params[:branch]
end
- # rubocop:enable Cop/BanCatchThrow
def new_or_default_branch?
!repository.branch_exists?(params[:branch]) || project.default_branch == params[:branch]
@@ -95,20 +122,22 @@ module Metrics
@new_dashboard_path ||= File.join(USER_DASHBOARDS_DIR, file_name)
end
- # rubocop:disable Cop/BanCatchThrow
def file_name
- @file_name ||= begin
- throw(:error, error(_('The file name should have a .yml extension'), :bad_request)) unless target_file_type_valid?
-
- File.basename(params[:file_name])
- end
+ @file_name ||= File.basename(params[:file_name])
end
- # rubocop:enable Cop/BanCatchThrow
def target_file_type_valid?
File.extname(params[:file_name]) == ALLOWED_FILE_TYPE
end
+ def wrap_error(result)
+ if result[:message] == 'A file with this name already exists'
+ error(_("A file with '%{file_name}' already exists in %{branch} branch") % { file_name: file_name, branch: branch }, :bad_request)
+ else
+ result
+ end
+ end
+
def new_dashboard_content
::Gitlab::Metrics::Dashboard::Processor
.new(project, raw_dashboard, sequence, {})
@@ -119,14 +148,6 @@ module Metrics
@repository ||= project.repository
end
- def wrap_error(result)
- if result[:message] == 'A file with this name already exists'
- error(_("A file with '%{file_name}' already exists in %{branch} branch") % { file_name: file_name, branch: branch }, :bad_request)
- else
- result
- end
- end
-
def raw_dashboard
YAML.safe_load(File.read(Rails.root.join(dashboard_template)))
end
diff --git a/app/views/projects/mirrors/_mirror_repos_push.html.haml b/app/views/projects/mirrors/_mirror_repos_push.html.haml
index b7c885b4a63..8482424a184 100644
--- a/app/views/projects/mirrors/_mirror_repos_push.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos_push.html.haml
@@ -1,8 +1,15 @@
- protocols = Gitlab::UrlSanitizer::ALLOWED_SCHEMES.join('|')
+- keep_divergent_refs = Feature.enabled?(:keep_divergent_refs, @project)
= f.fields_for :remote_mirrors, @project.remote_mirrors.build do |rm_f|
= rm_f.hidden_field :enabled, value: '1'
= rm_f.hidden_field :url, class: 'js-mirror-url-hidden', required: true, pattern: "(#{protocols}):\/\/.+"
= rm_f.hidden_field :only_protected_branches, class: 'js-mirror-protected-hidden'
+ - if keep_divergent_refs
+ = rm_f.hidden_field :keep_divergent_refs, class: 'js-mirror-keep-divergent-refs-hidden'
= render partial: 'projects/mirrors/ssh_host_keys', locals: { f: rm_f }
= render partial: 'projects/mirrors/authentication_method', locals: { f: rm_f }
+ - if keep_divergent_refs
+ .form-check.append-bottom-10
+ = check_box_tag :keep_divergent_refs, '1', false, class: 'js-mirror-keep-divergent-refs form-check-input'
+ = label_tag :keep_divergent_refs, 'Keep divergent refs', class: 'form-check-label'
diff --git a/app/views/projects/pages/_list.html.haml b/app/views/projects/pages/_list.html.haml
index 6d196b06135..0d40f375926 100644
--- a/app/views/projects/pages/_list.html.haml
+++ b/app/views/projects/pages/_list.html.haml
@@ -6,6 +6,7 @@
Domains (#{@domains.count})
%ul.list-group.list-group-flush.pages-domain-list{ class: ("has-verification-status" if verification_enabled) }
- @domains.each do |domain|
+ - domain = Gitlab::View::Presenter::Factory.new(domain, current_user: current_user).fabricate!
%li.pages-domain-list-item.list-group-item.d-flex.justify-content-between
- if verification_enabled
- tooltip, status = domain.unverified? ? [s_('GitLabPages|Unverified'), 'failed'] : [s_('GitLabPages|Verified'), 'success']
@@ -13,20 +14,27 @@
= sprite_icon("status_#{status}", size: 16 )
.domain-name
= external_link(domain.url, domain.url)
- - if domain.subject
+ - if domain.certificate
%div
%span.badge.badge-gray
- = s_('GitLabPages|Certificate: %{subject}') % { subject: domain.subject }
+ = s_('GitLabPages|Certificate: %{subject}') % { subject: domain.pages_domain.subject }
- if domain.expired?
%span.badge.badge-danger
= s_('GitLabPages|Expired')
%div
= link_to s_('GitLabPages|Edit'), project_pages_domain_path(@project, domain), class: "btn btn-sm btn-grouped btn-success btn-inverted"
= link_to s_('GitLabPages|Remove'), project_pages_domain_path(@project, domain), data: { confirm: s_('GitLabPages|Are you sure?')}, method: :delete, class: "btn btn-remove btn-sm btn-grouped"
- - if verification_enabled && domain.unverified?
+ - if domain.needs_verification?
%li.list-group-item.bs-callout-warning
- details_link_start = "<a href='#{project_pages_domain_path(@project, domain)}'>".html_safe
- details_link_end = '</a>'.html_safe
= s_('GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}.').html_safe % { domain: domain.domain,
link_start: details_link_start,
link_end: details_link_end }
+ - if domain.show_auto_ssl_failed_warning?
+ %li.list-group-item.bs-callout-warning
+ - details_link_start = "<a href='#{project_pages_domain_path(@project, domain)}'>".html_safe
+ - details_link_end = '</a>'.html_safe
+ = s_("GitLabPages|Something went wrong while obtaining Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}.").html_safe % { domain: domain.domain,
+ link_start: details_link_start,
+ link_end: details_link_end }
diff --git a/changelogs/unreleased/dz-scope-some-global-routes.yml b/changelogs/unreleased/dz-scope-some-global-routes.yml
new file mode 100644
index 00000000000..c908c316227
--- /dev/null
+++ b/changelogs/unreleased/dz-scope-some-global-routes.yml
@@ -0,0 +1,5 @@
+---
+title: Move some global routes to - scope
+merge_request: 27106
+author:
+type: changed
diff --git a/config/routes.rb b/config/routes.rb
index 466555eeee8..a8b2a9b6656 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -71,6 +71,8 @@ Rails.application.routes.draw do
# Health check
get 'health_check(/:checks)' => 'health_check#index', as: :health_check
+ # Begin of the /-/ scope.
+ # Use this scope for all new global routes.
scope path: '-' do
# '/-/health' implemented by BasicHealthCheck middleware
get 'liveness' => 'health#liveness'
@@ -122,6 +124,10 @@ Rails.application.routes.draw do
draw :country_state
draw :subscription
draw :analytics
+
+ scope '/push_from_secondary/:geo_node_id' do
+ draw :git_http
+ end
end
if ENV['GITLAB_CHAOS_SECRET'] || Rails.env.development? || Rails.env.test?
@@ -136,7 +142,24 @@ Rails.application.routes.draw do
# Notification settings
resources :notification_settings, only: [:create, :update]
+
+ resources :invites, only: [:show], constraints: { id: /[A-Za-z0-9_-]+/ } do
+ member do
+ post :accept
+ match :decline, via: [:get, :post]
+ end
+ end
+
+ resources :sent_notifications, only: [], constraints: { id: /\h{32}/ } do
+ member do
+ get :unsubscribe
+ end
+ end
+
+ # Spam reports
+ resources :abuse_reports, only: [:new, :create]
end
+ # End of the /-/ scope.
concern :clusterable do
resources :clusters, only: [:index, :new, :show, :update, :destroy] do
@@ -167,22 +190,24 @@ Rails.application.routes.draw do
end
end
- # Invites
- resources :invites, only: [:show], constraints: { id: /[A-Za-z0-9_-]+/ } do
- member do
- post :accept
- match :decline, via: [:get, :post]
+ # Deprecated routes.
+ # Will be removed as part of https://gitlab.com/gitlab-org/gitlab/-/issues/210024
+ scope as: :deprecated do
+ resources :invites, only: [:show], constraints: { id: /[A-Za-z0-9_-]+/ } do
+ member do
+ post :accept
+ match :decline, via: [:get, :post]
+ end
end
- end
- resources :sent_notifications, only: [], constraints: { id: /\h{32}/ } do
- member do
- get :unsubscribe
+ resources :sent_notifications, only: [], constraints: { id: /\h{32}/ } do
+ member do
+ get :unsubscribe
+ end
end
- end
- # Spam reports
- resources :abuse_reports, only: [:new, :create]
+ resources :abuse_reports, only: [:new, :create]
+ end
resources :groups, only: [:index, :new, :create] do
post :preview_markdown
@@ -192,12 +217,6 @@ Rails.application.routes.draw do
get '/projects/:id' => 'projects#resolve'
- Gitlab.ee do
- scope '/-/push_from_secondary/:geo_node_id' do
- draw :git_http
- end
- end
-
draw :git_http
draw :api
draw :sidekiq
diff --git a/db/migrate/20180102220145_add_pages_https_only_to_projects.rb b/db/migrate/20180102220145_add_pages_https_only_to_projects.rb
index 75488f57fa9..7bd646cd5fd 100644
--- a/db/migrate/20180102220145_add_pages_https_only_to_projects.rb
+++ b/db/migrate/20180102220145_add_pages_https_only_to_projects.rb
@@ -4,6 +4,6 @@ class AddPagesHttpsOnlyToProjects < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
- add_column :projects, :pages_https_only, :boolean
+ add_column :projects, :pages_https_only, :boolean # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20180228172924_add_include_private_contributions_to_users.rb b/db/migrate/20180228172924_add_include_private_contributions_to_users.rb
index 7921d3a14b6..58e50b2ee74 100644
--- a/db/migrate/20180228172924_add_include_private_contributions_to_users.rb
+++ b/db/migrate/20180228172924_add_include_private_contributions_to_users.rb
@@ -2,6 +2,6 @@ class AddIncludePrivateContributionsToUsers < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
- add_column :users, :include_private_contributions, :boolean
+ add_column :users, :include_private_contributions, :boolean # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20180503141722_add_remote_mirror_available_overridden_to_projects.rb b/db/migrate/20180503141722_add_remote_mirror_available_overridden_to_projects.rb
index 1d99d46b7d6..aa3d9a804ab 100644
--- a/db/migrate/20180503141722_add_remote_mirror_available_overridden_to_projects.rb
+++ b/db/migrate/20180503141722_add_remote_mirror_available_overridden_to_projects.rb
@@ -6,7 +6,7 @@ class AddRemoteMirrorAvailableOverriddenToProjects < ActiveRecord::Migration[4.2
disable_ddl_transaction!
def up
- add_column(:projects, :remote_mirror_available_overridden, :boolean) unless column_exists?(:projects, :remote_mirror_available_overridden)
+ add_column(:projects, :remote_mirror_available_overridden, :boolean) unless column_exists?(:projects, :remote_mirror_available_overridden) # rubocop:disable Migration/AddColumnsToWideTables
end
def down
diff --git a/db/migrate/20180722103201_add_private_profile_to_users.rb b/db/migrate/20180722103201_add_private_profile_to_users.rb
index c8d917065bb..63b7a631fc8 100644
--- a/db/migrate/20180722103201_add_private_profile_to_users.rb
+++ b/db/migrate/20180722103201_add_private_profile_to_users.rb
@@ -5,6 +5,6 @@ class AddPrivateProfileToUsers < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
- add_column :users, :private_profile, :boolean
+ add_column :users, :private_profile, :boolean # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20180814153625_add_commit_email_to_users.rb b/db/migrate/20180814153625_add_commit_email_to_users.rb
index 98bafc14a03..303be9b2312 100644
--- a/db/migrate/20180814153625_add_commit_email_to_users.rb
+++ b/db/migrate/20180814153625_add_commit_email_to_users.rb
@@ -27,7 +27,11 @@ class AddCommitEmailToUsers < ActiveRecord::Migration[4.2]
# comments:
# disable_ddl_transaction!
+ # rubocop:disable Migration/AddLimitToStringColumns
+ # rubocop:disable Migration/AddColumnsToWideTables
def change
- add_column :users, :commit_email, :string # rubocop:disable Migration/AddLimitToStringColumns
+ add_column :users, :commit_email, :string
end
+ # rubocop:enable Migration/AddLimitToStringColumns
+ # rubocop:enable Migration/AddColumnsToWideTables
end
diff --git a/db/migrate/20180924190739_add_scheduled_at_to_ci_builds.rb b/db/migrate/20180924190739_add_scheduled_at_to_ci_builds.rb
index cd2f8b59d41..04a784a0c90 100644
--- a/db/migrate/20180924190739_add_scheduled_at_to_ci_builds.rb
+++ b/db/migrate/20180924190739_add_scheduled_at_to_ci_builds.rb
@@ -4,6 +4,6 @@ class AddScheduledAtToCiBuilds < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
- add_column :ci_builds, :scheduled_at, :datetime_with_timezone
+ add_column :ci_builds, :scheduled_at, :datetime_with_timezone # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20181019032408_add_repositories_table.rb b/db/migrate/20181019032408_add_repositories_table.rb
index dd510b44084..5ee31b37b66 100644
--- a/db/migrate/20181019032408_add_repositories_table.rb
+++ b/db/migrate/20181019032408_add_repositories_table.rb
@@ -9,7 +9,7 @@ class AddRepositoriesTable < ActiveRecord::Migration[4.2]
t.string :disk_path, null: false, index: { unique: true } # rubocop:disable Migration/AddLimitToStringColumns
end
- add_column :projects, :pool_repository_id, :bigint
+ add_column :projects, :pool_repository_id, :bigint # rubocop:disable Migration/AddColumnsToWideTables
add_index :projects, :pool_repository_id, where: 'pool_repository_id IS NOT NULL'
end
end
diff --git a/db/migrate/20181116141504_add_encrypted_runners_token_to_projects.rb b/db/migrate/20181116141504_add_encrypted_runners_token_to_projects.rb
index 3083dff49b8..f6986fcdfeb 100644
--- a/db/migrate/20181116141504_add_encrypted_runners_token_to_projects.rb
+++ b/db/migrate/20181116141504_add_encrypted_runners_token_to_projects.rb
@@ -5,7 +5,11 @@ class AddEncryptedRunnersTokenToProjects < ActiveRecord::Migration[4.2]
DOWNTIME = false
+ # rubocop:disable Migration/AddColumnsToWideTables
+ # rubocop:disable Migration/AddLimitToStringColumns
def change
- add_column :projects, :runners_token_encrypted, :string # rubocop:disable Migration/AddLimitToStringColumns
+ add_column :projects, :runners_token_encrypted, :string
end
+ # rubocop:enable Migration/AddColumnsToWideTables
+ # rubocop:enable Migration/AddLimitToStringColumns
end
diff --git a/db/migrate/20181129104854_add_token_encrypted_to_ci_builds.rb b/db/migrate/20181129104854_add_token_encrypted_to_ci_builds.rb
index 62a7421eae0..097cc59bcdc 100644
--- a/db/migrate/20181129104854_add_token_encrypted_to_ci_builds.rb
+++ b/db/migrate/20181129104854_add_token_encrypted_to_ci_builds.rb
@@ -5,7 +5,11 @@ class AddTokenEncryptedToCiBuilds < ActiveRecord::Migration[5.0]
DOWNTIME = false
+ # rubocop:disable Migration/AddColumnsToWideTables
+ # rubocop:disable Migration/AddLimitToStringColumns
def change
- add_column :ci_builds, :token_encrypted, :string # rubocop:disable Migration/AddLimitToStringColumns
+ add_column :ci_builds, :token_encrypted, :string
end
+ # rubocop:enable Migration/AddColumnsToWideTables
+ # rubocop:enable Migration/AddLimitToStringColumns
end
diff --git a/db/migrate/20181203002526_add_project_bfg_object_map_column.rb b/db/migrate/20181203002526_add_project_bfg_object_map_column.rb
index 5e6d416895c..d8c4fe1ecf6 100644
--- a/db/migrate/20181203002526_add_project_bfg_object_map_column.rb
+++ b/db/migrate/20181203002526_add_project_bfg_object_map_column.rb
@@ -3,7 +3,11 @@
class AddProjectBfgObjectMapColumn < ActiveRecord::Migration[5.0]
DOWNTIME = false
+ # rubocop:disable Migration/AddColumnsToWideTables
+ # rubocop:disable Migration/AddLimitToStringColumns
def change
- add_column :projects, :bfg_object_map, :string # rubocop:disable Migration/AddLimitToStringColumns
+ add_column :projects, :bfg_object_map, :string
end
+ # rubocop:enable Migration/AddColumnsToWideTables
+ # rubocop:enable Migration/AddLimitToStringColumns
end
diff --git a/db/migrate/20190312071108_add_detected_repository_languages_to_projects.rb b/db/migrate/20190312071108_add_detected_repository_languages_to_projects.rb
index 5ce0ca19888..82e7ec851c9 100644
--- a/db/migrate/20190312071108_add_detected_repository_languages_to_projects.rb
+++ b/db/migrate/20190312071108_add_detected_repository_languages_to_projects.rb
@@ -7,6 +7,6 @@ class AddDetectedRepositoryLanguagesToProjects < ActiveRecord::Migration[5.0]
DOWNTIME = false
def change
- add_column :projects, :detected_repository_languages, :boolean
+ add_column :projects, :detected_repository_languages, :boolean # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20190419121952_add_bridged_pipeline_id_to_bridges.rb b/db/migrate/20190419121952_add_bridged_pipeline_id_to_bridges.rb
index fac556c1897..efb59403df3 100644
--- a/db/migrate/20190419121952_add_bridged_pipeline_id_to_bridges.rb
+++ b/db/migrate/20190419121952_add_bridged_pipeline_id_to_bridges.rb
@@ -10,6 +10,6 @@ class AddBridgedPipelineIdToBridges < ActiveRecord::Migration[5.0]
DOWNTIME = false
def change
- add_column :ci_builds, :upstream_pipeline_id, :integer
+ add_column :ci_builds, :upstream_pipeline_id, :integer # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20190715215532_add_project_emails_disabled.rb b/db/migrate/20190715215532_add_project_emails_disabled.rb
index 536ea34c0fb..72dba82ef1c 100644
--- a/db/migrate/20190715215532_add_project_emails_disabled.rb
+++ b/db/migrate/20190715215532_add_project_emails_disabled.rb
@@ -4,6 +4,6 @@ class AddProjectEmailsDisabled < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
- add_column :projects, :emails_disabled, :boolean
+ add_column :projects, :emails_disabled, :boolean # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20190722104947_add_static_object_token_to_users.rb b/db/migrate/20190722104947_add_static_object_token_to_users.rb
index 6ef85d9acaa..180e6a30b04 100644
--- a/db/migrate/20190722104947_add_static_object_token_to_users.rb
+++ b/db/migrate/20190722104947_add_static_object_token_to_users.rb
@@ -9,7 +9,7 @@ class AddStaticObjectTokenToUsers < ActiveRecord::Migration[5.2]
disable_ddl_transaction!
def up
- add_column :users, :static_object_token, :string, limit: 255
+ add_column :users, :static_object_token, :string, limit: 255 # rubocop:disable Migration/AddColumnsToWideTables
end
def down
diff --git a/db/migrate/20190820163320_add_first_last_name_to_user.rb b/db/migrate/20190820163320_add_first_last_name_to_user.rb
index 0ea465fc2e2..62bd1443b9d 100644
--- a/db/migrate/20190820163320_add_first_last_name_to_user.rb
+++ b/db/migrate/20190820163320_add_first_last_name_to_user.rb
@@ -7,8 +7,10 @@ class AddFirstLastNameToUser < ActiveRecord::Migration[5.2]
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
+ # rubocop:disable Migration/AddColumnsToWideTables
def change
add_column(:users, :first_name, :string, null: true, limit: 255)
add_column(:users, :last_name, :string, null: true, limit: 255)
end
+ # rubocop:enable Migration/AddColumnsToWideTables
end
diff --git a/db/migrate/20190911115056_add_projects_max_pages_size.rb b/db/migrate/20190911115056_add_projects_max_pages_size.rb
index 175c66953ed..70812e31ab8 100644
--- a/db/migrate/20190911115056_add_projects_max_pages_size.rb
+++ b/db/migrate/20190911115056_add_projects_max_pages_size.rb
@@ -4,6 +4,6 @@ class AddProjectsMaxPagesSize < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
- add_column :projects, :max_pages_size, :integer
+ add_column :projects, :max_pages_size, :integer # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20190911115207_add_projects_max_artifacts_size.rb b/db/migrate/20190911115207_add_projects_max_artifacts_size.rb
index 41cab7e5282..cd4574ad9c8 100644
--- a/db/migrate/20190911115207_add_projects_max_artifacts_size.rb
+++ b/db/migrate/20190911115207_add_projects_max_artifacts_size.rb
@@ -4,6 +4,6 @@ class AddProjectsMaxArtifactsSize < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
- add_column :projects, :max_artifacts_size, :integer
+ add_column :projects, :max_artifacts_size, :integer # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20190912223232_add_role_to_users.rb b/db/migrate/20190912223232_add_role_to_users.rb
index afbd78ed509..a6405ab896d 100644
--- a/db/migrate/20190912223232_add_role_to_users.rb
+++ b/db/migrate/20190912223232_add_role_to_users.rb
@@ -7,6 +7,6 @@ class AddRoleToUsers < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
- add_column :users, :role, :smallint
+ add_column :users, :role, :smallint # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20190924124627_add_pull_mirror_branch_prefix_to_projects.rb b/db/migrate/20190924124627_add_pull_mirror_branch_prefix_to_projects.rb
index b9f729d7d66..f1af925c421 100644
--- a/db/migrate/20190924124627_add_pull_mirror_branch_prefix_to_projects.rb
+++ b/db/migrate/20190924124627_add_pull_mirror_branch_prefix_to_projects.rb
@@ -4,6 +4,6 @@ class AddPullMirrorBranchPrefixToProjects < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
- add_column :projects, :pull_mirror_branch_prefix, :string, limit: 50
+ add_column :projects, :pull_mirror_branch_prefix, :string, limit: 50 # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20191003161031_add_mark_for_deletion_to_projects.rb b/db/migrate/20191003161031_add_mark_for_deletion_to_projects.rb
index 86d581a4383..12f17c849aa 100644
--- a/db/migrate/20191003161031_add_mark_for_deletion_to_projects.rb
+++ b/db/migrate/20191003161031_add_mark_for_deletion_to_projects.rb
@@ -4,8 +4,10 @@ class AddMarkForDeletionToProjects < ActiveRecord::Migration[5.2]
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
+ # rubocop:disable Migration/AddColumnsToWideTables
def change
add_column :projects, :marked_for_deletion_at, :date
add_column :projects, :marked_for_deletion_by_user_id, :integer
end
+ # rubocop:enable Migration/AddColumnsToWideTables
end
diff --git a/db/migrate/20191017094449_add_remove_source_branch_after_merge_to_projects.rb b/db/migrate/20191017094449_add_remove_source_branch_after_merge_to_projects.rb
index 021bf7d9870..d4f84b066a3 100644
--- a/db/migrate/20191017094449_add_remove_source_branch_after_merge_to_projects.rb
+++ b/db/migrate/20191017094449_add_remove_source_branch_after_merge_to_projects.rb
@@ -8,7 +8,7 @@ class AddRemoveSourceBranchAfterMergeToProjects < ActiveRecord::Migration[5.1]
DOWNTIME = false
def up
- add_column :projects, :remove_source_branch_after_merge, :boolean
+ add_column :projects, :remove_source_branch_after_merge, :boolean # rubocop:disable Migration/AddColumnsToWideTables
end
def down
diff --git a/db/migrate/20191115114032_add_processed_to_ci_builds.rb b/db/migrate/20191115114032_add_processed_to_ci_builds.rb
index f6f8f5e85d6..6fece99cb02 100644
--- a/db/migrate/20191115114032_add_processed_to_ci_builds.rb
+++ b/db/migrate/20191115114032_add_processed_to_ci_builds.rb
@@ -4,6 +4,6 @@ class AddProcessedToCiBuilds < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
- add_column :ci_builds, :processed, :boolean
+ add_column :ci_builds, :processed, :boolean # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20191129144630_add_resource_group_id_to_ci_builds.rb b/db/migrate/20191129144630_add_resource_group_id_to_ci_builds.rb
index 2e696c32e7e..245df7fdcf3 100644
--- a/db/migrate/20191129144630_add_resource_group_id_to_ci_builds.rb
+++ b/db/migrate/20191129144630_add_resource_group_id_to_ci_builds.rb
@@ -3,6 +3,7 @@
class AddResourceGroupIdToCiBuilds < ActiveRecord::Migration[5.2]
DOWNTIME = false
+ # rubocop:disable Migration/AddColumnsToWideTables
def up
unless column_exists?(:ci_builds, :resource_group_id)
add_column :ci_builds, :resource_group_id, :bigint
@@ -12,6 +13,7 @@ class AddResourceGroupIdToCiBuilds < ActiveRecord::Migration[5.2]
add_column :ci_builds, :waiting_for_resource_at, :datetime_with_timezone
end
end
+ # rubocop:enable Migration/AddColumnsToWideTables
def down
if column_exists?(:ci_builds, :resource_group_id)
diff --git a/db/migrate/20191208110214_add_suggestion_commit_message_to_projects.rb b/db/migrate/20191208110214_add_suggestion_commit_message_to_projects.rb
index c4344cf212c..cb897edde8e 100644
--- a/db/migrate/20191208110214_add_suggestion_commit_message_to_projects.rb
+++ b/db/migrate/20191208110214_add_suggestion_commit_message_to_projects.rb
@@ -4,6 +4,6 @@ class AddSuggestionCommitMessageToProjects < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
- add_column :projects, :suggestion_commit_message, :string, limit: 255
+ add_column :projects, :suggestion_commit_message, :string, limit: 255 # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20191223124940_add_scheduling_type_to_ci_builds.rb b/db/migrate/20191223124940_add_scheduling_type_to_ci_builds.rb
index 0cb42cdc328..bb849aa8a95 100644
--- a/db/migrate/20191223124940_add_scheduling_type_to_ci_builds.rb
+++ b/db/migrate/20191223124940_add_scheduling_type_to_ci_builds.rb
@@ -6,6 +6,6 @@ class AddSchedulingTypeToCiBuilds < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
- add_column :ci_builds, :scheduling_type, :integer, limit: 2
+ add_column :ci_builds, :scheduling_type, :integer, limit: 2 # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20200103195205_add_autoclose_referenced_issues_to_projects.rb b/db/migrate/20200103195205_add_autoclose_referenced_issues_to_projects.rb
index ac1aa2276fc..db473434205 100644
--- a/db/migrate/20200103195205_add_autoclose_referenced_issues_to_projects.rb
+++ b/db/migrate/20200103195205_add_autoclose_referenced_issues_to_projects.rb
@@ -4,6 +4,6 @@ class AddAutocloseReferencedIssuesToProjects < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
- add_column :projects, :autoclose_referenced_issues, :boolean
+ add_column :projects, :autoclose_referenced_issues, :boolean # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20200304085423_add_user_type.rb b/db/migrate/20200304085423_add_user_type.rb
index 355a16897f4..3c20f2d26d8 100644
--- a/db/migrate/20200304085423_add_user_type.rb
+++ b/db/migrate/20200304085423_add_user_type.rb
@@ -7,7 +7,7 @@ class AddUserType < ActiveRecord::Migration[6.0]
def up
with_lock_retries do
- add_column :users, :user_type, :integer, limit: 2
+ add_column :users, :user_type, :integer, limit: 2 # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/post_migrate/20190424134256_drop_projects_ci_id.rb b/db/post_migrate/20190424134256_drop_projects_ci_id.rb
index 44e8f316393..223e9fd4a94 100644
--- a/db/post_migrate/20190424134256_drop_projects_ci_id.rb
+++ b/db/post_migrate/20190424134256_drop_projects_ci_id.rb
@@ -23,7 +23,7 @@ class DropProjectsCiId < ActiveRecord::Migration[5.1]
def down
unless column_exists?(:projects, :ci_id)
- add_column :projects, :ci_id, :integer
+ add_column :projects, :ci_id, :integer # rubocop:disable Migration/AddColumnsToWideTables
end
unless index_exists?(:projects, :ci_id)
diff --git a/db/post_migrate/20190511144331_remove_users_support_type.rb b/db/post_migrate/20190511144331_remove_users_support_type.rb
index 32df33432b9..e72fbb229b8 100644
--- a/db/post_migrate/20190511144331_remove_users_support_type.rb
+++ b/db/post_migrate/20190511144331_remove_users_support_type.rb
@@ -17,7 +17,7 @@ class RemoveUsersSupportType < ActiveRecord::Migration[5.1]
end
def down
- add_column :users, :support_bot, :boolean
+ add_column :users, :support_bot, :boolean # rubocop:disable Migration/AddColumnsToWideTables
add_concurrent_index :users, :support_bot
add_concurrent_index :users, :state,
diff --git a/db/post_migrate/20191015154408_drop_merge_requests_require_code_owner_approval_from_projects.rb b/db/post_migrate/20191015154408_drop_merge_requests_require_code_owner_approval_from_projects.rb
index a1d763b7ed1..f31471c2891 100644
--- a/db/post_migrate/20191015154408_drop_merge_requests_require_code_owner_approval_from_projects.rb
+++ b/db/post_migrate/20191015154408_drop_merge_requests_require_code_owner_approval_from_projects.rb
@@ -15,7 +15,7 @@ class DropMergeRequestsRequireCodeOwnerApprovalFromProjects < ActiveRecord::Migr
end
def down
- add_column :projects, :merge_requests_require_code_owner_approval, :boolean
+ add_column :projects, :merge_requests_require_code_owner_approval, :boolean # rubocop:disable Migration/AddColumnsToWideTables
add_concurrent_index(
:projects,
diff --git a/doc/administration/troubleshooting/log_parsing.md b/doc/administration/troubleshooting/log_parsing.md
new file mode 100644
index 00000000000..b882595ea4a
--- /dev/null
+++ b/doc/administration/troubleshooting/log_parsing.md
@@ -0,0 +1,152 @@
+# Parsing GitLab logs with `jq`
+
+We recommend using log aggregation and search tools like Kibana and Splunk whenever possible,
+but if they are not available you can still quickly parse
+[GitLab logs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26311) in JSON format
+(the default since GitLab 12.0) using [`jq`](https://stedolan.github.io/jq/).
+
+## What is JQ?
+
+As noted in its [manual](https://stedolan.github.io/jq/manual), jq is a command-line JSON processor. The following examples
+include use cases targeted for parsing GitLab log files.
+
+## Parsing Logs
+
+### General Commands
+
+#### Pipe colorized `jq` output into `less`
+
+```sh
+jq . <FILE> -C | less -R
+```
+
+#### Search for a term and pretty-print all matching lines
+
+```sh
+grep <TERM> <FILE> | jq .
+```
+
+#### Skip invalid lines of JSON
+
+```sh
+jq -cR 'fromjson?' file.json | jq <COMMAND>
+```
+
+By default `jq` will error out when it encounters a line that is not valid JSON.
+This skips over all invalid lines and parses the rest.
+
+### Parsing `production_json.log` and `api_json.log`
+
+#### Find all requests with a 5XX status code
+
+```sh
+jq 'select(status >= 500)' <FILE>
+```
+
+#### Top 10 slowest requests
+
+```sh
+jq -s 'sort_by(-.duration) | limit(10; .[])' <FILE>
+```
+
+#### Find and pretty print all requests related to a project
+
+```sh
+grep <PROJECT_NAME> <FILE> | jq .
+```
+
+#### Find all requests with a total duration > 5 seconds
+
+```sh
+jq 'select(.duration > 5000)' <FILE>
+```
+
+#### Find all project requests with more than 5 rugged calls
+
+```sh
+grep <PROJECT_NAME> <FILE> | jq 'select(.rugged_calls > 5)'
+```
+
+#### Find all requests with a Gitaly duration > 10 seconds
+
+```sh
+jq 'select(.gitaly_duration > 10000)' <FILE>
+```
+
+#### Find all requests with a queue duration > 10 seconds
+
+```sh
+jq 'select(.queue_duration > 10000)' <FILE>
+```
+
+#### Top 10 requests by # of Gitaly calls
+
+```sh
+jq -s 'map(select(.gitaly_calls != null)) | sort_by(-.gitaly_calls) | limit(10; .[])' <FILE>
+```
+
+### Parsing `production_json.log`
+
+#### Print the top three controller methods by request volume and their three longest durations
+
+```sh
+jq -s -r 'group_by(.controller+.action) | sort_by(-length) | limit(3; .[]) | sort_by(-.duration) | "CT: \(length)\tMETHOD: \(.[0].controller)#\(.[0].action)\tDURS: \(.[0].duration), \(.[1].duration), \(.[2].duration)"' production_json.log
+```
+
+**Example output**
+
+```plaintext
+CT: 2721 METHOD: SessionsController#new DURS: 844.06, 713.81, 704.66
+CT: 2435 METHOD: MetricsController#index DURS: 299.29, 284.01, 158.57
+CT: 1328 METHOD: Projects::NotesController#index DURS: 403.99, 386.29, 384.39
+```
+
+### Parsing `api_json.log`
+
+#### Print top three routes with request count and their three longest durations
+
+```sh
+jq -s -r 'group_by(.route) | sort_by(-length) | limit(3; .[]) | sort_by(-.duration) | "CT: \(length)\tROUTE: \(.[0].route)\tDURS: \(.[0].duration), \(.[1].duration), \(.[2].duration)"' api_json.log
+```
+
+**Example output**
+
+```plaintext
+CT: 2472 ROUTE: /api/:version/internal/allowed DURS: 56402.65, 38411.43, 19500.41
+CT: 297 ROUTE: /api/:version/projects/:id/repository/tags DURS: 731.39, 685.57, 480.86
+CT: 190 ROUTE: /api/:version/projects/:id/repository/commits DURS: 1079.02, 979.68, 958.21
+```
+
+### Parsing `gitaly/current`
+
+#### Find all Gitaly requests sent from web UI
+
+```sh
+jq 'select(."grpc.meta.client_name" == "gitlab-web")' current
+```
+
+#### Find all failed Gitaly requests
+
+```sh
+jq 'select(."grpc.code" != null and ."grpc.code" != "OK")' current
+```
+
+#### Find all requests that took longer than 30 seconds
+
+```sh
+jq 'select(."grpc.time_ms" > 30000)' current
+```
+
+#### Print top three projects by request volume and their three longest durations
+
+```sh
+jq -s -r 'map(select(."grpc.request.glProjectPath" != null and ."grpc.request.glProjectPath" != "" and ."grpc.time_ms" != null)) | group_by(."grpc.request.glProjectPath") | sort_by(-length) | limit(3; .[]) | sort_by(-."grpc.time_ms") | "CT: \(length)\tPROJECT: \(.[0]."grpc.request.glProjectPath")\tDURS: \(.[0]."grpc.time_ms"), \(.[1]."grpc.time_ms"), \(.[2]."grpc.time_ms")"' current
+```
+
+**Example output**
+
+```plaintext
+CT: 635 PROJECT: groupA/project1 DURS: 4292.269, 4228.853, 2885.548
+CT: 462 PROJECT: groupB/project5 DURS: 4368.981, 3623.553, 361.399
+CT: 455 PROJECT: groupC/project7 DURS: 387.295, 381.874, 373.988
+```
diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md
index 3c828ef1726..ed46876619d 100644
--- a/doc/install/aws/index.md
+++ b/doc/install/aws/index.md
@@ -115,12 +115,12 @@ RDS instances as well:
1. Follow the same steps to create all subnets:
- | Name tag | Type | Availability Zone | CIDR block |
- | ------------------------- | ------- | ----------------- | ---------- |
- | `gitlab-public-10.0.0.0` | public | `us-west-2a` | `10.0.0.0` |
- | `gitlab-private-10.0.1.0` | private | `us-west-2a` | `10.0.1.0` |
- | `gitlab-public-10.0.2.0` | public | `us-west-2b` | `10.0.2.0` |
- | `gitlab-private-10.0.3.0` | private | `us-west-2b` | `10.0.3.0` |
+ | Name tag | Type | Availability Zone | CIDR block |
+ | ------------------------- | ------- | ----------------- | ------------- |
+ | `gitlab-public-10.0.0.0` | public | `us-west-2a` | `10.0.0.0/24` |
+ | `gitlab-private-10.0.1.0` | private | `us-west-2a` | `10.0.1.0/24` |
+ | `gitlab-public-10.0.2.0` | public | `us-west-2b` | `10.0.2.0/24` |
+ | `gitlab-private-10.0.3.0` | private | `us-west-2b` | `10.0.3.0/24` |
### Create NAT Gateways
diff --git a/doc/user/project/integrations/img/prometheus_dashboard_bar_chart_panel_type_v12.10.png b/doc/user/project/integrations/img/prometheus_dashboard_bar_chart_panel_type_v12.10.png
new file mode 100644
index 00000000000..593e31477f4
--- /dev/null
+++ b/doc/user/project/integrations/img/prometheus_dashboard_bar_chart_panel_type_v12.10.png
Binary files differ
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index 1ff58930a61..230b4a379b1 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -434,6 +434,35 @@ Note the following properties:
![anomaly panel type](img/prometheus_dashboard_anomaly_panel_type.png)
+##### Bar chart
+
+To add a bar chart to a dashboard, look at the following sample dashboard file:
+
+```yaml
+dashboard: 'Dashboard Title'
+panel_groups:
+ - group: 'Group title'
+ panels:
+ - type: bar
+ title: "Http Handlers"
+ x_label: 'Response Size'
+ y_axis:
+ name: "Handlers"
+ metrics:
+ - id: prometheus_http_response_size_bytes_bucket
+ query_range: "sum(increase(prometheus_http_response_size_bytes_bucket[1d])) by (handler)"
+ unit: 'Bytes'
+```
+
+Note the following properties:
+
+| Property | Type | Required | Description |
+| ------ | ------ | ------ | ------ |
+| `type` | string | yes | Type of panel to be rendered. For bar chart types, set to `bar` |
+| `query_range` | yes | yes | For bar chart, you must use a [range query]
+
+![bar chart panel type](img/prometheus_dashboard_bar_chart_panel_type_v12.10.png)
+
##### Column chart
To add a column panel type to a dashboard, look at the following sample dashboard file:
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 14cd6a7a2d1..49c1f32affc 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -9723,6 +9723,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|Something went wrong while obtaining Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
+msgstr ""
+
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
@@ -24067,7 +24070,7 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
-msgid "is not allowed for sign-up"
+msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
msgid "is not an email you own"
diff --git a/package.json b/package.json
index 225c8e7817b..b3c01541d0e 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,7 @@
"@gitlab/ui": "^10.0.1",
"@gitlab/visual-review-tools": "1.5.1",
"@sentry/browser": "^5.10.2",
- "@sourcegraph/code-host-integration": "0.0.33",
+ "@sourcegraph/code-host-integration": "0.0.34",
"apollo-cache-inmemory": "^1.6.3",
"apollo-client": "^2.6.4",
"apollo-link": "^1.2.11",
diff --git a/rubocop/cop/migration/add_columns_to_wide_tables.rb b/rubocop/cop/migration/add_columns_to_wide_tables.rb
new file mode 100644
index 00000000000..4618e4ae890
--- /dev/null
+++ b/rubocop/cop/migration/add_columns_to_wide_tables.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require_relative '../../migration_helpers'
+
+module RuboCop
+ module Cop
+ module Migration
+ # Cop that prevents adding columns to wide tables.
+ class AddColumnsToWideTables < RuboCop::Cop::Cop
+ include MigrationHelpers
+
+ MSG = '`%s` is a wide table with several columns, addig more should be avoided unless absolutely necessary.' \
+ ' Consider storing the column in a different table or creating a new one.'.freeze
+
+ BLACKLISTED_METHODS = %i[
+ add_column
+ add_column_with_default
+ add_reference
+ add_timestamps_with_timezone
+ ].freeze
+
+ def on_send(node)
+ return unless in_migration?(node)
+
+ method_name = node.children[1]
+ table_name = node.children[2]
+
+ return unless offense?(method_name, table_name)
+
+ add_offense(node, location: :selector, message: format(MSG, table_name.value))
+ end
+
+ private
+
+ def offense?(method_name, table_name)
+ wide_table?(table_name) &&
+ BLACKLISTED_METHODS.include?(method_name)
+ end
+
+ def wide_table?(table_name)
+ table_name && table_name.type == :sym &&
+ WIDE_TABLES.include?(table_name.value)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/migration_helpers.rb b/rubocop/migration_helpers.rb
index b5edb502d4c..5fa6f8c2a2c 100644
--- a/rubocop/migration_helpers.rb
+++ b/rubocop/migration_helpers.rb
@@ -6,7 +6,7 @@ module RuboCop
plan_limits
].freeze
- # Blacklisted table due to:
+ # Blacklisted tables due to:
# - size in GB (>= 10 GB on GitLab.com as of 02/2020)
# - number of records
BLACKLISTED_TABLES = %i[
@@ -44,6 +44,15 @@ module RuboCop
web_hook_logs
].freeze
+ # Blacklisted tables due to:
+ # - number of columns (> 50 on GitLab.com as of 03/2020)
+ # - number of records
+ WIDE_TABLES = %i[
+ users
+ projects
+ ci_builds
+ ].freeze
+
# Returns true if the given node originated from the db/migrate directory.
def in_migration?(node)
dirname(node).end_with?('db/migrate', 'db/geo/migrate') || in_post_deployment_migration?(node)
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index 9b956dee089..28a238a5423 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -72,6 +72,21 @@ describe 'Projects > Settings > Repository settings' do
expect(project.remote_mirrors.first.only_protected_branches).to eq(true)
end
+ it 'creates a push mirror that keeps divergent refs', :js do
+ select_direction
+
+ fill_in 'url', with: 'ssh://user@localhost/project.git'
+ fill_in 'Password', with: 'password'
+ check 'Keep divergent refs'
+
+ Sidekiq::Testing.fake! do
+ click_button 'Mirror repository'
+ end
+
+ expect(page).to have_content('Mirroring settings were successfully updated')
+ expect(project.reload.remote_mirrors.first.keep_divergent_refs).to eq(true)
+ end
+
it 'generates an SSH public key on submission', :js do
fill_in 'url', with: 'ssh://user@localhost/project.git'
select 'SSH public key', from: 'Authentication method'
@@ -110,6 +125,20 @@ describe 'Projects > Settings > Repository settings' do
end
end
+ # Removal: https://gitlab.com/gitlab-org/gitlab/-/issues/208828
+ context 'with the `keep_divergent_refs` feature flag disabled' do
+ before do
+ stub_feature_flags(keep_divergent_refs: { enabled: false, thing: project })
+ end
+
+ it 'hides the "Keep divergent refs" option' do
+ visit project_settings_repository_path(project)
+
+ expect(page).not_to have_selector('#keep_divergent_refs')
+ expect(page).not_to have_text('Keep divergent refs')
+ end
+ end
+
context 'repository cleanup settings' do
let(:object_map_file) { Rails.root.join('spec', 'fixtures', 'bfg_object_map.txt') }
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index b7abcb31321..608e3a6e938 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -529,7 +529,7 @@ describe User, :do_not_mock_admin_mode do
user = build(:user, email: 'info@gitlab.com')
expect(user).not_to be_valid
- expect(user.errors.messages[:email].first).to eq(_('is not allowed for sign-up'))
+ expect(user.errors.messages[:email].first).to eq(_('is not allowed. Try again with a different email address, or contact your GitLab admin.'))
end
it 'does accept a valid email address' do
diff --git a/spec/presenters/pages_domain_presenter_spec.rb b/spec/presenters/pages_domain_presenter_spec.rb
new file mode 100644
index 00000000000..1cae3a8c9be
--- /dev/null
+++ b/spec/presenters/pages_domain_presenter_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe PagesDomainPresenter do
+ using RSpec::Parameterized::TableSyntax
+ include LetsEncryptHelpers
+
+ let(:presenter) { Gitlab::View::Presenter::Factory.new(domain).fabricate! }
+
+ describe 'needs_validation?' do
+ where(:pages_verification_enabled, :traits, :expected) do
+ false | :unverified | false
+ false | [] | false
+ true | :unverified | true
+ true | [] | false
+ end
+
+ with_them do
+ before do
+ stub_application_setting(pages_domain_verification_enabled: pages_verification_enabled)
+ end
+
+ let(:domain) { create(:pages_domain, *traits) }
+
+ it { expect(presenter.needs_verification?).to eq(expected) }
+ end
+ end
+
+ describe 'show_auto_ssl_failed_warning?' do
+ subject { presenter.show_auto_ssl_failed_warning? }
+
+ let(:domain) { create(:pages_domain) }
+
+ before do
+ stub_lets_encrypt_settings
+ end
+
+ it { is_expected.to eq(false) }
+
+ context "when we failed to obtain Let's Encrypt's certificate" do
+ before do
+ domain.update!(auto_ssl_failed: true)
+ end
+
+ it { is_expected.to eq(true) }
+
+ context 'when lets_encrypt_error feature flag is disabled' do
+ before do
+ stub_feature_flags(pages_letsencrypt_errors: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+
+ context "when Let's Encrypt integration is disabled" do
+ before do
+ allow(::Gitlab::LetsEncrypt).to receive(:enabled?).and_return false
+ end
+
+ it { is_expected.to eq(false) }
+ end
+
+ context "when domain is unverified" do
+ before do
+ domain.update!(verified_at: nil)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+ end
+end
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index ff002469e3c..61599f0876f 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -313,3 +313,34 @@ describe HealthCheckController, 'routing' do
expect(get('/health_check/email')).to route_to('health_check#index', checks: 'email')
end
end
+
+describe InvitesController, 'routing' do
+ let_it_be(:member) { create(:project_member, :invited) }
+
+ it 'to #show' do
+ expect(get("/-/invites/#{member.invite_token}")).to route_to('invites#show', id: member.invite_token)
+ end
+
+ it 'to legacy route' do
+ expect(get("/invites/#{member.invite_token}")).to route_to('invites#show', id: member.invite_token)
+ end
+end
+
+describe AbuseReportsController, 'routing' do
+ let_it_be(:user) { create(:user) }
+
+ it 'to #new' do
+ expect(get("/-/abuse_reports/new?user_id=#{user.id}")).to route_to('abuse_reports#new', user_id: user.id.to_s)
+ end
+
+ it 'to legacy route' do
+ expect(get("/abuse_reports/new?user_id=#{user.id}")).to route_to('abuse_reports#new', user_id: user.id.to_s)
+ end
+end
+
+describe SentNotificationsController, 'routing' do
+ it 'to #unsubscribe' do
+ expect(get("/-/sent_notifications/4bee17d4a63ed60cf5db53417e9aeb4c/unsubscribe"))
+ .to route_to('sent_notifications#unsubscribe', id: '4bee17d4a63ed60cf5db53417e9aeb4c')
+ end
+end
diff --git a/spec/rubocop/cop/migration/add_columns_to_wide_tables_spec.rb b/spec/rubocop/cop/migration/add_columns_to_wide_tables_spec.rb
new file mode 100644
index 00000000000..f0c64740e63
--- /dev/null
+++ b/spec/rubocop/cop/migration/add_columns_to_wide_tables_spec.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'rubocop'
+
+require_relative '../../../../rubocop/cop/migration/add_columns_to_wide_tables'
+
+describe RuboCop::Cop::Migration::AddColumnsToWideTables do
+ include CopHelper
+
+ let(:cop) { described_class.new }
+
+ context 'outside of a migration' do
+ it 'does not register any offenses' do
+ expect_no_offenses(<<~RUBY)
+ def up
+ add_column(:users, :another_column, :string)
+ end
+ RUBY
+ end
+ end
+
+ context 'in a migration' do
+ before do
+ allow(cop).to receive(:in_migration?).and_return(true)
+ end
+
+ context 'with wide tables' do
+ it 'registers an offense when adding a column to a wide table' do
+ offense = '`projects` is a wide table with several columns, addig more should be avoided unless absolutely necessary. Consider storing the column in a different table or creating a new one.'
+
+ expect_offense(<<~RUBY)
+ def up
+ add_column(:projects, :another_column, :integer)
+ ^^^^^^^^^^ #{offense}
+ end
+ RUBY
+ end
+
+ it 'registers an offense when adding a column with default to a wide table' do
+ offense = '`users` is a wide table with several columns, addig more should be avoided unless absolutely necessary. Consider storing the column in a different table or creating a new one.'
+
+ expect_offense(<<~RUBY)
+ def up
+ add_column_with_default(:users, :another_column, :boolean, default: false)
+ ^^^^^^^^^^^^^^^^^^^^^^^ #{offense}
+ end
+ RUBY
+ end
+
+ it 'registers an offense when adding a reference' do
+ offense = '`ci_builds` is a wide table with several columns, addig more should be avoided unless absolutely necessary. Consider storing the column in a different table or creating a new one.'
+
+ expect_offense(<<~RUBY)
+ def up
+ add_reference(:ci_builds, :issue, :boolean, index: true)
+ ^^^^^^^^^^^^^ #{offense}
+ end
+ RUBY
+ end
+
+ it 'registers an offense when adding timestamps' do
+ offense = '`projects` is a wide table with several columns, addig more should be avoided unless absolutely necessary. Consider storing the column in a different table or creating a new one.'
+
+ expect_offense(<<~RUBY)
+ def up
+ add_timestamps_with_timezone(:projects, null: false)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{offense}
+ end
+ RUBY
+ end
+
+ it 'register no offense when using other method' do
+ expect_no_offenses(<<~RUBY)
+ def up
+ add_concurrent_index(:projects, :new_index)
+ end
+ RUBY
+ end
+ end
+
+ context 'with a regular table' do
+ it 'registers no offense for notes' do
+ expect_no_offenses(<<~RUBY)
+ def up
+ add_column(:notes, :another_column, :boolean)
+ end
+ RUBY
+ end
+ end
+ end
+end
diff --git a/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb b/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb
index 6f7250037cd..b386159541a 100644
--- a/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb
+++ b/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb
@@ -29,7 +29,7 @@ describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memory_stor
end
context 'user does not have push right to repository' do
- it_behaves_like 'misconfigured dashboard service response', :forbidden, %q(You are not allowed to push into this branch. Create another branch or open a merge request.)
+ it_behaves_like 'misconfigured dashboard service response with stepable', :forbidden, 'You are not allowed to push into this branch. Create another branch or open a merge request.'
end
context 'with rights to push to the repository' do
@@ -40,19 +40,19 @@ describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memory_stor
context 'wrong target file extension' do
let(:file_name) { 'custom_dashboard.txt' }
- it_behaves_like 'misconfigured dashboard service response', :bad_request, 'The file name should have a .yml extension'
+ it_behaves_like 'misconfigured dashboard service response with stepable', :bad_request, 'The file name should have a .yml extension'
end
context 'wrong source dashboard file' do
let(:dashboard) { 'config/prometheus/common_metrics_123.yml' }
- it_behaves_like 'misconfigured dashboard service response', :not_found, 'Not found.'
+ it_behaves_like 'misconfigured dashboard service response with stepable', :not_found, 'Not found.'
end
context 'path traversal attack attempt' do
let(:dashboard) { 'config/prometheus/../database.yml' }
- it_behaves_like 'misconfigured dashboard service response', :not_found, 'Not found.'
+ it_behaves_like 'misconfigured dashboard service response with stepable', :not_found, 'Not found.'
end
context 'path traversal attack attempt on target file' do
@@ -92,7 +92,7 @@ describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memory_stor
project.repository.add_branch(user, branch, 'master')
end
- it_behaves_like 'misconfigured dashboard service response', :bad_request, "There was an error creating the dashboard, branch named: existing_branch already exists."
+ it_behaves_like 'misconfigured dashboard service response with stepable', :bad_request, 'There was an error creating the dashboard, branch named: existing_branch already exists.'
# temporary not available function for first iteration
# follow up issue https://gitlab.com/gitlab-org/gitlab/issues/196237 which
@@ -111,7 +111,7 @@ describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memory_stor
context 'blank branch name' do
let(:branch) { '' }
- it_behaves_like 'misconfigured dashboard service response', :bad_request, 'There was an error creating the dashboard, branch name is invalid.'
+ it_behaves_like 'misconfigured dashboard service response with stepable', :bad_request, 'There was an error creating the dashboard, branch name is invalid.'
end
context 'dashboard file already exists' do
@@ -129,7 +129,7 @@ describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memory_stor
).execute
end
- it_behaves_like 'misconfigured dashboard service response', :bad_request, "A file with 'custom_dashboard.yml' already exists in custom_dashboard branch"
+ it_behaves_like 'misconfigured dashboard service response with stepable', :bad_request, "A file with 'custom_dashboard.yml' already exists in custom_dashboard branch"
end
it 'extends dashboard template path to absolute url' do
diff --git a/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb b/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb
index 48e4b4a18fd..bcd69b9e4f6 100644
--- a/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb
+++ b/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb
@@ -107,3 +107,14 @@ RSpec.shared_examples 'valid dashboard update process' do
service_call
end
end
+
+RSpec.shared_examples 'misconfigured dashboard service response with stepable' do |status_code, message = nil|
+ it 'returns an appropriate message and status code', :aggregate_failures do
+ result = service_call
+
+ expect(result.keys).to contain_exactly(:message, :http_status, :status, :last_step)
+ expect(result[:status]).to eq(:error)
+ expect(result[:http_status]).to eq(status_code)
+ expect(result[:message]).to eq(message) if message
+ end
+end
diff --git a/spec/views/projects/pages/show.html.haml_spec.rb b/spec/views/projects/pages/show.html.haml_spec.rb
new file mode 100644
index 00000000000..80410e7bc32
--- /dev/null
+++ b/spec/views/projects/pages/show.html.haml_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'projects/pages/show' do
+ include LetsEncryptHelpers
+
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user) }
+ let(:domain) { create(:pages_domain, project: project) }
+
+ before do
+ allow(project).to receive(:pages_deployed?).and_return(true)
+ stub_pages_setting(external_https: true)
+ stub_lets_encrypt_settings
+ project.add_maintainer(user)
+
+ assign(:project, project)
+ allow(view).to receive(:current_user).and_return(user)
+ assign(:domains, [domain])
+ end
+
+ describe 'validation warning' do
+ let(:warning_message) do
+ "#{domain.domain} is not verified. To learn how to verify ownership, "\
+ "visit your domain details."
+ end
+
+ it "doesn't show auto ssl error warning" do
+ render
+
+ expect(rendered).not_to have_content(warning_message)
+ end
+
+ context "when domain is not verified" do
+ before do
+ domain.update!(verified_at: nil)
+ end
+
+ it 'shows auto ssl error warning' do
+ render
+
+ expect(rendered).to have_content(warning_message)
+ end
+ end
+ end
+
+ describe "warning about failed Let's Encrypt" do
+ let(:error_message) do
+ "Something went wrong while obtaining Let's Encrypt certificate for #{domain.domain}. "\
+ "To retry visit your domain details."
+ end
+
+ it "doesn't show auto ssl error warning" do
+ render
+
+ expect(rendered).not_to have_content(error_message)
+ end
+
+ context "when we failed to obtain Let's Encrypt's certificate" do
+ before do
+ domain.update!(auto_ssl_failed: true)
+ end
+
+ it 'shows auto ssl error warning' do
+ render
+
+ expect(rendered).to have_content(error_message)
+ end
+ end
+ end
+end
diff --git a/yarn.lock b/yarn.lock
index 4886a3651d1..d78aee490e2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1036,10 +1036,10 @@
"@sentry/types" "5.10.0"
tslib "^1.9.3"
-"@sourcegraph/code-host-integration@0.0.33":
- version "0.0.33"
- resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.33.tgz#133f11535be0cc937fbadc6a6951ee9fd21fbe1d"
- integrity sha512-J49ljHsSIe8KD5+ke9C3ugGO9T6R2M96miiGEZFRHJQ7FXyKi/zP5N4BFVweHjE+b15BLSicoaAnnyg4nhIBIw==
+"@sourcegraph/code-host-integration@0.0.34":
+ version "0.0.34"
+ resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.34.tgz#c8f94854d64fe035926bbda7bed3a538a7259d03"
+ integrity sha512-TAa5kU/zPb9PfB4HIhaEDhKKdW5Fx9YVx9WWMOwz9elD0y9FZoAXDO1o4Pz1cm1IP/VZwd8csypAWgfxsAmfzw==
"@types/anymatch@*":
version "1.3.0"