2019-07-26 00:36:33 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
# Realiza el deploy de un sitio
|
2019-09-16 16:44:29 +00:00
|
|
|
class DeployJob < ApplicationJob
|
2019-09-25 22:34:39 +00:00
|
|
|
class DeployException < StandardError; end
|
2023-03-13 20:29:13 +00:00
|
|
|
class DeployTimedOutException < DeployException; end
|
2023-04-10 16:28:32 +00:00
|
|
|
class DeployAlreadyRunningException < DeployException; end
|
2019-09-25 22:34:39 +00:00
|
|
|
|
2022-04-05 19:25:47 +00:00
|
|
|
discard_on ActiveRecord::RecordNotFound
|
|
|
|
|
2023-04-10 16:28:32 +00:00
|
|
|
# Lanzar lo antes posible
|
|
|
|
self.priority = 10
|
|
|
|
|
|
|
|
def handle_error(error)
|
|
|
|
case error
|
|
|
|
when DeployAlreadyRunningException then retry_in 1.minute
|
|
|
|
when DeployTimedOutException then expire
|
|
|
|
else super
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-09-25 22:34:39 +00:00
|
|
|
# rubocop:disable Metrics/MethodLength
|
2022-03-15 19:03:16 +00:00
|
|
|
def perform(site, notify: true, time: Time.now, output: false)
|
|
|
|
@output = output
|
|
|
|
|
2019-09-18 19:28:30 +00:00
|
|
|
ActiveRecord::Base.connection_pool.with_connection do
|
2019-09-25 22:34:39 +00:00
|
|
|
@site = Site.find(site)
|
2021-05-10 13:56:08 +00:00
|
|
|
|
2021-07-29 17:46:29 +00:00
|
|
|
# Si ya hay una tarea corriendo, aplazar esta. Si estuvo
|
|
|
|
# esperando más de 10 minutos, recuperar el estado anterior.
|
|
|
|
#
|
|
|
|
# Como el trabajo actual se aplaza al siguiente, arrastrar la
|
|
|
|
# hora original para poder ir haciendo timeouts.
|
2021-05-10 16:14:02 +00:00
|
|
|
if @site.building?
|
2023-04-10 16:28:32 +00:00
|
|
|
notify = false
|
|
|
|
|
2021-07-29 17:46:29 +00:00
|
|
|
if 10.minutes.ago >= time
|
2023-03-13 20:29:13 +00:00
|
|
|
raise DeployTimedOutException,
|
2021-07-29 17:46:29 +00:00
|
|
|
"#{@site.name} la tarea estuvo más de 10 minutos esperando, volviendo al estado original"
|
2023-04-10 16:28:32 +00:00
|
|
|
else
|
|
|
|
raise DeployAlreadyRunningException
|
2021-07-29 17:46:29 +00:00
|
|
|
end
|
2021-05-10 13:56:08 +00:00
|
|
|
end
|
|
|
|
|
2023-03-18 16:42:47 +00:00
|
|
|
@deployed = {}
|
2021-05-10 13:56:08 +00:00
|
|
|
@site.update status: 'building'
|
2023-03-18 16:42:47 +00:00
|
|
|
@site.deployment_list.each do |d|
|
|
|
|
begin
|
|
|
|
raise DeployException, 'Una dependencia falló' if failed_dependencies? d
|
2019-07-26 00:36:33 +00:00
|
|
|
|
2023-03-18 20:01:38 +00:00
|
|
|
status = d.deploy(output: @output)
|
2023-03-18 20:00:29 +00:00
|
|
|
seconds = d.build_stats.last.try(:seconds) || 0
|
2023-03-18 16:47:34 +00:00
|
|
|
size = d.size
|
2023-08-31 17:41:34 +00:00
|
|
|
urls = (d.respond_to?(:urls) ? d.urls : [d.url].compact).map do |url|
|
|
|
|
URI.parse url
|
|
|
|
rescue URI::Error
|
|
|
|
nil
|
|
|
|
end.compact
|
2023-03-18 16:42:47 +00:00
|
|
|
rescue StandardError => e
|
|
|
|
status = false
|
2023-03-18 18:22:10 +00:00
|
|
|
seconds ||= 0
|
|
|
|
size ||= 0
|
2023-03-24 16:30:14 +00:00
|
|
|
# XXX: Hace que se vea la tabla
|
|
|
|
urls ||= [nil]
|
2023-03-18 16:42:47 +00:00
|
|
|
|
|
|
|
notify_exception e, d
|
|
|
|
end
|
2019-07-26 00:36:33 +00:00
|
|
|
|
2023-03-18 16:42:47 +00:00
|
|
|
@deployed[d.type.underscore.to_sym] = {
|
|
|
|
status: status,
|
2023-03-18 18:22:10 +00:00
|
|
|
seconds: seconds,
|
2023-03-18 16:47:34 +00:00
|
|
|
size: size,
|
2023-03-18 18:22:10 +00:00
|
|
|
urls: urls
|
2023-03-18 16:42:47 +00:00
|
|
|
}
|
|
|
|
end
|
2023-03-18 17:59:34 +00:00
|
|
|
|
|
|
|
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)
|
2023-03-13 21:46:22 +00:00
|
|
|
ensure
|
2023-03-23 21:02:43 +00:00
|
|
|
if @site.present?
|
|
|
|
@site.update status: 'waiting'
|
2021-07-29 17:46:29 +00:00
|
|
|
|
2023-03-23 21:02:43 +00:00
|
|
|
notify_usuaries if notify
|
2023-03-18 20:02:38 +00:00
|
|
|
|
2023-03-23 21:02:43 +00:00
|
|
|
puts "\a" if @output
|
|
|
|
end
|
2019-09-18 19:28:30 +00:00
|
|
|
end
|
2019-07-26 00:36:33 +00:00
|
|
|
end
|
2019-09-25 22:34:39 +00:00
|
|
|
# rubocop:enable Metrics/MethodLength
|
2019-07-26 00:36:33 +00:00
|
|
|
|
|
|
|
private
|
|
|
|
|
2023-03-18 16:42:47 +00:00
|
|
|
# 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
|
|
|
|
|
2023-03-13 22:27:03 +00:00
|
|
|
# @param :exception [StandardError]
|
|
|
|
# @param :deploy [Deploy]
|
|
|
|
def notify_exception(exception, deploy = nil)
|
2023-03-13 23:04:53 +00:00
|
|
|
data = {
|
|
|
|
site: @site.id,
|
|
|
|
deploy: deploy&.type,
|
2023-03-18 16:42:47 +00:00
|
|
|
log: deploy&.build_stats&.last&.log,
|
|
|
|
failed_dependencies: (failed_dependencies(deploy) if deploy)
|
2023-03-13 23:04:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ExceptionNotifier.notify_exception(exception, data: data)
|
2023-03-13 22:27:03 +00:00
|
|
|
end
|
|
|
|
|
2019-09-25 22:34:39 +00:00
|
|
|
def notify_usuaries
|
2020-04-06 22:03:49 +00:00
|
|
|
@site.roles.where(rol: 'usuarie', temporal: false).pluck(:usuarie_id).each do |usuarie|
|
2020-03-24 17:14:55 +00:00
|
|
|
DeployMailer.with(usuarie: usuarie, site: @site.id)
|
2019-09-25 22:34:39 +00:00
|
|
|
.deployed(@deployed)
|
2019-07-26 00:36:33 +00:00
|
|
|
.deliver_now
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|