right_branch 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/right_branch +5 -0
- data/lib/right_branch/commands/change_pull_request_target.rb +94 -0
- data/lib/right_branch/updater.rb +52 -0
- data/lib/right_branch/version.rb +3 -0
- data/lib/right_branch.rb +2 -0
- data/spec/commands/change_pull_request_target_spec.rb +76 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/updater_spec.rb +34 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 03e90279927b64245f2cafc2605e98d8832f88cb
|
4
|
+
data.tar.gz: 66ced768c06d6baad8ad0ebbcdc518853de0e64c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7ff827ae6c9f78c9a9e44271713b1bdbe6566f78241bff29ca36ad67bf8445273bf6498b2415a8bd624c850061ba70c8e229f383c6fa4e7cf1fbc44afb812350
|
7
|
+
data.tar.gz: 40b149508d08044ff6fed1d8712e47c7615dc713f6334ebe1012f895293d56a711033ca50d60ebd2a7875a6024bda498d822adc7a32f17172861fdfc611d5581
|
data/bin/right_branch
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'octokit'
|
2
|
+
require 'optparse'
|
3
|
+
require 'highline/import'
|
4
|
+
require_relative '../updater'
|
5
|
+
|
6
|
+
module RightBranch::Commands
|
7
|
+
class ChangePullRequestTarget
|
8
|
+
REQUIRED_OPTIONS = %i(username repository new_branch pull_request)
|
9
|
+
|
10
|
+
attr_accessor :stream
|
11
|
+
|
12
|
+
def self.run(stream = $stdout)
|
13
|
+
new(stream).run!
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(stream = $stdout)
|
17
|
+
@stream = stream
|
18
|
+
end
|
19
|
+
|
20
|
+
def run!
|
21
|
+
options = build_options
|
22
|
+
updater(options).run!
|
23
|
+
rescue ::Octokit::Unauthorized
|
24
|
+
abort 'Invalid credentials to update pull request'
|
25
|
+
rescue ::Octokit::UnprocessableEntity
|
26
|
+
abort 'Invalid branch'
|
27
|
+
rescue ::Octokit::NotFound
|
28
|
+
abort 'Pull request not found'
|
29
|
+
end
|
30
|
+
|
31
|
+
def build_options
|
32
|
+
options = {}
|
33
|
+
opt_parser = build_opt_parser(options)
|
34
|
+
opt_parser.parse!
|
35
|
+
fallback_to_options_from_env(options)
|
36
|
+
|
37
|
+
missing = missing_opt_keys(options)
|
38
|
+
unless missing.empty?
|
39
|
+
abort missing_key_abort_message(missing, opt_parser)
|
40
|
+
end
|
41
|
+
|
42
|
+
if String(options[:password]).empty?
|
43
|
+
options[:password] = ask("Enter your password: ") { |q| q.echo = '*' }
|
44
|
+
end
|
45
|
+
|
46
|
+
options
|
47
|
+
end
|
48
|
+
|
49
|
+
def missing_opt_keys(options)
|
50
|
+
missing = REQUIRED_OPTIONS - options.keys
|
51
|
+
missing += options.select { |_, v| v.nil? || v.empty? }.keys
|
52
|
+
missing
|
53
|
+
end
|
54
|
+
|
55
|
+
def missing_key_abort_message(keys, opt_parser)
|
56
|
+
"Missing required options: #{keys.join(', ')}\n\n#{opt_parser}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def updater(options)
|
60
|
+
RightBranch::Updater.new(options)
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_opt_parser(options)
|
64
|
+
OptionParser.new do |opts|
|
65
|
+
opts.banner = 'Usage: right_branch [options]'
|
66
|
+
|
67
|
+
opts.on("-u", "--username USERNAME", "Username") do |v|
|
68
|
+
options[:username] = v
|
69
|
+
end
|
70
|
+
|
71
|
+
opts.on("-r", "--repository REPOSITORY", "Repository") do |v|
|
72
|
+
options[:repository] = v
|
73
|
+
end
|
74
|
+
|
75
|
+
opts.on("-b", "--new-branch NEW_BRANCH", "New branch") do |v|
|
76
|
+
options[:new_branch] = v
|
77
|
+
end
|
78
|
+
|
79
|
+
opts.on("-p", "--pull-request PULL_REQUEST", "Pull request") do |v|
|
80
|
+
options[:pull_request] = v
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on("--password PASSWORD", "Password") do |v|
|
84
|
+
options[:password] = v
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def fallback_to_options_from_env(options)
|
90
|
+
options[:username] ||= ENV['RIGHT_BRANCH_USERNAME']
|
91
|
+
options[:repository] ||= ENV['RIGHT_BRANCH_REPOSITORY']
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'octokit'
|
2
|
+
|
3
|
+
module RightBranch
|
4
|
+
class Updater
|
5
|
+
attr_reader :username, :password, :pull_request,
|
6
|
+
:new_branch, :repository
|
7
|
+
|
8
|
+
def initialize(options)
|
9
|
+
@username = options.fetch(:username)
|
10
|
+
@password = options.fetch(:password)
|
11
|
+
@pull_request = options.fetch(:pull_request)
|
12
|
+
@new_branch = options.fetch(:new_branch)
|
13
|
+
@repository = options.fetch(:repository)
|
14
|
+
end
|
15
|
+
|
16
|
+
def run!
|
17
|
+
old_pr = get_pr(pull_request)
|
18
|
+
new_pr = submit_pr(old_pr, new_branch)
|
19
|
+
update_pr(old_pr[:number], state: 'closed')
|
20
|
+
comment_on_issue old_pr[:number] ,
|
21
|
+
"Reopened against `#{new_branch}` (##{new_pr.number})"
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def github
|
27
|
+
@github ||= Octokit::Client.new \
|
28
|
+
login: username, password: password
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_pr(pr)
|
32
|
+
github.pull_request(repository, pr)
|
33
|
+
end
|
34
|
+
|
35
|
+
def comment_on_issue(number, comment)
|
36
|
+
github.add_comment(repository, number, comment)
|
37
|
+
end
|
38
|
+
|
39
|
+
def update_pr(number, args)
|
40
|
+
github.update_pull_request(repository, number, args)
|
41
|
+
end
|
42
|
+
|
43
|
+
def submit_pr(pr, new_branch)
|
44
|
+
github.create_pull_request \
|
45
|
+
repository,
|
46
|
+
new_branch,
|
47
|
+
pr[:head][:label],
|
48
|
+
pr[:title],
|
49
|
+
pr[:body]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/right_branch.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative '../../lib/right_branch/commands/change_pull_request_target'
|
3
|
+
|
4
|
+
describe RightBranch::Commands::ChangePullRequestTarget do
|
5
|
+
subject { described_class.new(StringIO.new) }
|
6
|
+
|
7
|
+
describe '#run!' do
|
8
|
+
let(:updater) { double }
|
9
|
+
|
10
|
+
before do
|
11
|
+
allow(subject).to receive(:build_options).and_return({})
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'aborts on not found error' do
|
15
|
+
allow(updater).to receive(:run!).and_raise \
|
16
|
+
::Octokit::NotFound
|
17
|
+
|
18
|
+
allow(subject).to receive(:updater).and_return updater
|
19
|
+
|
20
|
+
expect { subject.run! }.to raise_error SystemExit,
|
21
|
+
'Pull request not found'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'aborts on unauthorized error' do
|
25
|
+
allow(updater).to receive(:run!).and_raise \
|
26
|
+
::Octokit::Unauthorized
|
27
|
+
|
28
|
+
allow(subject).to receive(:updater).and_return updater
|
29
|
+
|
30
|
+
expect { subject.run! }.to raise_error SystemExit,
|
31
|
+
'Invalid credentials to update pull request'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'aborts on invalid branch error' do
|
35
|
+
allow(updater).to receive(:run!).and_raise \
|
36
|
+
::Octokit::UnprocessableEntity
|
37
|
+
|
38
|
+
allow(subject).to receive(:updater).and_return updater
|
39
|
+
|
40
|
+
expect { subject.run! }.to raise_error SystemExit,
|
41
|
+
'Invalid branch'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#missing_required_keys' do
|
46
|
+
before do
|
47
|
+
stub_const("#{described_class}::REQUIRED_OPTIONS", [:a, :b])
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns not provided keys' do
|
51
|
+
actual = subject.missing_opt_keys b: 'foo'
|
52
|
+
expect(actual).to eq([:a])
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'returns blank keys' do
|
56
|
+
actual = subject.missing_opt_keys a: 'foo', b: ''
|
57
|
+
expect(actual).to eq([:b])
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'returns empty array if all provided' do
|
61
|
+
actual = subject.missing_opt_keys a: 'foo', b: 'bar'
|
62
|
+
expect(actual).to eq([])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#build_options' do
|
67
|
+
it 'aborts when keys are missing' do
|
68
|
+
allow(subject).to receive(:missing_opt_keys).and_return [:a, :b]
|
69
|
+
allow(subject).to receive(:build_opt_parser)
|
70
|
+
.and_return double(parse!: true, to_s: 'wow')
|
71
|
+
|
72
|
+
expect { subject.build_options }.to raise_error SystemExit,
|
73
|
+
"Missing required options: a, b\n\nwow"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RightBranch::Updater do
|
4
|
+
subject { described_class.new default_options }
|
5
|
+
|
6
|
+
let(:default_options) do
|
7
|
+
{
|
8
|
+
pull_request: '1',
|
9
|
+
new_branch: 'test',
|
10
|
+
username: 'doge',
|
11
|
+
password: 'very_secure',
|
12
|
+
repository: 'foo/bar',
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#submit_pr' do
|
17
|
+
it 'creats new pull request againts branch' do
|
18
|
+
gh = double(:github)
|
19
|
+
title, body, label, branch = %w(title body label branch)
|
20
|
+
pr = { title: title, body: body, head: { label: label } }
|
21
|
+
|
22
|
+
allow(subject).to receive(:github).and_return(gh)
|
23
|
+
|
24
|
+
expect(gh).to receive(:create_pull_request).with \
|
25
|
+
default_options[:repository],
|
26
|
+
branch,
|
27
|
+
label,
|
28
|
+
title,
|
29
|
+
body
|
30
|
+
|
31
|
+
subject.send(:submit_pr, pr, branch)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: right_branch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dyego Costa
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: octokit
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: highline
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.1'
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 3.1.0
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - "~>"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '3.1'
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 3.1.0
|
61
|
+
description: If you submit a Pull Request to a wrong branch on GitHub you can use
|
62
|
+
this gem to change it
|
63
|
+
email: dyego@dyegocosta.com
|
64
|
+
executables:
|
65
|
+
- right_branch
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- bin/right_branch
|
70
|
+
- lib/right_branch.rb
|
71
|
+
- lib/right_branch/commands/change_pull_request_target.rb
|
72
|
+
- lib/right_branch/updater.rb
|
73
|
+
- lib/right_branch/version.rb
|
74
|
+
- spec/commands/change_pull_request_target_spec.rb
|
75
|
+
- spec/spec_helper.rb
|
76
|
+
- spec/updater_spec.rb
|
77
|
+
homepage: https://github.com/dyegocosta/right_branch
|
78
|
+
licenses:
|
79
|
+
- MIT
|
80
|
+
metadata: {}
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 2.4.5.1
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: Change GitHub Pull Request target branch
|
101
|
+
test_files: []
|
102
|
+
has_rdoc:
|