toys-release 0.1.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a3ff3cf2eca9706959eddfb418f6b32a26be0b6b38729060daf8eea59b328a22
4
- data.tar.gz: 7859d5108f62f3cfe45107aaf737ca278866d07edab8d7cdf678ff9e5b6c5124
3
+ metadata.gz: '019248786a71a0bd4f1afc4eb48fd79ca81205ef43141619643bb59c2e0063a7'
4
+ data.tar.gz: 5e847ffe3fb7bf789cd66d102c5118886f417b3ed496cc010b5e5427e2b4387d
5
5
  SHA512:
6
- metadata.gz: 794cd275768b4a657558527699cb1c5fd1ca628115cf144e30b9f4c2f4ac10ab939381203c1784cc5d92cfaa05c39f9c2999d799c9334140b64765989b7d9850
7
- data.tar.gz: 18c092ffbfc0489fd064548778350bf22cc3cb2f436aa02bc23c9a4488879768dc3b875b92de8440306c8ef20142c148a46ee331e67e8983703c5efe7ed47fc1
6
+ metadata.gz: 8286d5ca56e71bbd76809b87c4bc5003fbce363b541f0f8e76d710a88f3e4fed0a10a1a5a19b2585b00dbdefb212dde034f9ac4b693a5642ef768c148dde961e
7
+ data.tar.gz: ac59da66c4d90fe5911a5ff18e50f38b04d9d88c6acb86abdd1fc45645c3a6d758b9c6979acd96ee11a0082abeb4403fbd93d9161fb4765fb98deb0023b59682
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Release History
2
2
 
3
+ ### v0.2.2 / 2025-11-30
4
+
5
+ * FIXED: Fixed several crashes in the retry tool
6
+ * FIXED: Fixed step cleaner trying to clean the .git directory on non-monorepos
7
+ * FIXED: Repo prechecks can now actually stop releases from being performed
8
+ * FIXED: Retry tool uses --work-dir= instead of --gh-pages-dir=
9
+ * FIXED: Dry run mode no longer attempts to update pull requests or open issues
10
+
11
+ ### v0.2.1 / 2025-11-30
12
+
13
+ * FIXED: Fixed some typos in the release pipeline logs
14
+ * DOCS: Fixed minor typos in readme files
15
+
16
+ ### v0.2.0 / 2025-11-30
17
+
18
+ * BREAKING CHANGE: Reworked pipeline design and normalized how steps communicate
19
+ * BREAKING CHANGE: Removed defunct commit linter
20
+
3
21
  ### v0.1.1 / 2025-11-09
4
22
 
5
23
  * FIXED: The gen-gh-pages script now generates the correct redirect paths on a non-monorepo with the default directory structure
data/README.md CHANGED
@@ -7,7 +7,7 @@ based on semantic versioning, and supports fine tuning and approval of releases
7
7
  using GitHub pull requests.
8
8
 
9
9
  Out of the box, Toys-Release knows how to tag GitHub releases, build and push
10
- gems to Rubygems, and build and publish documentation to gh-pages. You can also
10
+ gems to RubyGems, and build and publish documentation to gh-pages. You can also
11
11
  customize the build pipeline and many aspects of its behavior.
12
12
 
13
13
  ## Description
@@ -62,11 +62,11 @@ by closing the pull request without merging.
62
62
  Toys-Release requires Ruby 2.7 or later, and Toys 0.17 or later. We recommend
63
63
  the latest version of the standard C implementation of Ruby. (JRuby or
64
64
  TruffleRuby _may_ work, but are unsupported.) The Ruby provided by the standard
65
- setup-ruby GitHub Action is sufficient.
65
+ `setup-ruby` GitHub Action is sufficient.
66
66
 
67
67
  ## License
68
68
 
69
- Copyright 2019-2025 Daniel Azuma and the Toys contributors
69
+ Copyright 2025 Daniel Azuma and the Toys contributors
70
70
 
71
71
  Permission is hereby granted, free of charge, to any person obtaining a copy
72
72
  of this software and associated documentation files (the "Software"), to deal
@@ -6,6 +6,6 @@ module Toys
6
6
  # Current version of the Toys release system.
7
7
  # @return [String]
8
8
  #
9
- VERSION = "0.1.1"
9
+ VERSION = "0.2.2"
10
10
  end
11
11
  end
@@ -15,11 +15,13 @@ module Toys
15
15
  # @param base_dir [String] Optional base directory, within which all the
16
16
  # artifact directories will be created. If not provided, a temporary
17
17
  # directory will be used.
18
+ # @param auto_cleanup [boolean] Whether to cleanup automatically at_exit.
18
19
  #
19
- def initialize(base_dir = nil)
20
+ def initialize(base_dir = nil, auto_cleanup: false)
20
21
  @base_dir = base_dir
21
22
  @needs_cleanup = false
22
23
  @initialized = {}
24
+ at_exit { cleanup } if auto_cleanup
23
25
  end
24
26
 
25
27
  ##
@@ -40,6 +42,24 @@ module Toys
40
42
  path
41
43
  end
42
44
 
45
+ ##
46
+ # Get the path to the output directory for the given step name.
47
+ #
48
+ # @param name [String] Step name
49
+ #
50
+ def output(name)
51
+ get("out-#{name}")
52
+ end
53
+
54
+ ##
55
+ # Get the path to the temp directory for the given step name.
56
+ #
57
+ # @param name [String] Step name
58
+ #
59
+ def temp(name)
60
+ get("temp-#{name}")
61
+ end
62
+
43
63
  ##
44
64
  # Perform cleanup, removing the directories if they were created under a
45
65
  # temporary directory.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "semver"
3
+ require "toys/release/semver"
4
4
 
5
5
  module Toys
6
6
  module Release
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "change_set"
4
- require_relative "changelog_file"
5
- require_relative "version_rb_file"
3
+ require "toys/release/change_set"
4
+ require "toys/release/changelog_file"
5
+ require "toys/release/version_rb_file"
6
6
 
7
7
  module Toys
8
8
  module Release
@@ -83,17 +83,17 @@ module Toys
83
83
 
84
84
  ##
85
85
  # Returns the directory path. It can be returned either as a relative path
86
- # from the context directory or an absolute path.
86
+ # from the repo root directory or an absolute path.
87
87
  #
88
- # @param from [:context,:absolute] From where (defaults to `:context`)
88
+ # @param from [:repo_root,:absolute] From where (defaults to `:repo_root`)
89
89
  # @return [String] The directory path
90
90
  #
91
- def directory(from: :context)
91
+ def directory(from: :repo_root)
92
92
  case from
93
- when :context
93
+ when :repo_root
94
94
  settings.directory
95
95
  when :absolute
96
- ::File.expand_path(settings.directory, @utils.context_directory)
96
+ ::File.expand_path(settings.directory, @utils.repo_root_directory)
97
97
  else
98
98
  raise ArgumentError, "Unknown from value: #{from.inspect}"
99
99
  end
@@ -101,10 +101,10 @@ module Toys
101
101
 
102
102
  ##
103
103
  # Returns the path to a given file. It can be returned as a relative path
104
- # from the component directory, a relative path from the context
104
+ # from the component directory, a relative path from the repo root
105
105
  # directory, or an absolute path.
106
106
  #
107
- # @param from [:directory,:context,:absolute] From where (defaults to
107
+ # @param from [:directory,:repo_root,:absolute] From where (defaults to
108
108
  # `:directory`)
109
109
  # @return [String] The path to the file
110
110
  #
@@ -112,7 +112,7 @@ module Toys
112
112
  case from
113
113
  when :directory
114
114
  path
115
- when :context
115
+ when :repo_root
116
116
  ::File.join(directory, path)
117
117
  when :absolute
118
118
  ::File.expand_path(path, directory(from: :absolute))
@@ -123,10 +123,10 @@ module Toys
123
123
 
124
124
  ##
125
125
  # Returns the path to the changelog. It can be returned as a relative
126
- # path from the component directory, a relative path from the context
126
+ # path from the component directory, a relative path from the repo root
127
127
  # directory, or an absolute path.
128
128
  #
129
- # @param from [:directory,:context,:absolute] From where (defaults to
129
+ # @param from [:directory,:repo_root,:absolute] From where (defaults to
130
130
  # `:directory`)
131
131
  # @return [String] The path to the changelog
132
132
  #
@@ -136,10 +136,10 @@ module Toys
136
136
 
137
137
  ##
138
138
  # Returns the path to the version.rb. It can be returned as a relative
139
- # path from the component directory, a relative path from the context
139
+ # path from the component directory, a relative path from the repo root
140
140
  # directory, or an absolute path.
141
141
  #
142
- # @param from [:directory,:context,:absolute] From where (defaults to
142
+ # @param from [:directory,:repo_root,:absolute] From where (defaults to
143
143
  # `:directory`)
144
144
  # @return [String] The path to the `version.rb` file
145
145
  #
@@ -213,7 +213,7 @@ module Toys
213
213
  #
214
214
  def current_changelog_version(at: nil)
215
215
  if at
216
- path = changelog_path(from: :context)
216
+ path = changelog_path(from: :repo_root)
217
217
  content = @utils.capture(["git", "show", "#{at}:#{path}"], e: true)
218
218
  return ChangelogFile.current_version_from_content(content)
219
219
  end
@@ -228,7 +228,7 @@ module Toys
228
228
  #
229
229
  def current_constant_version(at: nil)
230
230
  if at
231
- path = version_rb_path(from: :context)
231
+ path = version_rb_path(from: :repo_root)
232
232
  content = @utils.capture(["git", "show", "#{at}:#{path}"], e: true)
233
233
  return VersionRbFile.current_version_from_content(content)
234
234
  end
@@ -338,10 +338,10 @@ module Toys
338
338
  class GemComponent < Component
339
339
  ##
340
340
  # Returns the path to the gemspec. It can be returned as a relative path
341
- # from the component directory, a relative path from the context
341
+ # from the component directory, a relative path from the repo root
342
342
  # directory, or an absolute path.
343
343
  #
344
- # @param from [:directory,:context,:absolute] From where (defaults to
344
+ # @param from [:directory,:repo_root,:absolute] From where (defaults to
345
345
  # `:directory`)
346
346
  # @return [String] The path to the gemspec file
347
347
  #
@@ -74,6 +74,13 @@ module Toys
74
74
  tool_context.context_directory
75
75
  end
76
76
 
77
+ ##
78
+ # @return [String] Absolute path to the repo root directory
79
+ #
80
+ def repo_root_directory
81
+ @repo_root_directory ||= capture(["git", "rev-parse", "--show-toplevel"], chdir: context_directory).strip
82
+ end
83
+
77
84
  ##
78
85
  # Log a message at INFO level
79
86
  #
@@ -120,10 +127,13 @@ module Toys
120
127
  #
121
128
  def accumulate_errors(main_message = nil)
122
129
  previous_list = @error_list
123
- @error_list = []
124
- result = yield
125
- current_list = @error_list
126
- @error_list = previous_list
130
+ @error_list = current_list = []
131
+ result =
132
+ begin
133
+ yield
134
+ ensure
135
+ @error_list = previous_list
136
+ end
127
137
  unless current_list.empty?
128
138
  current_list.unshift(main_message) if main_message
129
139
  error(*current_list)
@@ -141,11 +151,11 @@ module Toys
141
151
  # @return [Object] The block's result if success
142
152
  # @return [nil] if errors happened
143
153
  #
144
- def capture_errors(errors = nil)
154
+ def capture_errors(errors = nil, &block)
145
155
  return yield unless errors
146
156
  previous_option = on_error_option
147
157
  @on_error_option = :raise
148
- yield
158
+ accumulate_errors(&block)
149
159
  rescue ReleaseError => e
150
160
  errors.concat(e.all_messages)
151
161
  nil
@@ -3,8 +3,9 @@
3
3
  require "fileutils"
4
4
  require "json"
5
5
 
6
- require_relative "artifact_dir"
7
- require_relative "steps"
6
+ require "toys/release/artifact_dir"
7
+ require "toys/release/pipeline"
8
+ require "toys/release/steps"
8
9
 
9
10
  module Toys
10
11
  module Release
@@ -30,10 +31,10 @@ module Toys
30
31
  end
31
32
 
32
33
  ##
33
- # @return [boolean] Whether the result is capturing errors
34
+ # @return [boolean] Whether there were no errors
34
35
  #
35
- def capture_errors?
36
- !@errors.nil?
36
+ def succeeded?
37
+ @errors.empty?
37
38
  end
38
39
 
39
40
  ##
@@ -205,28 +206,13 @@ module Toys
205
206
  #
206
207
  def report_results
207
208
  report_text = build_report_text
208
- if @pull_request
209
- @utils.log("Updating release pull request #{@pull_request.url} ...")
210
- label = error? ? @settings.release_error_label : @settings.release_complete_label
211
- @pull_request.update(labels: label)
212
- @pull_request.add_comment(report_text)
213
- @utils.log("Updated release pull request #{@pull_request.url}")
214
- end
215
- if error?
216
- @utils.log("Opening a new issue to report the failure ...")
217
- body = <<~STR
218
- A release job failed.
219
-
220
- Release PR: #{@pull_request&.url || 'unknown'}
221
- Commit: https://github.com/#{@settings.repo_path}/commit/#{@release_sha}
222
-
223
- ----
224
-
225
- #{report_text}
226
- STR
227
- title = "Release PR ##{@pull_request&.number || 'unknown'} failed with errors"
228
- issue_number = @repository.open_issue(title, body)["number"]
229
- @utils.log("Issue ##{issue_number} opened")
209
+ puts report_text
210
+ if @dry_run
211
+ @utils.warning("DRY RUN: Skipped updating pull request #{@pull_request.url}") if @pull_request
212
+ @utils.warning("DRY RUN: Skipped opening release failure issue") if error?
213
+ else
214
+ update_pull_request(report_text) if @pull_request
215
+ open_error_issue(report_text) if error?
230
216
  end
231
217
  self
232
218
  end
@@ -317,17 +303,16 @@ module Toys
317
303
 
318
304
  def internal_perform_release(component, version, result)
319
305
  component_prechecks(component, version) if @enable_prechecks
320
- artifact_dir = Toys::Release::ArtifactDir.new(@work_dir)
306
+ artifact_dir = ArtifactDir.new(@work_dir)
321
307
  begin
322
308
  component.cd do
323
- component.settings.steps.each do |step_settings|
324
- result_code = Toys::Release::Steps.run(
325
- type: step_settings.type, name: step_settings.name, options: step_settings.options,
326
- repository: @repository, component: component, version: version, performer_result: result,
327
- artifact_dir: artifact_dir, dry_run: @dry_run, git_remote: @git_remote
328
- )
329
- break if result_code == :abort
330
- end
309
+ pipeline = Pipeline.new(
310
+ repository: @repository, component: component, version: version, performer_result: result,
311
+ artifact_dir: artifact_dir, dry_run: @dry_run, git_remote: @git_remote
312
+ )
313
+ component.settings.steps.each { |step_settings| pipeline.add_step(step_settings) }
314
+ pipeline.resolve_run
315
+ pipeline.run
331
316
  end
332
317
  ensure
333
318
  artifact_dir.cleanup
@@ -341,6 +326,31 @@ module Toys
341
326
  @utils.log("Completed prechecks for #{component.name.inspect}")
342
327
  self
343
328
  end
329
+
330
+ def update_pull_request(report_text)
331
+ @utils.log("Updating release pull request #{@pull_request.url} ...")
332
+ label = error? ? @settings.release_error_label : @settings.release_complete_label
333
+ @pull_request.update(labels: label)
334
+ @pull_request.add_comment(report_text)
335
+ @utils.log("Updated release pull request #{@pull_request.url}")
336
+ end
337
+
338
+ def open_error_issue(report_text)
339
+ @utils.log("Opening a new issue to report the failure ...")
340
+ body = <<~STR
341
+ A release job failed.
342
+
343
+ Release PR: #{@pull_request&.url || 'unknown'}
344
+ Commit: https://github.com/#{@settings.repo_path}/commit/#{@release_sha}
345
+
346
+ ----
347
+
348
+ #{report_text}
349
+ STR
350
+ title = "Release PR ##{@pull_request&.number || 'unknown'} failed with errors"
351
+ issue_number = @repository.open_issue(title, body)["number"]
352
+ @utils.log("Issue ##{issue_number} opened")
353
+ end
344
354
  end
345
355
  end
346
356
  end