thegarage-gitx 1.4.1 → 1.5.0.pre1
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/lib/thegarage/gitx/cli.rb +14 -6
- data/lib/thegarage/gitx/github.rb +50 -38
- data/lib/thegarage/gitx/version.rb +1 -1
- data/spec/thegarage/gitx/cli_spec.rb +94 -24
- data/spec/thegarage/gitx/github_spec.rb +21 -14
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9da76850a18efd35f1ad4755e580f74b2bddda17
|
4
|
+
data.tar.gz: c80377d9cf9269445ab266348a60c93777061992
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8461ef865ca67baf61344ccfdd29a0cf4820878343c606cfac1bde2892e658e6ca116575484097e81cec7809da617fcb08f5fc1c5b9871cd26a6c655d656ffc
|
7
|
+
data.tar.gz: 5965d506c234b42a3c014f87a1649173aeceaea0814a31537c0089bed3abafddb641f0f0d0a0bed35fe171a76df3b6098cd609e4a1f1fabe57e3b7d80374b15f
|
data/lib/thegarage/gitx/cli.rb
CHANGED
@@ -20,17 +20,25 @@ module Thegarage
|
|
20
20
|
RestClient.log = Logger.new(STDOUT) if options[:trace]
|
21
21
|
end
|
22
22
|
|
23
|
-
desc "reviewrequest", "Create a pull request on github"
|
23
|
+
desc "reviewrequest", "Create or update a pull request on github"
|
24
24
|
method_option :description, :type => :string, :aliases => '-d', :desc => 'pull request description'
|
25
25
|
method_option :assignee, :type => :string, :aliases => '-a', :desc => 'pull request assignee'
|
26
|
+
method_option :open, :type => :boolean, :aliases => '-o', :desc => 'open the pull request in a web browser'
|
26
27
|
# @see http://developer.github.com/v3/pulls/
|
27
28
|
def reviewrequest
|
28
29
|
update
|
30
|
+
fail 'Github authorization token not found' unless github.authorization_token
|
31
|
+
|
32
|
+
pull_request = github.find_pull_request(current_branch)
|
33
|
+
if pull_request.nil?
|
34
|
+
changelog = run_cmd "git log #{Thegarage::Gitx::BASE_BRANCH}...#{current_branch} --no-merges --pretty=format:'* %s%n%b'"
|
35
|
+
pull_request = github.create_pull_request(current_branch, changelog, options)
|
36
|
+
say 'Pull request created: '
|
37
|
+
say pull_request['html_url'], :green
|
38
|
+
end
|
39
|
+
github.assign_pull_request(pull_request, options[:assignee]) if options[:assignee]
|
29
40
|
|
30
|
-
|
31
|
-
url = github.create_pull_request(current_branch, changelog, options)
|
32
|
-
say 'Pull request created: '
|
33
|
-
say url, :green
|
41
|
+
run_cmd "open #{pull_request['html_url']}" if options[:open]
|
34
42
|
end
|
35
43
|
|
36
44
|
# TODO: use --no-edit to skip merge messages
|
@@ -73,7 +81,7 @@ module Thegarage
|
|
73
81
|
desc 'start', 'start a new git branch with latest changes from master'
|
74
82
|
def start(branch_name = nil)
|
75
83
|
unless branch_name
|
76
|
-
example_branch = %w{ api-fix-invalid-auth desktop-cleanup-avatar-markup share-form-add-edit-link }.
|
84
|
+
example_branch = %w{ api-fix-invalid-auth desktop-cleanup-avatar-markup share-form-add-edit-link }.shuffle.first
|
77
85
|
repo = Grit::Repo.new(Dir.pwd)
|
78
86
|
remote_branches = repo.remotes.collect {|b| b.name.split('/').last }
|
79
87
|
until branch_name = ask("What would you like to name your branch? (ex: #{example_branch})") {|q|
|
@@ -23,40 +23,7 @@ module Thegarage
|
|
23
23
|
@shell = shell
|
24
24
|
end
|
25
25
|
|
26
|
-
# returns
|
27
|
-
# @see http://developer.github.com/v3/pulls/
|
28
|
-
def create_pull_request(branch, changelog, options = {})
|
29
|
-
fail 'Github authorization token not found' unless authorization_token
|
30
|
-
remote = remote_origin_name
|
31
|
-
body = pull_request_body(changelog, options[:description])
|
32
|
-
|
33
|
-
shell.say "Creating pull request for "
|
34
|
-
shell.say "#{branch} ", :green
|
35
|
-
shell.say "against "
|
36
|
-
shell.say "#{Thegarage::Gitx::BASE_BRANCH} ", :green
|
37
|
-
shell.say "in "
|
38
|
-
shell.say remote, :green
|
39
|
-
|
40
|
-
payload = {
|
41
|
-
:title => branch,
|
42
|
-
:base => Thegarage::Gitx::BASE_BRANCH,
|
43
|
-
:head => branch,
|
44
|
-
:body => body
|
45
|
-
}.to_json
|
46
|
-
response = RestClient::Request.new(:url => "https://api.github.com/repos/#{remote}/pulls", :method => "POST", :payload => payload, :headers => request_headers).execute
|
47
|
-
data = JSON.parse response.body
|
48
|
-
|
49
|
-
assign_pull_request(branch, options[:assignee], data) if options[:assignee]
|
50
|
-
|
51
|
-
url = data['html_url']
|
52
|
-
url
|
53
|
-
rescue RestClient::Exception => e
|
54
|
-
process_error e
|
55
|
-
throw e
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
26
|
+
# returns [Hash] data structure of created pull request
|
60
27
|
# request github authorization token
|
61
28
|
# User-Agent is required
|
62
29
|
# store the token in local git config
|
@@ -93,19 +60,64 @@ module Thegarage
|
|
93
60
|
token
|
94
61
|
rescue RestClient::Exception => e
|
95
62
|
process_error e
|
96
|
-
throw e
|
97
63
|
end
|
98
64
|
|
99
|
-
|
100
|
-
|
101
|
-
|
65
|
+
# @see http://developer.github.com/v3/pulls/
|
66
|
+
def create_pull_request(branch, changelog, options = {})
|
67
|
+
remote = remote_origin_name
|
68
|
+
body = pull_request_body(changelog, options[:description])
|
69
|
+
|
70
|
+
shell.say "Creating pull request for "
|
71
|
+
shell.say "#{branch} ", :green
|
72
|
+
shell.say "against "
|
73
|
+
shell.say "#{Thegarage::Gitx::BASE_BRANCH} ", :green
|
74
|
+
shell.say "in "
|
75
|
+
shell.say remote, :green
|
76
|
+
|
77
|
+
payload = {
|
78
|
+
:title => branch,
|
79
|
+
:base => Thegarage::Gitx::BASE_BRANCH,
|
80
|
+
:head => branch,
|
81
|
+
:body => body
|
82
|
+
}.to_json
|
83
|
+
response = RestClient::Request.new(:url => "https://api.github.com/repos/#{remote}/pulls", :method => "POST", :payload => payload, :headers => request_headers).execute
|
84
|
+
pull_request = JSON.parse response.body
|
85
|
+
|
86
|
+
pull_request
|
87
|
+
rescue RestClient::Exception => e
|
88
|
+
process_error e
|
89
|
+
end
|
90
|
+
|
91
|
+
def assign_pull_request(pull_request, assignee)
|
92
|
+
branch = pull_request['head']['ref']
|
93
|
+
payload = {
|
94
|
+
:title => branch,
|
95
|
+
:assignee => assignee
|
96
|
+
}.to_json
|
97
|
+
RestClient::Request.new(:url => pull_request['issue_url'], :method => "PATCH", :payload => payload, :headers => request_headers).execute
|
98
|
+
rescue RestClient::Exception => e
|
99
|
+
process_error e
|
100
|
+
end
|
101
|
+
|
102
|
+
# @returns [Hash] data structure of pull request info if found
|
103
|
+
# @returns nil if no pull request found
|
104
|
+
def find_pull_request(branch)
|
105
|
+
payload = {
|
106
|
+
course: branch
|
107
|
+
}.to_json
|
108
|
+
response = RestClient::Request.new(:url => "https://api.github.com/repos/#{remote}/pulls", :method => "GET", :payload => payload, :headers => request_headers).execute
|
109
|
+
data = JSON.parse(response.body)
|
110
|
+
data.first
|
102
111
|
rescue RestClient::Exception => e
|
103
112
|
process_error e
|
104
113
|
end
|
105
114
|
|
115
|
+
private
|
116
|
+
|
106
117
|
def process_error(e)
|
107
118
|
data = JSON.parse e.http_body
|
108
119
|
shell.say "Github request failed: #{data['message']}", :red
|
120
|
+
throw e
|
109
121
|
end
|
110
122
|
|
111
123
|
def request_headers
|
@@ -24,7 +24,7 @@ describe Thegarage::Gitx::CLI do
|
|
24
24
|
|
25
25
|
cli.update
|
26
26
|
end
|
27
|
-
it '
|
27
|
+
it 'runs expected commands' do
|
28
28
|
should meet_expectations
|
29
29
|
end
|
30
30
|
end
|
@@ -45,7 +45,7 @@ describe Thegarage::Gitx::CLI do
|
|
45
45
|
|
46
46
|
cli.integrate
|
47
47
|
end
|
48
|
-
it '
|
48
|
+
it 'defaults to staging branch' do
|
49
49
|
should meet_expectations
|
50
50
|
end
|
51
51
|
end
|
@@ -64,12 +64,12 @@ describe Thegarage::Gitx::CLI do
|
|
64
64
|
|
65
65
|
cli.integrate 'prototype'
|
66
66
|
end
|
67
|
-
it '
|
67
|
+
it 'runs expected commands' do
|
68
68
|
should meet_expectations
|
69
69
|
end
|
70
70
|
end
|
71
71
|
context 'when target branch != staging || prototype' do
|
72
|
-
it '
|
72
|
+
it 'raises an error' do
|
73
73
|
expect(cli).to receive(:run).with("git pull origin feature-branch", capture: true).ordered
|
74
74
|
expect(cli).to receive(:run).with("git pull origin master", capture: true).ordered
|
75
75
|
expect(cli).to receive(:run).with("git push origin HEAD", capture: true).ordered
|
@@ -92,7 +92,7 @@ describe Thegarage::Gitx::CLI do
|
|
92
92
|
|
93
93
|
cli.release
|
94
94
|
end
|
95
|
-
it '
|
95
|
+
it 'only runs update commands' do
|
96
96
|
should meet_expectations
|
97
97
|
end
|
98
98
|
end
|
@@ -122,7 +122,7 @@ describe Thegarage::Gitx::CLI do
|
|
122
122
|
|
123
123
|
cli.release
|
124
124
|
end
|
125
|
-
it '
|
125
|
+
it 'runs expected commands' do
|
126
126
|
should meet_expectations
|
127
127
|
end
|
128
128
|
end
|
@@ -153,7 +153,7 @@ describe Thegarage::Gitx::CLI do
|
|
153
153
|
|
154
154
|
cli.nuke 'prototype'
|
155
155
|
end
|
156
|
-
it '
|
156
|
+
it 'runs expected commands' do
|
157
157
|
should meet_expectations
|
158
158
|
end
|
159
159
|
end
|
@@ -181,7 +181,7 @@ describe Thegarage::Gitx::CLI do
|
|
181
181
|
|
182
182
|
cli.nuke 'staging'
|
183
183
|
end
|
184
|
-
it '
|
184
|
+
it 'runs expected commands' do
|
185
185
|
should meet_expectations
|
186
186
|
end
|
187
187
|
end
|
@@ -229,17 +229,17 @@ describe Thegarage::Gitx::CLI do
|
|
229
229
|
|
230
230
|
cli.nuke 'prototype'
|
231
231
|
end
|
232
|
-
it '
|
232
|
+
it 'runs expected commands' do
|
233
233
|
should meet_expectations
|
234
234
|
end
|
235
235
|
end
|
236
236
|
context 'when target branch != staging || prototype' do
|
237
|
-
it '
|
237
|
+
it 'raises error' do
|
238
238
|
lambda {
|
239
239
|
expect(cli).to receive(:ask).and_return('master')
|
240
240
|
expect(cli).to receive(:yes?).and_return(true)
|
241
241
|
cli.nuke 'not-an-integration-branch'
|
242
|
-
}.should raise_error
|
242
|
+
}.should raise_error(/Only aggregate branches are allowed to be reset/)
|
243
243
|
end
|
244
244
|
end
|
245
245
|
context 'when user does not confirm nuking the target branch' do
|
@@ -255,7 +255,7 @@ describe Thegarage::Gitx::CLI do
|
|
255
255
|
|
256
256
|
cli.nuke 'prototype'
|
257
257
|
end
|
258
|
-
it '
|
258
|
+
it 'runs expected commands' do
|
259
259
|
should meet_expectations
|
260
260
|
end
|
261
261
|
end
|
@@ -269,29 +269,99 @@ describe Thegarage::Gitx::CLI do
|
|
269
269
|
expect(cli).to receive(:run).with("git fetch --tags", capture: true).ordered
|
270
270
|
expect(cli).to receive(:run).with("git tag -l 'build-master-*'", capture: true).and_return(buildtags).ordered
|
271
271
|
|
272
|
-
expect { cli.nuke('prototype') }.to raise_error
|
272
|
+
expect { cli.nuke('prototype') }.to raise_error(/No known good tag found for branch/)
|
273
273
|
end
|
274
274
|
end
|
275
275
|
end
|
276
276
|
|
277
277
|
describe '#reviewrequest' do
|
278
|
-
|
279
|
-
|
278
|
+
let(:github) { double('fake github') }
|
279
|
+
let(:pull_request) do
|
280
|
+
{
|
281
|
+
'html_url' => 'https://path/to/new/pull/request',
|
282
|
+
'head' => {
|
283
|
+
'ref' => 'branch_name'
|
284
|
+
}
|
285
|
+
}
|
286
|
+
end
|
287
|
+
before do
|
288
|
+
allow(cli).to receive(:github).and_return(github)
|
289
|
+
|
290
|
+
expect(cli).to receive(:run).with("git pull origin feature-branch", capture: true).ordered
|
291
|
+
expect(cli).to receive(:run).with("git pull origin master", capture: true).ordered
|
292
|
+
expect(cli).to receive(:run).with("git push origin HEAD", capture: true).ordered
|
293
|
+
end
|
294
|
+
context 'when pull request does not exist' do
|
295
|
+
let(:authorization_token) { '123123' }
|
296
|
+
let(:changelog) { '* made some fixes' }
|
280
297
|
before do
|
281
|
-
expect(
|
282
|
-
expect(github).to receive(:
|
298
|
+
expect(github).to receive(:authorization_token).and_return(authorization_token)
|
299
|
+
expect(github).to receive(:find_pull_request).and_return(nil)
|
300
|
+
expect(github).to receive(:create_pull_request).and_return(pull_request)
|
283
301
|
|
284
|
-
expect(cli).to receive(:run).with("git pull origin feature-branch", capture: true).ordered
|
285
|
-
expect(cli).to receive(:run).with("git pull origin master", capture: true).ordered
|
286
|
-
expect(cli).to receive(:run).with("git push origin HEAD", capture: true).ordered
|
287
302
|
expect(cli).to receive(:run).with("git log master...feature-branch --no-merges --pretty=format:'* %s%n%b'", capture: true).and_return("2013-01-01 did some stuff").ordered
|
303
|
+
cli.reviewrequest
|
304
|
+
end
|
305
|
+
it 'creates github pull request' do
|
306
|
+
should meet_expectations
|
307
|
+
end
|
308
|
+
it 'runs expected commands' do
|
309
|
+
should meet_expectations
|
310
|
+
end
|
311
|
+
end
|
312
|
+
context 'when authorization_token is missing' do
|
313
|
+
let(:authorization_token) { nil }
|
314
|
+
it do
|
315
|
+
expect(github).to receive(:authorization_token).and_return(authorization_token)
|
316
|
+
expect { cli.reviewrequest }.to raise_error(/token not found/)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
context 'when pull request already exists' do
|
320
|
+
let(:authorization_token) { '123123' }
|
321
|
+
before do
|
322
|
+
expect(github).to receive(:authorization_token).and_return(authorization_token)
|
323
|
+
expect(github).to receive(:find_pull_request).and_return(pull_request)
|
324
|
+
expect(github).to_not receive(:create_pull_request)
|
288
325
|
|
289
326
|
cli.reviewrequest
|
290
327
|
end
|
291
|
-
it '
|
328
|
+
it 'does not create new pull request' do
|
292
329
|
should meet_expectations
|
293
330
|
end
|
294
|
-
|
331
|
+
end
|
332
|
+
context 'when --assignee option passed' do
|
333
|
+
let(:options) do
|
334
|
+
{
|
335
|
+
assignee: 'johndoe'
|
336
|
+
}
|
337
|
+
end
|
338
|
+
let(:authorization_token) { '123123' }
|
339
|
+
before do
|
340
|
+
expect(github).to receive(:authorization_token).and_return(authorization_token)
|
341
|
+
expect(github).to receive(:find_pull_request).and_return(pull_request)
|
342
|
+
expect(github).to receive(:assign_pull_request)
|
343
|
+
|
344
|
+
cli.reviewrequest
|
345
|
+
end
|
346
|
+
it 'calls assign_pull_request method' do
|
347
|
+
should meet_expectations
|
348
|
+
end
|
349
|
+
end
|
350
|
+
context 'when --open flag passed' do
|
351
|
+
let(:options) do
|
352
|
+
{
|
353
|
+
open: true
|
354
|
+
}
|
355
|
+
end
|
356
|
+
let(:authorization_token) { '123123' }
|
357
|
+
before do
|
358
|
+
expect(github).to receive(:authorization_token).and_return(authorization_token)
|
359
|
+
expect(github).to receive(:find_pull_request).and_return(pull_request)
|
360
|
+
|
361
|
+
expect(cli).to receive(:run).with("open #{pull_request['html_url']}", capture: true).ordered
|
362
|
+
cli.reviewrequest
|
363
|
+
end
|
364
|
+
it 'runs open command with pull request url' do
|
295
365
|
should meet_expectations
|
296
366
|
end
|
297
367
|
end
|
@@ -307,7 +377,7 @@ describe Thegarage::Gitx::CLI do
|
|
307
377
|
ENV['TRAVIS_BUILD_NUMBER'] = env_travis_build_number
|
308
378
|
end
|
309
379
|
context 'when ENV[\'TRAVIS_BRANCH\'] is nil' do
|
310
|
-
it '
|
380
|
+
it 'raises Unknown Branch error' do
|
311
381
|
expect { cli.buildtag }.to raise_error "Unknown branch. ENV['TRAVIS_BRANCH'] is required."
|
312
382
|
end
|
313
383
|
end
|
@@ -344,7 +414,7 @@ describe Thegarage::Gitx::CLI do
|
|
344
414
|
cli.buildtag
|
345
415
|
end
|
346
416
|
end
|
347
|
-
it '
|
417
|
+
it 'creates a tag for the branch and push it to github' do
|
348
418
|
should meet_expectations
|
349
419
|
end
|
350
420
|
end
|
@@ -10,12 +10,12 @@ describe Thegarage::Gitx::Github do
|
|
10
10
|
let(:shell) { double('fake shell', say: nil, ask: nil) }
|
11
11
|
subject { Thegarage::Gitx::Github.new(repo, shell) }
|
12
12
|
|
13
|
-
describe '#
|
13
|
+
describe '#authorization_token' do
|
14
14
|
context 'when github.user is not configured' do
|
15
15
|
it 'raises error' do
|
16
16
|
expect do
|
17
|
-
subject.
|
18
|
-
end.to raise_error
|
17
|
+
subject.authorization_token
|
18
|
+
end.to raise_error(/Github user not configured/)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
context 'when config.authorization_token is nil' do
|
@@ -39,24 +39,31 @@ describe Thegarage::Gitx::Github do
|
|
39
39
|
with(:body => expected_auth_body).
|
40
40
|
to_return(:status => 200, :body => JSON.dump(token: authorization_token), :headers => {})
|
41
41
|
|
42
|
-
|
43
|
-
to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1"}), :headers => {})
|
44
|
-
|
45
|
-
expect(shell).to receive(:ask).with('Github password for ryan@codecrate.com: ', {:echo => false}).and_return(github_password).any_number_of_times
|
42
|
+
expect(shell).to receive(:ask).with('Github password for ryan@codecrate.com: ', {:echo => false}).and_return(github_password)
|
46
43
|
|
47
|
-
|
48
|
-
subject.create_pull_request 'example-branch', 'changelog'
|
44
|
+
@auth_token = subject.authorization_token
|
49
45
|
end
|
50
|
-
it '
|
46
|
+
it 'stores authorization_token in git config' do
|
51
47
|
expect(repo_config).to include('thegarage.gitx.githubauthtoken' => authorization_token)
|
52
48
|
end
|
53
|
-
it
|
54
|
-
|
49
|
+
it { expect(@auth_token).to eq authorization_token }
|
50
|
+
end
|
51
|
+
context 'when there is an existing authorization_token' do
|
52
|
+
let(:authorization_token) { '123981239123' }
|
53
|
+
let(:repo_config) do
|
54
|
+
{
|
55
|
+
'remote.origin.url' => 'https://github.com/thegarage/thegarage-gitx',
|
56
|
+
'github.user' => 'ryan@codecrate.com',
|
57
|
+
'thegarage.gitx.githubauthtoken' => authorization_token
|
58
|
+
}
|
55
59
|
end
|
56
|
-
|
57
|
-
|
60
|
+
before do
|
61
|
+
@auth_token = subject.authorization_token
|
58
62
|
end
|
63
|
+
it { expect(@auth_token).to eq authorization_token }
|
59
64
|
end
|
65
|
+
end
|
66
|
+
describe '#create_pull_request' do
|
60
67
|
context 'when there is an existing authorization_token' do
|
61
68
|
let(:authorization_token) { '123981239123' }
|
62
69
|
let(:repo_config) do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thegarage-gitx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0.pre1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Sonnek
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: grit
|
@@ -200,9 +200,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
200
200
|
version: '0'
|
201
201
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
202
202
|
requirements:
|
203
|
-
- - '
|
203
|
+
- - '>'
|
204
204
|
- !ruby/object:Gem::Version
|
205
|
-
version:
|
205
|
+
version: 1.3.1
|
206
206
|
requirements: []
|
207
207
|
rubyforge_project:
|
208
208
|
rubygems_version: 2.0.3
|