multi_repo 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yaml +3 -1
- data/CHANGELOG.md +17 -1
- data/lib/multi_repo/service/git.rb +11 -0
- data/lib/multi_repo/service/github.rb +64 -0
- data/lib/multi_repo/version.rb +1 -1
- data/scripts/destroy_remote +1 -5
- data/scripts/pull_request_labeler +17 -38
- data/scripts/pull_request_merger +16 -38
- data/scripts/show_commit_history +6 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8505baba7399c81174faea1dcce56eb3d16687d1c08c88ac1fe18c2eeae6f26a
|
4
|
+
data.tar.gz: d513358adc717ca4582c6f29864926a0a23bfb01a88a0622b55ff358939f7d35
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86f552f73954d01bbf06b31906170399eee68a60721538743dd5fdf2ce46832e918c89740d49e83c337a150f52dc9f8be3f73d0cb37f459fab3dcf317e244366
|
7
|
+
data.tar.gz: 86846ee0c472f5eb5b8ebade9bdafa87985db8ab114e210b6b0aa276e36466a56412260a6e503cc436dc874893f13baa140733542088816bae034c40ce7e3e5d
|
data/.github/workflows/ci.yaml
CHANGED
@@ -14,6 +14,8 @@ jobs:
|
|
14
14
|
ruby-version:
|
15
15
|
- '3.0'
|
16
16
|
- '3.1'
|
17
|
+
- '3.2'
|
18
|
+
- '3.3'
|
17
19
|
env:
|
18
20
|
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
19
21
|
steps:
|
@@ -29,4 +31,4 @@ jobs:
|
|
29
31
|
- name: Report code coverage
|
30
32
|
if: ${{ github.ref == 'refs/heads/master' && matrix.ruby-version == '3.1' }}
|
31
33
|
continue-on-error: true
|
32
|
-
uses: paambaati/codeclimate-action@
|
34
|
+
uses: paambaati/codeclimate-action@v9
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,21 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
4
4
|
|
5
5
|
## [Unreleased]
|
6
6
|
|
7
|
+
## [0.5.0] - 2024-11-12
|
8
|
+
### Added
|
9
|
+
- [pull_request_labeler] Add ability to also add a comment about why the labels are changing [[#30](https://github.com/ManageIQ/multi_repo/pull/30)]
|
10
|
+
- [pull_request_labeler] Add normalization of PR formats to org/repo#pr format [[#30](https://github.com/ManageIQ/multi_repo/pull/30)]
|
11
|
+
- [pull_request_merger] Add URL support to pull_request_merger [[#37](https://github.com/ManageIQ/multi_repo/pull/37)]
|
12
|
+
- [Git Service, GitHub service] Move helper methods into services [[#31](https://github.com/ManageIQ/multi_repo/pull/31)]
|
13
|
+
- Add testing with ruby 3.2, 3.3 [[#35](https://github.com/ManageIQ/multi_repo/pull/35)]
|
14
|
+
|
15
|
+
### Changed
|
16
|
+
- [pull_request_labeler] Make add and remove optional [[#30](https://github.com/ManageIQ/multi_repo/pull/30)]
|
17
|
+
|
18
|
+
### Fixed
|
19
|
+
- [pull_request_labeler] Fix cli description of --prs [[#30](https://github.com/ManageIQ/multi_repo/pull/30)]
|
20
|
+
- [show_commit_history] Handle issue where PR may not be found [[#36](https://github.com/ManageIQ/multi_repo/pull/30)]
|
21
|
+
|
7
22
|
## [0.4.0] - 2024-03-29
|
8
23
|
### Changed
|
9
24
|
- Allow overriding the path for a repo [[#28](https://github.com/ManageIQ/multi_repo/pull/28)]
|
@@ -18,6 +33,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
18
33
|
- [show_commit_history] Prevent missing ranges from failing the entire run [[#20](https://github.com/ManageIQ/multi_repo/pull/20)]
|
19
34
|
- [pull_request_merger] Fixing issue passing kwargs on Ruby 3 [[#23](https://github.com/ManageIQ/multi_repo/pull/23)]
|
20
35
|
|
21
|
-
[Unreleased]: https://github.com/ManageIQ/more_core_extensions/compare/v0.
|
36
|
+
[Unreleased]: https://github.com/ManageIQ/more_core_extensions/compare/v0.5.0...HEAD
|
37
|
+
[0.5.0]: https://github.com/ManageIQ/more_core_extensions/compare/v0.4.0...v0.5.0
|
22
38
|
[0.4.0]: https://github.com/ManageIQ/more_core_extensions/compare/v0.3.1...v0.4.0
|
23
39
|
[0.3.1]: https://github.com/ManageIQ/more_core_extensions/compare/v0.3.0...v0.3.1
|
@@ -83,6 +83,17 @@ module MultiRepo::Service
|
|
83
83
|
true
|
84
84
|
end
|
85
85
|
|
86
|
+
def destroy_remote(remote)
|
87
|
+
if dry_run
|
88
|
+
puts "** dry-run: git remote rm #{remote}".light_black
|
89
|
+
else
|
90
|
+
client.remote("rm", remote)
|
91
|
+
end
|
92
|
+
rescue MiniGit::GitError
|
93
|
+
# Ignore missing remotes because we want them destroyed anyway
|
94
|
+
nil
|
95
|
+
end
|
96
|
+
|
86
97
|
def remote_branch?(remote, branch)
|
87
98
|
client.capturing.ls_remote(remote, branch).present?
|
88
99
|
end
|
@@ -83,6 +83,24 @@ module MultiRepo::Service
|
|
83
83
|
client.workflows(repo_name)[:workflows].select { |w| w.state == "disabled_inactivity" }
|
84
84
|
end
|
85
85
|
|
86
|
+
PR_REGEX = %r{^([^/#]+/[^/#]+)#(\d+)$}
|
87
|
+
|
88
|
+
# Parse a list of PRs that are in URL or org/repo#pr format into a Array of
|
89
|
+
# [repo_name, pr_number] entries.
|
90
|
+
def self.parse_prs(*prs)
|
91
|
+
prs.flatten.map do |pr|
|
92
|
+
# Normalize to org/repo#pr
|
93
|
+
normalized_pr = pr.sub("https://github.com/", "").sub("/pull/", "#")
|
94
|
+
|
95
|
+
if (match = PR_REGEX.match(normalized_pr))
|
96
|
+
repo_name, pr_number = match.captures
|
97
|
+
[repo_name, pr_number.to_i]
|
98
|
+
else
|
99
|
+
raise ArgumentError, "Invalid PR '#{pr}'. PR must be a GitHub URL or in org/repo#pr format."
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
86
104
|
attr_reader :dry_run
|
87
105
|
|
88
106
|
def initialize(dry_run: false)
|
@@ -138,6 +156,44 @@ module MultiRepo::Service
|
|
138
156
|
end
|
139
157
|
end
|
140
158
|
|
159
|
+
def add_labels_to_an_issue(repo_name, issue_number, labels)
|
160
|
+
labels = Array(labels)
|
161
|
+
if dry_run
|
162
|
+
puts "** dry-run: github.add_labels_to_an_issue(#{repo_name.inspect}, #{issue_number.inspect}, #{labels.inspect})".light_black
|
163
|
+
else
|
164
|
+
client.add_labels_to_an_issue(repo_name, issue_number, labels)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def remove_labels_from_an_issue(repo_name, issue_number, labels)
|
169
|
+
Array(labels).each do |label|
|
170
|
+
if dry_run
|
171
|
+
puts "** dry-run: github.remove_label(#{repo_name.inspect}, #{issue_number.inspect}, #{label.inspect})".light_black
|
172
|
+
else
|
173
|
+
client.remove_label(repo_name, issue_number, label)
|
174
|
+
end
|
175
|
+
rescue Octokit::NotFound
|
176
|
+
# Ignore labels that are not found, because we want them removed anyway
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def add_comment(repo_name, issue_number, body)
|
181
|
+
if dry_run
|
182
|
+
puts "** dry-run: github.add_comment(#{repo_name.inspect}, #{issue_number.inspect}, #{body.pretty_inspect.chomp})".light_black
|
183
|
+
else
|
184
|
+
client.add_comment(repo_name, issue_number, body)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def assign_user(repo_name, issue_number, assignee)
|
189
|
+
assignee = assignee[1..] if assignee.start_with?("@")
|
190
|
+
if dry_run
|
191
|
+
puts "** dry-run: github.update_issue(#{repo_name.inspect}, #{issue_number.inspect}, \"assignee\" => #{assignee.inspect})".light_black
|
192
|
+
else
|
193
|
+
client.update_issue(repo_name, issue_number, "assignee" => assignee)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
141
197
|
def create_milestone(repo_name, title, due_on)
|
142
198
|
if dry_run
|
143
199
|
puts "** dry-run: github.create_milestone(#{repo_name.inspect}, #{title.inspect}, :due_on => #{due_on.strftime("%Y-%m-%d").inspect})".light_black
|
@@ -208,6 +264,14 @@ module MultiRepo::Service
|
|
208
264
|
end
|
209
265
|
end
|
210
266
|
|
267
|
+
def merge_pull_request(repo_name, pr_number)
|
268
|
+
if dry_run
|
269
|
+
puts "** dry-run: github.merge_pull_request(#{repo_name.inspect}, #{pr_number.inspect})".light_black
|
270
|
+
else
|
271
|
+
client.merge_pull_request(repo_name, pr_number)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
211
275
|
def create_or_update_repository_secret(repo_name, key, value)
|
212
276
|
payload = encode_secret(repo_name, value)
|
213
277
|
|
data/lib/multi_repo/version.rb
CHANGED
data/scripts/destroy_remote
CHANGED
@@ -9,53 +9,32 @@ end
|
|
9
9
|
opts = Optimist.options do
|
10
10
|
synopsis "Add or remove labels on a set of pull requests."
|
11
11
|
|
12
|
-
opt :prs, "The list of PRs to
|
13
|
-
opt :add, "Labels to add", :type => :strings
|
14
|
-
opt :remove, "Labels to remove", :type => :strings
|
12
|
+
opt :prs, "The list of PRs to label", :type => :strings, :required => true
|
13
|
+
opt :add, "Labels to add", :type => :strings
|
14
|
+
opt :remove, "Labels to remove", :type => :strings
|
15
15
|
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
# TODO: Normalize any PR format to `org/repo#pr`
|
20
|
-
PR_REGEX = %r{^([^/#]+/[^/#]+)#([^/#]+)$}
|
21
|
-
Optimist.die :prs, "must be in the form `org/repo#pr`" unless opts[:prs].all? { |pr| pr.match?(PR_REGEX) }
|
22
|
-
|
23
|
-
def github
|
24
|
-
MultiRepo::Service::Github.client
|
25
|
-
end
|
16
|
+
opt :comment, "Comment explaining the label change", :type => :string
|
26
17
|
|
27
|
-
|
28
|
-
labels = Array(labels)
|
29
|
-
if dry_run
|
30
|
-
puts "** dry-run: github.add_labels_to_an_issue(#{repo_name.inspect}, #{pr_number.inspect}, #{labels.inspect})".light_black
|
31
|
-
else
|
32
|
-
github.add_labels_to_an_issue(repo_name, pr_number, labels)
|
33
|
-
end
|
18
|
+
MultiRepo::CLI.common_options(self, :only => :dry_run)
|
34
19
|
end
|
35
20
|
|
36
|
-
|
37
|
-
Array(labels).each do |label|
|
38
|
-
remove_label(repo_name, pr_number, label: label, dry_run: dry_run)
|
39
|
-
end
|
40
|
-
end
|
21
|
+
Optimist.die "at least one of --add or --remove is required" unless opts[:add_given] || opts[:remove_given]
|
41
22
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
23
|
+
prs =
|
24
|
+
begin
|
25
|
+
MultiRepo::Service::Github.parse_prs(opts[:prs])
|
26
|
+
rescue ArgumentError => err
|
27
|
+
Optimist.die :prs, err.message
|
47
28
|
end
|
48
|
-
rescue Octokit::NotFound
|
49
|
-
# Ignore labels that are not found, because we want them removed anyway
|
50
|
-
end
|
51
29
|
|
52
|
-
opts[:
|
53
|
-
puts MultiRepo::CLI.header(pr)
|
30
|
+
github = MultiRepo::Service::Github.new(:dry_run => opts[:dry_run])
|
54
31
|
|
55
|
-
|
32
|
+
prs.each do |repo_name, pr_number|
|
33
|
+
puts MultiRepo::CLI.header("#{repo_name}##{pr_number}")
|
56
34
|
|
57
|
-
|
58
|
-
|
35
|
+
github.add_labels_to_an_issue(repo_name, pr_number, opts[:add]) if opts[:add].present?
|
36
|
+
github.remove_labels_from_an_issue(repo_name, pr_number, opts[:remove]) if opts[:remove].present?
|
37
|
+
github.add_comment(repo_name, pr_number, opts[:comment]) if opts[:comment].present?
|
59
38
|
|
60
39
|
puts
|
61
40
|
end
|
data/scripts/pull_request_merger
CHANGED
@@ -16,50 +16,28 @@ opts = Optimist.options do
|
|
16
16
|
MultiRepo::CLI.common_options(self)
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
if dry_run
|
25
|
-
puts "** dry-run: github.merge_pull_request(#{repo_name.inspect}, #{pr_number.inspect})".light_black
|
26
|
-
else
|
27
|
-
begin
|
28
|
-
MultiRepo::Service::Github.client.merge_pull_request(repo_name, pr_number)
|
29
|
-
rescue Octokit::MethodNotAllowed => err
|
30
|
-
raise unless err.to_s.include?("Pull Request is not mergeable")
|
31
|
-
|
32
|
-
puts "** WARN: Pull Request is not mergeable"
|
33
|
-
end
|
19
|
+
prs =
|
20
|
+
begin
|
21
|
+
MultiRepo::Service::Github.parse_prs(opts[:prs])
|
22
|
+
rescue ArgumentError => err
|
23
|
+
Optimist.die :prs, err.message
|
34
24
|
end
|
35
|
-
end
|
36
25
|
|
37
|
-
|
38
|
-
labels = Array(labels)
|
39
|
-
if dry_run
|
40
|
-
puts "** dry-run: github.add_labels_to_an_issue(#{repo_name.inspect}, #{pr_number.inspect}, #{labels.inspect})".light_black
|
41
|
-
else
|
42
|
-
MultiRepo::Service::Github.client.add_labels_to_an_issue(repo_name, pr_number, labels)
|
43
|
-
end
|
44
|
-
end
|
26
|
+
github = MultiRepo::Service::Github.new(:dry_run => opts[:dry_run])
|
45
27
|
|
46
|
-
|
47
|
-
|
48
|
-
if dry_run
|
49
|
-
puts "** dry-run: github.update_issue(#{repo_name.inspect}, #{pr_number.inspect}, \"assignee\" => #{assignee.inspect})".light_black
|
50
|
-
else
|
51
|
-
MultiRepo::Service::Github.client.update_issue(repo_name, pr_number, "assignee" => assignee)
|
52
|
-
end
|
53
|
-
end
|
28
|
+
prs.each do |repo_name, pr_number|
|
29
|
+
puts MultiRepo::CLI.header("#{repo_name}##{pr_number}")
|
54
30
|
|
55
|
-
|
56
|
-
|
31
|
+
begin
|
32
|
+
github.merge_pull_request(repo_name, pr_number)
|
33
|
+
rescue Octokit::MethodNotAllowed => err
|
34
|
+
raise unless err.to_s.include?("Pull Request is not mergeable")
|
57
35
|
|
58
|
-
|
36
|
+
puts "** WARN: Pull Request is not mergeable".light_yellow
|
37
|
+
end
|
59
38
|
|
60
|
-
|
61
|
-
|
62
|
-
assign_user(repo_name, pr_number, **opts)
|
39
|
+
github.add_labels_to_an_issue(repo_name, pr_number, opts[:labels]) if opts[:labels].present?
|
40
|
+
github.assign_user(repo_name, pr_number, opts[:assignee])
|
63
41
|
|
64
42
|
puts
|
65
43
|
end
|
data/scripts/show_commit_history
CHANGED
@@ -60,7 +60,12 @@ MultiRepo::CLI.repos_for(**opts).each do |repo|
|
|
60
60
|
log.lines.each do |line|
|
61
61
|
next unless (match = line.match(/Merge pull request #(\d+)\b/))
|
62
62
|
|
63
|
-
pr =
|
63
|
+
pr =
|
64
|
+
begin
|
65
|
+
github.pull_request(repo.name, match[1])
|
66
|
+
rescue Octokit::NotFound
|
67
|
+
next # PR not found could mean this was a cherry-pick from a different repo, so the PR doesn't exist.
|
68
|
+
end
|
64
69
|
label = pr.labels.detect { |l| results.key?(l.name) }&.name || "other"
|
65
70
|
results[label] << pr
|
66
71
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: multi_repo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ManageIQ Authors
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -360,7 +360,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
360
360
|
- !ruby/object:Gem::Version
|
361
361
|
version: '0'
|
362
362
|
requirements: []
|
363
|
-
rubygems_version: 3.3.
|
363
|
+
rubygems_version: 3.3.27
|
364
364
|
signing_key:
|
365
365
|
specification_version: 4
|
366
366
|
summary: MultiRepo is a library for managing multiple repositiories and running scripts
|