5
0
Fork 0
mirror of https://0xacab.org/sutty/sutty synced 2024-05-19 20:30:49 +00:00

Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-9357-2
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed

This commit is contained in:
f 2023-08-22 18:13:10 -03:00
commit 25c6b65bf0
24 changed files with 128 additions and 137 deletions

7
.gitignore vendored
View file

@ -34,12 +34,7 @@
/config/master.key
/config/credentials.yml.enc
/public/packs
/public/packs-test
/public/assets
/public/assets-production
/public/packs
/public/packs-production
/node_modules
/yarn-error.log
yarn-debug.log*
@ -49,8 +44,6 @@ yarn-debug.log*
*.key
*.crt
/public/packs
/public/packs-test
/node_modules
/yarn-error.log
yarn-debug.log*

10
Gemfile
View file

@ -32,6 +32,7 @@ gem 'turbolinks', '~> 5'
gem 'jbuilder', '~> 2.5'
# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
gem 'safely_block', '~> 0.3.0'
gem 'blazer'
gem 'chartkick'
gem 'commonmarker'
@ -64,13 +65,13 @@ gem 'mobility'
gem 'pundit'
gem 'rails-i18n'
gem 'rails_warden'
gem 'redis', require: %w[redis redis/connection/hiredis]
gem 'redis', '~> 4.0', require: %w[redis redis/connection/hiredis]
gem 'redis-rails'
gem 'rollups', git: 'https://github.com/fauno/rollup.git', branch: 'update'
gem 'rubyzip'
gem 'rugged'
gem 'concurrent-ruby-ext'
gem 'sucker_punch'
gem 'que'
gem 'symbol-fstring', require: 'fstring/all'
gem 'terminal-table'
gem 'validates_hostname'
@ -108,8 +109,9 @@ end
group :development, :test do
gem 'derailed_benchmarks'
gem 'pry'
gem 'capybara'
gem 'selenium-webdriver'
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '~> 2.13'
gem 'selenium-webdriver', '~> 4.8.0'
gem 'sqlite3'
end

View file

@ -91,7 +91,7 @@ GEM
ast (2.4.2)
autoprefixer-rails (10.4.13.0)
execjs (~> 2)
bcrypt (3.1.18-x86_64-linux-musl)
bcrypt (3.1.19-x86_64-linux-musl)
bcrypt_pbkdf (1.1.0-x86_64-linux-musl)
benchmark-ips (2.12.0)
bindex (0.8.1-x86_64-linux-musl)
@ -106,24 +106,21 @@ GEM
sassc-rails (>= 2.0.0)
brakeman (5.4.1)
builder (3.2.4)
capybara (3.39.1)
capybara (2.18.0)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (>= 2.0, < 4.0)
chartkick (5.0.2)
climate_control (1.2.0)
coderay (1.1.3)
colorator (1.1.0)
commonmarker (0.23.9-x86_64-linux-musl)
commonmarker (0.23.10-x86_64-linux-musl)
concurrent-ruby (1.2.2)
concurrent-ruby-ext (1.2.2-x86_64-linux-musl)
concurrent-ruby (= 1.2.2)
connection_pool (2.4.1)
crass (1.0.6)
database_cleaner (2.0.2)
database_cleaner-active_record (>= 2, < 3)
@ -156,7 +153,7 @@ GEM
devise_invitable (2.0.8)
actionmailer (>= 5.0)
devise (>= 4.6)
distributed-press-api-client (0.2.3)
distributed-press-api-client (0.2.4)
addressable (~> 2.3, >= 2.3.0)
climate_control
dry-schema
@ -199,6 +196,7 @@ GEM
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
errbase (0.2.2)
erubi (1.12.0)
eventmachine (1.2.7-x86_64-linux-musl)
exception_notification (4.5.0)
@ -227,7 +225,7 @@ GEM
activerecord (>= 6.0, < 8)
ruby2ruby (~> 2.4)
ruby_parser (~> 3.10)
haml (6.1.1-x86_64-linux-musl)
haml (6.1.2-x86_64-linux-musl)
temple (>= 0.8.2)
thor
tilt
@ -255,7 +253,7 @@ GEM
httparty (0.21.0)
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
i18n (1.13.0)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
icalendar (2.8.0)
ice_cube (~> 0.16)
@ -341,13 +339,13 @@ GEM
net-pop
net-smtp
marcel (1.0.2)
matrix (0.4.2)
memory_profiler (1.0.1)
mercenary (0.4.0)
method_source (1.0.0)
mini_histogram (0.3.1)
mini_magick (4.12.0)
mini_mime (1.1.2)
mini_portile2 (2.8.2)
minitest (5.18.0)
mobility (1.2.9)
i18n (>= 0.6.10, < 2)
@ -368,7 +366,8 @@ GEM
njalla-api-client (0.2.0)
dry-schema
httparty (~> 0.18)
nokogiri (1.15.1-x86_64-linux)
nokogiri (1.15.4-x86_64-linux-musl)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
orm_adapter (0.5.0)
pairing_heap (3.0.1)
@ -387,12 +386,13 @@ GEM
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
public_suffix (5.0.1)
puma (6.2.2-x86_64-linux-musl)
public_suffix (5.0.3)
puma (6.3.1-x86_64-linux-musl)
nio4r (~> 2.0)
pundit (2.3.0)
activesupport (>= 3.0.0)
racc (1.6.2-x86_64-linux-musl)
que (2.2.1)
racc (1.7.1-x86_64-linux-musl)
rack (2.2.7)
rack-cors (2.0.1)
rack (>= 2.0.0)
@ -438,8 +438,7 @@ GEM
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
redis (5.0.6)
redis-client (>= 0.9.0)
redis (4.8.1)
redis-actionpack (5.3.0)
actionpack (>= 5, < 8)
redis-rack (>= 2.1.0, < 3)
@ -447,8 +446,6 @@ GEM
redis-activesupport (5.3.0)
activesupport (>= 3, < 8)
redis-store (>= 1.3, < 2)
redis-client (0.14.1)
connection_pool
redis-rack (2.1.4)
rack (>= 2.0.8, < 3)
redis-store (>= 1.2, < 2)
@ -499,7 +496,8 @@ GEM
rubyzip (2.3.2)
rugged (1.6.3-x86_64-linux-musl)
safe_yaml (1.0.6)
safely_block (0.4.0)
safely_block (0.3.0)
errbase (>= 0.1.1)
sassc (2.4.0-x86_64-linux-musl)
ffi (~> 1.9)
sassc-rails (2.1.2)
@ -508,7 +506,7 @@ GEM
sprockets (> 3.0)
sprockets-rails
tilt
selenium-webdriver (4.9.1)
selenium-webdriver (4.8.6)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
@ -528,12 +526,11 @@ GEM
actionpack (>= 5.2)
activesupport (>= 5.2)
sprockets (>= 3.0.0)
sqlite3 (1.6.3-x86_64-linux)
sqlite3 (1.6.3-x86_64-linux-musl)
mini_portile2 (~> 2.8.0)
stackprof (0.2.25-x86_64-linux-musl)
stream (0.5.5)
sucker_punch (3.1.0)
concurrent-ruby (~> 1.0)
sutty-liquid (0.11.10)
sutty-liquid (0.11.11)
fast_blank (~> 1.0)
jekyll (~> 4)
symbol-fstring (1.0.2-x86_64-linux-musl)
@ -573,7 +570,7 @@ GEM
semantic_range (>= 2.3.0)
webrick (1.8.1)
websocket (1.2.9)
websocket-driver (0.7.5-x86_64-linux-musl)
websocket-driver (0.7.6-x86_64-linux-musl)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
@ -581,7 +578,6 @@ GEM
zeitwerk (2.6.8)
PLATFORMS
ruby
x86_64-linux-musl
DEPENDENCIES
@ -590,7 +586,7 @@ DEPENDENCIES
blazer
bootstrap (~> 4)
brakeman
capybara
capybara (~> 2.13)
chartkick
commonmarker
concurrent-ruby-ext
@ -642,12 +638,13 @@ DEPENDENCIES
pry
puma
pundit
que
rack-cors
rack-mini-profiler
rails (~> 6.1.0)
rails-i18n
rails_warden
redis
redis (~> 4.0)
redis-rails
rgl
rollups!
@ -655,14 +652,14 @@ DEPENDENCIES
rubyzip
rugged
safe_yaml
safely_block (~> 0.3.0)
sassc-rails
selenium-webdriver
selenium-webdriver (~> 4.8.0)
sourcemap
spring
spring-watcher-listen
sqlite3
stackprof
sucker_punch
sutty-liquid (>= 0.7.3)
symbol-fstring
terminal-table
@ -675,7 +672,7 @@ DEPENDENCIES
yaml_db!
RUBY VERSION
ruby 3.1.3p185
ruby 3.1.4p223
BUNDLED WITH
2.2.2
2.4.17

View file

@ -48,8 +48,6 @@ help: always ## Ayuda
@echo -e "\nArgumentos:\n"
@grep -E "^[a-z\-]+ \?=.*##" Makefile | sed -re "s/(.*) \?=.*##(.*)/\1;\2/" | column -s ";" -t | sed -re "s/^([^ ]+) /\x1B[38;5;197m\1\x1B[0m/"
assets: public/packs/manifest.json.br ## Compilar los assets
test: always ## Ejecutar los tests
$(MAKE) rake args="test RAILS_ENV=test $(args)"
@ -110,21 +108,13 @@ save: ## Subir la imagen Docker al nodo delegado
date +%F | xargs -I {} git tag -f $(container)-{}
@echo -e "\a"
ota-js: assets ## Actualizar Javascript en el nodo delegado
rsync -avi --delete-after --chown 1000:82 public/ root@$(delegate):/srv/sutty/srv/http/data/_$(public)/
ssh root@$(delegate) docker exec $(container) sh -c "cat /srv/http/tmp/puma.pid | xargs -r kill -USR2"
ota: ## Actualizar Rails en el nodo delegado
ssh $(delegate) git -C /srv/sutty/srv/http/panel.sutty.nl pull ; true
git push
ssh $(delegate) git -C /srv/sutty/srv/http/panel.sutty.nl pull
ssh $(delegate) git -C /srv/sutty/srv/http/panel.sutty.nl lfs prune
ssh $(delegate) chown -R 1000:82 /srv/sutty/srv/http/panel.sutty.nl
ssh $(delegate) docker exec $(container) rails reload
# Todos los archivos de assets. Si alguno cambia, se van a recompilar
# los assets que luego se suben al nodo delegado.
assets := package.json yarn.lock $(shell find app/assets/ app/javascript/ -type f)
public/packs/manifest.json.br: $(assets)
$(hain) 'PANEL_URL=https://panel.sutty.nl RAILS_ENV=production NODE_ENV=production bundle exec rake assets:precompile assets:clean'
# Correr un test en particular por ejemplo
# `make test/models/usuarie_test.rb`
tests := $(shell find test/ -name "*_test.rb")

View file

@ -8,4 +8,4 @@ prometheus: bundle exec prometheus_exporter -b 0.0.0.0 --prefix "sutty_"
distributed_press_tokens_renew: bundle exec rake distributed_press:tokens:renew
cleanup: bundle exec rake cleanup:everything
stats: bundle exec rake stats:process_all
distributed_press_renew_tokens: bundle exec rake distributed_press:tokens:renew
que: daemonize -c /srv/ -p /srv/tmp/que.pid -u rails /usr/local/bin/syslogize bundle exec que

View file

@ -525,3 +525,5 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1);
}
}
}
// force ci

View file

@ -5,6 +5,7 @@ class EnvController < ActionController::Base
def index
@site = Site.find_by_name('panel')
stale? @site
stale? @site if @site
end
end

View file

@ -2,11 +2,21 @@
import { Notifier } from '@airbrake/browser'
window.airbrake = new Notifier({
projectId: window.env.AIRBRAKE_SITE_ID,
projectKey: window.env.AIRBRAKE_API_KEY,
host: window.env.PANEL_URL
})
try {
window.airbrake = new Notifier({
projectId: window.env.AIRBRAKE_PROJECT_ID,
projectKey: window.env.AIRBRAKE_PROJECT_KEY,
host: window.env.PANEL_URL
});
console.originalError = console.error;
console.error = (...e) => {
window.airbrake.notify(e.join(" "));
return console.originalError(...e);
};
} catch(e) {
console.error(e);
}
import 'core-js/stable'
import 'regenerator-runtime/runtime'

View file

@ -2,7 +2,7 @@
# Base para trabajos
class ApplicationJob < ActiveJob::Base
include SuckerPunch::Job
include Que::ActiveJob::JobExtensions
private

View file

@ -6,8 +6,6 @@ class BacktraceJob < ApplicationJob
EMPTY_SOURCEMAP = { 'mappings' => '' }.freeze
queue_as :low_priority
attr_reader :params, :site_id
def perform(site_id:, params:)

View file

@ -10,8 +10,6 @@ class GitlabNotifierJob < ApplicationJob
# Variables que vamos a acceder luego
attr_reader :exception, :options, :issue_data, :cached
queue_as :low_priority
# @param [Exception] la excepción lanzada
# @param [Hash] opciones de ExceptionNotifier
def perform(exception, **options)

View file

@ -8,9 +8,9 @@ module ExceptionNotifier
# Recibe la excepción y empieza la tarea de notificación en segundo
# plano.
#
# @param [Exception]
# @param [Hash]
def call(exception, **options)
# @param :exception [Exception]
# @param :options [Hash]
def call(exception, options, &block)
case exception
when BacktraceJob::BacktraceException
GitlabNotifierJob.perform_later(exception, **options)

View file

@ -37,7 +37,7 @@ class Site
author = GitAuthor.new email: "sutty@#{Site.domain}", name: 'Sutty'
repository.commit(file: modified,
repository.commit(add: modified,
message: I18n.t('sites.find_and_replace'),
usuarie: author)
end

View file

@ -114,14 +114,21 @@ class Site
end
# Guarda los cambios en git
def commit(file:, usuarie:, message:, remove: false)
file = [file] unless file.respond_to? :each
#
# @param :add [Array] Archivos a agregar
# @param :rm [Array] Archivos a eliminar
# @param :usuarie [Usuarie] Quién hace el commit
# @param :message [String] Mensaje
def commit(add: [], rm: [], usuarie:, message:)
# Cargar el árbol actual
rugged.index.read_tree rugged.head.target.tree
file.each do |f|
remove ? rm(f) : add(f)
add.each do |file|
rugged.index.add(relativize(file))
end
rm.each do |file|
rugged.index.remove(relativize(file))
end
# Escribir los cambios para que el repositorio se vea tal cual
@ -142,14 +149,6 @@ class Site
{ name: 'Sutty', email: "sutty@#{Site.domain}", time: Time.now }
end
def add(file)
rugged.index.add(relativize(file))
end
def rm(file)
rugged.index.remove(relativize(file))
end
# Garbage collection
#
# @return [Boolean]
@ -158,10 +157,8 @@ class Site
cmd = 'git gc'
r = nil
Dir.chdir(path) do
Open3.popen2e(env, cmd, unsetenv_others: true) do |_, _, t|
r = t.value
end
Open3.popen2e(env, cmd, unsetenv_others: true, chdir: path) do |_, _, t|
r = t.value
end
r&.success?

View file

@ -22,7 +22,7 @@ class LfsObjectService
Site::Writer.new(site: site, file: path, content: pointer).save
# Commitear el pointer
site.repository.commit(file: path, usuarie: author, message: File.basename(path))
site.repository.commit(add: [path], usuarie: author, message: File.basename(path))
# Eliminar el pointer
FileUtils.rm(path)

View file

@ -16,7 +16,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
post.slug.value = p[:slug] if p[:slug].present?
end
commit(action: :created, file: update_related_posts) if post.update(post_params)
commit(action: :created, add: update_related_posts) if post.update(post_params)
update_site_license!
@ -34,7 +34,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
# Los artículos anónimos siempre son borradores
params[:draft] = true
commit(action: :created) if post.update(anon_post_params)
commit(action: :created, add: [post.path.absolute]) if post.update(anon_post_params)
post
end
@ -42,11 +42,17 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
post.usuaries << usuarie
params[:post][:draft] = true if site.invitade? usuarie
# Es importante que el artículo se guarde primero y luego los
# relacionados.
commit(action: :updated, file: update_related_posts) if post.update(post_params)
# Eliminar ("mover") el archivo si cambió de ubicación.
if post.update(post_params)
rm = []
rm << post.path.value_was if post.path.changed?
update_site_license!
# Es importante que el artículo se guarde primero y luego los
# relacionados.
commit(action: :updated, add: update_related_posts, rm: rm)
update_site_license!
end
# Devolver el post aunque no se haya salvado para poder rescatar los
# errores
@ -56,7 +62,7 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
def destroy
post.destroy!
commit(action: :destroyed) if post.destroyed?
commit(action: :destroyed, rm: [post.path.absolute]) if post.destroyed?
post
end
@ -85,15 +91,15 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
# TODO: Implementar transacciones!
posts.save_all(validate: false) &&
commit(action: :reorder, file: files)
commit(action: :reorder, add: files)
end
private
def commit(action:, file: nil)
site.repository.commit(file: file || post.path.absolute,
def commit(action:, add: [], rm: [])
site.repository.commit(add: add,
rm: rm,
usuarie: usuarie,
remove: action == :destroyed,
message: I18n.t("post_service.#{action}",
title: post&.title&.value))
end

View file

@ -94,7 +94,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
def commit_config(action:)
site.repository
.commit(usuarie: usuarie,
file: site.config.path,
add: [site.config.path],
message: I18n.t("site_service.#{action}",
name: site.name))
end

View file

@ -1,7 +1,8 @@
= cache @site do
:plain
window.env = {
AIRBRAKE_SITE_ID: #{@site.id},
AIRBRAKE_API_KEY: "#{@site.airbrake_api_key}",
PANEL_URL: "#{ENV['PANEL_URL']}"
}
- if @site
= cache @site do
:plain
window.env = {
AIRBRAKE_SITE_ID: #{@site.id},
AIRBRAKE_API_KEY: "#{@site.airbrake_api_key}",
PANEL_URL: "#{ENV['PANEL_URL']}"
}

View file

@ -39,6 +39,12 @@ module Sutty
config.active_storage.variant_processor = :vips
config.active_storage.web_image_content_types << 'image/webp'
# Que
config.action_mailer.deliver_later_queue_name = :default
config.active_storage.queues.analysis = :default
config.active_storage.queues.purge = :default
config.active_job.queue_adapter = :que
config.to_prepare do
# Load application's model / class decorators
Dir.glob(File.join(File.dirname(__FILE__), '..', 'app', '**', '*_decorator.rb')).sort.each do |c|

View file

@ -64,11 +64,6 @@ Rails.application.configure do
# Use a different cache store in production.
config.cache_store = :redis_cache_store, { url: ENV['REDIS_SERVER'] }
# Use a real queuing backend for Active Job (and separate queues per
# environment)
config.active_job.queue_adapter = :sucker_punch
config.active_job.queue_name_prefix = "sutty_#{Rails.env}"
config.action_mailer.perform_caching = false
# Ignore bad email addresses and do not raise email delivery errors.

View file

@ -4,5 +4,5 @@ ActiveJob::Serializers.add_serializers ActiveJob::Serializers::ExceptionSerializ
# Notificar los errores
Que.error_notifier = proc do |error, job|
ExceptionNotifier.notify_exception(error, data: (job || {}))
ExceptionNotifier.notify_exception(error, data: (job.dup || {}))
end

View file

@ -1,6 +0,0 @@
# frozen_string_literal: true
# Enviar una notificación cuando falla una tarea
SuckerPunch.exception_handler = lambda { |ex, _, args|
ExceptionNotifier.notify_exception(ex, data: args.last)
}

View file

@ -16,12 +16,14 @@ licencias.each do |l|
licencia.update l
end
unless Rails.env.test?
YAML.safe_load(File.read('db/seeds/sites.yml')).each do |site|
site = Site.find_or_create_by name: site['name']
site.update licencia: Licencia.first, design: Design.first,
title: site.name, description: 'x' * 50,
deploys: site.deploys.empty? ? [DeployLocal.new] : site.deploys
if CodeOfConduct.count.zero?
YAML.safe_load(File.read('db/seeds/codes_of_conduct.yml')).each do |coc|
CodeOfConduct.new(**coc).save!
end
end
end
if PrivacyPolicy.count.zero?
YAML.safe_load(File.read('db/seeds/privacy_policies.yml')).each do |pp|
PrivacyPolicy.new(**pp).save!
end
end

View file

@ -19,7 +19,6 @@ check program stats
every "0 1 * * *"
if status != 0 then alert
check program distributed_press_tokens_renew
with path "/usr/bin/foreman run -f /srv/Procfile -d /srv distributed_press_tokens_renew" as uid "rails" gid "www-data"
every "0 3 * * *"
if status != 0 then alert
check process que with pidfile /srv/tmp/que.pid
start program = "/usr/bin/foreman run -f /srv/Procfile -d /srv que"
stop program = "/bin/sh -c 'cat /srv/tmp/que.pid | xargs -r kill'"