# frozen_string_literal: true # Realiza el deploy de un sitio class DeployJob < ApplicationJob class DeployException < StandardError; end class DeployTimedOutException < DeployException; end discard_on ActiveRecord::RecordNotFound # rubocop:disable Metrics/MethodLength def perform(site, notify: true, time: Time.now, output: false) @output = output ActiveRecord::Base.connection_pool.with_connection do @site = Site.find(site) # 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. if @site.building? if 10.minutes.ago >= time notify = false raise DeployTimedOutException, "#{@site.name} la tarea estuvo más de 10 minutos esperando, volviendo al estado original" end DeployJob.perform_in(60, site, notify: notify, time: time, output: output) return end @site.update status: 'building' # Asegurarse que DeployLocal sea el primero! @deployed = { deploy_local: { status: deploy_locally, seconds: deploy_local.build_stats.last.seconds, size: deploy_local.size, urls: [deploy_local.url] } } # No es opcional unless @deployed[:deploy_local][:status] # Hacer fallar la tarea raise DeployException, "#{@site.name}: Falló la compilación" end deploy_others rescue DeployTimedOutException => e notify_exception e rescue DeployException => e notify_exception e, deploy_local ensure @site&.update status: 'waiting' notify_usuaries if notify end end # rubocop:enable Metrics/MethodLength private # @param :exception [StandardError] # @param :deploy [Deploy] def notify_exception(exception, deploy = nil) data = { site: @site.id, deploy: deploy&.type, log: deploy&.build_stats&.last&.log } ExceptionNotifier.notify_exception(exception, data: data) 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 @site.roles.where(rol: 'usuarie', temporal: false).pluck(:usuarie_id).each do |usuarie| DeployMailer.with(usuarie: usuarie, site: @site.id) .deployed(@deployed) .deliver_now end end end