mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-24 04:06:22 +00:00
poder compilar el sitio con sidekiq
This commit is contained in:
parent
b149374c41
commit
15b6493c08
15 changed files with 38 additions and 181 deletions
1
Capfile
1
Capfile
|
@ -11,7 +11,6 @@ require 'capistrano/passenger'
|
||||||
require 'capistrano/bundler'
|
require 'capistrano/bundler'
|
||||||
require 'capistrano/rbenv'
|
require 'capistrano/rbenv'
|
||||||
require 'capistrano/rails'
|
require 'capistrano/rails'
|
||||||
require 'whenever/capistrano'
|
|
||||||
require 'capistrano/scm/git'
|
require 'capistrano/scm/git'
|
||||||
install_plugin Capistrano::SCM::Git
|
install_plugin Capistrano::SCM::Git
|
||||||
|
|
||||||
|
|
1
Gemfile
1
Gemfile
|
@ -62,7 +62,6 @@ gem 'rugged'
|
||||||
gem 'sidekiq'
|
gem 'sidekiq'
|
||||||
gem 'terminal-table'
|
gem 'terminal-table'
|
||||||
gem 'validates_hostname'
|
gem 'validates_hostname'
|
||||||
gem 'whenever', require: false
|
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem 'pry'
|
gem 'pry'
|
||||||
|
|
|
@ -91,7 +91,6 @@ GEM
|
||||||
carrierwave-i18n (0.2.0)
|
carrierwave-i18n (0.2.0)
|
||||||
childprocess (0.9.0)
|
childprocess (0.9.0)
|
||||||
ffi (~> 1.0, >= 1.0.11)
|
ffi (~> 1.0, >= 1.0.11)
|
||||||
chronic (0.10.2)
|
|
||||||
coderay (1.1.2)
|
coderay (1.1.2)
|
||||||
colorator (1.1.0)
|
colorator (1.1.0)
|
||||||
commonmarker (0.18.2)
|
commonmarker (0.18.2)
|
||||||
|
@ -401,8 +400,6 @@ GEM
|
||||||
websocket-driver (0.7.0)
|
websocket-driver (0.7.0)
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
websocket-extensions (0.1.3)
|
websocket-extensions (0.1.3)
|
||||||
whenever (0.10.0)
|
|
||||||
chronic (>= 0.6.3)
|
|
||||||
xpath (3.2.0)
|
xpath (3.2.0)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
|
|
||||||
|
@ -467,7 +464,6 @@ DEPENDENCIES
|
||||||
uglifier (>= 1.3.0)
|
uglifier (>= 1.3.0)
|
||||||
validates_hostname
|
validates_hostname
|
||||||
web-console (>= 3.3.0)
|
web-console (>= 3.3.0)
|
||||||
whenever
|
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.17.3
|
1.17.3
|
||||||
|
|
|
@ -79,23 +79,15 @@ class SitesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def enqueue
|
def enqueue
|
||||||
@site = find_site
|
site = find_site
|
||||||
authorize @site
|
authorize site
|
||||||
@site.enqueue!
|
|
||||||
|
# XXX: Convertir en una máquina de estados?
|
||||||
|
DeployWorker.perform_async site.id if site.enqueue!
|
||||||
|
|
||||||
redirect_to sites_path
|
redirect_to sites_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_log
|
|
||||||
@site = find_site
|
|
||||||
authorize @site
|
|
||||||
|
|
||||||
# TODO: eliminar ANSI
|
|
||||||
render file: @site.build_log,
|
|
||||||
layout: false,
|
|
||||||
content_type: 'text/plain; charset=utf-8'
|
|
||||||
end
|
|
||||||
|
|
||||||
def reorder_posts
|
def reorder_posts
|
||||||
@site = find_site
|
@site = find_site
|
||||||
authorize @site
|
authorize @site
|
||||||
|
|
|
@ -7,8 +7,8 @@ class Site < ApplicationRecord
|
||||||
|
|
||||||
validates :name, uniqueness: true, hostname: true
|
validates :name, uniqueness: true, hostname: true
|
||||||
validates :design_id, presence: true
|
validates :design_id, presence: true
|
||||||
|
|
||||||
validate :deploy_local_presence
|
validate :deploy_local_presence
|
||||||
|
validates_inclusion_of :status, in: %w[waiting enqueued building]
|
||||||
|
|
||||||
friendly_id :name, use: %i[finders]
|
friendly_id :name, use: %i[finders]
|
||||||
|
|
||||||
|
@ -217,65 +217,13 @@ class Site < ApplicationRecord
|
||||||
end.flatten.uniq.compact
|
end.flatten.uniq.compact
|
||||||
end
|
end
|
||||||
|
|
||||||
def failed_file
|
def enqueue!
|
||||||
File.join(path, '.failed')
|
!enqueued? && update_attribute(:status, 'enqueued')
|
||||||
end
|
|
||||||
|
|
||||||
def failed?
|
|
||||||
File.exist? failed_file
|
|
||||||
end
|
|
||||||
|
|
||||||
def defail
|
|
||||||
FileUtils.rm failed_file if failed?
|
|
||||||
end
|
|
||||||
alias defail! defail
|
|
||||||
|
|
||||||
def build_log
|
|
||||||
File.join(path, 'build.log')
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_log?
|
|
||||||
File.exist? build_log
|
|
||||||
end
|
|
||||||
|
|
||||||
def queue_file
|
|
||||||
File.join(path, '.generate')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def enqueued?
|
def enqueued?
|
||||||
File.exist? queue_file
|
status == 'enqueued'
|
||||||
end
|
end
|
||||||
alias queued? enqueued?
|
|
||||||
|
|
||||||
# El sitio se genera cuando se coloca en una cola de generación, para
|
|
||||||
# que luego lo construya un cronjob
|
|
||||||
def enqueue
|
|
||||||
defail!
|
|
||||||
# TODO: ya van tres métodos donde usamos esta idea, convertir en un
|
|
||||||
# helper o algo
|
|
||||||
File.open(queue_file, File::RDWR | File::CREAT, 0o640) do |f|
|
|
||||||
# Bloquear el archivo para que no sea accedido por otro
|
|
||||||
# proceso u otra editora
|
|
||||||
f.flock(File::LOCK_EX)
|
|
||||||
|
|
||||||
# Empezar por el principio
|
|
||||||
f.rewind
|
|
||||||
|
|
||||||
# Escribir la fecha de creación
|
|
||||||
f.write(Time.now.to_i.to_s)
|
|
||||||
|
|
||||||
# Eliminar el resto
|
|
||||||
f.flush
|
|
||||||
f.truncate(f.pos)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
alias enqueue! enqueue
|
|
||||||
|
|
||||||
# Eliminar de la cola
|
|
||||||
def dequeue
|
|
||||||
FileUtils.rm(queue_file) if enqueued?
|
|
||||||
end
|
|
||||||
alias dequeue! dequeue
|
|
||||||
|
|
||||||
# Verifica si los posts están ordenados
|
# Verifica si los posts están ordenados
|
||||||
def ordered?(collection = 'posts')
|
def ordered?(collection = 'posts')
|
||||||
|
|
|
@ -55,10 +55,6 @@ class SitePolicy
|
||||||
build?
|
build?
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_log?
|
|
||||||
build?
|
|
||||||
end
|
|
||||||
|
|
||||||
def reorder_posts?
|
def reorder_posts?
|
||||||
build?
|
build?
|
||||||
end
|
end
|
||||||
|
|
|
@ -77,15 +77,6 @@
|
||||||
= fa_icon 'building'
|
= fa_icon 'building'
|
||||||
= t('sites.enqueue')
|
= t('sites.enqueue')
|
||||||
|
|
||||||
- if policy(site).build_log?
|
|
||||||
- if site.failed?
|
|
||||||
%button.btn.btn-danger= t('sites.failed')
|
|
||||||
- if site.build_log?
|
|
||||||
= render 'layouts/btn_with_tooltip',
|
|
||||||
tooltip: t('help.sites.build_log'),
|
|
||||||
text: t('sites.build_log'),
|
|
||||||
type: 'warning',
|
|
||||||
link: site_build_log_path(site)
|
|
||||||
- if policy(site).pull? && site.needs_pull?
|
- if policy(site).pull? && site.needs_pull?
|
||||||
= render 'layouts/btn_with_tooltip',
|
= render 'layouts/btn_with_tooltip',
|
||||||
tooltip: t('help.sites.pull'),
|
tooltip: t('help.sites.pull'),
|
||||||
|
|
|
@ -6,14 +6,20 @@ class DeployWorker
|
||||||
|
|
||||||
def perform(site)
|
def perform(site)
|
||||||
site = Site.find(site)
|
site = Site.find(site)
|
||||||
|
site.update_attribute :status, 'building'
|
||||||
# Asegurarse que DeployLocal sea el primero!
|
# Asegurarse que DeployLocal sea el primero!
|
||||||
deployed = { deploy_local: deploy_local(site) }
|
deployed = { deploy_local: deploy_local(site) }
|
||||||
|
|
||||||
# No es opcional
|
# No es opcional
|
||||||
raise unless deployed[:deploy_local]
|
unless deployed[:deploy_local]
|
||||||
|
site.update_attribute :status, 'waiting'
|
||||||
|
raise
|
||||||
|
end
|
||||||
|
|
||||||
deploy_others site, deployed
|
deploy_others site, deployed
|
||||||
notify_usuaries site, deployed
|
notify_usuaries site, deployed
|
||||||
|
|
||||||
|
site.update_attribute :status, 'waiting'
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# TODO convertir a ruby!
|
|
||||||
set -e
|
|
||||||
|
|
||||||
rails_root="${PWD}"
|
|
||||||
|
|
||||||
# Encontrar todos los sitios únicos con el archivo `.generate`. Esto
|
|
||||||
# significa que la usuaria quiso generar el sitio.
|
|
||||||
find -L ./_sites -mindepth 2 -maxdepth 2 -name .generate \
|
|
||||||
| sed "s/\/\.generate$//" \
|
|
||||||
| while read _path ; do
|
|
||||||
# Como seguimos todos los symlinks y los sitios pueden estar
|
|
||||||
# vinculados entre sí, volvemos a chequear si existe el archivo para
|
|
||||||
# no generarlo dos veces
|
|
||||||
test -f "${_path}/.generate" || continue
|
|
||||||
test -f "${_path}/.generating" && continue
|
|
||||||
|
|
||||||
# Obtenemos las direcciones de correo de las responsables
|
|
||||||
_mail=($(cat "${_path}/.usuarias"))
|
|
||||||
_site="$(echo "${_path}" | xargs basename)"
|
|
||||||
_deploy="${rails_root}/_deploy/${_site}"
|
|
||||||
|
|
||||||
# Entrar al directorio del sitio
|
|
||||||
pushd "${_path}" &>/dev/null
|
|
||||||
|
|
||||||
# Reiniciar el log con la fecha
|
|
||||||
date > build.log
|
|
||||||
|
|
||||||
# Instalar las gemas si no están
|
|
||||||
test -f .bundle/config \
|
|
||||||
|| bundle install --path=/srv/http/gems.kefir.red \
|
|
||||||
>> build.log
|
|
||||||
|
|
||||||
# Actualizar las gemas
|
|
||||||
bundle >> build.log
|
|
||||||
# Instalar los assets
|
|
||||||
test -f yarn.lock \
|
|
||||||
&& yarn >> build.log
|
|
||||||
|
|
||||||
# Crear el sitio con lujo de detalles y guardar un log, pero a la vez
|
|
||||||
# tenerlo en la salida estándar para poder enviar al MAILTO del
|
|
||||||
# cronjob.
|
|
||||||
#
|
|
||||||
# Ya que estamos, eliminamos la ruta donde estamos paradas para no dar
|
|
||||||
# información sobre la servidora.
|
|
||||||
touch .generating
|
|
||||||
# Correr en baja prioridad
|
|
||||||
nice -n 19 \
|
|
||||||
bundle exec \
|
|
||||||
jekyll build --trace --destination "${_deploy}" 2>&1 \
|
|
||||||
| sed -re "s,${_path},,g" \
|
|
||||||
>> "build.log"
|
|
||||||
|
|
||||||
# Acciones posteriores
|
|
||||||
# TODO convertir en un plugin de cada sitio?
|
|
||||||
if test $? -eq 0; then
|
|
||||||
# Si funciona, enviar un mail
|
|
||||||
# TODO enviar un mail más completo y no hardcodear direcciones
|
|
||||||
echo "Everything was good! You can see your changes in https://${_site}" \
|
|
||||||
| mail -b "sysadmin@kefir.red" \
|
|
||||||
-s "${_site}: :)" \
|
|
||||||
${_mail[@]}
|
|
||||||
else
|
|
||||||
echo "There was an error, please check build log at https://sutty.kefir.red/" \
|
|
||||||
| mail -b "sysadmin@kefir.red" \
|
|
||||||
-s "${_site}: :(" \
|
|
||||||
${_mail[@]}
|
|
||||||
date +%s >.failed
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Eliminar el archivo para sacar el sitio de la cola de compilación
|
|
||||||
rm -f .generate .generating
|
|
||||||
# TODO descubrir el grupo según la distro?
|
|
||||||
chgrp -R http "${_deploy}"
|
|
||||||
find "${_deploy}" -type f -print0 | xargs -r -0 chmod 640
|
|
||||||
find "${_deploy}" -type d -print0 | xargs -r -0 chmod 2750
|
|
||||||
|
|
||||||
# Volver al principio para continuar con el siguiente sitio
|
|
||||||
popd &>/dev/null
|
|
||||||
done
|
|
|
@ -1,6 +1,5 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# rubocop:disable Metrics/BlockLength
|
|
||||||
Rails.application.routes.draw do
|
Rails.application.routes.draw do
|
||||||
devise_for :usuaries
|
devise_for :usuaries
|
||||||
|
|
||||||
|
@ -42,8 +41,6 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
# Compilar el sitio
|
# Compilar el sitio
|
||||||
post 'enqueue', to: 'sites#enqueue'
|
post 'enqueue', to: 'sites#enqueue'
|
||||||
get 'build_log', to: 'sites#build_log'
|
|
||||||
post 'reorder_posts', to: 'sites#reorder_posts'
|
post 'reorder_posts', to: 'sites#reorder_posts'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/BlockLength
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
env 'MAILTO', 'sysadmin@kefir.red'
|
|
||||||
job_type :bash, 'cd :path && ./bin/:task'
|
|
||||||
|
|
||||||
every 3.minutes do
|
|
||||||
bash 'jekyll_build_all'
|
|
||||||
end
|
|
|
@ -1,5 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Crea la tabla de estadísticas de compilación
|
||||||
class CreateBuildStats < ActiveRecord::Migration[5.2]
|
class CreateBuildStats < ActiveRecord::Migration[5.2]
|
||||||
def change
|
def change
|
||||||
create_table :build_stats do |t|
|
create_table :build_stats do |t|
|
||||||
|
|
8
db/migrate/20190726003756_add_status_to_site.rb
Normal file
8
db/migrate/20190726003756_add_status_to_site.rb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# El status de un sitio
|
||||||
|
class AddStatusToSite < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :sites, :status, :string, default: 'waiting'
|
||||||
|
end
|
||||||
|
end
|
|
@ -12,7 +12,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 20_190_725_185_427) do
|
ActiveRecord::Schema.define(version: 20_190_726_003_756) do
|
||||||
create_table 'build_stats', force: :cascade do |t|
|
create_table 'build_stats', force: :cascade do |t|
|
||||||
t.datetime 'created_at', null: false
|
t.datetime 'created_at', null: false
|
||||||
t.datetime 'updated_at', null: false
|
t.datetime 'updated_at', null: false
|
||||||
|
@ -98,6 +98,7 @@ ActiveRecord::Schema.define(version: 20_190_725_185_427) do
|
||||||
t.string 'name'
|
t.string 'name'
|
||||||
t.integer 'design_id'
|
t.integer 'design_id'
|
||||||
t.integer 'licencia_id'
|
t.integer 'licencia_id'
|
||||||
|
t.string 'status', default: 'waiting'
|
||||||
t.index ['design_id'], name: 'index_sites_on_design_id'
|
t.index ['design_id'], name: 'index_sites_on_design_id'
|
||||||
t.index ['licencia_id'], name: 'index_sites_on_licencia_id'
|
t.index ['licencia_id'], name: 'index_sites_on_licencia_id'
|
||||||
t.index ['name'], name: 'index_sites_on_name', unique: true
|
t.index ['name'], name: 'index_sites_on_name', unique: true
|
||||||
|
|
|
@ -71,4 +71,15 @@ class SitesControllerTest < ActionDispatch::IntegrationTest
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'se pueden encolar' do
|
||||||
|
Sidekiq::Testing.fake!
|
||||||
|
|
||||||
|
post site_enqueue_url(@site), headers: @authorization
|
||||||
|
|
||||||
|
assert DeployWorker.jobs.count.positive?
|
||||||
|
assert @site.reload.enqueued?
|
||||||
|
|
||||||
|
Sidekiq::Testing.inline!
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue