Class: Rake::Gem::Maintenance::UpgradeTask

Inherits:
TaskLib
  • Object
show all
Defined in:
lib/rake/gem/maintenance/upgrade_task.rb

Overview

Defines Rake tasks for upgrading gem dependencies and publishing to multiple repositories.

Creates: upgrade, upgrade:auto, upgrade:branch, upgrade:gems, upgrade:commit, upgrade:prepare_version, upgrade:push rubocop:disable Metrics/ClassLength, Metrics/MethodLength

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name = :upgrade) {|_self| ... } ⇒ UpgradeTask

Returns a new instance of UpgradeTask.

Yields:

  • (_self)

Yield Parameters:



36
37
38
39
40
41
42
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 36

def initialize(name = :upgrade)
  super()
  apply_default_configuration(name)

  yield self if block_given?
  define_tasks
end

Instance Attribute Details

#auto_pipelineObject

Returns the value of attribute auto_pipeline.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def auto_pipeline
  @auto_pipeline
end

#commit_messageObject

Returns the value of attribute commit_message.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def commit_message
  @commit_message
end

#files_to_commitObject

Returns the value of attribute files_to_commit.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def files_to_commit
  @files_to_commit
end

#gem_nameObject

Returns the value of attribute gem_name.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def gem_name
  @gem_name
end

#gem_publisher_classObject

Returns the value of attribute gem_publisher_class.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def gem_publisher_class
  @gem_publisher_class
end

#gem_repositoriesObject

Returns the value of attribute gem_repositories.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def gem_repositories
  @gem_repositories
end

#gem_versionObject

Returns the value of attribute gem_version.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def gem_version
  @gem_version
end

#main_branchObject

Returns the value of attribute main_branch.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def main_branch
  @main_branch
end

#nameObject

Returns the value of attribute name.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def name
  @name
end

#release_taskObject

Returns the value of attribute release_task.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def release_task
  @release_task
end

#renew_api_key_task_classObject



32
33
34
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 32

def renew_api_key_task_class
  @renew_api_key_task_class || RenewApiKeyTask
end

#ruby_version_checker_classObject

Returns the value of attribute ruby_version_checker_class.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def ruby_version_checker_class
  @ruby_version_checker_class
end

#ruby_version_updater_classObject

Returns the value of attribute ruby_version_updater_class.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def ruby_version_updater_class
  @ruby_version_updater_class
end

#run_bundle_auditObject

Returns the value of attribute run_bundle_audit.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def run_bundle_audit
  @run_bundle_audit
end

#update_gemsObject

Returns the value of attribute update_gems.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def update_gems
  @update_gems
end

#update_rubyObject

Returns the value of attribute update_ruby.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def update_ruby
  @update_ruby
end

#update_rubygemsObject

Returns the value of attribute update_rubygems.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def update_rubygems
  @update_rubygems
end

#upgrade_branchObject

Returns the value of attribute upgrade_branch.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def upgrade_branch
  @upgrade_branch
end

#verification_taskObject

Returns the value of attribute verification_task.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def verification_task
  @verification_task
end

#version_bump_taskObject

Returns the value of attribute version_bump_task.



23
24
25
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 23

def version_bump_task
  @version_bump_task
end

Instance Method Details

#apply_default_configuration(name) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 44

def apply_default_configuration(name)
  @name = name
  @main_branch = "main"
  @upgrade_branch = "upgrade/gems"
  @commit_message = "chore(deps): upgrade gems"
  @files_to_commit = %w[Gemfile Gemfile.lock]
  @verification_task = :verify
  @release_task = :release
  @version_bump_task = "version:bump"
  @auto_pipeline = nil
  @gem_repositories = Repos.rubygems
  @gem_publisher_class = GemPublisher
  @gem_name = detect_gem_name
  @gem_version = detect_gem_version
  apply_default_gem_update_configuration
  apply_default_ruby_version_configuration
end

#apply_default_gem_update_configurationObject



62
63
64
65
66
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 62

def apply_default_gem_update_configuration
  @update_rubygems = true
  @update_gems = true
  @run_bundle_audit = true
end

#apply_default_ruby_version_configurationObject



68
69
70
71
72
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 68

def apply_default_ruby_version_configuration
  @update_ruby = true
  @ruby_version_checker_class = RubyVersionChecker
  @ruby_version_updater_class = RubyVersionUpdater
end

#check_version_on_repositoriesObject

rubocop:disable Metrics/AbcSize



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 261

def check_version_on_repositories
  unless gem_name && gem_version
    puts "[ERROR] No gemspec found - cannot check version/upgrade"
    abort
  end

  publisher = gem_publisher_class.new(gem_repositories)
  gemspec_repos = gem_repositories.select { |repo| repo_available?(repo) }

  if gemspec_repos.empty?
    puts "[ERROR] No repositories available. Cannot check version."
    abort
  end

  publisher.check_all_repositories(gem_name)

  print_failed_repository_warnings(publisher)
  version = gem_version
  next_ver = publisher.next_version(gem_name, version)

  if next_ver == version
    puts "[INFO] Version #{version} not found on any repository - will publish"
  else
    puts "[INFO] Version #{version} already published to all repositories"
    puts "[INFO] Next available version: #{next_ver}"
  end

  handle_partial_publish_warning(publisher, version)
end

#commit_changesObject



251
252
253
254
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 251

def commit_changes
  sh "git add #{files_to_commit.join(' ')}"
  sh "git commit -m '#{commit_message}'"
end

#create_upgrade_branchObject



225
226
227
228
229
230
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 225

def create_upgrade_branch
  sh "git checkout #{main_branch}"
  sh "git pull"
  sh "git branch -D #{upgrade_branch}" unless `git branch --list #{upgrade_branch}`.chomp.empty?
  sh "git checkout -b #{upgrade_branch}"
end

#define_auto_taskObject



174
175
176
177
178
179
180
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 174

def define_auto_task
  task_instance = self
  namespace name do
    desc "Update gems automatically (branch to push and release)"
    task auto: task_instance.send(:pipeline_tasks)
  end
end

#define_branch_taskObject



182
183
184
185
186
187
188
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 182

def define_branch_task
  task_instance = self
  namespace name do
    desc "Create a branch for the upgrade"
    task(:branch) { task_instance.send(:create_upgrade_branch) }
  end
end

#define_commit_taskObject



198
199
200
201
202
203
204
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 198

def define_commit_task
  task_instance = self
  namespace name do
    desc "Commit the upgrade branch"
    task(:commit) { task_instance.send(:commit_changes) }
  end
end

#define_gems_taskObject



190
191
192
193
194
195
196
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 190

def define_gems_task
  task_instance = self
  namespace name do
    desc "Upgrade gems, including bundler and gem"
    task(:gems) { task_instance.send(:do_upgrade_gems) }
  end
end

#define_info_name_task(task_instance) ⇒ Object



151
152
153
154
155
156
157
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 151

def define_info_name_task(task_instance)
  desc "Show current gem name"
  task :name do
    name = task_instance.gem_name || "unknown"
    puts "Gem name: #{name}"
  end
end

#define_info_repos_task(task_instance) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 130

def define_info_repos_task(task_instance)
  desc "Show configured gem repositories"
  task :repos do
    puts "Gem repositories:"
    task_instance.gem_repositories.each do |repo|
      available = task_instance.send(:repo_available?, repo)
      status = available ? "" : ""
      avail_text = available ? "AVAILABLE" : "NOT AVAILABLE"
      puts "  - #{repo[:name]} (#{status}) - #{avail_text}: #{repo[:url]}"
    end
  end
end

#define_info_tasksObject



115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 115

def define_info_tasks
  task_instance = self
  namespace name do
    namespace :info do
      define_info_repos_task(task_instance)
      define_info_version_task(task_instance)
      define_info_name_task(task_instance)
      desc "Show all upgrade info"
      task all: %i[name version repos]
    end
    desc "Show all upgrade info"
    task info: "#{name}:info:all"
  end
end

#define_info_version_task(task_instance) ⇒ Object



143
144
145
146
147
148
149
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 143

def define_info_version_task(task_instance)
  desc "Show current gem version"
  task :version do
    ver = task_instance.gem_version || "unknown"
    puts "Current version: #{ver}"
  end
end

#define_prepare_version_taskObject



164
165
166
167
168
169
170
171
172
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 164

def define_prepare_version_task
  task_instance = self
  namespace name do
    desc "Check version on all repositories before bumping"
    task :prepare_version do
      task_instance.send(:check_version_on_repositories)
    end
  end
end

#define_push_taskObject



206
207
208
209
210
211
212
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 206

def define_push_task
  task_instance = self
  namespace name do
    desc "Push the upgrade"
    task(:push) { task_instance.send(:push_branch) }
  end
end

#define_renew_api_key_taskObject



214
215
216
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 214

def define_renew_api_key_task
  renew_api_key_task_class.new(name)
end

#define_tasksObject



103
104
105
106
107
108
109
110
111
112
113
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 103

def define_tasks
  define_top_level_task
  define_info_tasks
  define_prepare_version_task
  define_auto_task
  define_branch_task
  define_gems_task
  define_commit_task
  define_push_task
  define_renew_api_key_task
end

#define_top_level_taskObject



159
160
161
162
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 159

def define_top_level_task
  desc "Alias for #{name}:auto"
  task name => "#{name}:auto"
end

#do_upgrade_gemsObject



232
233
234
235
236
237
238
239
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 232

def do_upgrade_gems
  update_ruby_versions if update_ruby
  sh "gem update --system" if update_rubygems
  sh "gem update" if update_gems
  sh "bundle update --bundler"
  sh "bundle update --all"
  sh "bundle audit" if run_bundle_audit
end

#handle_partial_publish_warning(publisher, version) ⇒ Object

rubocop:enable Metrics/AbcSize



292
293
294
295
296
297
298
299
300
301
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 292

def handle_partial_publish_warning(publisher, version)
  return if publisher.successful_repos.empty?

  published = publisher.successful_repos
  total = gem_repositories.size
  return unless published.size < total

  puts "[WARN] Version #{version} was only published to #{published.size} of #{total} repositories"
  puts "[WARN] Run 'rake upgrade:prepare_version' manually to check status"
end

#pipeline_tasksObject



218
219
220
221
222
223
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 218

def pipeline_tasks
  return auto_pipeline if auto_pipeline

  %i[branch
     gems] + [verification_task, :commit, version_bump_task.to_sym, :prepare_version, release_task, :push]
end


310
311
312
313
314
315
316
317
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 310

def print_failed_repository_warnings(publisher)
  return if publisher.failed_repositories.empty?

  puts "[WARN] The following repositories were unavailable:"
  publisher.failed_repositories.each do |repo_name|
    puts "  - #{repo_name}"
  end
end

#push_branchObject



256
257
258
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 256

def push_branch
  sh "git push origin #{upgrade_branch}"
end

#repos_available?(publisher) ⇒ Boolean

Returns:

  • (Boolean)


303
304
305
306
307
308
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 303

def repos_available?(publisher)
  return true if publisher.any_available?

  puts "[ERROR] No repositories available. Cannot check version."
  abort
end

#update_ruby_versionsObject



241
242
243
244
245
246
247
248
249
# File 'lib/rake/gem/maintenance/upgrade_task.rb', line 241

def update_ruby_versions
  checker = ruby_version_checker_class.new
  if checker.latest_stable.nil?
    puts "[WARN] Could not fetch Ruby version info — skipping Ruby update"
    return
  end
  modified = ruby_version_updater_class.new.update(checker: checker)
  files_to_commit.concat(modified) if modified.any?
end