generar los sitios!

This commit is contained in:
f 2018-02-20 14:47:11 -03:00
parent 3a8c004ec7
commit 79a0053dbd
No known key found for this signature in database
GPG Key ID: F3FDAB97B5F9F7E7
17 changed files with 230 additions and 2 deletions

3
.gitignore vendored
View File

@ -21,3 +21,6 @@
/yarn-error.log
.byebug_history
/_sites/*
/_deploy/*

View File

@ -10,6 +10,7 @@ require 'capistrano/passenger'
require 'capistrano/bundler'
require 'capistrano/rbenv'
require 'capistrano/rails'
require 'whenever/capistrano'
require 'capistrano/scm/git'
install_plugin Capistrano::SCM::Git

View File

@ -38,6 +38,7 @@ gem 'jekyll'
gem 'jquery-rails'
gem 'font-awesome-rails'
gem 'exception_notification'
gem 'whenever', require: false
group :development, :test do
gem 'pry'

View File

@ -77,6 +77,7 @@ GEM
xpath (~> 2.0)
childprocess (0.8.0)
ffi (~> 1.0, >= 1.0.11)
chronic (0.10.2)
coderay (1.1.2)
colorator (1.1.0)
concurrent-ruby (1.0.5)
@ -270,6 +271,8 @@ GEM
websocket-driver (0.6.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3)
whenever (0.10.0)
chronic (>= 0.6.3)
xpath (2.1.0)
nokogiri (~> 1.3)
@ -307,6 +310,7 @@ DEPENDENCIES
turbolinks (~> 5)
uglifier (>= 1.3.0)
web-console (>= 3.3.0)
whenever
BUNDLED WITH
1.16.0

0
_deploy/.keep Normal file
View File

View File

@ -14,4 +14,19 @@ class SitesController < ApplicationController
redirect_to site_posts_path(site)
end
def enqueue
@site = find_site
@site.enqueue!
redirect_to sites_path
end
def build_log
@site = find_site
render file: @site.build_log,
layout: false,
content_type: 'text/plain'
end
end

View File

@ -86,6 +86,79 @@ class Site
end.flatten.uniq
end
# Las usuarias que tienen acceso a este sitio se guardan en un archivo
# `.usuarias` que tiene la dirección de correo de cada una
def usuarias_file
File.join(path, '.usuarias')
end
# Obtiene las usuarias que gestionan este sitio
def usuarias
@usuarias ||= File.read(usuarias_file).split("\n").map do |u|
Usuaria.find(u)
end
end
def failed_file
File.join(path, '.failed')
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
def enqueued?
File.exist? queue_file
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
r = 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
# El directorio donde se almacenan los sitios
def self.site_path
File.join(Rails.root, '_sites')

View File

@ -0,0 +1,13 @@
- if site.enqueued?
%span.badge.badge-warning= t('sites.enqueued')
- else
= form_tag site_enqueue_path(site), method: :post, class: 'form-inline' do
= button_tag type: 'submit', class: 'btn btn-success' do
= fa_icon 'building'
= t('sites.enqueue')
- if site.failed?
%span.badge.badge-alert= t('sites.failed')
- if site.build_log?
= link_to t('sites.build_log'), site_build_log_path(site),
class: 'badge badge-info'

View File

@ -12,3 +12,4 @@
%tr
%td= link_to site.name, site_path(site)
%td= link_to t('i18n.edit'), site_i18n_edit_path(site)
%td= render 'sites/enqueue', site: site

58
bin/jekyll_build_all Executable file
View File

@ -0,0 +1,58 @@
#!/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 3 -maxdepth 3 -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
# 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
# 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.
bundle exec \
jekyll build --trace --destination "${_deploy}" \
| 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
mail -b "sysadmin@kefir.red" \
-r "sutty@kefir.red" \
-s "${_site}: :)" \
${_mail[@]}
else
mail -b "sysadmin@kefir.red" \
-r "sutty@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
# Volver al principio para continuar con el siguiente sitio
popd &>/dev/null
done

21
bin/whenever Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
#
# This file was generated by Bundler.
#
# The application 'whenever' is installed as part of a gem, and
# this file is here to facilitate running it.
#
bundle_binstub = File.expand_path("../bundle", __FILE__)
load(bundle_binstub) if File.file?(bundle_binstub)
require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)
require "rubygems"
require "bundler/setup"
load Gem.bin_path("whenever", "whenever")

21
bin/wheneverize Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
#
# This file was generated by Bundler.
#
# The application 'wheneverize' is installed as part of a gem, and
# this file is here to facilitate running it.
#
bundle_binstub = File.expand_path("../bundle", __FILE__)
load(bundle_binstub) if File.file?(bundle_binstub)
require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)
require "rubygems"
require "bundler/setup"
load Gem.bin_path("whenever", "wheneverize")

View File

@ -5,5 +5,5 @@ set :repo_url, 'git@0xacab.org:itacate-kefir/sutty.git'
set :bundle_flags, '--deployment'
set :default_env, path: '/usr/lib/passenger/bin:$PATH'
set :linked_dirs, %w{_sites}
set :linked_dirs, %w{_sites _deploy}
set :linked_files, %w{.env}

View File

@ -9,6 +9,10 @@ en:
sites:
title: 'Sites'
index: 'Sites'
enqueued: 'Waiting for build'
enqueue: 'Build'
failed: 'Failed!'
build_log: 'Read log'
footer:
powered_by: 'is developed by'
i18n:

View File

@ -9,6 +9,10 @@ es:
sites:
title: 'Sitios'
index: 'Sitios'
enqueued: 'Esperando compilación'
enqueue: 'Compilar'
failed: '¡Falló!'
build_log: 'Ver registro'
footer:
powered_by: 'es desarrollada por'
i18n:

View File

@ -4,11 +4,14 @@ Rails.application.routes.draw do
get 'login/new', to: 'login#new'
post 'login', to: 'login#create'
resources :sites do
resources :sites, only: [ :index, :show ] do
resources :posts
get 'i18n', to: 'i18n#index'
get 'i18n/edit', to: 'i18n#edit'
post 'i18n', to: 'i18n#update'
post 'enqueue', to: 'sites#enqueue'
get 'build_log', to: 'sites#build_log'
end
end

6
config/schedule.rb Normal file
View File

@ -0,0 +1,6 @@
env 'MAILTO', 'sysadmin@kefir.red'
job_type :bash, 'cd :path && ./bin/:task'
every 3.minutes do
bash 'jekyll_build_all'
end