git-pr-release 2.5.0 → 2.6.0
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/.github/dependabot.yml +15 -0
- data/.github/workflows/release.yml +3 -3
- data/.github/workflows/test.yml +9 -18
- data/CHANGELOG.md +6 -0
- data/git-pr-release.gemspec +4 -1
- data/lib/git/pr/release/cli.rb +23 -3
- data/spec/git/pr/release/cli_spec.rb +118 -0
- metadata +18 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 10a02af243f4da16852984b6f131d360f2f815f1706ee3f1cc46a568827f86f1
|
|
4
|
+
data.tar.gz: 42df34c42101d8f15fedeeafe9b06e27adedfa90d88033b72b5644748d163dca
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ab9372594976f0953e8dc7520453c8108cb304d5a0570b2d20e6c7c0a5614bb34db41e5ce25a975ae58ea18b5f2d6be04aa933c0a21d630ae0e4348119661d3a
|
|
7
|
+
data.tar.gz: 7b57ebdd687de251b86d9e496e5f2f860ec99b6375c0167154e62dde26624f7932612c18b9da39f990f18b845fa0f96f496e7f338dd4e2d818d2bdb046a9dc68
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "github-actions"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
cooldown:
|
|
8
|
+
default-days: 3
|
|
9
|
+
|
|
10
|
+
- package-ecosystem: "bundler"
|
|
11
|
+
directory: "/"
|
|
12
|
+
schedule:
|
|
13
|
+
interval: "weekly"
|
|
14
|
+
cooldown:
|
|
15
|
+
default-days: 3
|
|
@@ -12,13 +12,13 @@ jobs:
|
|
|
12
12
|
id-token: write
|
|
13
13
|
|
|
14
14
|
steps:
|
|
15
|
-
- uses: actions/checkout@
|
|
15
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
16
16
|
with:
|
|
17
17
|
persist-credentials: false
|
|
18
18
|
|
|
19
|
-
- uses: ruby/setup-ruby@
|
|
19
|
+
- uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
|
|
20
20
|
with:
|
|
21
21
|
bundler-cache: true
|
|
22
22
|
ruby-version: ruby
|
|
23
23
|
|
|
24
|
-
- uses: rubygems/release-gem@
|
|
24
|
+
- uses: rubygems/release-gem@7f9650160c1a4e7989fdc9855807bdbd421d8b6b # v1.4.1
|
data/.github/workflows/test.yml
CHANGED
|
@@ -15,34 +15,25 @@ jobs:
|
|
|
15
15
|
fail-fast: false
|
|
16
16
|
matrix:
|
|
17
17
|
ruby:
|
|
18
|
+
- "3.0"
|
|
18
19
|
- "3.1"
|
|
19
20
|
- "3.2"
|
|
20
21
|
- "3.3"
|
|
21
22
|
- "3.4"
|
|
23
|
+
- "4.0"
|
|
22
24
|
- head
|
|
23
25
|
|
|
24
26
|
steps:
|
|
25
|
-
- uses: actions/checkout@
|
|
26
|
-
|
|
27
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
28
|
+
with:
|
|
29
|
+
persist-credentials: false
|
|
30
|
+
- uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
|
|
27
31
|
with:
|
|
28
32
|
ruby-version: ${{ matrix.ruby }}
|
|
29
33
|
bundler-cache: true
|
|
30
|
-
- name: Cache vendor/bundle
|
|
31
|
-
uses: actions/cache@v4
|
|
32
|
-
with:
|
|
33
|
-
path: vendor/bundle
|
|
34
|
-
key: v1-gem-${{ runner.os }}-${{ matrix.ruby }}-${{ github.sha }}
|
|
35
|
-
restore-keys: |
|
|
36
|
-
v1-gem-${{ runner.os }}-${{ matrix.ruby }}-
|
|
37
|
-
continue-on-error: ${{ matrix.allow_failures == 'true' }}
|
|
38
34
|
- name: bundle update
|
|
39
|
-
run:
|
|
40
|
-
set -xe
|
|
41
|
-
bundle config path vendor/bundle
|
|
42
|
-
bundle update --jobs $(nproc) --retry 3
|
|
35
|
+
run: bundle update --jobs $(nproc) --retry 3
|
|
43
36
|
continue-on-error: ${{ matrix.allow_failures == 'true' }}
|
|
44
|
-
- name: Run
|
|
45
|
-
run:
|
|
46
|
-
set -xe
|
|
47
|
-
bundle exec rspec
|
|
37
|
+
- name: Run RSpec
|
|
38
|
+
run: bundle exec rspec
|
|
48
39
|
continue-on-error: ${{ matrix.allow_failures == 'true' }}
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# git-pr-release
|
|
2
2
|
|
|
3
|
+
## v2.6.0 (2026-09-09)
|
|
4
|
+
|
|
5
|
+
[full changelog](https://github.com/x-motemen/git-pr-release/compare/v2.5.0...v2.6.0)
|
|
6
|
+
|
|
7
|
+
* (#123) Retry GitHub API requests failing with a server error (@exoego)
|
|
8
|
+
|
|
3
9
|
## v2.5.0 (2025-12-16)
|
|
4
10
|
|
|
5
11
|
[full changelog](https://github.com/x-motemen/git-pr-release/compare/v2.4.0...v2.5.0)
|
data/git-pr-release.gemspec
CHANGED
|
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = "git-pr-release"
|
|
7
|
-
spec.version = '2.
|
|
7
|
+
spec.version = '2.6.0'
|
|
8
8
|
spec.authors = ["motemen"]
|
|
9
9
|
spec.email = ["motemen@gmail.com"]
|
|
10
10
|
spec.summary = 'Creates a release pull request'
|
|
@@ -17,7 +17,10 @@ Gem::Specification.new do |spec|
|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
18
18
|
spec.require_paths = ["lib"]
|
|
19
19
|
|
|
20
|
+
spec.required_ruby_version = '>= 3.0'
|
|
21
|
+
|
|
20
22
|
spec.add_dependency 'octokit'
|
|
23
|
+
spec.add_dependency 'faraday-retry'
|
|
21
24
|
spec.add_dependency 'highline'
|
|
22
25
|
spec.add_dependency 'colorize'
|
|
23
26
|
spec.add_dependency 'diff-lcs'
|
data/lib/git/pr/release/cli.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'faraday/retry'
|
|
1
2
|
require 'octokit'
|
|
2
3
|
require 'optparse'
|
|
3
4
|
|
|
@@ -54,8 +55,23 @@ module Git
|
|
|
54
55
|
return 0
|
|
55
56
|
end
|
|
56
57
|
|
|
58
|
+
# POST is left out: retrying it could create a duplicated release pull request.
|
|
59
|
+
RETRY_OPTIONS = {
|
|
60
|
+
max: 5,
|
|
61
|
+
interval: 1,
|
|
62
|
+
interval_randomness: 0.5,
|
|
63
|
+
backoff_factor: 2,
|
|
64
|
+
retry_statuses: [500, 502, 503, 504],
|
|
65
|
+
methods: %i[delete get head options patch put]
|
|
66
|
+
}.freeze
|
|
67
|
+
|
|
57
68
|
def client
|
|
58
|
-
@client ||= Octokit::Client.new
|
|
69
|
+
@client ||= Octokit::Client.new(:access_token => obtain_token!).tap do |client|
|
|
70
|
+
# Inside RaiseError so retry_statuses sees the response, not Octokit::ServerError.
|
|
71
|
+
client.middleware = client.middleware.dup.tap do |builder|
|
|
72
|
+
builder.insert_after Octokit::Response::RaiseError, Faraday::Retry::Middleware, RETRY_OPTIONS
|
|
73
|
+
end
|
|
74
|
+
end
|
|
59
75
|
end
|
|
60
76
|
|
|
61
77
|
def configure
|
|
@@ -175,9 +191,13 @@ module Git
|
|
|
175
191
|
# This is difficult to read from the current documentation, but that is the current
|
|
176
192
|
# behavior and GitHub support has responded that this is the spec.
|
|
177
193
|
shas.each do |sha|
|
|
178
|
-
#
|
|
194
|
+
# GitHub documents a 256-character limit for search queries, but in practice
|
|
195
|
+
# the API enforces a stricter limit, likely due to URL-encoded length counting.
|
|
196
|
+
# Multiple users have reported errors at 220-240 characters, with 200 being stable.
|
|
179
197
|
# ref. https://docs.github.com/en/rest/reference/search#limitations-on-query-length
|
|
180
|
-
|
|
198
|
+
# ref. https://github.com/x-motemen/git-pr-release/issues/103
|
|
199
|
+
# ref. https://github.com/orgs/community/discussions/186957
|
|
200
|
+
if query.length + 1 + sha.length >= 200
|
|
181
201
|
pr_nums.concat(search_issue_numbers(query))
|
|
182
202
|
query = query_base
|
|
183
203
|
end
|
|
@@ -313,6 +313,64 @@ RSpec.describe Git::Pr::Release::CLI do
|
|
|
313
313
|
end
|
|
314
314
|
end
|
|
315
315
|
|
|
316
|
+
describe "#client" do
|
|
317
|
+
subject { @cli.client }
|
|
318
|
+
|
|
319
|
+
let(:pull_request_url) { "https://api.github.com/repos/motemen/git-pr-release/pulls/1023" }
|
|
320
|
+
|
|
321
|
+
before {
|
|
322
|
+
@cli = configured_cli
|
|
323
|
+
|
|
324
|
+
allow(@cli).to receive(:obtain_token!) { "dummy token" }
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
context "When the GitHub API responds a server error to an idempotent request" do
|
|
328
|
+
before {
|
|
329
|
+
stub_request(:patch, pull_request_url).to_return(
|
|
330
|
+
{ status: 502, body: "", headers: {} },
|
|
331
|
+
{ status: 200, body: %({"number":1023}), headers: { "Content-Type" => "application/json" } },
|
|
332
|
+
)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
it "retries the request" do
|
|
336
|
+
expect(subject.update_pull_request("motemen/git-pr-release", 1023, title: "PR Title").number).to eq 1023
|
|
337
|
+
expect(a_request(:patch, pull_request_url)).to have_been_made.twice
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
context "When the GitHub API responds a server error to a request creating a pull request" do
|
|
342
|
+
let(:pull_requests_url) { "https://api.github.com/repos/motemen/git-pr-release/pulls" }
|
|
343
|
+
|
|
344
|
+
before {
|
|
345
|
+
stub_request(:post, pull_requests_url).to_return(status: 502, body: "", headers: {})
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
it "does not retry the request" do
|
|
349
|
+
expect {
|
|
350
|
+
subject.create_pull_request("motemen/git-pr-release", "master", "staging", "PR Title", "")
|
|
351
|
+
}.to raise_error Octokit::BadGateway
|
|
352
|
+
expect(a_request(:post, pull_requests_url)).to have_been_made.once
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
context "When the GitHub API responds a client error" do
|
|
357
|
+
before {
|
|
358
|
+
stub_request(:patch, pull_request_url).to_return(status: 404, body: "", headers: {})
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
it "does not retry the request" do
|
|
362
|
+
expect {
|
|
363
|
+
subject.update_pull_request("motemen/git-pr-release", 1023, title: "PR Title")
|
|
364
|
+
}.to raise_error Octokit::NotFound
|
|
365
|
+
expect(a_request(:patch, pull_request_url)).to have_been_made.once
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
it "does not modify the middleware shared by every Octokit client" do
|
|
370
|
+
expect { subject }.not_to change { Octokit::Default::MIDDLEWARE.handlers }
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
|
|
316
374
|
describe "#fetch_merged_prs" do
|
|
317
375
|
subject { @cli.fetch_merged_prs }
|
|
318
376
|
|
|
@@ -707,4 +765,64 @@ RSpec.describe Git::Pr::Release::CLI do
|
|
|
707
765
|
expect(@client).to have_received(:auto_paginate=).with(false)
|
|
708
766
|
}
|
|
709
767
|
end
|
|
768
|
+
|
|
769
|
+
describe "#fetch_squash_merged_pr_numbers_from_github" do
|
|
770
|
+
subject { @cli.send(:fetch_squash_merged_pr_numbers_from_github) }
|
|
771
|
+
|
|
772
|
+
before {
|
|
773
|
+
@cli = configured_cli
|
|
774
|
+
|
|
775
|
+
allow(@cli).to receive(:git).with(:log, '--pretty=format:%h', "--abbrev=7", "--no-merges", "--first-parent",
|
|
776
|
+
"origin/master..origin/staging") { shas.map { |sha| "#{sha}\n" } }
|
|
777
|
+
allow(@cli).to receive(:search_issue_numbers) { |query| [123] }
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
context "When SHAs fit within query length limit" do
|
|
781
|
+
let(:shas) { ["abc1234", "def5678"] }
|
|
782
|
+
|
|
783
|
+
it "makes a single search request" do
|
|
784
|
+
subject
|
|
785
|
+
|
|
786
|
+
expect(@cli).to have_received(:search_issue_numbers).once
|
|
787
|
+
end
|
|
788
|
+
end
|
|
789
|
+
|
|
790
|
+
context "When SHAs exceed query length limit" do
|
|
791
|
+
# query_base = "repo:motemen/git-pr-release is:pr is:closed" (44 characters)
|
|
792
|
+
# Each SHA is 7 characters + 1 space = 8 characters
|
|
793
|
+
# Available space for SHAs: 200 - 44 = 156 characters
|
|
794
|
+
# To exceed the limit: 156 / 8 = ~19.5, so 20 SHAs will trigger a split
|
|
795
|
+
let(:shas) { (1..25).map { |i| sprintf("%07d", i) } }
|
|
796
|
+
|
|
797
|
+
it "splits into multiple search requests" do
|
|
798
|
+
subject
|
|
799
|
+
|
|
800
|
+
expect(@cli).to have_received(:search_issue_numbers).at_least(2).times
|
|
801
|
+
end
|
|
802
|
+
|
|
803
|
+
it "keeps total query length under 200 characters" do
|
|
804
|
+
call_count = 0
|
|
805
|
+
|
|
806
|
+
allow(@cli).to receive(:search_issue_numbers) do |query|
|
|
807
|
+
call_count += 1
|
|
808
|
+
expect(query.length).to be < 200
|
|
809
|
+
[123]
|
|
810
|
+
end
|
|
811
|
+
|
|
812
|
+
subject
|
|
813
|
+
|
|
814
|
+
expect(call_count).to be > 1
|
|
815
|
+
end
|
|
816
|
+
end
|
|
817
|
+
|
|
818
|
+
context "When query_base is empty after processing all SHAs" do
|
|
819
|
+
let(:shas) { ["abc1234"] }
|
|
820
|
+
|
|
821
|
+
it "makes exactly one search request" do
|
|
822
|
+
subject
|
|
823
|
+
|
|
824
|
+
expect(@cli).to have_received(:search_issue_numbers).once
|
|
825
|
+
end
|
|
826
|
+
end
|
|
827
|
+
end
|
|
710
828
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: git-pr-release
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- motemen
|
|
@@ -23,6 +23,20 @@ dependencies:
|
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: faraday-retry
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
26
40
|
- !ruby/object:Gem::Dependency
|
|
27
41
|
name: highline
|
|
28
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -130,6 +144,7 @@ executables:
|
|
|
130
144
|
extensions: []
|
|
131
145
|
extra_rdoc_files: []
|
|
132
146
|
files:
|
|
147
|
+
- ".github/dependabot.yml"
|
|
133
148
|
- ".github/workflows/release.yml"
|
|
134
149
|
- ".github/workflows/test.yml"
|
|
135
150
|
- ".gitignore"
|
|
@@ -171,14 +186,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
171
186
|
requirements:
|
|
172
187
|
- - ">="
|
|
173
188
|
- !ruby/object:Gem::Version
|
|
174
|
-
version: '0'
|
|
189
|
+
version: '3.0'
|
|
175
190
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
176
191
|
requirements:
|
|
177
192
|
- - ">="
|
|
178
193
|
- !ruby/object:Gem::Version
|
|
179
194
|
version: '0'
|
|
180
195
|
requirements: []
|
|
181
|
-
rubygems_version:
|
|
196
|
+
rubygems_version: 4.0.16
|
|
182
197
|
specification_version: 4
|
|
183
198
|
summary: Creates a release pull request
|
|
184
199
|
test_files:
|