mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-22 20:26:22 +00:00
Merge branch 'issue-10464' into panel.sutty.nl
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
commit
978fe20859
15 changed files with 229 additions and 70 deletions
1
Gemfile
1
Gemfile
|
@ -25,6 +25,7 @@ if ENV['RAILS_GROUPS']&.split(',')&.include? 'assets'
|
||||||
end
|
end
|
||||||
|
|
||||||
gem 'nokogiri'
|
gem 'nokogiri'
|
||||||
|
gem 'rgl'
|
||||||
|
|
||||||
# Turbolinks makes navigating your web application faster. Read more:
|
# Turbolinks makes navigating your web application faster. Read more:
|
||||||
# https://github.com/turbolinks/turbolinks
|
# https://github.com/turbolinks/turbolinks
|
||||||
|
|
|
@ -361,6 +361,7 @@ GEM
|
||||||
dry-schema
|
dry-schema
|
||||||
httparty (~> 0.18)
|
httparty (~> 0.18)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
|
pairing_heap (3.0.0)
|
||||||
parallel (1.22.1)
|
parallel (1.22.1)
|
||||||
parser (3.1.3.0)
|
parser (3.1.3.0)
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
|
@ -455,6 +456,10 @@ GEM
|
||||||
actionpack (>= 5.0)
|
actionpack (>= 5.0)
|
||||||
railties (>= 5.0)
|
railties (>= 5.0)
|
||||||
rexml (3.2.5)
|
rexml (3.2.5)
|
||||||
|
rgl (0.6.2)
|
||||||
|
pairing_heap (>= 0.3.0)
|
||||||
|
rexml (~> 3.2, >= 3.2.4)
|
||||||
|
stream (~> 0.5.3)
|
||||||
rouge (3.30.0)
|
rouge (3.30.0)
|
||||||
rubocop (1.41.1)
|
rubocop (1.41.1)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
|
@ -518,6 +523,7 @@ GEM
|
||||||
sqlite3 (1.5.4-x86_64-linux-musl)
|
sqlite3 (1.5.4-x86_64-linux-musl)
|
||||||
mini_portile2 (~> 2.8.0)
|
mini_portile2 (~> 2.8.0)
|
||||||
stackprof (0.2.23-x86_64-linux-musl)
|
stackprof (0.2.23-x86_64-linux-musl)
|
||||||
|
stream (0.5.5)
|
||||||
sucker_punch (3.1.0)
|
sucker_punch (3.1.0)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
sutty-liquid (0.11.6)
|
sutty-liquid (0.11.6)
|
||||||
|
@ -637,6 +643,7 @@ DEPENDENCIES
|
||||||
redis (~> 4.0)
|
redis (~> 4.0)
|
||||||
redis-rails
|
redis-rails
|
||||||
reek
|
reek
|
||||||
|
rgl
|
||||||
rollups!
|
rollups!
|
||||||
rubocop-rails
|
rubocop-rails
|
||||||
rubyzip
|
rubyzip
|
||||||
|
|
|
@ -28,28 +28,46 @@ class DeployJob < ApplicationJob
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@deployed = {}
|
||||||
@site.update status: 'building'
|
@site.update status: 'building'
|
||||||
# Asegurarse que DeployLocal sea el primero!
|
@site.deployment_list.each do |d|
|
||||||
@deployed = {
|
begin
|
||||||
deploy_local: {
|
raise DeployException, 'Una dependencia falló' if failed_dependencies? d
|
||||||
status: deploy_locally,
|
|
||||||
seconds: deploy_local.build_stats.last.seconds,
|
|
||||||
size: deploy_local.size,
|
|
||||||
urls: [deploy_local.url]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# No es opcional
|
status = d.deploy
|
||||||
unless @deployed[:deploy_local][:status]
|
seconds = d.build_stats.last.try(:seconds)
|
||||||
# Hacer fallar la tarea
|
size = d.size
|
||||||
raise DeployException, "#{@site.name}: Falló la compilación"
|
urls = d.respond_to?(:urls) ? d.urls : [d.url].compact
|
||||||
|
rescue StandardError => e
|
||||||
|
status = false
|
||||||
|
seconds ||= 0
|
||||||
|
size ||= 0
|
||||||
|
urls ||= []
|
||||||
|
|
||||||
|
notify_exception e, d
|
||||||
|
end
|
||||||
|
|
||||||
|
@deployed[d.type.underscore.to_sym] = {
|
||||||
|
status: status,
|
||||||
|
seconds: seconds,
|
||||||
|
size: size,
|
||||||
|
urls: urls
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
deploy_others
|
return unless @output
|
||||||
|
|
||||||
|
puts (Terminal::Table.new do |t|
|
||||||
|
t << (%w[type] + @deployed.values.first.keys)
|
||||||
|
t.add_separator
|
||||||
|
@deployed.each do |type, row|
|
||||||
|
t << ([type.to_s] + row.values)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
puts "\a"
|
||||||
rescue DeployTimedOutException => e
|
rescue DeployTimedOutException => e
|
||||||
notify_exception e
|
notify_exception e
|
||||||
rescue DeployException => e
|
|
||||||
notify_exception e, deploy_local
|
|
||||||
ensure
|
ensure
|
||||||
@site&.update status: 'waiting'
|
@site&.update status: 'waiting'
|
||||||
|
|
||||||
|
@ -60,47 +78,37 @@ class DeployJob < ApplicationJob
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# Detecta si un método de publicación tiene dependencias fallidas
|
||||||
|
#
|
||||||
|
# @param :deploy [Deploy]
|
||||||
|
# @return [Boolean]
|
||||||
|
def failed_dependencies?(deploy)
|
||||||
|
failed_dependencies(deploy).present?
|
||||||
|
end
|
||||||
|
|
||||||
|
# Obtiene las dependencias fallidas de un deploy
|
||||||
|
#
|
||||||
|
# @param :deploy [Deploy]
|
||||||
|
# @return [Array]
|
||||||
|
def failed_dependencies(deploy)
|
||||||
|
deploy.class::DEPENDENCIES & (@deployed.reject do |_, v|
|
||||||
|
v[:status]
|
||||||
|
end.keys)
|
||||||
|
end
|
||||||
|
|
||||||
# @param :exception [StandardError]
|
# @param :exception [StandardError]
|
||||||
# @param :deploy [Deploy]
|
# @param :deploy [Deploy]
|
||||||
def notify_exception(exception, deploy = nil)
|
def notify_exception(exception, deploy = nil)
|
||||||
data = {
|
data = {
|
||||||
site: @site.id,
|
site: @site.id,
|
||||||
deploy: deploy&.type,
|
deploy: deploy&.type,
|
||||||
log: deploy&.build_stats&.last&.log
|
log: deploy&.build_stats&.last&.log,
|
||||||
|
failed_dependencies: (failed_dependencies(deploy) if deploy)
|
||||||
}
|
}
|
||||||
|
|
||||||
ExceptionNotifier.notify_exception(exception, data: data)
|
ExceptionNotifier.notify_exception(exception, data: data)
|
||||||
end
|
end
|
||||||
|
|
||||||
def deploy_local
|
|
||||||
@deploy_local ||= @site.deploys.find_by(type: 'DeployLocal')
|
|
||||||
end
|
|
||||||
|
|
||||||
def deploy_locally
|
|
||||||
deploy_local.deploy(output: @output)
|
|
||||||
end
|
|
||||||
|
|
||||||
def deploy_others
|
|
||||||
@site.deploys.where.not(type: 'DeployLocal').find_each do |d|
|
|
||||||
begin
|
|
||||||
status = d.deploy(output: @output)
|
|
||||||
seconds = d.build_stats.last.try(:seconds)
|
|
||||||
rescue StandardError => e
|
|
||||||
status = false
|
|
||||||
seconds = 0
|
|
||||||
|
|
||||||
notify_exception e, d
|
|
||||||
end
|
|
||||||
|
|
||||||
@deployed[d.type.underscore.to_sym] = {
|
|
||||||
status: status,
|
|
||||||
seconds: seconds || 0,
|
|
||||||
size: d.size,
|
|
||||||
urls: d.respond_to?(:urls) ? d.urls : [d.url].compact
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def notify_usuaries
|
def notify_usuaries
|
||||||
@site.roles.where(rol: 'usuarie', temporal: false).pluck(:usuarie_id).each do |usuarie|
|
@site.roles.where(rol: 'usuarie', temporal: false).pluck(:usuarie_id).each do |usuarie|
|
||||||
DeployMailer.with(usuarie: usuarie, site: @site.id)
|
DeployMailer.with(usuarie: usuarie, site: @site.id)
|
||||||
|
|
|
@ -15,12 +15,13 @@ class DeployMailer < ApplicationMailer
|
||||||
def deployed(deploys)
|
def deployed(deploys)
|
||||||
usuarie = Usuarie.find(params[:usuarie])
|
usuarie = Usuarie.find(params[:usuarie])
|
||||||
site = usuarie.sites.find(params[:site])
|
site = usuarie.sites.find(params[:site])
|
||||||
subject = t('.subject', site: site.name)
|
|
||||||
hostname = site.hostname
|
hostname = site.hostname
|
||||||
|
|
||||||
# Informamos a cada quien en su idioma y damos una dirección de
|
# Informamos a cada quien en su idioma y damos una dirección de
|
||||||
# respuesta porque a veces les usuaries nos escriben
|
# respuesta porque a veces les usuaries nos escriben
|
||||||
I18n.with_locale(usuarie.lang) do
|
I18n.with_locale(usuarie.lang) do
|
||||||
|
subject = t('.subject', site: site.name)
|
||||||
|
|
||||||
@hi = t('.hi')
|
@hi = t('.hi')
|
||||||
@explanation = t('.explanation', fqdn: hostname)
|
@explanation = t('.explanation', fqdn: hostname)
|
||||||
@help = t('.help')
|
@help = t('.help')
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'open3'
|
require 'open3'
|
||||||
|
|
||||||
# Este modelo implementa los distintos tipos de alojamiento que provee
|
# Este modelo implementa los distintos tipos de alojamiento que provee
|
||||||
# Sutty.
|
# Sutty.
|
||||||
#
|
#
|
||||||
|
@ -11,6 +12,8 @@ class Deploy < ApplicationRecord
|
||||||
belongs_to :site
|
belongs_to :site
|
||||||
has_many :build_stats, dependent: :destroy
|
has_many :build_stats, dependent: :destroy
|
||||||
|
|
||||||
|
DEPENDENCIES = []
|
||||||
|
|
||||||
def deploy(**)
|
def deploy(**)
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
class DeployAlternativeDomain < Deploy
|
class DeployAlternativeDomain < Deploy
|
||||||
store :values, accessors: %i[hostname], coder: JSON
|
store :values, accessors: %i[hostname], coder: JSON
|
||||||
|
|
||||||
|
DEPENDENCIES = %i[deploy_local]
|
||||||
|
|
||||||
# Generar un link simbólico del sitio principal al alternativo
|
# Generar un link simbólico del sitio principal al alternativo
|
||||||
def deploy(**)
|
def deploy(**)
|
||||||
File.symlink?(destination) ||
|
File.symlink?(destination) ||
|
||||||
|
@ -18,7 +20,11 @@ class DeployAlternativeDomain < Deploy
|
||||||
end
|
end
|
||||||
|
|
||||||
def destination
|
def destination
|
||||||
@destination ||= File.join(Rails.root, '_deploy', hostname.gsub(/\.\z/, ''))
|
@destination ||= File.join(Rails.root, '_deploy', fqdn)
|
||||||
|
end
|
||||||
|
|
||||||
|
def fqdn
|
||||||
|
hostname.gsub(/\.\z/, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
def url
|
def url
|
||||||
|
|
22
app/models/deploy_full_rsync.rb
Normal file
22
app/models/deploy_full_rsync.rb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class DeployFullRsync < DeployRsync
|
||||||
|
DEPENDENCIES = %i[
|
||||||
|
deploy_alternative_domain
|
||||||
|
deploy_hidden_service
|
||||||
|
deploy_local
|
||||||
|
deploy_www
|
||||||
|
]
|
||||||
|
|
||||||
|
# Sincroniza las ubicaciones alternativas también
|
||||||
|
#
|
||||||
|
# @param :output [Boolean]
|
||||||
|
# @return [Boolean]
|
||||||
|
def rsync(output: false)
|
||||||
|
DEPENDENCIES.map(&:to_s).map(&:classify).map do |dependency|
|
||||||
|
site.deploys.where(type: dependency).find_each.map do |deploy|
|
||||||
|
run %(rsync -aviH --delete-after --timeout=5 #{Shellwords.escape deploy.destination} #{Shellwords.escape destination}), output: output
|
||||||
|
end
|
||||||
|
end.flatten.all?
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,14 +2,10 @@
|
||||||
|
|
||||||
# Genera una versión onion
|
# Genera una versión onion
|
||||||
class DeployHiddenService < DeployWww
|
class DeployHiddenService < DeployWww
|
||||||
def deploy(**)
|
|
||||||
return true if fqdn.blank?
|
|
||||||
|
|
||||||
super
|
|
||||||
end
|
|
||||||
|
|
||||||
def fqdn
|
def fqdn
|
||||||
values[:onion]
|
values[:onion].tap do |onion|
|
||||||
|
raise ArgumentError, 'Aun no se generó la dirección .onion' if onion.blank?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def url
|
def url
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
class DeployRsync < Deploy
|
class DeployRsync < Deploy
|
||||||
store :values, accessors: %i[destination host_keys], coder: JSON
|
store :values, accessors: %i[destination host_keys], coder: JSON
|
||||||
|
|
||||||
|
DEPENDENCIES = %i[deploy_local]
|
||||||
|
|
||||||
def deploy(output: false)
|
def deploy(output: false)
|
||||||
ssh? && rsync(output: output)
|
ssh? && rsync(output: output)
|
||||||
end
|
end
|
||||||
|
@ -88,7 +90,7 @@ class DeployRsync < Deploy
|
||||||
#
|
#
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
def rsync(output: false)
|
def rsync(output: false)
|
||||||
run %(rsync -aviH --timeout=5 #{Shellwords.escape source}/ #{Shellwords.escape destination}/), output: output
|
run %(rsync -aviH --delete-after --timeout=5 #{Shellwords.escape source}/ #{Shellwords.escape destination}/), output: output
|
||||||
end
|
end
|
||||||
|
|
||||||
# El origen es el destino de la compilación
|
# El origen es el destino de la compilación
|
||||||
|
|
|
@ -4,9 +4,13 @@
|
||||||
class DeployWww < Deploy
|
class DeployWww < Deploy
|
||||||
store :values, accessors: %i[], coder: JSON
|
store :values, accessors: %i[], coder: JSON
|
||||||
|
|
||||||
|
DEPENDENCIES = %i[deploy_local]
|
||||||
|
|
||||||
before_destroy :remove_destination!
|
before_destroy :remove_destination!
|
||||||
|
|
||||||
def deploy(**)
|
def deploy(output: false)
|
||||||
|
puts "Creando symlink #{site.hostname} => #{destination}" if output
|
||||||
|
|
||||||
File.symlink?(destination) ||
|
File.symlink?(destination) ||
|
||||||
File.symlink(site.hostname, destination).zero?
|
File.symlink(site.hostname, destination).zero?
|
||||||
end
|
end
|
||||||
|
@ -28,7 +32,7 @@ class DeployWww < Deploy
|
||||||
end
|
end
|
||||||
|
|
||||||
def url
|
def url
|
||||||
"https://www.#{site.hostname}/"
|
"https://#{fqdn}/"
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -8,28 +8,49 @@ require 'zip'
|
||||||
class DeployZip < Deploy
|
class DeployZip < Deploy
|
||||||
store :values, accessors: %i[], coder: JSON
|
store :values, accessors: %i[], coder: JSON
|
||||||
|
|
||||||
|
DEPENDENCIES = %i[deploy_local]
|
||||||
|
|
||||||
# Una vez que el sitio está generado, tomar todos los archivos y
|
# Una vez que el sitio está generado, tomar todos los archivos y
|
||||||
# y generar un zip accesible públicamente.
|
# y generar un zip accesible públicamente.
|
||||||
#
|
#
|
||||||
# rubocop:disable Metrics/MethodLength
|
# rubocop:disable Metrics/MethodLength
|
||||||
def deploy(**)
|
def deploy(output: false)
|
||||||
FileUtils.rm_f path
|
FileUtils.rm_f path
|
||||||
|
|
||||||
time_start
|
time_start
|
||||||
Dir.chdir(destination) do
|
Zip::File.open(path, Zip::File::CREATE) do |zip|
|
||||||
Zip::File.open(path, Zip::File::CREATE) do |z|
|
Dir.glob(File.join(destination, '**', '**')).each do |file|
|
||||||
Dir.glob('./**/**').each do |f|
|
entry = Pathname.new(file).relative_path_from(destination).to_s
|
||||||
File.directory?(f) ? z.mkdir(f) : z.add(f, f)
|
|
||||||
|
if File.directory? file
|
||||||
|
log "Creando directorio #{entry}", output
|
||||||
|
|
||||||
|
zip.mkdir(entry)
|
||||||
|
else
|
||||||
|
log "Comprimiendo #{entry}", output
|
||||||
|
zip.add(entry, file)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
time_stop
|
time_stop
|
||||||
|
|
||||||
build_stats.create action: 'zip',
|
File.exist?(path).tap do |status|
|
||||||
seconds: time_spent_in_seconds,
|
build_stats.create action: 'zip',
|
||||||
bytes: size
|
seconds: time_spent_in_seconds,
|
||||||
|
bytes: size,
|
||||||
|
log: @log.join("\n"),
|
||||||
|
status: status
|
||||||
|
end
|
||||||
|
rescue Zip::Error => e
|
||||||
|
ExceptionNotifier.notify_exception(e, data: { site: site.name })
|
||||||
|
|
||||||
File.exist? path
|
build_stats.create action: 'zip',
|
||||||
|
seconds: 0,
|
||||||
|
bytes: 0,
|
||||||
|
log: @log.join("\n"),
|
||||||
|
status: false
|
||||||
|
|
||||||
|
false
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/MethodLength
|
# rubocop:enable Metrics/MethodLength
|
||||||
|
|
||||||
|
@ -41,8 +62,9 @@ class DeployZip < Deploy
|
||||||
File.size path
|
File.size path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [String]
|
||||||
def destination
|
def destination
|
||||||
File.join(Rails.root, '_deploy', site.hostname)
|
Rails.root.join('_deploy', site.hostname).realpath.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def file
|
def file
|
||||||
|
@ -56,4 +78,15 @@ class DeployZip < Deploy
|
||||||
def path
|
def path
|
||||||
File.join(destination, file)
|
File.join(destination, file)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# @param :line [String]
|
||||||
|
# @param :output [Boolean]
|
||||||
|
def log(line, output)
|
||||||
|
@log ||= []
|
||||||
|
@log << line
|
||||||
|
|
||||||
|
puts line if output
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,7 @@ class Site < ApplicationRecord
|
||||||
include Site::Forms
|
include Site::Forms
|
||||||
include Site::FindAndReplace
|
include Site::FindAndReplace
|
||||||
include Site::Api
|
include Site::Api
|
||||||
|
include Site::DeployDependencies
|
||||||
include Tienda
|
include Tienda
|
||||||
|
|
||||||
# Cifrar la llave privada que cifra y decifra campos ocultos. Sutty
|
# Cifrar la llave privada que cifra y decifra campos ocultos. Sutty
|
||||||
|
|
38
app/models/site/deploy_dependencies.rb
Normal file
38
app/models/site/deploy_dependencies.rb
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rgl/adjacency'
|
||||||
|
require 'rgl/topsort'
|
||||||
|
|
||||||
|
class Site
|
||||||
|
module DeployDependencies
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
# Genera un grafo dirigido de todos los métodos de publicación
|
||||||
|
#
|
||||||
|
# @return [RGL::DirectedAdjacencyGraph]
|
||||||
|
def deployment_graph
|
||||||
|
@deployment_graph ||= RGL::DirectedAdjacencyGraph.new.tap do |graph|
|
||||||
|
deploys.each do |deploy|
|
||||||
|
graph.add_vertex deploy
|
||||||
|
end
|
||||||
|
|
||||||
|
deploys.each do |deploy|
|
||||||
|
deploy.class::DEPENDENCIES.each do |dependency|
|
||||||
|
deploys.where(type: dependency.to_s.classify).each do |deploy_dependency|
|
||||||
|
graph.add_edge deploy_dependency, deploy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Devuelve una lista ordenada de todos los métodos de publicación
|
||||||
|
#
|
||||||
|
# @return [Array]
|
||||||
|
def deployment_list
|
||||||
|
@deployment_list ||= deployment_graph.topsort_iterator.to_a
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -152,7 +152,7 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
|
||||||
# Crea los deploys necesarios para sincronizar a otros nodos de Sutty
|
# Crea los deploys necesarios para sincronizar a otros nodos de Sutty
|
||||||
def sync_nodes
|
def sync_nodes
|
||||||
Rails.application.nodes.each do |node|
|
Rails.application.nodes.each do |node|
|
||||||
site.deploys.build(type: 'DeployRsync', destination: "sutty@#{node}:#{site.hostname}")
|
site.deploys.build(type: 'DeployFullRsync', destination: "sutty@#{node}:")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Cambia todos los DeployRsync propios de Sutty a DeployFullRsync que se
|
||||||
|
# encarga de sincronizar todo.
|
||||||
|
class RenameDeployRsyncToDeployFullRsync < ActiveRecord::Migration[6.1]
|
||||||
|
def up
|
||||||
|
DeployRsync.all.find_each do |deploy|
|
||||||
|
dest = deploy.destination.split(':', 2).first
|
||||||
|
|
||||||
|
next unless nodes.include? dest
|
||||||
|
|
||||||
|
deploy.destination = "#{dest}:"
|
||||||
|
deploy.type = 'DeployFullRsync'
|
||||||
|
|
||||||
|
deploy.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
DeployFullRsync.all.find_each do |deploy|
|
||||||
|
next unless nodes.include? deploy.destination.split(':', 2).first
|
||||||
|
|
||||||
|
deploy.destination = "#{deploy.destination}#{deploy.site.hostname}"
|
||||||
|
deploy.type = 'DeployRsync'
|
||||||
|
|
||||||
|
deploy.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def nodes
|
||||||
|
@nodes ||= Rails.application.nodes.map do |node|
|
||||||
|
"sutty@#{node}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue