From e1664d0c1299e242bcfb87aa377e6b95db820dea Mon Sep 17 00:00:00 2001 From: f Date: Sun, 1 Aug 2021 21:50:44 -0300 Subject: [PATCH] Refactorizar Deploy * Validar los hostnames * Generar los hostnames por defecto * Cada Deploy sabe su propia URL --- app/models/deploy.rb | 87 ++++++++++++++++++++++++++++++++++++++------ app/models/site.rb | 71 +++++++++++++++++------------------- 2 files changed, 110 insertions(+), 48 deletions(-) diff --git a/app/models/deploy.rb b/app/models/deploy.rb index 3f034ad..cd70907 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -1,44 +1,85 @@ # frozen_string_literal: true require 'open3' + # Este modelo implementa los distintos tipos de alojamiento que provee # Sutty. # -# Los datos se guardan en la tabla `deploys`. Para guardar los -# atributos, cada modelo tiene que definir su propio `store -# :attributes`. +# TODO: Cambiar el nombre a algo que no sea industrial/militar. class Deploy < ApplicationRecord + # Un sitio puede tener muchas formas de publicarse. belongs_to :site + + # Siempre generar el hostname + after_initialize :default_hostname! + # Eliminar los archivos generados por el deploy. + before_destroy :remove_destination! + + # Registro de las tareas ejecutadas has_many :build_stats, dependent: :destroy + # Siempre tienen que pertenecer a un sitio + validates :site, presence: true + # El hostname tiene que ser único en toda la plataforma + validates :hostname, uniqueness: true + # Cada deploy puede implementar su propia validación + validates :hostname, hostname: true, unless: :implements_hostname_validation? + + # Genera el hostname + # + # @return [String] + def default_hostname + raise NotImplementedError + end + + # Devolver la URL + # + # @return [String] + def url + "https://#{hostname}" + end + + # Ejecutar la tarea + # + # @return [Boolean] def deploy raise NotImplementedError end - def limit - raise NotImplementedError - end - + # El espacio ocupado por este deploy. + # + # @return [Integer] def size raise NotImplementedError end + # Empezar a contar el tiempo + # + # @return [Time] def time_start @start = Time.now end + # Detener el contador + # + # @return [Time] def time_stop @stop = Time.now end + # Obtener la demora de la tarea + # + # @return [Float] def time_spent_in_seconds (@stop - @start).round(3) end - def home_dir - site.path - end - + # El directorio donde se almacenan las gemas. + # + # TODO: En un momento podíamos tenerlas todas compartidas y ahorrar + # espacio, pero bundler empezó a mezclar cosas. + # + # @return [String] def gems_dir @gems_dir ||= Rails.root.join('_storage', 'gems', site.name) end @@ -77,9 +118,33 @@ class Deploy < ApplicationRecord private + # Genera el hostname + # + # @return [Boolean] + def default_hostname! + self.hostname = default_hostname + true + end + + # Elimina los archivos generados por el deploy + # + # @return [Boolean] + def remove_destination! + raise NotImplementedError + end + + # Convierte el comando en una versión resumida. + # # @param [String] # @return [String] def readable_cmd(cmd) cmd.split(' -', 2).first.tr(' ', '_') end + + # Cada deploy puede decidir su propia validación + # + # @return [Boolean] + def implements_hostname_validation? + false + end end diff --git a/app/models/site.rb b/app/models/site.rb index 58f2074..2fc1344 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -85,47 +85,44 @@ class Site < ApplicationRecord @repository ||= Site::Repository.new path end - def hostname - sub = name || I18n.t('deploys.deploy_local.ejemplo') - - if sub.ends_with? '.' - sub.gsub(/\.\Z/, '') - else - "#{sub}.#{Site.domain}" - end + # El primer deploy del sitio + # + # @return [DeployLocal] + def deploy_local + @deploy_local ||= deploys.order(created_at: :asc).find_by(type: 'DeployLocal') end - # Devuelve la URL siempre actualizada a través del hostname + # Todas las URLs posibles para este sitio, ordenados según fecha de + # creación. # - # @param slash Boolean Agregar / al final o no - # @return String La URL con o sin / al final - def url(slash: true) - "https://#{hostname}#{slash ? '/' : ''}" - end - - # Obtiene los dominios alternativos - # - # @return Array - def alternative_hostnames - deploys.where(type: 'DeployAlternativeDomain').map(&:hostname).map do |h| - h.end_with?('.') ? h[0..-2] : "#{h}.#{Site.domain}" - end - end - - # Obtiene todas las URLs alternativas para este sitio - # - # @return Array - def alternative_urls(slash: true) - alternative_hostnames.map do |h| - "https://#{h}#{slash ? '/' : ''}" - end - end - - # Todas las URLs posibles para este sitio - # - # @return Array + # @param :slash [Boolean] Con o sin / al final, por defecto con + # @return [Array] def urls(slash: true) - alternative_urls(slash: slash) << url(slash: slash) + deploys.order(created_at: :asc).map(&:url).map do |url| + slash ? "#{url}/" : url + end + end + + # Todos los hostnames, ordenados según fecha de creación. + # + # @return [Array] + def hostnames + deploys.order(created_at: :asc).pluck(:hostname) + end + + # Obtiene la URL principal + # + # @param :slash [Boolean] + # @return [String] + def url(slash: true) + deploy_local.url.tap do |url| + "#{url}/" if slash + end + end + + # TODO: Usar DeployCanonical + def hostname + deploy_local.hostname end def invitade?(usuarie)