Skip to content

Commit d72eda8

Browse files
authored
chore: Provide a release retry script
1 parent 7dfcb6e commit d72eda8

File tree

9 files changed

+309
-43
lines changed

9 files changed

+309
-43
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ jobs:
8181
- name: Checkout
8282
uses: actions/checkout@v2
8383
- name: Install tools
84-
run: gem install --no-document bundler:2.1.4 toys:0.11.2
84+
run: gem install --no-document bundler:2.1.4 toys:0.11.4
8585
- name: Run tests
8686
env:
8787
TEST_KAFKA_HOST: kafka
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Retry release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
release_pr:
7+
description: Release PR number
8+
required: true
9+
flags:
10+
description: Extra flags to pass to the release script
11+
required: false
12+
default: ""
13+
14+
jobs:
15+
release-retry:
16+
if: ${{ github.repository == 'open-telemetry/opentelemetry-ruby' }}
17+
env:
18+
ruby_version: "2.7"
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Install Ruby ${{ env.ruby_version }}
22+
uses: ruby/setup-ruby@v1
23+
with:
24+
ruby-version: ${{ env.ruby_version }}
25+
- name: Checkout repo
26+
uses: actions/checkout@v2
27+
- name: Install Toys
28+
run: "gem install --no-document toys"
29+
- name: Retry release
30+
env:
31+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32+
run: |
33+
toys release retry --yes --verbose \
34+
"--enable-releases=${{ secrets.ENABLE_RELEASES }}" \
35+
"--rubygems-api-key=${{ secrets.RUBYGEMS_API_KEY }}" \
36+
${{ github.event.inputs.flags }} \
37+
"${{ github.event.inputs.release_pr }}" \
38+
< /dev/null
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Retry release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
release_pr:
7+
description: Release PR number
8+
required: true
9+
flags:
10+
description: Extra flags to pass to the release script
11+
required: false
12+
default: ""
13+
14+
jobs:
15+
release-retry:
16+
if: ${{ github.repository == '<%= @settings.repo_path %>' }}
17+
env:
18+
ruby_version: "2.7"
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Install Ruby ${{ env.ruby_version }}
22+
uses: ruby/setup-ruby@v1
23+
with:
24+
ruby-version: ${{ env.ruby_version }}
25+
- name: Checkout repo
26+
uses: actions/checkout@v2
27+
- name: Install Toys
28+
run: "gem install --no-document toys"
29+
- name: Retry release
30+
env:
31+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32+
run: |
33+
toys release retry --yes --verbose \
34+
"--enable-releases=${{ secrets.ENABLE_RELEASES }}" \
35+
"--rubygems-api-key=${{ secrets.RUBYGEMS_API_KEY }}" \
36+
${{ github.event.inputs.flags }} \
37+
"${{ github.event.inputs.release_pr }}" \
38+
< /dev/null

.toys/release/.lib/release_performer.rb

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ def perform_steps
5656
@parent.initial_setup
5757
verify unless @parent.skip_checks?
5858

59+
check_release_exists
60+
check_gem_exists
61+
check_docs_exists
62+
5963
build_gem if @include_gem
6064
if @include_docs
6165
build_docs
@@ -67,6 +71,42 @@ def perform_steps
6771
push_docs if @include_docs
6872
end
6973

74+
def check_gem_exists
75+
return if !@parent.check_exists? || !@include_gem
76+
result = @utils.capture(["gem", "info", "-r", "-a", @gem_name])
77+
if result =~ /#{@gem_name} \(([\w\., ]+)\)/
78+
if Regexp.last_match[1].split(/,\s+/).include?(@gem_version)
79+
@utils.logger.warn("Gem already pushed for #{@gem_name} #{@gem_version}. Skipping.")
80+
@include_gem = false
81+
end
82+
end
83+
end
84+
85+
def check_docs_exists
86+
return if !@parent.check_exists? || !@include_docs
87+
base_path = ::File.expand_path(@utils.gem_info(@gem_name, "gh_pages_directory"),
88+
@parent.gh_pages_dir)
89+
versioned_path = ::File.expand_path("v#{@gem_version}", base_path)
90+
if File.directory?(versioned_path)
91+
@utils.logger.warn("Docs already pushed for #{@gem_name} #{@gem_version}. Skipping.")
92+
@include_docs = false
93+
end
94+
end
95+
96+
def check_release_exists
97+
return if !@parent.check_exists? || !@include_github_release
98+
result = @utils.exec(["gh", "api",
99+
"repos/#{@utils.repo_path}/releases/tags/#{@gem_name}/v#{@gem_version}",
100+
"-H", "Accept: application/vnd.github.v3+json"],
101+
out: :null, e: false)
102+
if result.success?
103+
@utils.logger.warn(
104+
"GitHub release already exists for #{@gem_name} #{@gem_version}. Skipping."
105+
)
106+
@include_github_release = false
107+
end
108+
end
109+
70110
def verify
71111
@utils.error("Gem #{@gem_name} not known.") unless @utils.gem_info(@gem_name)
72112
@utils.verify_library_version(@gem_name, @gem_version)
@@ -79,7 +119,7 @@ def create_github_release(content = nil)
79119
body = ::JSON.dump(tag_name: "#{@gem_name}/v#{@gem_version}",
80120
target_commitish: @parent.release_sha,
81121
name: "#{@gem_name} #{@gem_version}",
82-
body: content.strip)
122+
body: content.to_s.strip)
83123
@utils.exec(["gh", "api", "repos/#{@utils.repo_path}/releases", "--input", "-",
84124
"-H", "Accept: application/vnd.github.v3+json"],
85125
in: [:string, body], out: :null)
@@ -167,13 +207,15 @@ def initialize(utils,
167207
gh_pages_dir: nil,
168208
gh_token: nil,
169209
pr_info: nil,
210+
check_exists: false,
170211
dry_run: false)
171212
@utils = utils
172213
@release_sha = @utils.current_sha release_sha
173214
@skip_checks = skip_checks
174215
@rubygems_api_key = rubygems_api_key
175216
@git_remote = git_remote || "origin"
176217
@dry_run = dry_run
218+
@check_exists = check_exists
177219
@gh_pages_dir = gh_pages_dir
178220
@gh_token = gh_token
179221
@pr_info = pr_info
@@ -200,6 +242,10 @@ def skip_checks?
200242
@skip_checks
201243
end
202244

245+
def check_exists?
246+
@check_exists
247+
end
248+
203249
def add_extra_errors(*messages)
204250
@extra_errors.concat(messages)
205251
end

.toys/release/.lib/release_utils.rb

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ def capture(cmd, **opts, &block)
7777
tool_context.capture(cmd, **opts, &block)
7878
end
7979

80+
def capture_ruby(code, **opts, &block)
81+
opts[:in] = [:string, code]
82+
opts = modify_exec_opts(opts, "ruby")
83+
tool_context.capture_ruby([], **opts, &block)
84+
end
85+
8086
def ensure_gh_binary
8187
result = exec(["gh", "--version"], out: :capture, exit_on_nonzero_status: false)
8288
match = /^gh version (\d+)\.(\d+)\.(\d+)/.match(result.captured_out.to_s)
@@ -184,14 +190,17 @@ def add_pr_message(pr_number, message)
184190
self
185191
end
186192

187-
def current_library_version(gem_name)
188-
path = gem_version_rb_path(gem_name, from: :absolute)
189-
require path
190-
const = ::Object
191-
gem_version_constant(gem_name).each do |name|
192-
const = const.const_get(name)
193-
end
194-
const
193+
def current_library_version(gem_name, at: nil)
194+
content =
195+
if at
196+
path = gem_version_rb_path(gem_name, from: :context)
197+
capture(["git", "show", "#{at}:#{path}"])
198+
else
199+
File.read(gem_version_rb_path(gem_name, from: :absolute))
200+
end
201+
const = gem_version_constant(gem_name).join("::")
202+
content += "\nputs ::#{const}\n"
203+
capture_ruby(content).strip
195204
end
196205

197206
def verify_library_version(gem_name, gem_vers)
@@ -331,6 +340,10 @@ def git_set_user_info
331340
self
332341
end
333342

343+
def released_gems_and_versions(pr_info)
344+
single_released_gem_and_version(pr_info) || multiple_released_gems_and_versions(pr_info)
345+
end
346+
334347
def log(message)
335348
logger.info(message)
336349
end
@@ -397,4 +410,32 @@ def wait_github_checks_internal(ref, deadline)
397410
interval += 10 unless interval >= 60
398411
end
399412
end
413+
414+
def single_released_gem_and_version(pr_info)
415+
gem_name =
416+
if all_gems.size == 1
417+
default_gem
418+
else
419+
gem_name_from_release_branch(pr_info["head"]["ref"])
420+
end
421+
return nil unless gem_name
422+
merge_sha = pr_info["merge_commit_sha"]
423+
gem_version = current_library_version(gem_name, at: merge_sha)
424+
logger.info("Found single gem to release: #{gem_name} #{gem_version}.")
425+
{ gem_name => gem_version }
426+
end
427+
428+
def multiple_released_gems_and_versions(pr_info)
429+
merge_sha = pr_info["merge_commit_sha"]
430+
output = capture(["git", "diff", "--name-only", "#{merge_sha}^..#{merge_sha}"])
431+
files = output.split("\n")
432+
gems = all_gems.find_all do |gem_name|
433+
dir = gem_directory(gem_name)
434+
files.any? { |file| file.start_with?(dir) }
435+
end
436+
gems.each_with_object({}) do |gem_name, result|
437+
result[gem_name] = gem_version = current_library_version(gem_name, at: merge_sha)
438+
logger.info("Releasing gem due to file changes: #{gem_name} #{gem_version}.")
439+
end
440+
end
400441
end

.toys/release/.lib/repo_settings.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def gem_changelog_path(gem_name, from: :directory)
8686
when :directory
8787
path
8888
when :context
89-
::File.expand_path(path, gem_directory(gem_name))
89+
::File.join(gem_directory(gem_name), path)
9090
when :absolute
9191
::File.expand_path(path, gem_directory(gem_name, from: :absolute))
9292
else
@@ -100,7 +100,7 @@ def gem_version_rb_path(gem_name, from: :directory)
100100
when :directory
101101
path
102102
when :context
103-
::File.expand_path(path, gem_directory(gem_name))
103+
::File.join(gem_directory(gem_name), path)
104104
when :absolute
105105
::File.expand_path(path, gem_directory(gem_name, from: :absolute))
106106
else

.toys/release/_onclosed.rb

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def handle_release_merged
8989
performer = create_performer
9090
github_check_errors = @utils.wait_github_checks
9191
if github_check_errors.empty?
92-
find_gems_and_versions.each do |gem_name, gem_version|
92+
@utils.released_gems_and_versions(@pr_info).each do |gem_name, gem_version|
9393
if performer.instance(gem_name, gem_version).perform
9494
puts("SUCCESS: Released #{gem_name} #{gem_version}", :bold, :green)
9595
end
@@ -110,35 +110,6 @@ def setup_git
110110
exec(["git", "checkout", "release/current"])
111111
end
112112

113-
def find_gems_and_versions
114-
gem_name =
115-
if @utils.all_gems.size == 1
116-
@utils.default_gem
117-
else
118-
@utils.gem_name_from_release_branch(@pr_info["head"]["ref"])
119-
end
120-
if gem_name
121-
gem_version = @utils.current_library_version(gem_name)
122-
logger.info("Found single gem to release: #{gem_name} #{gem_version}.")
123-
result = { gem_name => gem_version }
124-
return result
125-
end
126-
gems_and_versions_from_git
127-
end
128-
129-
def gems_and_versions_from_git
130-
output = capture(["git", "diff", "--name-only", "release/current^..release/current"])
131-
files = output.split("\n")
132-
gems = @utils.all_gems.find_all do |gem_name|
133-
dir = @utils.gem_directory(gem_name)
134-
files.any? { |file| file.start_with?(dir) }
135-
end
136-
gems.each_with_object({}) do |gem_name, result|
137-
result[gem_name] = gem_version = @utils.current_library_version(gem_name)
138-
logger.info("Releasing gem due to file changes: #{gem_name} #{gem_version}.")
139-
end
140-
end
141-
142113
def create_performer
143114
require "release_performer"
144115
dry_run = /^t/i =~ enable_releases.to_s ? false : true

.toys/release/gen-workflows.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ def run
3838
@workflows_dir = ::File.join(context_directory, ".github", "workflows")
3939
files = [
4040
"release-hook-on-closed.yml",
41-
"release-hook-on-open.yml",
4241
"release-hook-on-push.yml",
4342
"release-perform.yml",
4443
"release-request.yml",
44+
"release-retry.yml",
4545
]
4646

4747
files.each { |name| generate(name) }

0 commit comments

Comments
 (0)