From 215c03fc9a53098e7c4b78378f42dc80287cd2de Mon Sep 17 00:00:00 2001 From: Brian Shand Date: Wed, 20 Nov 2024 20:40:48 +0000 Subject: [PATCH 1/4] Add csv library to explicit dependency list --- ndr_dev_support.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/ndr_dev_support.gemspec b/ndr_dev_support.gemspec index 7ff7327..74b9982 100644 --- a/ndr_dev_support.gemspec +++ b/ndr_dev_support.gemspec @@ -25,6 +25,7 @@ Gem::Specification.new do |spec| spec.add_dependency 'pry' # Audit dependencies: + spec.add_dependency 'csv' spec.add_dependency 'highline', '>= 1.6.0' # Rubocop dependencies: From 951c488e3f8542871a0c0d87da86152b83fdc657 Mon Sep 17 00:00:00 2001 From: Brian Shand Date: Wed, 20 Nov 2024 20:42:07 +0000 Subject: [PATCH 2/4] Capistrano: install rbenv and ruby from /opt/rbenv.tar.gz --- CHANGELOG.md | 3 +- .../capistrano/install_ruby.rb | 66 +++++++++++++++++++ lib/ndr_dev_support/capistrano/ndr_model.rb | 1 + 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 lib/ndr_dev_support/capistrano/install_ruby.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index ea27ee7..fbf3146 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## [Unreleased] -*no unreleased changes* +### Added +* Capistrano: install rbenv and ruby from /opt/rbenv.tar.gz ## 7.2.6 / 2024-11-13 ### Fixed diff --git a/lib/ndr_dev_support/capistrano/install_ruby.rb b/lib/ndr_dev_support/capistrano/install_ruby.rb new file mode 100644 index 0000000..01ec8ea --- /dev/null +++ b/lib/ndr_dev_support/capistrano/install_ruby.rb @@ -0,0 +1,66 @@ +Capistrano::Configuration.instance(:must_exist).load do + namespace :ndr_dev_support do + desc <<~DESC + Ensure that the required ruby version is installed. + + An offline copy of rbenv should be placed in /opt/rbenv.tar.gz + To make this file, for ruby 3.1.6, run the following commands: + $ mkdir clone_rbenv + $ git clone https://github.com/rbenv/rbenv.git clone_rbenv/.rbenv + $ git clone https://github.com/rbenv/ruby-build.git clone_rbenv/.rbenv/plugins/ruby-build + $ mkdir clone_rbenv/.rbenv/cache + $ (cd clone_rbenv/.rbenv/cache; curl -O https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.6.tar.gz) + $ (cd clone_rbenv; rm -f ../rbenv.tar.gz; tar czf ../rbenv.tar.gz .rbenv) + $ rm -rf clone_rbenv + $ scp -p rbenv.tar.gz app-server:/opt/rbenv.tar.gz + DESC + task :install_ruby do + version = fetch(:ruby) + # Note that ruby 3.1.x on CentOS 7 generally installs successfully but then reports an error: + # ERROR: While executing gem ... (URI::InvalidURIError) + # bad URI(is not URI?): "bundler\r" + # For this reason, we ignore the exit status, and run our own test. + # + # For some reason, SSH keepalive options have no effect with capistrano 2 and net-ssh 7. + # So we run a poor-man's keepalive, because this installation can take over 10 minutes + # and some of our SSH servers disconnect inactive sessions after 5 minutes. + # + # We remove ~/.rbenv paths from capistrano-defined PATH when running `rbenv init` + # so that it knows the path is needed in ~/.bash_profile + run <<~SHELL + set -e; + if ! rbenv versions --bare 2> /dev/null | grep -qF #{version}; then + echo Installing ruby #{version}; + { while true; do sleep 20; echo -n '.'; done & } 2> /dev/null; + sudo -i -n -u #{fetch(:application_user)} sh -c " + if [ ! -e .rbenv ] && [ -e /opt/rbenv.tar.gz ]; then + tar xf /opt/rbenv.tar.gz .rbenv; + PATH=\\`echo \\"\\$PATH\\"|sed -e \\"s_[^:=]*/[.]rbenv[^:]*:__g\\"\\` .rbenv/bin/rbenv init bash; + fi; + eval \\"\\$(.rbenv/bin/rbenv init - --no-rehash bash)\\"; + export TMPDIR=\\`mktemp -d \\"\\$HOME\\"/rbenv_tmp_XXXX\\`; + set +e; + rbenv install #{version} --skip-existing 2>&1; + set -e; + RBENV_VERSION=#{version} ruby --version; + rm -rf \\"\\`printenv TMPDIR\\`\\"; + rbenv global #{version}; + "; + { kill % && wait; } 2> /dev/null; + set -e; + if [ "`RBENV_VERSION=#{version} gem list --exact --installed bundler`" == "true" ]; then + echo 'Please ignore the following error above:'; + echo '> ERROR: While executing gem ... (URI::InvalidURIError)'; + echo '> bad URI(is not URI?): "bundler\\r"'; + echo Successfully installed ruby #{version}; + else + echo ERROR: Failure installing ruby #{version}: aborting; + exit 1; + fi; + fi + SHELL + end + end + + before 'bundle:install', 'ndr_dev_support:install_ruby' +end diff --git a/lib/ndr_dev_support/capistrano/ndr_model.rb b/lib/ndr_dev_support/capistrano/ndr_model.rb index 287b4fa..e79a9af 100644 --- a/lib/ndr_dev_support/capistrano/ndr_model.rb +++ b/lib/ndr_dev_support/capistrano/ndr_model.rb @@ -2,6 +2,7 @@ # Discrete bits of functionality we use automatically: require_relative 'assets' +require_relative 'install_ruby' require_relative 'restart' require_relative 'revision_logger' require_relative 'ruby_version' From fe069899060cdf8a6948be03127442423c14a33d Mon Sep 17 00:00:00 2001 From: Brian Shand Date: Tue, 10 Dec 2024 15:36:42 +0000 Subject: [PATCH 3/4] Support psych 4 --- lib/ndr_dev_support/capistrano/assets.rb | 4 ++-- lib/ndr_dev_support/capistrano/ndr_model.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ndr_dev_support/capistrano/assets.rb b/lib/ndr_dev_support/capistrano/assets.rb index 3acfab4..b00e0c0 100644 --- a/lib/ndr_dev_support/capistrano/assets.rb +++ b/lib/ndr_dev_support/capistrano/assets.rb @@ -4,8 +4,8 @@ task :configure_assets do asset_script = fetch(:asset_script, <<~SHELL) set -e - ruby -ryaml -e "puts YAML.dump('production' => { 'secret_key_base' => 'compile_me' })" > config/secrets.yml - ruby -ryaml -e "puts YAML.dump('production' => { 'adapter' => 'placeholder' })" > config/database.yml + ruby -e "require 'yaml'; puts YAML.dump('production' => { 'secret_key_base' => 'compile_me' })" > config/secrets.yml + ruby -e "require 'yaml'; puts YAML.dump('production' => { 'adapter' => 'placeholder' })" > config/database.yml RAILS_ENV=production bundle exec rake assets:clobber assets:precompile rm config/secrets.yml config/database.yml SHELL diff --git a/lib/ndr_dev_support/capistrano/ndr_model.rb b/lib/ndr_dev_support/capistrano/ndr_model.rb index e79a9af..f0917e0 100644 --- a/lib/ndr_dev_support/capistrano/ndr_model.rb +++ b/lib/ndr_dev_support/capistrano/ndr_model.rb @@ -173,7 +173,7 @@ end def release_config_for(env) - branches = YAML.load_file('config/deployments.yml') + branches = YAML.safe_load_file('config/deployments.yml', permitted_classes: [Date]) branches.fetch(env.to_s) { raise 'Unknown release branch!' } end From 227a40c2e3fb8104a94178b56a7f75d7a28fe058 Mon Sep 17 00:00:00 2001 From: Brian Shand Date: Tue, 10 Dec 2024 16:56:17 +0000 Subject: [PATCH 4/4] Install rbenv, ruby-build and updated ruby versions from vendor/rbenv/ Better rbenv installation error handling --- CHANGELOG.md | 2 +- .../capistrano/install_ruby.rb | 61 +++++++++++++++---- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbf3146..b7d72a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## [Unreleased] ### Added -* Capistrano: install rbenv and ruby from /opt/rbenv.tar.gz +* Capistrano: install rbenv and ruby from /opt/rbenv.tar.gz or vendor/rbenv/ ## 7.2.6 / 2024-11-13 ### Fixed diff --git a/lib/ndr_dev_support/capistrano/install_ruby.rb b/lib/ndr_dev_support/capistrano/install_ruby.rb index 01ec8ea..87ab17b 100644 --- a/lib/ndr_dev_support/capistrano/install_ruby.rb +++ b/lib/ndr_dev_support/capistrano/install_ruby.rb @@ -3,8 +3,10 @@ desc <<~DESC Ensure that the required ruby version is installed. - An offline copy of rbenv should be placed in /opt/rbenv.tar.gz - To make this file, for ruby 3.1.6, run the following commands: + This can be installed from /opt/rbenv.tar.gz (first installation only) or vendor/rbenv/ + + To place an offline copy of rbenv in /opt/rbenv.tar.gz + For ruby 3.1.6, run the following commands: $ mkdir clone_rbenv $ git clone https://github.com/rbenv/rbenv.git clone_rbenv/.rbenv $ git clone https://github.com/rbenv/ruby-build.git clone_rbenv/.rbenv/plugins/ruby-build @@ -13,6 +15,21 @@ $ (cd clone_rbenv; rm -f ../rbenv.tar.gz; tar czf ../rbenv.tar.gz .rbenv) $ rm -rf clone_rbenv $ scp -p rbenv.tar.gz app-server:/opt/rbenv.tar.gz + + To add rbenv, ruby-build and additional ruby versions to the application vendor directory + For ruby 3.2.6: + $ mkdir clone_rbenv + $ git clone https://github.com/rbenv/rbenv.git clone_rbenv/.rbenv + $ mkdir -p vendor/rbenv; rm -f vendor/rbenv/rbenv.tar.gz + $ tar czf vendor/rbenv/rbenv.tar.gz -C clone_rbenv .rbenv + $ rm -rf clone_rbenv + $ mkdir clone_ruby-build + $ git clone https://github.com/rbenv/ruby-build.git clone_ruby-build/ruby-build + $ mkdir -p vendor/rbenv/cache; rm -f vendor/rbenv/ruby-build.tar.gz + $ tar czf vendor/rbenv/ruby-build.tar.gz -C clone_ruby-build ruby-build + $ rm -rf clone_ruby-build + $ (cd vendor/rbenv/cache; curl -O https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.6.tar.gz) + $ git add vendor/rbenv/{rbenv,ruby-build}.tar.gz vendor/rbenv/cache/* DESC task :install_ruby do version = fetch(:ruby) @@ -24,27 +41,47 @@ # For some reason, SSH keepalive options have no effect with capistrano 2 and net-ssh 7. # So we run a poor-man's keepalive, because this installation can take over 10 minutes # and some of our SSH servers disconnect inactive sessions after 5 minutes. + # We have a keepalive time limit of 40 minutes in case the installation fails unexpectedly. # # We remove ~/.rbenv paths from capistrano-defined PATH when running `rbenv init` # so that it knows the path is needed in ~/.bash_profile + # + # We use latest_release: this is broadly well-defined, and will point to the in-progress + # release if we're part way through a deployment, or the most recent release if run + # after a deployment has happened, or be blank if attempted after cap deploy:setup run <<~SHELL set -e; - if ! rbenv versions --bare 2> /dev/null | grep -qF #{version}; then + if ! rbenv versions --bare 2> /dev/null | grep -q ^#{Regexp.escape(version)}$; then echo Installing ruby #{version}; - { while true; do sleep 20; echo -n '.'; done & } 2> /dev/null; + { sleep 10; for i in `seq 1 80`; do echo -n '.'; sleep 30; done & } 2> /dev/null; sudo -i -n -u #{fetch(:application_user)} sh -c " if [ ! -e .rbenv ] && [ -e /opt/rbenv.tar.gz ]; then tar xf /opt/rbenv.tar.gz .rbenv; PATH=\\`echo \\"\\$PATH\\"|sed -e \\"s_[^:=]*/[.]rbenv[^:]*:__g\\"\\` .rbenv/bin/rbenv init bash; fi; - eval \\"\\$(.rbenv/bin/rbenv init - --no-rehash bash)\\"; - export TMPDIR=\\`mktemp -d \\"\\$HOME\\"/rbenv_tmp_XXXX\\`; - set +e; - rbenv install #{version} --skip-existing 2>&1; - set -e; - RBENV_VERSION=#{version} ruby --version; - rm -rf \\"\\`printenv TMPDIR\\`\\"; - rbenv global #{version}; + if [ ! -e .rbenv ] && [ -f #{latest_release}/vendor/rbenv/rbenv.tar.gz ]; then + tar xf #{latest_release}/vendor/rbenv/rbenv.tar.gz .rbenv; + PATH=\\`echo \\"\\$PATH\\"|sed -e \\"s_[^:=]*/[.]rbenv[^:]*:__g\\"\\` .rbenv/bin/rbenv init bash; + fi; + if [ ! -e .rbenv ]; then + echo rbenv not installed: aborting; + else + if [ -d #{latest_release}/vendor/rbenv/cache ] && [ -n \\"\\`ls #{latest_release}/vendor/rbenv/cache\\`\\" ]; then + mkdir -p .rbenv/cache/; + cp -nvp #{latest_release}/vendor/rbenv/cache/* .rbenv/cache/; + fi; + if [ -f #{latest_release}/vendor/rbenv/ruby-build.tar.gz ]; then + mkdir -p .rbenv/plugins/; + tar xf #{latest_release}/vendor/rbenv/ruby-build.tar.gz -C .rbenv/plugins/ ruby-build; + fi; + eval \\"\\$(.rbenv/bin/rbenv init - --no-rehash bash)\\"; + export TMPDIR=\\`mktemp -d \\"\\$HOME\\"/rbenv_tmp_XXXX\\`; + if rbenv install #{version} --skip-existing 2>&1; then + RBENV_VERSION=#{version} ruby --version; + rm -rf \\"\\`printenv TMPDIR\\`\\"; + rbenv global #{version}; + fi; + fi; "; { kill % && wait; } 2> /dev/null; set -e;