Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ jobs:
- '3.2'
- '3.3'
gemfile:
- gemfiles/Gemfile.rails61
- gemfiles/Gemfile.rails70
- gemfiles/Gemfile.rails71
- gemfiles/Gemfile.rails72
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
## [Unreleased]
### Fixed
* 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

## Changed
* Drop support for Rails 6.1

## 7.3.1 / 2025-01-02
### Added
Expand Down
2 changes: 1 addition & 1 deletion config/rubocop/ndr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# See the README for instructions on using in a project.

require:
plugins:
- rubocop-rails
- rubocop-rake

Expand Down
7 changes: 0 additions & 7 deletions gemfiles/Gemfile.rails61

This file was deleted.

25 changes: 21 additions & 4 deletions lib/ndr_dev_support/capistrano/ndr_model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -53,11 +54,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`'
Expand All @@ -67,8 +72,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|
Expand Down Expand Up @@ -185,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
Expand Down
37 changes: 37 additions & 0 deletions lib/ndr_dev_support/capistrano/preinstall.rb
Original file line number Diff line number Diff line change
@@ -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
6 changes: 1 addition & 5 deletions lib/ndr_dev_support/capistrano/revision_logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down