Merge pull request #1519 from ClearlyClaire/glitch-soc/merge-upstream

Merge upstream changes
This commit is contained in:
Claire 2021-04-06 11:17:52 +02:00 committed by GitHub
commit df326b8b5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 245 additions and 51 deletions

View File

@ -54,7 +54,6 @@ gem 'fast_blank', '~> 1.0'
gem 'fastimage' gem 'fastimage'
gem 'hiredis', '~> 0.6' gem 'hiredis', '~> 0.6'
gem 'redis-namespace', '~> 1.8' gem 'redis-namespace', '~> 1.8'
gem 'health_check', git: 'https://github.com/ianheggie/health_check', ref: '0b799ead604f900ed50685e9b2d469cd2befba5b'
gem 'htmlentities', '~> 4.3' gem 'htmlentities', '~> 4.3'
gem 'http', '~> 4.4' gem 'http', '~> 4.4'
gem 'http_accept_language', '~> 2.1' gem 'http_accept_language', '~> 2.1'

View File

@ -21,14 +21,6 @@ GIT
sidekiq (>= 3.5) sidekiq (>= 3.5)
statsd-ruby (~> 1.4, >= 1.4.0) statsd-ruby (~> 1.4, >= 1.4.0)
GIT
remote: https://github.com/ianheggie/health_check
revision: 0b799ead604f900ed50685e9b2d469cd2befba5b
ref: 0b799ead604f900ed50685e9b2d469cd2befba5b
specs:
health_check (4.0.0.pre)
rails (>= 4.0)
GIT GIT
remote: https://github.com/nsommer/pluck_each remote: https://github.com/nsommer/pluck_each
revision: 73be0947c52fc54bf6d7085378db008358aac5eb revision: 73be0947c52fc54bf6d7085378db008358aac5eb
@ -567,7 +559,7 @@ GEM
rspec-support (3.10.2) rspec-support (3.10.2)
rspec_junit_formatter (0.4.1) rspec_junit_formatter (0.4.1)
rspec-core (>= 2, < 4, != 2.12.0) rspec-core (>= 2, < 4, != 2.12.0)
rubocop (1.12.0) rubocop (1.12.1)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 3.0.0.0) parser (>= 3.0.0.0)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
@ -756,7 +748,6 @@ DEPENDENCIES
fog-openstack (~> 0.3) fog-openstack (~> 0.3)
fuubar (~> 2.5) fuubar (~> 2.5)
hamlit-rails (~> 0.2) hamlit-rails (~> 0.2)
health_check!
hiredis (~> 0.6) hiredis (~> 0.6)
htmlentities (~> 4.3) htmlentities (~> 4.3)
http (~> 4.4) http (~> 4.4)

View File

@ -3,13 +3,8 @@ require 'sidekiq/api'
module Admin module Admin
class DashboardController < BaseController class DashboardController < BaseController
SIDEKIQ_QUEUES = %w(default push mailers pull scheduler).freeze
def index def index
missing_queues = Sidekiq::ProcessSet.new.reduce(SIDEKIQ_QUEUES) { |queues, process| queues - process['queues'] } @system_checks = Admin::SystemCheck.perform
flash.now[:alert] = I18n.t('admin.dashboard.misconfigured_sidekiq_alert', queues: missing_queues.join(', ')) unless missing_queues.empty?
@users_count = User.count @users_count = User.count
@pending_users_count = User.pending.count @pending_users_count = User.pending.count
@registrations_week = Redis.current.get("activity:accounts:local:#{current_week}") || 0 @registrations_week = Redis.current.get("activity:accounts:local:#{current_week}") || 0

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class HealthController < ActionController::Base
def show
render plain: 'OK'
end
end

View File

@ -90,7 +90,11 @@ class ColumnsArea extends ImmutablePureComponent {
} }
if (this.mediaQuery) { if (this.mediaQuery) {
if (this.mediaQuery.addEventListener) {
this.mediaQuery.addEventListener('change', this.handleLayoutChange); this.mediaQuery.addEventListener('change', this.handleLayoutChange);
} else {
this.mediaQuery.addListener(this.handleLayoutChange);
}
this.setState({ renderComposePanel: !this.mediaQuery.matches }); this.setState({ renderComposePanel: !this.mediaQuery.matches });
} }
@ -125,7 +129,11 @@ class ColumnsArea extends ImmutablePureComponent {
} }
if (this.mediaQuery) { if (this.mediaQuery) {
if (this.mediaQuery.removeEventListener) {
this.mediaQuery.removeEventListener('change', this.handleLayoutChange); this.mediaQuery.removeEventListener('change', this.handleLayoutChange);
} else {
this.mediaQuery.removeListener(this.handleLayouteChange);
}
} }
} }

View File

@ -595,6 +595,12 @@ code {
color: $valid-value-color; color: $valid-value-color;
} }
&.warning {
border: 1px solid rgba($gold-star, 0.5);
background: rgba($gold-star, 0.25);
color: $gold-star;
}
&.alert { &.alert {
border: 1px solid rgba($error-value-color, 0.5); border: 1px solid rgba($error-value-color, 0.5);
background: rgba($error-value-color, 0.1); background: rgba($error-value-color, 0.1);
@ -616,6 +622,19 @@ code {
} }
} }
&.warning a {
font-weight: 700;
color: inherit;
text-decoration: underline;
&:hover,
&:focus,
&:active {
text-decoration: none;
color: inherit;
}
}
p { p {
margin-bottom: 15px; margin-bottom: 15px;
} }
@ -672,6 +691,29 @@ code {
} }
} }
.flash-message-stack {
margin-bottom: 30px;
.flash-message {
border-radius: 0;
margin-bottom: 0;
border-top-width: 0;
&:first-child {
border-radius: 4px 4px 0 0;
border-top-width: 1px;
}
&:last-child {
border-radius: 0 0 4px 4px;
&:first-child {
border-radius: 4px;
}
}
}
}
.form-footer { .form-footer {
margin-top: 30px; margin-top: 30px;
text-align: center; text-align: center;

View File

@ -90,7 +90,11 @@ class ColumnsArea extends ImmutablePureComponent {
} }
if (this.mediaQuery) { if (this.mediaQuery) {
if (this.mediaQuery.addEventListener) {
this.mediaQuery.addEventListener('change', this.handleLayoutChange); this.mediaQuery.addEventListener('change', this.handleLayoutChange);
} else {
this.mediaQuery.addListener(this.handleLayoutChange);
}
this.setState({ renderComposePanel: !this.mediaQuery.matches }); this.setState({ renderComposePanel: !this.mediaQuery.matches });
} }
@ -125,7 +129,11 @@ class ColumnsArea extends ImmutablePureComponent {
} }
if (this.mediaQuery) { if (this.mediaQuery) {
if (this.mediaQuery.removeEventListener) {
this.mediaQuery.removeEventListener('change', this.handleLayoutChange); this.mediaQuery.removeEventListener('change', this.handleLayoutChange);
} else {
this.mediaQuery.removeListener(this.handleLayouteChange);
}
} }
} }

View File

@ -604,6 +604,12 @@ code {
color: $valid-value-color; color: $valid-value-color;
} }
&.warning {
border: 1px solid rgba($gold-star, 0.5);
background: rgba($gold-star, 0.25);
color: $gold-star;
}
&.alert { &.alert {
border: 1px solid rgba($error-value-color, 0.5); border: 1px solid rgba($error-value-color, 0.5);
background: rgba($error-value-color, 0.1); background: rgba($error-value-color, 0.1);
@ -625,6 +631,19 @@ code {
} }
} }
&.warning a {
font-weight: 700;
color: inherit;
text-decoration: underline;
&:hover,
&:focus,
&:active {
text-decoration: none;
color: inherit;
}
}
p { p {
margin-bottom: 15px; margin-bottom: 15px;
} }
@ -681,6 +700,29 @@ code {
} }
} }
.flash-message-stack {
margin-bottom: 30px;
.flash-message {
border-radius: 0;
margin-bottom: 0;
border-top-width: 0;
&:first-child {
border-radius: 4px 4px 0 0;
border-top-width: 1px;
}
&:last-child {
border-radius: 0 0 4px 4px;
&:first-child {
border-radius: 4px;
}
}
}
}
.form-footer { .form-footer {
margin-top: 30px; margin-top: 30px;
text-align: center; text-align: center;

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
class Admin::SystemCheck
ACTIVE_CHECKS = [
Admin::SystemCheck::DatabaseSchemaCheck,
Admin::SystemCheck::SidekiqProcessCheck,
Admin::SystemCheck::RulesCheck,
].freeze
def self.perform
ACTIVE_CHECKS.each_with_object([]) do |klass, arr|
check = klass.new
if check.pass?
arr
else
arr << check.message
end
end
end
end

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class Admin::SystemCheck::BaseCheck
def pass?
raise NotImplementedError
end
def message
raise NotImplementedError
end
end

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class Admin::SystemCheck::DatabaseSchemaCheck < Admin::SystemCheck::BaseCheck
def pass?
!ActiveRecord::Base.connection.migration_context.needs_migration?
end
def message
Admin::SystemCheck::Message.new(:database_schema_check)
end
end

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class Admin::SystemCheck::Message
attr_reader :key, :value, :action
def initialize(key, value = nil, action = nil)
@key = key
@value = value
@action = action
end
end

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
class Admin::SystemCheck::RulesCheck < Admin::SystemCheck::BaseCheck
include RoutingHelper
def pass?
Rule.kept.exists?
end
def message
Admin::SystemCheck::Message.new(:rules_check, nil, admin_rules_path)
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
class Admin::SystemCheck::SidekiqProcessCheck < Admin::SystemCheck::BaseCheck
SIDEKIQ_QUEUES = %w(
default
push
mailers
pull
scheduler
ingress
).freeze
def pass?
missing_queues.empty?
end
def message
Admin::SystemCheck::Message.new(:sidekiq_process_check, missing_queues.join(', '))
end
private
def missing_queues
@missing_queues ||= Sidekiq::ProcessSet.new.reduce(SIDEKIQ_QUEUES) { |queues, process| queues - process['queues'] }
end
end

View File

@ -1,6 +1,14 @@
- content_for :page_title do - content_for :page_title do
= t('admin.dashboard.title') = t('admin.dashboard.title')
- unless @system_checks.empty?
.flash-message-stack
- @system_checks.each do |message|
.flash-message.warning
= t("admin.system_checks.#{message.key}.message_html", message.value ? { value: content_tag(:strong, message.value) } : {})
- if message.action
= link_to t("admin.system_checks.#{message.key}.action"), message.action
.dashboard__counters .dashboard__counters
%div %div
= link_to admin_accounts_url(local: 1, recent: 1) do = link_to admin_accounts_url(local: 1, recent: 1) do

View File

@ -45,5 +45,5 @@
= content_for?(:content) ? yield(:content) : yield = content_for?(:content) ? yield(:content) : yield
.logo-resources .logo-resources
= render file: Rails.root.join('app', 'javascript', 'images', 'logo_transparent.svg') = raw render file: Rails.root.join('app', 'javascript', 'images', 'logo_transparent.svg')
= render file: Rails.root.join('app', 'javascript', 'images', 'logo_full.svg') = raw render file: Rails.root.join('app', 'javascript', 'images', 'logo_full.svg')

View File

@ -25,4 +25,4 @@
= yield = yield
.logo-resources .logo-resources
= render file: Rails.root.join('app', 'javascript', 'images', 'logo_transparent.svg') = raw render file: Rails.root.join('app', 'javascript', 'images', 'logo_transparent.svg')

View File

@ -1,8 +0,0 @@
HealthCheck.setup do |config|
config.uri = 'health'
config.standard_checks = %w(database migrations cache)
config.full_checks = %w(database migrations cache)
config.include_error_in_response_body = false
end

View File

@ -367,7 +367,6 @@ en:
feature_timeline_preview: Timeline preview feature_timeline_preview: Timeline preview
features: Features features: Features
hidden_service: Federation with hidden services hidden_service: Federation with hidden services
misconfigured_sidekiq_alert: 'No Sidekiq process seems to be handling the following queues: %{queues}. Please review your Sidekiq configuration.'
open_reports: open reports open_reports: open reports
pending_tags: hashtags waiting for review pending_tags: hashtags waiting for review
pending_users: users waiting for review pending_users: users waiting for review
@ -661,6 +660,14 @@ en:
no_status_selected: No statuses were changed as none were selected no_status_selected: No statuses were changed as none were selected
title: Account statuses title: Account statuses
with_media: With media with_media: With media
system_checks:
database_schema_check:
message_html: There are pending database migrations. Please run them to ensure the application behaves as expected
rules_check:
action: Manage server rules
message_html: You haven't defined any server rules.
sidekiq_process_check:
message_html: No Sidekiq process running for the %{value} queue(s). Please review your Sidekiq configuration
tags: tags:
accounts_today: Unique uses today accounts_today: Unique uses today
accounts_week: Unique uses this week accounts_week: Unique uses this week

View File

@ -10,7 +10,7 @@ Rails.application.routes.draw do
mount LetterOpenerWeb::Engine, at: 'letter_opener' if Rails.env.development? mount LetterOpenerWeb::Engine, at: 'letter_opener' if Rails.env.development?
health_check_routes get 'health', to: 'health#show'
authenticate :user, lambda { |u| u.admin? } do authenticate :user, lambda { |u| u.admin? } do
mount Sidekiq::Web, at: 'sidekiq', as: :sidekiq mount Sidekiq::Web, at: 'sidekiq', as: :sidekiq

View File

@ -25,7 +25,9 @@ module Mastodon
exit(1) exit(1)
end end
ActiveRecord::Base.configurations[Rails.env]['pool'] = options[:concurrency] + 1 db_config = ActiveRecord::Base.configurations[Rails.env].dup
db_config['pool'] = options[:concurrency] + 1
ActiveRecord::Base.establish_connection(db_config)
progress = create_progress_bar(scope.count) progress = create_progress_bar(scope.count)
pool = Concurrent::FixedThreadPool.new(options[:concurrency]) pool = Concurrent::FixedThreadPool.new(options[:concurrency])

View File

@ -167,7 +167,7 @@
"twitter-text": "3.1.0", "twitter-text": "3.1.0",
"uuid": "^8.3.1", "uuid": "^8.3.1",
"webpack": "^4.46.0", "webpack": "^4.46.0",
"webpack-assets-manifest": "^4.0.1", "webpack-assets-manifest": "^4.0.2",
"webpack-bundle-analyzer": "^4.4.0", "webpack-bundle-analyzer": "^4.4.0",
"webpack-cli": "^3.3.12", "webpack-cli": "^3.3.12",
"webpack-merge": "^5.7.3", "webpack-merge": "^5.7.3",
@ -176,7 +176,7 @@
}, },
"devDependencies": { "devDependencies": {
"@testing-library/jest-dom": "^5.11.10", "@testing-library/jest-dom": "^5.11.10",
"@testing-library/react": "^11.2.5", "@testing-library/react": "^11.2.6",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3", "babel-jest": "^26.6.3",
"eslint": "^7.23.0", "eslint": "^7.23.0",

View File

@ -1,10 +1,10 @@
require 'rails_helper' require 'rails_helper'
describe HealthCheck::HealthCheckController do describe HealthController do
render_views render_views
describe 'GET #show' do describe 'GET #show' do
subject(:response) { get :index, params: { format: :json } } subject(:response) { get :show, params: { format: :json } }
it 'returns the right response' do it 'returns the right response' do
expect(response).to have_http_status 200 expect(response).to have_http_status 200

View File

@ -1405,10 +1405,10 @@
lodash "^4.17.15" lodash "^4.17.15"
redent "^3.0.0" redent "^3.0.0"
"@testing-library/react@^11.2.5": "@testing-library/react@^11.2.6":
version "11.2.5" version "11.2.6"
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-11.2.5.tgz#ae1c36a66c7790ddb6662c416c27863d87818eb9" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-11.2.6.tgz#586a23adc63615985d85be0c903f374dab19200b"
integrity sha512-yEx7oIa/UWLe2F2dqK0FtMF9sJWNXD+2PPtp39BvE0Kh9MJ9Kl0HrZAgEuhUJR+Lx8Di6Xz+rKwSdEPY2UV8ZQ== integrity sha512-TXMCg0jT8xmuU8BkKMtp8l7Z50Ykew5WNX8UoIKTaLFwKkP2+1YDhOLA2Ga3wY4x29jyntk7EWfum0kjlYiSjQ==
dependencies: dependencies:
"@babel/runtime" "^7.12.5" "@babel/runtime" "^7.12.5"
"@testing-library/dom" "^7.28.1" "@testing-library/dom" "^7.28.1"
@ -3696,7 +3696,7 @@ deep-is@^0.1.3, deep-is@~0.1.3:
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
deepmerge@^4.2.2: deepmerge@^4.0, deepmerge@^4.2.2:
version "4.2.2" version "4.2.2"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
@ -6894,7 +6894,7 @@ locate-path@^5.0.0:
dependencies: dependencies:
p-locate "^4.1.0" p-locate "^4.1.0"
lockfile@^1.0.4: lockfile@^1.0:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.4.tgz#07f819d25ae48f87e538e6578b6964a4981a5609" resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.4.tgz#07f819d25ae48f87e538e6578b6964a4981a5609"
integrity sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA== integrity sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==
@ -11213,14 +11213,14 @@ webidl-conversions@^6.1.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
webpack-assets-manifest@^4.0.1: webpack-assets-manifest@^4.0.2:
version "4.0.1" version "4.0.2"
resolved "https://registry.yarnpkg.com/webpack-assets-manifest/-/webpack-assets-manifest-4.0.1.tgz#918989c51a7800be6683aaa27b9f36bcc7a9afdc" resolved "https://registry.yarnpkg.com/webpack-assets-manifest/-/webpack-assets-manifest-4.0.2.tgz#ead6e6dbdcd1c2af45d11a382246fcc79a286372"
integrity sha512-NS7Bx2C3JsEj6a0MB/PPmPOD/BzDYjB3PaKcI7/r2fKXq0PuZ4YtcbZ5Og+q4gkmetGX9v21vejeAlbru/Fvhw== integrity sha512-bBb9PvEGDOCFvW5/t6Yp9MEE0fymNJ0OvEud9nPvQegDbQEUZ/2WTeHnNoALwWMu1x3JHPyqHVYh8SwtYZ/dww==
dependencies: dependencies:
chalk "^4.0" chalk "^4.0"
deepmerge "^4.2.2" deepmerge "^4.0"
lockfile "^1.0.4" lockfile "^1.0"
lodash.escaperegexp "^4.0" lodash.escaperegexp "^4.0"
lodash.get "^4.0" lodash.get "^4.0"
lodash.has "^4.0" lodash.has "^4.0"