Skip to content

Commit c42848a

Browse files
committed
capistrano: Support bundler 4 with capistrano 2
1 parent 9c5c91c commit c42848a

2 files changed

Lines changed: 91 additions & 0 deletions

File tree

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Support capistrano 2 with old (< 4) and new (>= 4) bundler versions
2+
#
3+
# Add "require 'ndr_dev_support/capistrano/ndr_model'" in your Capistrano deploy.rb,
4+
# but remove calls to "require 'bundler/capistrano'", and
5+
# Bundler will be activated after each new deployment.
6+
7+
if Gem::Version.new(Bundler::VERSION).release < Gem::Version.new('4.0')
8+
require 'bundler/capistrano'
9+
else
10+
# Redefine deployment helpers for Capistrano 2, previously defined in bundler < 4
11+
# cf. https://blog.rubygems.org/2025/12/03/upgrade-to-rubygems-bundler-4.html
12+
# Code copied from bundler 2 source files bundler/deployment.rb and bundler/capistrano.rb
13+
# rubocop:disable Style/Documentation, Metrics/AbcSize, Metrics/MethodLength, Style/StringLiterals, Style/SymbolArray, Style/RaiseArgs, Layout/EmptyLineAfterGuardClause, Style/StringLiteralsInInterpolation, Style/Lambda
14+
module Bundler
15+
class Deployment
16+
def self.define_task(context, task_method = :task, opts = {})
17+
if defined?(Capistrano) && context.is_a?(Capistrano::Configuration)
18+
context_name = "capistrano"
19+
role_default = "{:except => {:no_release => true}}"
20+
error_type = ::Capistrano::CommandError
21+
else
22+
context_name = "vlad"
23+
role_default = "[:app]"
24+
error_type = ::Rake::CommandFailedError
25+
end
26+
27+
roles = context.fetch(:bundle_roles, false)
28+
opts[:roles] = roles if roles
29+
30+
context.send :namespace, :bundle do
31+
send :desc, <<-DESC
32+
Install the current Bundler environment. By default, gems will be \
33+
installed to the shared/bundle path. Gems in the development and \
34+
test group will not be installed. The install command is executed \
35+
with the --deployment and --quiet flags. If the bundle cmd cannot \
36+
be found then you can override the bundle_cmd variable to specify \
37+
which one it should use. The base path to the app is fetched from \
38+
the :latest_release variable. Set it for custom deploy layouts.
39+
40+
You can override any of these defaults by setting the variables shown below.
41+
42+
N.B. bundle_roles must be defined before you require 'bundler/#{context_name}' \
43+
in your deploy.rb file.
44+
45+
set :bundle_gemfile, "Gemfile"
46+
set :bundle_dir, File.join(fetch(:shared_path), 'bundle')
47+
set :bundle_flags, "--deployment --quiet"
48+
set :bundle_without, [:development, :test]
49+
set :bundle_with, [:mysql]
50+
set :bundle_cmd, "bundle" # e.g. "/opt/ruby/bin/bundle"
51+
set :bundle_roles, #{role_default} # e.g. [:app, :batch]
52+
DESC
53+
send task_method, :install, opts do
54+
bundle_cmd = context.fetch(:bundle_cmd, "bundle")
55+
bundle_flags = context.fetch(:bundle_flags, "--deployment --quiet")
56+
bundle_dir = context.fetch(:bundle_dir, File.join(context.fetch(:shared_path), "bundle"))
57+
bundle_gemfile = context.fetch(:bundle_gemfile, "Gemfile")
58+
bundle_without = [*context.fetch(:bundle_without, [:development, :test])].compact
59+
bundle_with = [*context.fetch(:bundle_with, [])].compact
60+
app_path = context.fetch(:latest_release)
61+
if app_path.to_s.empty?
62+
raise error_type.new("Cannot detect current release path - make sure you have deployed at least once.")
63+
end
64+
args = ["--gemfile #{File.join(app_path, bundle_gemfile)}"]
65+
args << "--path #{bundle_dir}" unless bundle_dir.to_s.empty?
66+
args << bundle_flags.to_s
67+
args << "--without #{bundle_without.join(" ")}" unless bundle_without.empty?
68+
args << "--with #{bundle_with.join(" ")}" unless bundle_with.empty?
69+
70+
run "cd #{app_path} && #{bundle_cmd} install #{args.join(" ")}"
71+
end
72+
end
73+
end
74+
end
75+
end
76+
77+
# Capistrano task for Bundler.
78+
require "capistrano/version"
79+
80+
if defined?(Capistrano::Version) && Gem::Version.new(Capistrano::Version).release >= Gem::Version.new("3.0")
81+
raise "For Capistrano 3.x integration, please use https://github.com/capistrano/bundler"
82+
end
83+
84+
Capistrano::Configuration.instance(:must_exist).load do
85+
before "deploy:finalize_update", "bundle:install"
86+
Bundler::Deployment.define_task(self, :task, except: { no_release: true })
87+
set :rake, lambda { "#{fetch(:bundle_cmd, "bundle")} exec rake" }
88+
end
89+
# rubocop:enable Style/Documentation, Metrics/AbcSize, Metrics/MethodLength, Style/StringLiterals, Style/SymbolArray, Style/RaiseArgs, Layout/EmptyLineAfterGuardClause, Style/StringLiteralsInInterpolation, Style/Lambda
90+
end

lib/ndr_dev_support/capistrano/ndr_model.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
# Discrete bits of functionality we use automatically:
44
require_relative 'assets'
5+
require_relative 'bundler_deployment'
56
require_relative 'deploy_secrets'
67
require_relative 'install_ruby'
78
require_relative 'macos_bsdtar'

0 commit comments

Comments
 (0)