geet 0.24.0 → 0.25.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/workflows/ci.yml +17 -4
- data/lib/geet/commandline/configuration.rb +1 -0
- data/lib/geet/github/api_interface.rb +37 -0
- data/lib/geet/github/pr.rb +31 -1
- data/lib/geet/services/create_pr.rb +20 -1
- data/lib/geet/version.rb +1 -1
- data/spec/integration/create_pr_spec.rb +68 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f33191668d757cda4abaccb0524277d39923df81e1c17e7175fd6ccd27e0751
|
|
4
|
+
data.tar.gz: 0650f891e46a6c108cd59fd91cae1a396214dda38497eefa1cc6712df42b8971
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6748bd9048d5d828bf30e356d134c37f607370102792408535717f97e1a46938e59078c4f331173634e4e694ca05b68b8ae6d19464d02c19493533bc3a52b4fa
|
|
7
|
+
data.tar.gz: 1c27b254f20de196d7e74de519cc47358b9a0c2daf3fe565e7f593b8af6dae109dbab066015eda103c9599480ad1231b5e9b4318c96a3578bb15b002b7e82d17
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -3,7 +3,8 @@ name: CI
|
|
|
3
3
|
on: [pull_request]
|
|
4
4
|
|
|
5
5
|
jobs:
|
|
6
|
-
|
|
6
|
+
test_suite:
|
|
7
|
+
name: Test Suite
|
|
7
8
|
runs-on: ubuntu-latest
|
|
8
9
|
env:
|
|
9
10
|
GITHUB_API_TOKEN: foo
|
|
@@ -12,9 +13,9 @@ jobs:
|
|
|
12
13
|
matrix:
|
|
13
14
|
ruby-version: [head, 4.0, 3.4, 3.3, 3.2]
|
|
14
15
|
fail-fast: false
|
|
15
|
-
continue-on-error: ${{ endsWith(matrix['ruby-version'], 'head')
|
|
16
|
+
continue-on-error: ${{ endsWith(matrix['ruby-version'], 'head') }}
|
|
16
17
|
steps:
|
|
17
|
-
- uses: actions/checkout@
|
|
18
|
+
- uses: actions/checkout@v6
|
|
18
19
|
- uses: ruby/setup-ruby@v1
|
|
19
20
|
with:
|
|
20
21
|
ruby-version: ${{ matrix.ruby-version }}
|
|
@@ -22,9 +23,10 @@ jobs:
|
|
|
22
23
|
- run: bundle install
|
|
23
24
|
- run: bundle exec rspec
|
|
24
25
|
sorbet:
|
|
26
|
+
name: Sorbet typecheck
|
|
25
27
|
runs-on: ubuntu-latest
|
|
26
28
|
steps:
|
|
27
|
-
- uses: actions/checkout@
|
|
29
|
+
- uses: actions/checkout@v6
|
|
28
30
|
with:
|
|
29
31
|
fetch-depth: ${{ env.REPO_FETCH_DEPTH }}
|
|
30
32
|
- uses: ruby/setup-ruby@v1
|
|
@@ -32,3 +34,14 @@ jobs:
|
|
|
32
34
|
bundler-cache: true
|
|
33
35
|
- name: Sorbet
|
|
34
36
|
run: bundle exec srb typecheck
|
|
37
|
+
# Ruby summary job, for branch protection rules
|
|
38
|
+
# Head ruby failures are ignored due to continue-on-error in the test job.
|
|
39
|
+
all-tests:
|
|
40
|
+
name: Ruby (non-head) tests passed
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
needs: [test_suite]
|
|
43
|
+
if: always()
|
|
44
|
+
steps:
|
|
45
|
+
- name: Check test suite results
|
|
46
|
+
run: |
|
|
47
|
+
[[ "${{ needs.test_suite.result }}" == "success" ]] || exit 1
|
|
@@ -66,6 +66,7 @@ module Geet
|
|
|
66
66
|
]
|
|
67
67
|
|
|
68
68
|
PR_CREATE_OPTIONS = [
|
|
69
|
+
['-a', '--automerge', "Enable automerge (with default strategy)"],
|
|
69
70
|
['-o', '--open-browser', "Don't open the PR link in the browser after creation"],
|
|
70
71
|
['-b', '--base develop', "Specify the base branch; defaults to the main branch"],
|
|
71
72
|
['-d', '--draft', "Create as draft"],
|
|
@@ -9,6 +9,7 @@ module Geet
|
|
|
9
9
|
class ApiInterface
|
|
10
10
|
API_AUTH_USER = '' # We don't need the login, as the API key uniquely identifies the user
|
|
11
11
|
API_BASE_URL = 'https://api.github.com'
|
|
12
|
+
GRAPHQL_API_URL = 'https://api.github.com/graphql'
|
|
12
13
|
|
|
13
14
|
attr_reader :repository_path
|
|
14
15
|
|
|
@@ -69,6 +70,42 @@ module Geet
|
|
|
69
70
|
end
|
|
70
71
|
end
|
|
71
72
|
|
|
73
|
+
# Send a GraphQL request.
|
|
74
|
+
#
|
|
75
|
+
# Returns the parsed response data.
|
|
76
|
+
#
|
|
77
|
+
# params:
|
|
78
|
+
# :query: GraphQL query string
|
|
79
|
+
# :variables: (Hash) GraphQL variables
|
|
80
|
+
#
|
|
81
|
+
def send_graphql_request(query, variables: {})
|
|
82
|
+
uri = URI(GRAPHQL_API_URL)
|
|
83
|
+
|
|
84
|
+
Net::HTTP.start(uri.host, use_ssl: true) do |http|
|
|
85
|
+
request = Net::HTTP::Post.new(uri).tap do
|
|
86
|
+
it.basic_auth API_AUTH_USER, @api_token
|
|
87
|
+
it['Accept'] = 'application/vnd.github.v3+json'
|
|
88
|
+
it.body = {query:, variables:}.to_json
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
response = http.request(request)
|
|
92
|
+
|
|
93
|
+
parsed_response = JSON.parse(response.body) if response.body
|
|
94
|
+
|
|
95
|
+
if error?(response)
|
|
96
|
+
error_message = decode_and_format_error(parsed_response)
|
|
97
|
+
raise Geet::Shared::HttpError.new(error_message, response.code)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
if parsed_response&.key?('errors')
|
|
101
|
+
error_messages = parsed_response['errors'].map { |err| err['message'] }.join(', ')
|
|
102
|
+
raise Geet::Shared::HttpError.new("GraphQL errors: #{error_messages}", response.code)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
parsed_response&.fetch('data')
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
72
109
|
private
|
|
73
110
|
|
|
74
111
|
def api_url(api_path)
|
data/lib/geet/github/pr.rb
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
module Geet
|
|
4
4
|
module Github
|
|
5
5
|
class PR < AbstractIssue
|
|
6
|
+
attr_reader :node_id
|
|
7
|
+
|
|
8
|
+
def initialize(number, api_interface, title, link, node_id: nil)
|
|
9
|
+
super(number, api_interface, title, link)
|
|
10
|
+
@node_id = node_id
|
|
11
|
+
end
|
|
12
|
+
|
|
6
13
|
# See https://developer.github.com/v3/pulls/#create-a-pull-request
|
|
7
14
|
#
|
|
8
15
|
def self.create(title, description, head, api_interface, base, draft: false)
|
|
@@ -18,8 +25,9 @@ module Geet
|
|
|
18
25
|
response = api_interface.send_request(api_path, data: request_data)
|
|
19
26
|
|
|
20
27
|
number, title, link = response.fetch_values('number', 'title', 'html_url')
|
|
28
|
+
node_id = response['node_id']
|
|
21
29
|
|
|
22
|
-
new(number, api_interface, title, link)
|
|
30
|
+
new(number, api_interface, title, link, node_id:)
|
|
23
31
|
end
|
|
24
32
|
|
|
25
33
|
# See https://developer.github.com/v3/pulls/#list-pull-requests
|
|
@@ -83,6 +91,28 @@ module Geet
|
|
|
83
91
|
@api_interface.send_request(api_path, data: request_data)
|
|
84
92
|
end
|
|
85
93
|
|
|
94
|
+
# Enable auto-merge for this PR using the repository's default merge method.
|
|
95
|
+
# See https://docs.github.com/en/graphql/reference/mutations#enablepullrequestautomerge
|
|
96
|
+
#
|
|
97
|
+
def enable_automerge
|
|
98
|
+
query = <<~GRAPHQL
|
|
99
|
+
mutation($pullRequestId: ID!) {
|
|
100
|
+
enablePullRequestAutoMerge(input: {pullRequestId: $pullRequestId}) {
|
|
101
|
+
pullRequest {
|
|
102
|
+
id
|
|
103
|
+
autoMergeRequest {
|
|
104
|
+
enabledAt
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
GRAPHQL
|
|
110
|
+
|
|
111
|
+
variables = { pullRequestId: @node_id }
|
|
112
|
+
|
|
113
|
+
@api_interface.send_graphql_request(query, variables:)
|
|
114
|
+
end
|
|
115
|
+
|
|
86
116
|
class << self
|
|
87
117
|
private
|
|
88
118
|
|
|
@@ -21,10 +21,11 @@ module Geet
|
|
|
21
21
|
# :labels
|
|
22
22
|
# :reviewers
|
|
23
23
|
# :open_browser
|
|
24
|
+
# :automerge
|
|
24
25
|
#
|
|
25
26
|
def execute(
|
|
26
27
|
title, description, labels: nil, milestone: nil, reviewers: nil,
|
|
27
|
-
base: nil, draft: false, open_browser: false, **
|
|
28
|
+
base: nil, draft: false, open_browser: false, automerge: false, **
|
|
28
29
|
)
|
|
29
30
|
ensure_clean_tree
|
|
30
31
|
|
|
@@ -50,6 +51,8 @@ module Geet
|
|
|
50
51
|
edit_pr(pr, selected_labels, selected_milestone, selected_reviewers)
|
|
51
52
|
end
|
|
52
53
|
|
|
54
|
+
enable_automerge(pr) if automerge
|
|
55
|
+
|
|
53
56
|
if open_browser
|
|
54
57
|
open_file_with_default_application(pr.link)
|
|
55
58
|
else
|
|
@@ -187,6 +190,22 @@ module Geet
|
|
|
187
190
|
pr.request_review(reviewer_usernames)
|
|
188
191
|
end
|
|
189
192
|
end
|
|
193
|
+
|
|
194
|
+
def enable_automerge(pr)
|
|
195
|
+
if !pr.respond_to?(:enable_automerge)
|
|
196
|
+
raise "Automerge is not supported for this repository provider"
|
|
197
|
+
elsif !pr.respond_to?(:node_id) || pr.node_id.nil?
|
|
198
|
+
raise "Automerge requires node_id from the API (not available in the response)"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
@out.puts "Enabling automerge..."
|
|
202
|
+
|
|
203
|
+
begin
|
|
204
|
+
pr.enable_automerge
|
|
205
|
+
rescue Geet::Shared::HttpError => e
|
|
206
|
+
@out.puts "Warning: Could not enable automerge: #{e.message}"
|
|
207
|
+
end
|
|
208
|
+
end
|
|
190
209
|
end
|
|
191
210
|
end
|
|
192
211
|
end
|
data/lib/geet/version.rb
CHANGED
|
@@ -194,6 +194,74 @@ describe Geet::Services::CreatePr do
|
|
|
194
194
|
|
|
195
195
|
expect(actual_output.string).to eql(expected_output)
|
|
196
196
|
end
|
|
197
|
+
|
|
198
|
+
it 'should enable automerge after creating a PR' do
|
|
199
|
+
allow(git_client).to receive(:working_tree_clean?).and_return(true)
|
|
200
|
+
allow(git_client).to receive(:current_branch).and_return('mybranch')
|
|
201
|
+
allow(git_client).to receive(:main_branch).and_return('master')
|
|
202
|
+
allow(git_client).to receive(:remote_branch).and_return('mybranch')
|
|
203
|
+
allow(git_client).to receive(:remote_branch_diff_commits).and_return([])
|
|
204
|
+
allow(git_client).to receive(:fetch)
|
|
205
|
+
allow(git_client).to receive(:push)
|
|
206
|
+
allow(git_client).to receive(:remote).with(no_args).and_return('git@github.com:donaldduck/testrepo_f')
|
|
207
|
+
|
|
208
|
+
actual_output = StringIO.new
|
|
209
|
+
|
|
210
|
+
# Mock the repository and PR
|
|
211
|
+
allow(repository).to receive(:authenticated_user).and_return(
|
|
212
|
+
double(is_collaborator?: true, has_permission?: true)
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
mock_pr = double(
|
|
216
|
+
'PR',
|
|
217
|
+
number: 1,
|
|
218
|
+
title: 'Title',
|
|
219
|
+
link: 'https://github.com/donaldduck/testrepo_f/pull/1',
|
|
220
|
+
node_id: 'PR_test123'
|
|
221
|
+
)
|
|
222
|
+
allow(mock_pr).to receive(:enable_automerge)
|
|
223
|
+
|
|
224
|
+
allow(repository).to receive(:create_pr).and_return(mock_pr)
|
|
225
|
+
|
|
226
|
+
service_instance = described_class.new(repository, out: actual_output, git_client: git_client)
|
|
227
|
+
service_instance.execute('Title', 'Description', automerge: true)
|
|
228
|
+
|
|
229
|
+
expect(mock_pr).to have_received(:enable_automerge)
|
|
230
|
+
expect(actual_output.string).to include('Enabling automerge...')
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it 'should raise an error when automerge is requested but not supported' do
|
|
234
|
+
allow(git_client).to receive(:working_tree_clean?).and_return(true)
|
|
235
|
+
allow(git_client).to receive(:current_branch).and_return('mybranch')
|
|
236
|
+
allow(git_client).to receive(:main_branch).and_return('master')
|
|
237
|
+
allow(git_client).to receive(:remote_branch).and_return('mybranch')
|
|
238
|
+
allow(git_client).to receive(:remote_branch_diff_commits).and_return([])
|
|
239
|
+
allow(git_client).to receive(:fetch)
|
|
240
|
+
allow(git_client).to receive(:push)
|
|
241
|
+
allow(git_client).to receive(:remote).with(no_args).and_return('git@github.com:donaldduck/testrepo_f')
|
|
242
|
+
|
|
243
|
+
actual_output = StringIO.new
|
|
244
|
+
|
|
245
|
+
# Mock the repository and PR without enable_automerge method (simulating GitLab)
|
|
246
|
+
allow(repository).to receive(:authenticated_user).and_return(
|
|
247
|
+
double(is_collaborator?: true, has_permission?: true)
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
mock_pr = double(
|
|
251
|
+
'PR',
|
|
252
|
+
number: 1,
|
|
253
|
+
title: 'Title',
|
|
254
|
+
link: 'https://github.com/donaldduck/testrepo_f/pull/1'
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
allow(repository).to receive(:create_pr).and_return(mock_pr)
|
|
258
|
+
|
|
259
|
+
service_instance = described_class.new(repository, out: actual_output, git_client: git_client)
|
|
260
|
+
|
|
261
|
+
expect do
|
|
262
|
+
service_instance.execute('Title', 'Description', automerge: true)
|
|
263
|
+
end.to raise_error(RuntimeError, 'Automerge is not supported for this repository provider')
|
|
264
|
+
end
|
|
197
265
|
end
|
|
198
266
|
end # context 'with github.com'
|
|
199
267
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: geet
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.25.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Saverio Miroddi
|
|
@@ -309,7 +309,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
309
309
|
- !ruby/object:Gem::Version
|
|
310
310
|
version: '0'
|
|
311
311
|
requirements: []
|
|
312
|
-
rubygems_version:
|
|
312
|
+
rubygems_version: 3.6.9
|
|
313
313
|
specification_version: 4
|
|
314
314
|
summary: Commandline interface for performing SCM host operations, eg. create a PR
|
|
315
315
|
on GitHub
|