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 +4 -4
- data/CHANGELOG.md +18 -0
- data/README.md +3 -3
- data/lib/toys/release/version.rb +1 -1
- data/toys/.lib/toys/release/artifact_dir.rb +21 -1
- data/toys/.lib/toys/release/change_set.rb +1 -1
- data/toys/.lib/toys/release/component.rb +19 -19
- data/toys/.lib/toys/release/environment_utils.rb +16 -6
- data/toys/.lib/toys/release/performer.rb +46 -36
- data/toys/.lib/toys/release/pipeline.rb +548 -0
- data/toys/.lib/toys/release/pull_request.rb +0 -2
- data/toys/.lib/toys/release/repo_settings.rb +250 -114
- data/toys/.lib/toys/release/repository.rb +4 -5
- data/toys/.lib/toys/release/request_spec.rb +1 -1
- data/toys/.lib/toys/release/steps.rb +265 -428
- data/toys/_onclosed.rb +1 -1
- data/toys/perform.rb +7 -5
- data/toys/retry.rb +20 -14
- metadata +4 -5
- data/toys/.data/templates/release-hook-on-open.yml.erb +0 -30
- data/toys/_onopen.rb +0 -158
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '019248786a71a0bd4f1afc4eb48fd79ca81205ef43141619643bb59c2e0063a7'
|
|
4
|
+
data.tar.gz: 5e847ffe3fb7bf789cd66d102c5118886f417b3ed496cc010b5e5427e2b4387d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
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
|
|
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
|
data/lib/toys/release/version.rb
CHANGED
|
@@ -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,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
|
86
|
+
# from the repo root directory or an absolute path.
|
|
87
87
|
#
|
|
88
|
-
# @param from [:
|
|
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: :
|
|
91
|
+
def directory(from: :repo_root)
|
|
92
92
|
case from
|
|
93
|
-
when :
|
|
93
|
+
when :repo_root
|
|
94
94
|
settings.directory
|
|
95
95
|
when :absolute
|
|
96
|
-
::File.expand_path(settings.directory, @utils.
|
|
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
|
|
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,:
|
|
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 :
|
|
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
|
|
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,:
|
|
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
|
|
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,:
|
|
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: :
|
|
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: :
|
|
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
|
|
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,:
|
|
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 =
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
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
|
-
|
|
7
|
-
|
|
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
|
|
34
|
+
# @return [boolean] Whether there were no errors
|
|
34
35
|
#
|
|
35
|
-
def
|
|
36
|
-
|
|
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
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
@
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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 =
|
|
306
|
+
artifact_dir = ArtifactDir.new(@work_dir)
|
|
321
307
|
begin
|
|
322
308
|
component.cd do
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
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
|