zenflow 0.8.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 +7 -0
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.zenflow +10 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +95 -0
- data/Guardfile +6 -0
- data/LICENSE.md +22 -0
- data/README.markdown +92 -0
- data/VERSION.yml +5 -0
- data/bin/zenflow +17 -0
- data/lib/zenflow.rb +35 -0
- data/lib/zenflow/cli.rb +130 -0
- data/lib/zenflow/commands/deploy.rb +33 -0
- data/lib/zenflow/commands/feature.rb +10 -0
- data/lib/zenflow/commands/hotfix.rb +15 -0
- data/lib/zenflow/commands/release.rb +16 -0
- data/lib/zenflow/commands/reviews.rb +12 -0
- data/lib/zenflow/helpers/ask.rb +66 -0
- data/lib/zenflow/helpers/branch.rb +80 -0
- data/lib/zenflow/helpers/branch_command.rb +95 -0
- data/lib/zenflow/helpers/branch_commands/abort.rb +21 -0
- data/lib/zenflow/helpers/branch_commands/branches.rb +21 -0
- data/lib/zenflow/helpers/branch_commands/compare.rb +20 -0
- data/lib/zenflow/helpers/branch_commands/deploy.rb +29 -0
- data/lib/zenflow/helpers/branch_commands/diff.rb +19 -0
- data/lib/zenflow/helpers/branch_commands/finish.rb +68 -0
- data/lib/zenflow/helpers/branch_commands/review.rb +58 -0
- data/lib/zenflow/helpers/branch_commands/start.rb +39 -0
- data/lib/zenflow/helpers/branch_commands/update.rb +22 -0
- data/lib/zenflow/helpers/changelog.rb +100 -0
- data/lib/zenflow/helpers/config.rb +36 -0
- data/lib/zenflow/helpers/github.rb +40 -0
- data/lib/zenflow/helpers/help.rb +37 -0
- data/lib/zenflow/helpers/log.rb +21 -0
- data/lib/zenflow/helpers/pull_request.rb +68 -0
- data/lib/zenflow/helpers/repo.rb +13 -0
- data/lib/zenflow/helpers/shell.rb +89 -0
- data/lib/zenflow/helpers/version.rb +87 -0
- data/lib/zenflow/version.rb +3 -0
- data/spec/fixtures/VERSION.yml +5 -0
- data/spec/fixtures/cassettes/create_bad_pull_request.yml +57 -0
- data/spec/fixtures/cassettes/create_pull_request.yml +68 -0
- data/spec/fixtures/cassettes/existing_pull_request.yml +145 -0
- data/spec/fixtures/cassettes/pull_request_by_ref.yml +145 -0
- data/spec/fixtures/cassettes/pull_request_find.yml +70 -0
- data/spec/fixtures/cassettes/pull_request_for_non-existent_ref.yml +145 -0
- data/spec/fixtures/cassettes/pull_request_list.yml +74 -0
- data/spec/fixtures/cassettes/unexisting_pull_request.yml +145 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/support/shared_examples_for_version_number.rb +19 -0
- data/spec/zenflow/commands/deploy_spec.rb +48 -0
- data/spec/zenflow/commands/feature_spec.rb +11 -0
- data/spec/zenflow/commands/hotfix_spec.rb +14 -0
- data/spec/zenflow/commands/release_spec.rb +15 -0
- data/spec/zenflow/commands/reviews_spec.rb +15 -0
- data/spec/zenflow/helpers/ask_spec.rb +115 -0
- data/spec/zenflow/helpers/branch_command_spec.rb +310 -0
- data/spec/zenflow/helpers/branch_spec.rb +300 -0
- data/spec/zenflow/helpers/changelog_spec.rb +188 -0
- data/spec/zenflow/helpers/cli_spec.rb +277 -0
- data/spec/zenflow/helpers/github_spec.rb +45 -0
- data/spec/zenflow/helpers/help_spec.rb +36 -0
- data/spec/zenflow/helpers/log_spec.rb +31 -0
- data/spec/zenflow/helpers/pull_request_spec.rb +108 -0
- data/spec/zenflow/helpers/shell_spec.rb +135 -0
- data/spec/zenflow/helpers/version_spec.rb +111 -0
- data/zenflow.gemspec +33 -0
- metadata +273 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
module Zenflow
|
2
|
+
module BranchCommands
|
3
|
+
module Finish
|
4
|
+
|
5
|
+
def self.included(thor)
|
6
|
+
thor.class_eval do
|
7
|
+
|
8
|
+
desc "finish", "Finish the branch and close the code review"
|
9
|
+
option :offline, type: :boolean, desc: "Runs in offline mode"
|
10
|
+
def finish
|
11
|
+
branch_name
|
12
|
+
confirm(:confirm_staging, "Has this been tested in a staging environment first?",
|
13
|
+
"Sorry, deploy to a staging environment first")
|
14
|
+
confirm(:confirm_review, "Has this been code reviewed yet?",
|
15
|
+
"Please have someone look at this first")
|
16
|
+
update_branch_from_destination
|
17
|
+
update_version_and_changelog(version, changelog)
|
18
|
+
merge_branch_into_destination
|
19
|
+
create_tag
|
20
|
+
delete_branches
|
21
|
+
end
|
22
|
+
|
23
|
+
no_commands do
|
24
|
+
def confirm(confirmation, question, failure_response)
|
25
|
+
return unless Zenflow::Config[confirmation]
|
26
|
+
if Zenflow::Ask(question, options: ["Y", "n"], default: "Y") == "n"
|
27
|
+
Zenflow::Log(failure_response, color: :red)
|
28
|
+
exit(1)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def update_version_and_changelog(version, changelog)
|
33
|
+
if version
|
34
|
+
Zenflow::Version.update(version)
|
35
|
+
end
|
36
|
+
if changelog
|
37
|
+
@change = Zenflow::Changelog.update(rotate: (changelog == :rotate), name: branch_name)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_tag
|
42
|
+
return unless tag
|
43
|
+
Zenflow::Branch.tag(Zenflow::Version.current.to_s, @change)
|
44
|
+
Zenflow::Branch.push(:tags) if !options[:offline]
|
45
|
+
end
|
46
|
+
|
47
|
+
def update_branch_from_destination
|
48
|
+
destination = (branch(:destination) || branch(:source))
|
49
|
+
Zenflow::Branch.update(destination) if !options[:offline]
|
50
|
+
Zenflow::Branch.checkout("#{flow}/#{branch_name}")
|
51
|
+
Zenflow::Branch.merge(destination)
|
52
|
+
end
|
53
|
+
|
54
|
+
def merge_branch_into_destination
|
55
|
+
[branch(:source), branch(:destination)].compact.each do |finish|
|
56
|
+
Zenflow::Branch.checkout(finish)
|
57
|
+
Zenflow::Branch.merge("#{flow}/#{branch_name}")
|
58
|
+
Zenflow::Branch.push(finish) if !options[:offline]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Zenflow
|
2
|
+
module BranchCommands
|
3
|
+
module Review
|
4
|
+
|
5
|
+
def self.included(thor)
|
6
|
+
thor.class_eval do
|
7
|
+
|
8
|
+
desc "review", "Start a code review."
|
9
|
+
def review
|
10
|
+
branch_name
|
11
|
+
create_pull_request
|
12
|
+
end
|
13
|
+
|
14
|
+
no_commands do
|
15
|
+
def create_pull_request
|
16
|
+
already_created?(Zenflow::PullRequest.find_by_ref("#{flow}/#{branch_name}"))
|
17
|
+
|
18
|
+
pull = Zenflow::PullRequest.create(
|
19
|
+
base: branch(:source),
|
20
|
+
head: "#{flow}/#{branch_name}",
|
21
|
+
title: "#{flow}: #{branch_name}",
|
22
|
+
body: Zenflow::Ask("Describe this #{flow}:", required: true)
|
23
|
+
)
|
24
|
+
|
25
|
+
return handle_invalid_pull_request(pull) unless pull.valid?
|
26
|
+
|
27
|
+
Zenflow::Log("Pull request was created!")
|
28
|
+
Zenflow::Log(pull["html_url"], indent: true, color: false)
|
29
|
+
Zenflow::Shell["open #{pull['html_url']}"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def already_created?(pull)
|
33
|
+
return unless pull
|
34
|
+
Zenflow::Log("A pull request for #{flow}/#{branch_name} already exists", color: :red)
|
35
|
+
Zenflow::Log(pull[:html_url], indent: true, color: false)
|
36
|
+
exit(1)
|
37
|
+
end
|
38
|
+
|
39
|
+
def handle_invalid_pull_request(pull)
|
40
|
+
Zenflow::Log("There was a problem creating the pull request:", color: :red)
|
41
|
+
if pull["errors"]
|
42
|
+
pull["errors"].each do |error|
|
43
|
+
Zenflow::Log("* #{error['message'].gsub(/^base\s*/,'')}", indent: true, color: :red)
|
44
|
+
end
|
45
|
+
elsif pull["message"]
|
46
|
+
Zenflow::Log("* #{pull['message']}", indent: true, color: :red)
|
47
|
+
else
|
48
|
+
Zenflow::Log(" * unexpected failure, both 'errors' and 'message' were empty in the response")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Zenflow
|
2
|
+
module BranchCommands
|
3
|
+
module Start
|
4
|
+
|
5
|
+
def self.included(thor)
|
6
|
+
thor.class_eval do
|
7
|
+
|
8
|
+
desc "start [NAME]", "Start a branch"
|
9
|
+
option :offline, type: :boolean, desc: "Runs in offline mode"
|
10
|
+
def start(name=nil)
|
11
|
+
@branch_name = Zenflow::Ask("Name of the #{flow}:",
|
12
|
+
required: true,
|
13
|
+
validate: /^[-0-9a-z]+$/,
|
14
|
+
error_message: "Names can only contain dashes, 0-9, and a-z",
|
15
|
+
response: name).downcase
|
16
|
+
|
17
|
+
create_new_branch(options[:offline])
|
18
|
+
end
|
19
|
+
|
20
|
+
no_commands do
|
21
|
+
def create_new_branch(offline=false)
|
22
|
+
if !offline
|
23
|
+
Zenflow::Branch.update(branch(:source))
|
24
|
+
Zenflow::Branch.create("#{flow}/#{branch_name}", branch(:source))
|
25
|
+
Zenflow::Branch.push("#{flow}/#{branch_name}")
|
26
|
+
Zenflow::Branch.track("#{flow}/#{branch_name}")
|
27
|
+
else
|
28
|
+
Zenflow::Branch.checkout(branch(:source))
|
29
|
+
Zenflow::Branch.create("#{flow}/#{branch_name}", branch(:source))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Zenflow
|
2
|
+
module BranchCommands
|
3
|
+
module Update
|
4
|
+
|
5
|
+
def self.included(thor)
|
6
|
+
thor.class_eval do
|
7
|
+
|
8
|
+
desc "update", "Update the branch to the latest code"
|
9
|
+
option :offline, type: :boolean, desc: "Runs in offline mode"
|
10
|
+
def update
|
11
|
+
branch_name
|
12
|
+
Zenflow::Branch.update(branch(:source)) if !options[:offline]
|
13
|
+
Zenflow::Branch.checkout("#{flow}/#{branch_name}")
|
14
|
+
Zenflow::Branch.merge(branch(:source))
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Zenflow
|
2
|
+
module Changelog
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def exist?
|
6
|
+
File.exist?("CHANGELOG.md")
|
7
|
+
end
|
8
|
+
|
9
|
+
def update(options={})
|
10
|
+
return unless exist?
|
11
|
+
change = prompt_for_change(options)
|
12
|
+
if change
|
13
|
+
prepend_change_to_changelog(change, options)
|
14
|
+
else
|
15
|
+
rotate(:commit => true) if options[:rotate]
|
16
|
+
end
|
17
|
+
change
|
18
|
+
end
|
19
|
+
|
20
|
+
def prompt_for_change(options={})
|
21
|
+
required = ' (optional)' if options[:required] == false
|
22
|
+
Zenflow::Ask("Add one line to the changelog#{required}:", :required => !(options[:required] == false))
|
23
|
+
end
|
24
|
+
|
25
|
+
def prepend_change_to_changelog(change, options={})
|
26
|
+
return unless exist?
|
27
|
+
new_changes = Zenflow::Shell.shell_escape_for_single_quoting(change)
|
28
|
+
File.open("CHANGELOG.md", "w") do |f|
|
29
|
+
f.write prepended_changelog(new_changes)
|
30
|
+
end
|
31
|
+
rotate(:name => options[:name]) if options[:rotate]
|
32
|
+
Zenflow::Shell["git add . && git commit -a -m 'Adding line to CHANGELOG: #{new_changes}'"]
|
33
|
+
end
|
34
|
+
|
35
|
+
def prepended_changelog(new_changes)
|
36
|
+
existing_changes, changelog = get_changes
|
37
|
+
|
38
|
+
<<-EOS
|
39
|
+
#{new_changes}
|
40
|
+
#{existing_changes}
|
41
|
+
--------------------------------------------------------------------------------
|
42
|
+
#{changelog}
|
43
|
+
EOS
|
44
|
+
end
|
45
|
+
|
46
|
+
def rotate(options={})
|
47
|
+
return unless changelog = rotated_changelog(options)
|
48
|
+
Zenflow::Log("Managing changelog for version #{Zenflow::Version.current} / #{Time.now.strftime('%Y-%m-%d')} #{"/ " + options[:name] + " " if options[:name]}")
|
49
|
+
|
50
|
+
File.open("CHANGELOG.md", "w") do |f|
|
51
|
+
f.write changelog
|
52
|
+
end
|
53
|
+
Zenflow::Shell["git add CHANGELOG.md && git commit -a -m 'Rotating CHANGELOG.'"] if options[:commit]
|
54
|
+
end
|
55
|
+
|
56
|
+
def rotated_changelog(options={})
|
57
|
+
changes, changelog = get_changes
|
58
|
+
return if changes.nil?
|
59
|
+
<<-EOS
|
60
|
+
#{changelog}
|
61
|
+
|
62
|
+
#{row_name(options[:name])}
|
63
|
+
#{changes}
|
64
|
+
EOS
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_changes
|
68
|
+
return unless exist?
|
69
|
+
changelog = File.read("CHANGELOG.md").strip
|
70
|
+
changes = changelog.split("--------------------------------------------------------------------------------")[0]
|
71
|
+
return if changes.strip.empty?
|
72
|
+
changelog = changelog.sub(changes, "")
|
73
|
+
return changes.strip, changelog
|
74
|
+
end
|
75
|
+
|
76
|
+
def row_name(name=nil)
|
77
|
+
formatted_name = "/ #{name} " if name
|
78
|
+
"---- #{Zenflow::Version.current} / #{Time.now.strftime('%Y-%m-%d')} #{formatted_name}".ljust(80, "-")
|
79
|
+
end
|
80
|
+
|
81
|
+
def create
|
82
|
+
File.open("CHANGELOG.md", "w") do |f|
|
83
|
+
f.write changelog_template
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def changelog_template
|
88
|
+
<<-EOS
|
89
|
+
--------------------------------------------------------------------------------
|
90
|
+
^ ADD NEW CHANGES ABOVE ^
|
91
|
+
--------------------------------------------------------------------------------
|
92
|
+
|
93
|
+
CHANGELOG
|
94
|
+
=========
|
95
|
+
|
96
|
+
EOS
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Zenflow
|
2
|
+
class Config
|
3
|
+
class << self
|
4
|
+
attr_accessor :config
|
5
|
+
|
6
|
+
CONFIG_FILE = "#{Dir.pwd}/.zenflow"
|
7
|
+
|
8
|
+
def load!
|
9
|
+
@config = {}
|
10
|
+
@config = YAML.load_file(CONFIG_FILE) if configured?
|
11
|
+
end
|
12
|
+
|
13
|
+
def save!
|
14
|
+
File.open(CONFIG_FILE, "w") do |out|
|
15
|
+
YAML.dump(@config, out)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](key)
|
20
|
+
load!
|
21
|
+
@config[key.to_s]
|
22
|
+
end
|
23
|
+
|
24
|
+
def []=(key, value)
|
25
|
+
load!
|
26
|
+
@config[key.to_s] = value
|
27
|
+
save!
|
28
|
+
end
|
29
|
+
|
30
|
+
def configured?
|
31
|
+
File.exist?(CONFIG_FILE)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Zenflow
|
2
|
+
|
3
|
+
module Github
|
4
|
+
def self.user
|
5
|
+
Zenflow::Shell.run('git config --get github.user', silent: true).chomp
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.zenflow_token
|
9
|
+
zenflow_token = Zenflow::Shell.run('git config --get zenflow.token', silent: true).chomp
|
10
|
+
zenflow_token = nil if zenflow_token.to_s.strip == ''
|
11
|
+
zenflow_token
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.authorize
|
15
|
+
Zenflow::Log("Authorizing with GitHub... Enter your GitHub password.")
|
16
|
+
oauth_response = JSON.parse(Zenflow::Shell.run(%{curl -u "#{Zenflow::Github.user}" https://api.github.com/authorizations -d '{"scopes":["repo"], "note":"Zenflow"}' --silent}, silent: true))
|
17
|
+
if oauth_response['token']
|
18
|
+
Zenflow::Shell.run("git config --global zenflow.token #{oauth_response['token']}", silent: true)
|
19
|
+
Zenflow::Log("Authorized!")
|
20
|
+
else
|
21
|
+
Zenflow::Log("Something went wrong. Error from GitHub was: #{oauth_response['message']}")
|
22
|
+
return
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.set_user
|
28
|
+
username = Zenflow::Ask("What is your Github username?")
|
29
|
+
Zenflow::Shell.run("git config --global github.user #{username}", silent: true)
|
30
|
+
end
|
31
|
+
|
32
|
+
class GithubRequest
|
33
|
+
include HTTParty
|
34
|
+
base_uri "https://api.github.com/repos/#{Zenflow::Repo.slug}"
|
35
|
+
format :json
|
36
|
+
headers "Authorization" => "token #{Zenflow::Github.zenflow_token}"
|
37
|
+
headers "User-Agent" => "Zencoder/Zenflow-#{VERSION}"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Zenflow
|
2
|
+
|
3
|
+
def self.Help(options={})
|
4
|
+
Zenflow::Help.new(options)
|
5
|
+
end
|
6
|
+
|
7
|
+
class Help
|
8
|
+
attr_accessor :options
|
9
|
+
|
10
|
+
def initialize(options={})
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def title(text)
|
15
|
+
"- #{text} ".ljust(40, "-").cyan
|
16
|
+
end
|
17
|
+
|
18
|
+
def banner
|
19
|
+
help = []
|
20
|
+
help << "#{title("Summary")}\n#{options[:summary]}" if options[:summary]
|
21
|
+
help << "#{title("Usage")}\n#{options[:usage]}" if options[:usage]
|
22
|
+
help << "#{title("Available Commands")}\n#{options[:commands]}" if options[:commands]
|
23
|
+
help << "#{title("Options")}"
|
24
|
+
help.join("\n\n")
|
25
|
+
end
|
26
|
+
|
27
|
+
def unknown_command
|
28
|
+
if options[:command].nil?
|
29
|
+
Zenflow::Log("Missing command", :color => :red)
|
30
|
+
else
|
31
|
+
Zenflow::Log("Unknown command #{options[:command].inspect}", :color => :red)
|
32
|
+
end
|
33
|
+
exit(1)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Zenflow
|
2
|
+
|
3
|
+
LOG_PATH = File.join(Dir.pwd, ".zenflow-log")
|
4
|
+
|
5
|
+
def self.Log(message, options={})
|
6
|
+
output = ""
|
7
|
+
output << " " if options[:indent]
|
8
|
+
output << "-----> " if !(options[:arrows] === false)
|
9
|
+
output << message
|
10
|
+
LogToFile(output)
|
11
|
+
output = output.send(options[:color] || :cyan) unless options[:color] == false
|
12
|
+
puts output
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.LogToFile(message)
|
16
|
+
File.open(LOG_PATH, "a") do |f|
|
17
|
+
f.write(message+"\n")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Zenflow
|
2
|
+
class PullRequest
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def list
|
6
|
+
response = Zenflow::GithubRequest.get("/pulls").parsed_response
|
7
|
+
response.map{ |pull| new(pull) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def find(number)
|
11
|
+
new(Zenflow::GithubRequest.get("/pulls/#{number}").parsed_response["pull"])
|
12
|
+
end
|
13
|
+
|
14
|
+
def find_by_ref(ref, options={})
|
15
|
+
Zenflow::Log("Looking up pull request for #{ref}") unless options[:silent]
|
16
|
+
if !list.nil?
|
17
|
+
pull = list.detect do |p|
|
18
|
+
p["head"]["ref"] == ref
|
19
|
+
end
|
20
|
+
if pull
|
21
|
+
new(pull)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def find_by_ref!(ref)
|
27
|
+
if pull = find_by_ref(ref)
|
28
|
+
new(pull)
|
29
|
+
else
|
30
|
+
Zenflow::Log("No open pull request was found for #{ref}", color: :red)
|
31
|
+
exit(1)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def exist?(ref)
|
36
|
+
!!find_by_ref(ref)
|
37
|
+
end
|
38
|
+
|
39
|
+
def create(options={})
|
40
|
+
response = Zenflow::GithubRequest.post("/pulls",
|
41
|
+
body: {
|
42
|
+
"base" => options[:base],
|
43
|
+
"head" => options[:head],
|
44
|
+
"title" => options[:title],
|
45
|
+
"body" => options[:body]
|
46
|
+
}.to_json
|
47
|
+
)
|
48
|
+
new(response.parsed_response)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
attr_reader :pull
|
54
|
+
|
55
|
+
def initialize(pull)
|
56
|
+
@pull = pull || {}
|
57
|
+
end
|
58
|
+
|
59
|
+
def valid?
|
60
|
+
!pull["errors"] && pull['html_url']
|
61
|
+
end
|
62
|
+
|
63
|
+
def [](key)
|
64
|
+
pull[key.to_s]
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|