diff --git a/Gemfile b/Gemfile index 813c7ebd..eab87148 100644 --- a/Gemfile +++ b/Gemfile @@ -44,7 +44,6 @@ gem 'devise' gem 'devise-i18n' gem 'devise_invitable' gem 'distributed-press-api-client', '~> 0.3.0rc0' -gem 'njalla-api-client', '~> 0.2.0' gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n' gem 'exception_notification' gem 'fast_blank' diff --git a/Gemfile.lock b/Gemfile.lock index 79fbdde6..0dd841b0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -359,9 +359,6 @@ GEM net-ssh (7.1.0) netaddr (2.0.6) nio4r (2.5.9-x86_64-linux-musl) - njalla-api-client (0.2.0) - dry-schema - httparty (~> 0.18) nokogiri (1.15.4-x86_64-linux-musl) mini_portile2 (~> 2.8.2) racc (~> 1.4) @@ -623,7 +620,6 @@ DEPENDENCIES mini_magick mobility net-ssh - njalla-api-client (~> 0.2.0) nokogiri pg pg_search diff --git a/app/jobs/deploy_job.rb b/app/jobs/deploy_job.rb index 54a67093..1476315d 100644 --- a/app/jobs/deploy_job.rb +++ b/app/jobs/deploy_job.rb @@ -56,6 +56,10 @@ class DeployJob < ApplicationJob rescue URI::Error nil end.compact + + if d == @site.deployment_list.last && !status + raise DeployException, 'Falló la compilación' + end rescue StandardError => e status = false seconds ||= 0 diff --git a/app/jobs/git_pull_job.rb b/app/jobs/git_pull_job.rb index 1dab07bf..16e2fe5b 100644 --- a/app/jobs/git_pull_job.rb +++ b/app/jobs/git_pull_job.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true -# Permite traer los cambios desde webhooks - +# Permite traer los cambios desde el repositorio remoto class GitPullJob < ApplicationJob # @param :site [Site] # @param :usuarie [Usuarie] @@ -9,9 +8,20 @@ class GitPullJob < ApplicationJob # @return [nil] def perform(site, usuarie, message) return unless site.repository.origin - return unless site.repository.fetch.positive? - site.repository.merge(usuarie, message) + site.repository.fetch + + return if site.repository.up_to_date? + + if site.repository.fast_forward? + site.repository.fast_forward! + else + site.repository.merge(usuarie, message) + end + + site.repository.git_lfs_checkout site.reindex_changes! + + nil end end diff --git a/app/models/deploy_distributed_press.rb b/app/models/deploy_distributed_press.rb index 10d6b9b1..addb817d 100644 --- a/app/models/deploy_distributed_press.rb +++ b/app/models/deploy_distributed_press.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'distributed_press/v1/client/site' -require 'njalla/v1' # Soportar Distributed Press APIv1 # @@ -13,10 +12,10 @@ require 'njalla/v1' # Al ser publicado, envía los archivos en un tarball y actualiza la # información. class DeployDistributedPress < Deploy - store :values, accessors: %i[hostname remote_site_id remote_info], coder: JSON + store :values, accessors: %i[hostname remote_site_id remote_info distributed_press_publisher_id], coder: JSON - before_create :create_remote_site!, :create_njalla_records! - before_destroy :delete_remote_site!, :delete_njalla_records! + before_create :create_remote_site! + before_destroy :delete_remote_site! DEPENDENCIES = %i[deploy_local] @@ -31,17 +30,12 @@ class DeployDistributedPress < Deploy time_start create_remote_site! if remote_site_id.blank? - create_njalla_records! save if remote_site_id.blank? raise DeployJob::DeployException, 'El sitio no se creó en Distributed Press' end - if create_njalla_records? && remote_info[:njalla].blank? - raise DeployJob::DeployException, 'No se pudieron crear los registros necesarios en Njalla' - end - site_client.tap do |c| stdout = Thread.new(publisher.logger_out) do |io| until io.eof? @@ -101,12 +95,14 @@ class DeployDistributedPress < Deploy # El cliente de la API # - # TODO: cuando soportemos más, tiene que haber una relación entre - # DeployDistributedPress y DistributedPressPublisher. - # # @return [DistributedPressPublisher] def publisher - @publisher ||= DistributedPressPublisher.last + @publisher ||= + if distributed_press_publisher_id + DistributedPressPublisher.find(distributed_press_publisher_id) + else + DistributedPressPublisher.find_by_default(true) + end end # El cliente para actualizar el sitio @@ -147,29 +143,6 @@ class DeployDistributedPress < Deploy nil end - # Crea los registros en Njalla - # - # XXX: Esto depende de nuestro DNS actual, cuando lo migremos hay - # que eliminarlo. - # - # @return [nil] - def create_njalla_records! - return unless create_njalla_records? - - self.remote_info ||= {} - self.remote_info[:njalla] ||= {} - self.remote_info[:njalla][:a] ||= njalla.add_record(name: site.name, type: 'CNAME', content: "#{Site.domain}.").to_h - self.remote_info[:njalla][:cname] ||= njalla.add_record(name: "www.#{site.name}", type: 'CNAME', content: "#{Site.domain}.").to_h - self.remote_info[:njalla][:ns] ||= njalla.add_record(name: "_dnslink.#{site.name}", type: 'NS', content: "#{publisher.hostname}.").to_h - - nil - rescue HTTParty::Error => e - ExceptionNotifier.notify_exception(e, data: { site: site.name }) - self.remote_info.delete :njalla - ensure - nil - end - # Registra lo que sucedió # # @param status [Bool] @@ -187,31 +160,4 @@ class DeployDistributedPress < Deploy ExceptionNotifier.notify_exception(e, data: { site: site.name }) nil end - - def delete_njalla_records! - return unless create_njalla_records? - - %w[a ns cname].each do |type| - next if (id = remote_info.dig('njalla', type, 'id')).blank? - - njalla.remove_record(id: id.to_i) - end - end - - # Actualizar registros en Njalla - # - # @return [Njalla::V1::Domain] - def njalla - @njalla ||= - begin - client = Njalla::V1::Client.new(token: Rails.application.credentials.njalla) - - Njalla::V1::Domain.new(domain: Site.domain, client: client) - end - end - - # Detecta si tenemos que crear registros en Njalla - def create_njalla_records? - !site.name.end_with?('.') - end end diff --git a/app/models/distributed_press_publisher.rb b/app/models/distributed_press_publisher.rb index 6139db93..4c3293e3 100644 --- a/app/models/distributed_press_publisher.rb +++ b/app/models/distributed_press_publisher.rb @@ -13,8 +13,8 @@ class DistributedPressPublisher < ApplicationRecord # @return [IO] attr_reader :logger_out - # La instancia es única - validates_uniqueness_of :instance + # La instancia es necesaria pero no única + validates_presence_of :instance # El token es necesario validates_presence_of :token diff --git a/app/models/site.rb b/app/models/site.rb index 0139d8ed..0addd134 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -429,8 +429,8 @@ class Site < ApplicationRecord config.theme = design.gem unless design.no_theme? config.description = description config.title = title - config.url = url(slash: false) - config.hostname = hostname + config.url ||= url(slash: false) + config.hostname ||= hostname config.locales = locales.map(&:to_s) end diff --git a/app/models/site/repository.rb b/app/models/site/repository.rb index acbf6553..e77aded9 100644 --- a/app/models/site/repository.rb +++ b/app/models/site/repository.rb @@ -75,13 +75,18 @@ class Site # Forzamos el checkout para mover el HEAD al último commit y # escribir los cambios rugged.checkout 'HEAD', strategy: :force - - git_sh("git", "lfs", "fetch", "origin", default_branch) - # reemplaza los pointers por los archivos correspondientes - git_sh("git", "lfs", "checkout") + commit end + # Trae todos los archivos desde LFS + # + # @return [Boolean] + def git_lfs_checkout + git_sh('git', 'lfs', 'fetch', 'origin', default_branch) + git_sh('git', 'lfs', 'checkout') + end + # El último commit # # @return [Rugged::Commit] @@ -111,10 +116,30 @@ class Site walker.each.to_a end - # Hay commits sin aplicar? - def needs_pull? - fetch - !commits.empty? + # Detecta si hay que hacer un pull o no + # + # @return [Boolean] + def up_to_date? + rugged.merge_analysis(remote_head_commit).include?(:up_to_date) + end + + # Detecta si es posible adelantar la historia local a la remota o + # necesitamos un merge + # + # @return [Boolean] + def fast_forward? + rugged.merge_analysis(remote_head_commit).include?(:fastforward) + end + + # Mueve la historia local a la remota + # + # @see {https://stackoverflow.com/a/27077322} + # @return [nil] + def fast_forward! + rugged.checkout_tree(remote_head_commit) + rugged.references.update(rugged.head.resolve, remote_head_commit.oid) + + nil end # Guarda los cambios en git diff --git a/db/migrate/20231101200026_add_default_to_distributed_press_publisher.rb b/db/migrate/20231101200026_add_default_to_distributed_press_publisher.rb new file mode 100644 index 00000000..ada9392f --- /dev/null +++ b/db/migrate/20231101200026_add_default_to_distributed_press_publisher.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Una instancia es la instancia por defecto +class AddDefaultToDistributedPressPublisher < ActiveRecord::Migration[6.1] + def up + add_column :distributed_press_publishers, :default, :boolean, default: false + + DistributedPressPublisher.last.update(default: true) + end + + def down + remove_column :distributed_press_publishers, :default + end +end diff --git a/db/structure.sql b/db/structure.sql index e0d8f710..20c552a1 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -16,6 +16,20 @@ SET row_security = off; -- *not* creating schema, since initdb creates it +-- +-- Name: dblink; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS dblink WITH SCHEMA public; + + +-- +-- Name: EXTENSION dblink; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION dblink IS 'connect to other PostgreSQL databases from within a database'; + + -- -- Name: pg_trgm; Type: EXTENSION; Schema: -; Owner: - -- @@ -1149,7 +1163,8 @@ CREATE TABLE public.roles ( site_id integer, usuarie_id integer, rol character varying, - temporal boolean + temporal boolean, + token character varying ); @@ -1236,7 +1251,9 @@ CREATE TABLE public.sites ( tienda_url character varying DEFAULT ''::character varying, api_key_ciphertext character varying, slugify_mode character varying DEFAULT 'default'::character varying, - pagination boolean DEFAULT false + pagination boolean DEFAULT false, + private_key_pem_ciphertext text, + last_indexed_commit character varying ); @@ -2234,6 +2251,13 @@ ALTER TABLE ONLY public.active_storage_attachments ADD CONSTRAINT fk_rails_c3b3935057 FOREIGN KEY (blob_id) REFERENCES public.active_storage_blobs(id); +-- +-- Name: publisher; Type: PUBLICATION; Schema: -; Owner: - +-- + +CREATE PUBLICATION publisher FOR ALL TABLES WITH (publish = 'insert, update, delete, truncate'); + + -- -- PostgreSQL database dump complete -- @@ -2318,6 +2342,10 @@ INSERT INTO "schema_migrations" (version) VALUES ('20230421182627'), ('20230424174544'), ('20230519143500'), -('20230524190240'); +('20230524190240'), +('20230731195050'), +('20230829204127'), +('20230921155401'), +('20230927153926');