diff --git a/Gemfile b/Gemfile index 7e1beda9..9c50e322 100644 --- a/Gemfile +++ b/Gemfile @@ -69,7 +69,8 @@ gem 'redis', '~> 4.0', require: %w[redis redis/connection/hiredis] gem 'redis-rails' gem 'rollups', git: 'https://github.com/fauno/rollup.git', branch: 'update' gem 'rubyzip' -gem 'rugged' +gem 'rugged', '1.5.0.1' +gem 'git_clone_url' gem 'concurrent-ruby-ext' gem 'que' gem 'symbol-fstring', require: 'fstring/all' diff --git a/Gemfile.lock b/Gemfile.lock index a786e060..84ee0b5e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -218,6 +218,8 @@ GEM activerecord (>= 4.0.0) get_process_mem (0.2.7) ffi (~> 1.0) + git_clone_url (2.0.0) + uri-ssh_git (>= 2.0) globalid (1.1.0) activesupport (>= 5.0) groupdate (6.2.1) @@ -495,7 +497,7 @@ GEM ruby_parser (3.20.1) sexp_processor (~> 4.16) rubyzip (2.3.2) - rugged (1.6.3-x86_64-linux-musl) + rugged (1.5.0.1-x86_64-linux-musl) safe_yaml (1.0.6) safely_block (0.3.0) errbase (>= 0.1.1) @@ -554,6 +556,7 @@ GEM unf_ext unf_ext (0.0.8.2-x86_64-linux-musl) unicode-display_width (1.8.0) + uri-ssh_git (2.0.0) validates_hostname (1.0.13) activerecord (>= 3.0) activesupport (>= 3.0) @@ -608,6 +611,7 @@ DEPENDENCIES fast_jsonparser (~> 0.5.0) flamegraph friendly_id + git_clone_url hairtrigger haml-lint hamlit-rails @@ -652,7 +656,7 @@ DEPENDENCIES rollups! rubocop-rails rubyzip - rugged + rugged (= 1.5.0.1) safe_yaml safely_block (~> 0.3.0) sassc-rails diff --git a/app/jobs/git_push_job.rb b/app/jobs/git_push_job.rb new file mode 100644 index 00000000..3c62bee2 --- /dev/null +++ b/app/jobs/git_push_job.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +# Permite pushear los cambios cada vez que se +# hacen commits en un sitio +class GitPushJob < ApplicationJob + # @param :site [Site] + # @return [nil] + def perform(site) + site.repository.push if site.repository.origin + end +end \ No newline at end of file diff --git a/app/models/site.rb b/app/models/site.rb index 81264a24..e4e9799c 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -478,6 +478,9 @@ class Site < ApplicationRecord return if jekyll? Rugged::Repository.clone_at ENV['SKEL_SUTTY'], path + + # Necesita un bloque + repository.rugged.remotes.rename('origin', 'upstream') {} end # Elimina el directorio del sitio diff --git a/app/models/site/repository.rb b/app/models/site/repository.rb index 9c435fb5..2eafb92e 100644 --- a/app/models/site/repository.rb +++ b/app/models/site/repository.rb @@ -29,7 +29,7 @@ class Site # Obtiene el origin # - # @return [Rugged::Remote] + # @return [Rugged::Remote, nil] def origin @origin ||= rugged.remotes.find do |remote| remote.name == 'origin' @@ -153,27 +153,54 @@ class Site # # @return [Boolean] def gc - env = { 'PATH' => '/usr/bin', 'LANG' => ENV['LANG'], 'HOME' => path } - cmd = 'git gc' + git_sh("git", "gc") + end - r = nil - Open3.popen2e(env, cmd, unsetenv_others: true, chdir: path) do |_, _, t| - r = t.value - end - - r&.success? + # Pushea cambios al repositorio remoto + # + # @param :remote [Rugged::Remote] + # @return [Boolean, nil] + def push(remote = origin) + remote.push(rugged.head.canonical_name, credentials: credentials_for(remote)) + git_sh('git', 'lfs', 'push', remote.name, default_branch) end private + # @deprecated + def credentials + @credentials ||= credentials_for(origin) + end + # Si Sutty tiene una llave privada de tipo ED25519, devuelve las # credenciales necesarias para trabajar con repositorios remotos. # + # @param :remote [Rugged::Remote] # @return [Nil, Rugged::Credentials::SshKey] - def credentials + def credentials_for(remote) return unless File.exist? private_key - @credentials ||= Rugged::Credentials::SshKey.new username: 'git', publickey: public_key, privatekey: private_key + Rugged::Credentials::SshKey.new username: username_for(remote), publickey: public_key, privatekey: private_key + end + + # Obtiene el nombre de usuario para el repositorio remoto, por + # defecto git + # + # @param :remote [Rugged::Remote] + # @return [String] + def username_for(remote) + username = parse_url(remote.url)&.user if remote.respond_to? :url + + username || 'git' + end + + # @param :url [String] + # @return [URI, nil] + def parse_url(url) + GitCloneUrl.parse(url) + rescue URI::Error => e + ExceptionNotifier.notify_exception(e, data: { path: path, url: url }) + nil end # @return [String] @@ -189,5 +216,20 @@ class Site def relativize(file) Pathname.new(file).relative_path_from(Pathname.new(path)).to_s end + + # Ejecuta un comando de git + # + # @param :args [Array] + # @return [Boolean] + def git_sh(*args) + env = { 'PATH' => '/usr/bin', 'LANG' => ENV['LANG'], 'HOME' => path } + + r = nil + Open3.popen2e(env, *args, unsetenv_others: true, chdir: path) do |_, _, t| + r = t.value + end + + r&.success? + end end end diff --git a/app/services/post_service.rb b/app/services/post_service.rb index dda7992d..4631a9a4 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -102,6 +102,8 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do usuarie: usuarie, message: I18n.t("post_service.#{action}", title: post&.title&.value)) + + GitPushJob.perform_later(site) end # Solo permitir cambiar estos atributos de cada articulo diff --git a/app/services/site_service.rb b/app/services/site_service.rb index b1df3d10..5ed44b11 100644 --- a/app/services/site_service.rb +++ b/app/services/site_service.rb @@ -97,6 +97,8 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do add: [site.config.path], message: I18n.t("site_service.#{action}", name: site.name)) + + GitPushJob.perform_later(site) end def add_role(temporal: true, rol: 'invitade') diff --git a/db/migrate/20230921155401_site_rename_origin_to_upstream.rb b/db/migrate/20230921155401_site_rename_origin_to_upstream.rb new file mode 100644 index 00000000..864f4c4a --- /dev/null +++ b/db/migrate/20230921155401_site_rename_origin_to_upstream.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +# Renombrar todos los repositorios que apunten a skel como su origin +class SiteRenameOriginToUpstream < ActiveRecord::Migration[6.1] + # Renombrar + def up + Site.find_each do |site| + next unless site.repository.origin&.url == ENV['SKEL_SUTTY'] + + site.repository.rugged.remotes.rename('origin', 'upstream') do |_| + Rails.logger.info "#{site.name}: renamed origin to upstream" + end + rescue Rugged::Error, Rugged::OSError => e + Rails.logger.warn "#{site.name}: #{e.message}" + end + end + + # No se puede deshacer + def down; end +end