From 05813710f0bc3c2fc15b816996e9c9b7d3ccc435 Mon Sep 17 00:00:00 2001 From: Brian Shand Date: Wed, 30 Apr 2025 11:02:20 +0100 Subject: [PATCH 1/4] Capistrano: cap deploy:setup should be safe on existing deployments --- CHANGELOG.md | 1 + lib/ndr_dev_support/capistrano/ndr_model.rb | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5efd83a..117ee23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## [Unreleased] ### Fixed * Capistrano: Add missing `tmpdir` requirement to deploy application secrets +* Capistrano: cap deploy:setup should be safe on existing deployments ## 7.3.1 / 2025-01-02 ### Added diff --git a/lib/ndr_dev_support/capistrano/ndr_model.rb b/lib/ndr_dev_support/capistrano/ndr_model.rb index e423af9..1b209ac 100644 --- a/lib/ndr_dev_support/capistrano/ndr_model.rb +++ b/lib/ndr_dev_support/capistrano/ndr_model.rb @@ -53,11 +53,15 @@ # sticky; all deployments made within it should be owned by the deployer group too. This # means that e.g. a deployment by "bob.smith" can then be rolled back by "tom.jones". run "mkdir -p #{deploy_to}" - run "chgrp -R deployer #{deploy_to}" + # Set deployer group for everything created by this user + # run "chgrp -R deployer #{deploy_to}" + run "find #{deploy_to} -group #{fetch(:user)} -print0 |xargs -r0 chgrp -h deployer" # The sticky group will apply automatically to new subdirectories, but # any existing subdirectories will need it manually applying via `-R`. - run "chmod -R g+s #{deploy_to}" + # run "chmod -R g+s #{deploy_to}" + run "find #{deploy_to} -user #{fetch(:user)} -type d " \ + '-not -perm -2000 -print0 |xargs -r0 chmod g+s' end desc 'Custom tasks to be run once, after the initial `cap setup`' @@ -67,8 +71,12 @@ run "mkdir -p #{full_path}" # Allow the application to write into here: - run "chgrp -R #{application_group} #{full_path}" - run "chmod -R g+s #{full_path}" + # run "chgrp -R #{application_group} #{full_path}" + # run "chmod -R g+s #{full_path}" + run "find #{full_path} -user #{fetch(:user)} -not -group #{application_group} " \ + "-print0 |xargs -r0 chgrp -h #{application_group}" + run "find #{full_path} -user #{fetch(:user)} -type d " \ + '-not -perm -2000 -print0 |xargs -r0 chmod g+s' end fetch(:shared_paths, []).each do |path| From 14a9c57214287950b4cefdf87ef3b1652ac9634d Mon Sep 17 00:00:00 2001 From: Brian Shand Date: Wed, 30 Apr 2025 23:14:50 +0100 Subject: [PATCH 2/4] Capistrano: add task deploy:preinstall to preinstall ruby and bundled gems --- CHANGELOG.md | 3 ++ lib/ndr_dev_support/capistrano/ndr_model.rb | 9 +++++ lib/ndr_dev_support/capistrano/preinstall.rb | 37 +++++++++++++++++++ .../capistrano/revision_logger.rb | 6 +-- 4 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 lib/ndr_dev_support/capistrano/preinstall.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 117ee23..cec350b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ * Capistrano: Add missing `tmpdir` requirement to deploy application secrets * Capistrano: cap deploy:setup should be safe on existing deployments +### Added +* Capistrano: add task deploy:preinstall to preinstall ruby and bundled gems + ## 7.3.1 / 2025-01-02 ### Added * Capistrano: deploy application secrets from a subversion or git repository diff --git a/lib/ndr_dev_support/capistrano/ndr_model.rb b/lib/ndr_dev_support/capistrano/ndr_model.rb index 1b209ac..b229a01 100644 --- a/lib/ndr_dev_support/capistrano/ndr_model.rb +++ b/lib/ndr_dev_support/capistrano/ndr_model.rb @@ -4,6 +4,7 @@ require_relative 'assets' require_relative 'deploy_secrets' require_relative 'install_ruby' +require_relative 'preinstall' require_relative 'restart' require_relative 'revision_logger' require_relative 'ruby_version' @@ -193,6 +194,14 @@ def target_ruby_version_for(env) match ? match[:version] : raise('Unrecognized Ruby version!') end +def log_deployment_message(msg) + name = fetch(:deployer_name, capture('id -un').chomp) + log = File.join(shared_path, 'revisions.log') + msg = "[#{Time.now}] #{name} #{msg}" # rubocop:disable Rails/TimeZone + + run "(test -e #{log} || (touch #{log} && chmod 664 #{log})) && echo #{Shellwords.escape(msg)} >> #{log};" +end + def add_target(env, name, app, port, app_user, is_web_server) desc "Deploy to #{env} service #{app_user || 'you'}@#{app}:#{port}" task(name) do diff --git a/lib/ndr_dev_support/capistrano/preinstall.rb b/lib/ndr_dev_support/capistrano/preinstall.rb new file mode 100644 index 0000000..f71c995 --- /dev/null +++ b/lib/ndr_dev_support/capistrano/preinstall.rb @@ -0,0 +1,37 @@ +Capistrano::Configuration.instance(:must_exist).load do + namespace :deploy do + desc <<~DESC + Preinstall ruby and gems, then abort and rollback cleanly, leaving the + current installation unchanged. + + This is particularly useful for ruby version bumps: installing the new + ruby version and all the bundled gems can take a long time. + + This aborts before updating out-of-bundle gems, in case that causes + issues when restarting the currently installed version. + + Usage: + cap target deploy:preinstall + DESC + task :preinstall do + # Running this task sets a flag, to make ndr_dev_support:check_preinstall abort. + # We do this in a roundabout way on Capistrano 2, because deploy:update_code + # explicitly runs deploy:finalize_update, instead of using task dependencies. + set :preinstall, true + end + end + + namespace :ndr_dev_support do + desc 'Hook to abort capistrano installation early after preinstalling ruby and in-bundle gems' + task :check_preinstall do + next unless fetch(:preinstall, false) + + log_deployment_message("preinstalled #{real_revision}") + warn Rainbow("Successful preinstall for target: #{fetch(:name)}") + abort 'Aborting after successful preinstall' + end + end + + after 'deploy:preinstall', 'deploy:update' + before 'ndr_dev_support:update_out_of_bundle_gems', 'ndr_dev_support:check_preinstall' +end diff --git a/lib/ndr_dev_support/capistrano/revision_logger.rb b/lib/ndr_dev_support/capistrano/revision_logger.rb index 97af468..8178b74 100644 --- a/lib/ndr_dev_support/capistrano/revision_logger.rb +++ b/lib/ndr_dev_support/capistrano/revision_logger.rb @@ -2,11 +2,7 @@ namespace :ndr_dev_support do desc 'Append to the log of deployments the user and revision.' task :log_deployment, except: { no_release: true } do - name = fetch(:deployer_name, capture('id -un')) - log = File.join(shared_path, 'revisions.log') - msg = "[#{Time.now}] #{name} deployed #{latest_revision}" - - run "(test -e #{log} || (touch #{log} && chmod 664 #{log})) && echo #{msg} >> #{log};" + log_deployment_message("deployed #{latest_revision}") end end From 3ce898224702b45244fc5aa5f50cbb61b554fa4f Mon Sep 17 00:00:00 2001 From: Brian Shand Date: Wed, 30 Apr 2025 23:22:30 +0100 Subject: [PATCH 3/4] Drop support for Rails 6.1 --- .github/workflows/test.yml | 1 - CHANGELOG.md | 3 +++ gemfiles/Gemfile.rails61 | 7 ------- 3 files changed, 3 insertions(+), 8 deletions(-) delete mode 100644 gemfiles/Gemfile.rails61 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 15c5779..1dfda55 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,6 @@ jobs: - '3.2' - '3.3' gemfile: - - gemfiles/Gemfile.rails61 - gemfiles/Gemfile.rails70 - gemfiles/Gemfile.rails71 - gemfiles/Gemfile.rails72 diff --git a/CHANGELOG.md b/CHANGELOG.md index cec350b..a47295e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ ### Added * Capistrano: add task deploy:preinstall to preinstall ruby and bundled gems +## Changed +* Drop support for Rails 6.1 + ## 7.3.1 / 2025-01-02 ### Added * Capistrano: deploy application secrets from a subversion or git repository diff --git a/gemfiles/Gemfile.rails61 b/gemfiles/Gemfile.rails61 deleted file mode 100644 index 6083b3b..0000000 --- a/gemfiles/Gemfile.rails61 +++ /dev/null @@ -1,7 +0,0 @@ -source 'https://rubygems.org' -gemspec path: '..' - -gem 'activesupport', '~> 6.1.0' - -# Latest concurrent-ruby breaks Rails < 7.1. See https://github.com/rails/rails/issues/54260 -gem 'concurrent-ruby', '1.3.4' From dc8da419fb1a96b1e01f5535ae3be78b8b73c703 Mon Sep 17 00:00:00 2001 From: Brian Shand Date: Wed, 30 Apr 2025 23:26:23 +0100 Subject: [PATCH 4/4] Fix rubocop plugin warning --- config/rubocop/ndr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/rubocop/ndr.yml b/config/rubocop/ndr.yml index 853f50a..e843553 100644 --- a/config/rubocop/ndr.yml +++ b/config/rubocop/ndr.yml @@ -4,7 +4,7 @@ # # See the README for instructions on using in a project. -require: +plugins: - rubocop-rails - rubocop-rake