git_reflow 0.8.9 → 0.8.10

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.
@@ -1,84 +1,84 @@
1
- require 'git_reflow/git_server/pull_request'
2
-
3
- module GitReflow
4
- module GitServer
5
- class BitBucket
6
- class PullRequest < GitReflow::GitServer::PullRequest
7
- def initialize(attributes)
8
- self.number = attributes.id
9
- self.description = attributes.body || attributes.description
10
- self.html_url = "#{attributes.source.repository.links.html.href}/pull-request/#{self.number}"
11
- self.feature_branch_name = attributes.source.branch.name[/[^:]+$/]
12
- self.base_branch_name = attributes.destination.branch.name[/[^:]+$/]
13
- self.build = Build.new
14
- self.source_object = attributes
15
- end
16
-
17
- def self.create(options = {})
18
- self.new GitReflow.git_server.connection.repos.pull_requests.create(
19
- GitReflow.git_server.class.remote_user,
20
- GitReflow.git_server.class.remote_repo_name,
21
- title: options[:title],
22
- description: options[:body] || options[:description],
23
- source: {
24
- branch: { name: GitReflow.git_server.class.current_branch },
25
- repository: { full_name: "#{GitReflow.git_server.class.remote_user}/#{GitReflow.git_server.class.remote_repo_name}" }
26
- },
27
- destination: {
28
- branch: { name: options[:base] }
29
- },
30
- reviewers: [username: GitReflow.git_server.class.user])
31
- end
32
-
33
- def self.find_open(to: 'master', from: GitReflow.git_server.class.current_branch)
34
- begin
35
- matching_pull = GitReflow.git_server.connection.repos.pull_requests.all(GitReflow.git_server.class.remote_user, GitReflow.git_server.class.remote_repo_name, limit: 1).select do |pr|
36
- pr.source.branch.name == from and
37
- pr.destination.branch.name == to
38
- end.first
39
-
40
- if matching_pull
41
- self.new matching_pull
42
- end
43
- rescue ::BitBucket::Error::NotFound => e
44
- GitReflow.git_server.say "No BitBucket repo found for #{GitReflow.git_server.class.remote_user}/#{GitReflow.git_server.class.remote_repo_name}", :error
45
- rescue ::BitBucket::Error::Forbidden => e
46
- GitReflow.git_server.say "You don't have API access to this repo", :error
47
- end
48
- end
49
-
50
- def commit_author
51
- # use the author of the pull request
52
- self.author.username
53
- end
54
-
55
- def comments
56
- GitReflow.git_server.connection.repos.pull_requests.comments.all(GitReflow.git_server.class.remote_user, GitReflow.git_server.class.remote_repo_name, self.id)
57
- end
58
-
59
- def last_comment
60
- last_comment = comments.first
61
- return "" unless last_comment
62
- "#{last_comment.content.raw}"
63
- end
64
-
65
- def reviewers
66
- return [] unless comments.size > 0
67
- comments.map {|c| c.user.username }.uniq - [GitReflow.git_server.class.user]
68
- end
69
-
70
- def approvals
71
- approved = []
72
-
73
- GitReflow.git_server.connection.repos.pull_requests.activity(GitReflow.git_server.class.remote_user, GitReflow.git_server.class.remote_repo_name, self.id).each do |activity|
74
- break unless activity.respond_to?(:approval) and activity.approval.user.username != GitReflow.git_server.class.user
75
- approved |= [activity.approval.user.username]
76
- end
77
-
78
- approved
79
- end
80
-
81
- end
82
- end
83
- end
84
- end
1
+ require 'git_reflow/git_server/pull_request'
2
+
3
+ module GitReflow
4
+ module GitServer
5
+ class BitBucket
6
+ class PullRequest < GitReflow::GitServer::PullRequest
7
+ def initialize(attributes)
8
+ self.number = attributes.id
9
+ self.description = attributes.body || attributes.description
10
+ self.html_url = "#{attributes.source.repository.links.html.href}/pull-request/#{self.number}"
11
+ self.feature_branch_name = attributes.source.branch.name[/[^:]+$/]
12
+ self.base_branch_name = attributes.destination.branch.name[/[^:]+$/]
13
+ self.build = Build.new
14
+ self.source_object = attributes
15
+ end
16
+
17
+ def self.create(options = {})
18
+ self.new GitReflow.git_server.connection.repos.pull_requests.create(
19
+ GitReflow.git_server.class.remote_user,
20
+ GitReflow.git_server.class.remote_repo_name,
21
+ title: options[:title],
22
+ description: options[:body] || options[:description],
23
+ source: {
24
+ branch: { name: GitReflow.git_server.class.current_branch },
25
+ repository: { full_name: "#{GitReflow.git_server.class.remote_user}/#{GitReflow.git_server.class.remote_repo_name}" }
26
+ },
27
+ destination: {
28
+ branch: { name: options[:base] }
29
+ },
30
+ reviewers: [username: GitReflow.git_server.class.user])
31
+ end
32
+
33
+ def self.find_open(to: 'master', from: GitReflow.git_server.class.current_branch)
34
+ begin
35
+ matching_pull = GitReflow.git_server.connection.repos.pull_requests.all(GitReflow.git_server.class.remote_user, GitReflow.git_server.class.remote_repo_name, limit: 1).select do |pr|
36
+ pr.source.branch.name == from and
37
+ pr.destination.branch.name == to
38
+ end.first
39
+
40
+ if matching_pull
41
+ self.new matching_pull
42
+ end
43
+ rescue ::BitBucket::Error::NotFound => e
44
+ GitReflow.git_server.say "No BitBucket repo found for #{GitReflow.git_server.class.remote_user}/#{GitReflow.git_server.class.remote_repo_name}", :error
45
+ rescue ::BitBucket::Error::Forbidden => e
46
+ GitReflow.git_server.say "You don't have API access to this repo", :error
47
+ end
48
+ end
49
+
50
+ def commit_author
51
+ # use the author of the pull request
52
+ self.author.username
53
+ end
54
+
55
+ def comments
56
+ GitReflow.git_server.connection.repos.pull_requests.comments.all(GitReflow.git_server.class.remote_user, GitReflow.git_server.class.remote_repo_name, self.id)
57
+ end
58
+
59
+ def last_comment
60
+ last_comment = comments.first
61
+ return "" unless last_comment
62
+ "#{last_comment.content.raw}"
63
+ end
64
+
65
+ def reviewers
66
+ return [] unless comments.size > 0
67
+ comments.map {|c| c.user.username }.uniq - [GitReflow.git_server.class.user]
68
+ end
69
+
70
+ def approvals
71
+ approved = []
72
+
73
+ GitReflow.git_server.connection.repos.pull_requests.activity(GitReflow.git_server.class.remote_user, GitReflow.git_server.class.remote_repo_name, self.id).each do |activity|
74
+ break unless activity.respond_to?(:approval) and activity.approval.user.username != GitReflow.git_server.class.user
75
+ approved |= [activity.approval.user.username]
76
+ end
77
+
78
+ approved
79
+ end
80
+
81
+ end
82
+ end
83
+ end
84
+ end
@@ -9,7 +9,7 @@ module GitReflow
9
9
  extend GitHelpers
10
10
  include Sandbox
11
11
 
12
- attr_accessor :connection
12
+ attr_reader :connection
13
13
 
14
14
  def initialize(config_options = {})
15
15
  project_only = !!config_options.delete(:project_only)
@@ -87,7 +87,7 @@ module GitReflow
87
87
  def merge!(options = {})
88
88
 
89
89
  # fallback to default merge process if user "forces" merge
90
- if(options[:skip_lgtm])
90
+ if(options[:force])
91
91
  super options
92
92
  else
93
93
  if deliver?
@@ -1,2 +1,2 @@
1
- require_relative 'rspec/command_line_helpers'
2
- require_relative 'rspec/stub_helpers'
1
+ require_relative 'rspec/command_line_helpers'
2
+ require_relative 'rspec/stub_helpers'
@@ -1,3 +1,3 @@
1
1
  module GitReflow
2
- VERSION = "0.8.9"
2
+ VERSION = "0.8.10"
3
3
  end
@@ -1,238 +1,235 @@
1
- $: << File.expand_path(File.dirname(File.realpath(__FILE__)) + '/../..')
2
- require 'git_reflow/workflow'
3
-
4
- module GitReflow
5
- module Workflows
6
- # This class contains the core workflow for git-reflow. Going forward, this
7
- # will act as the base class for customizing and extending git-reflow.
8
- class Core
9
- include GitReflow::Workflow
10
-
11
- # Sets up the required git configurations that git-reflow depends on.
12
- #
13
- # @param local [Boolean] whether to configure git-reflow specific to the current project
14
- # @param enterprise [Boolean] whether to configure git-reflow for use with Github Enterprise
15
- command(:setup, defaults: {local: false, enterprise: false}) do |**params|
16
- reflow_options = { project_only: params[:local], enterprise: params[:enterprise] }
17
- existing_git_include_paths = GitReflow::Config.get('include.path', all: true).split("\n")
18
-
19
- unless File.exist?(GitReflow::Config::CONFIG_FILE_PATH) or existing_git_include_paths.include?(GitReflow::Config::CONFIG_FILE_PATH)
20
- GitReflow.say "We'll walk you through setting up git-reflow's defaults for all your projects.", :notice
21
- GitReflow.say "In the future, you can run \`git-reflow setup\` from the root of any project you want to setup differently.", :notice
22
- GitReflow.say "To adjust these settings globally, you can run \`git-reflow setup --global\`.", :notice
23
- GitReflow.run "touch #{GitReflow::Config::CONFIG_FILE_PATH}"
24
- GitReflow.say "Created #{GitReflow::Config::CONFIG_FILE_PATH} for git-reflow specific configurations.", :notice
25
- GitReflow::Config.add "include.path", GitReflow::Config::CONFIG_FILE_PATH, global: true
26
- GitReflow.say "Added #{GitReflow::Config::CONFIG_FILE_PATH} to include.path in $HOME/.gitconfig.", :notice
27
- end
28
-
29
- choose do |menu|
30
- menu.header = "Available remote Git Server services"
31
- menu.prompt = "Which service would you like to use for this project? "
32
-
33
- menu.choice('GitHub') { GitReflow::GitServer.connect reflow_options.merge({ provider: 'GitHub', silent: false }) }
34
- menu.choice('BitBucket (team-owned repos only)') { GitReflow::GitServer.connect reflow_options.merge({ provider: 'BitBucket', silent: false }) }
35
- end
36
-
37
- GitReflow::Config.set "constants.minimumApprovals", ask("Set the minimum number of approvals (leaving blank will require approval from all commenters): "), local: reflow_options[:project_only]
38
- GitReflow::Config.set "constants.approvalRegex", GitReflow::GitServer::PullRequest::DEFAULT_APPROVAL_REGEX, local: reflow_options[:project_only]
39
-
40
- if GitReflow::Config.get('core.editor').length <= 0
41
- GitReflow::Config.set('core.editor', GitReflow.default_editor, local: reflow_options[:project_only])
42
- GitReflow.say "Updated git's editor (via git config key 'core.editor') to: #{GitReflow.default_editor}.", :notice
43
- end
44
- end
45
-
46
- # Start a new feature branch
47
- #
48
- # @param feature_branch [String] the name of the branch to create your feature on
49
- # @option base [String] the name of the base branch you want to checkout your feature from
50
- command(:start, defaults: {base: 'master'}) do |**params|
51
- base_branch = params[:base]
52
- feature_branch = params[:feature_branch]
53
-
54
- if feature_branch.nil? or feature_branch.length <= 0
55
- GitReflow.say "usage: git-reflow start [new-branch-name]", :error
56
- else
57
- GitReflow.run_command_with_label "git checkout #{base_branch}"
58
- GitReflow.run_command_with_label "git pull origin #{base_branch}"
59
- GitReflow.run_command_with_label "git push origin #{base_branch}:refs/heads/#{feature_branch}"
60
- GitReflow.run_command_with_label "git checkout --track -b #{feature_branch} origin/#{feature_branch}"
61
- end
62
- end
63
-
64
- # Submit a feature branch for review
65
- #
66
- # @option base [String] the name of the base branch you want to merge your feature into
67
- # @option title [String] the title of your pull request
68
- # @option body [String] the body of your pull request
69
- command(:review, defaults: {base: 'master'}) do |**params|
70
- base_branch = params[:base]
71
- create_pull_request = true
72
-
73
- GitReflow.fetch_destination base_branch
74
- begin
75
- GitReflow.push_current_branch
76
-
77
- existing_pull_request = GitReflow.git_server.find_open_pull_request( from: GitReflow.current_branch, to: base_branch )
78
- if existing_pull_request
79
- say "A pull request already exists for these branches:", :notice
80
- existing_pull_request.display_pull_request_summary
81
- else
82
- unless params[:title] || params[:body]
83
- pull_request_msg_file = "#{GitReflow.git_root_dir}/.git/GIT_REFLOW_PR_MSG"
84
-
85
- File.open(pull_request_msg_file, 'w') do |file|
86
- file.write(params[:title] || GitReflow.pull_request_template || GitReflow.current_branch)
87
- end
88
-
89
- GitReflow.run("#{GitReflow.git_editor_command} #{pull_request_msg_file}", with_system: true)
90
-
91
- pr_msg = File.read(pull_request_msg_file).split(/[\r\n]|\r\n/).map(&:strip)
92
- title = pr_msg.shift
93
-
94
- File.delete(pull_request_msg_file)
95
-
96
- unless pr_msg.empty?
97
- pr_msg.shift if pr_msg.first.empty?
98
- end
99
-
100
- params[:title] = title
101
- params[:body] = "#{pr_msg.join("\n")}\n"
102
-
103
- say "\nReview your PR:\n"
104
- say "--------\n"
105
- say "Title:\n#{params[:title]}\n\n"
106
- say "Body:\n#{params[:body]}\n"
107
- say "--------\n"
108
-
109
- create_pull_request = ask("Submit pull request? (Y)") =~ /y/i
110
- end
111
-
112
- if create_pull_request
113
- pull_request = GitReflow.git_server.create_pull_request(title: params[:title] || params[:body],
114
- body: params[:body],
115
- head: "#{GitReflow.remote_user}:#{GitReflow.current_branch}",
116
- base: params[:base])
117
-
118
- say "Successfully created pull request ##{pull_request.number}: #{pull_request.title}\nPull Request URL: #{pull_request.html_url}\n", :success
119
- else
120
- say "Review aborted. No pull request has been created.", :review_halted
121
- end
122
- end
123
- rescue Github::Error::UnprocessableEntity => e
124
- say "Github Error: #{e.to_s}", :error
125
- rescue StandardError => e
126
- say "\nError: #{e.inspect}", :error
127
- end
128
- end
129
-
130
- # Checks the status of an existing pull request
131
- #
132
- # @option destination_branch [String] the branch you're merging your feature into ('master' is default)
133
- command(:status, defaults: {destination_branch: 'master'}) do |**params|
134
- pull_request = GitReflow.git_server.find_open_pull_request( :from => GitReflow.current_branch, :to => params[:destination_branch] )
135
-
136
- if pull_request.nil?
137
- say "No pull request exists for #{GitReflow.current_branch} -> #{params[:destination_branch]}", :notice
138
- say "Run 'git reflow review #{params[:destination_branch]}' to start the review process", :notice
139
- else
140
- say "Here's the status of your review:"
141
- pull_request.display_pull_request_summary
142
- end
143
- end
144
-
145
- command(:deploy) do |**params|
146
- destination_server = params[:destination_server] || 'default'
147
- deploy_command = GitReflow::Config.get("reflow.deploy-to-#{destination_server}-command", local: true)
148
-
149
- # first check is to allow for automated setup
150
- if deploy_command.empty?
151
- deploy_command = ask("Enter the command you use to deploy to #{destination_server} (leaving blank will skip deployment)")
152
- end
153
-
154
- # second check is to see if the user wants to skip
155
- if deploy_command.empty?
156
- say "Skipping deployment..."
157
- false
158
- else
159
- GitReflow::Config.set("reflow.deploy-to-#{destination_server}-command", deploy_command, local: true)
160
- run_command_with_label(deploy_command, with_system: true)
161
- end
162
- end
163
-
164
- # Merge and deploy a feature branch to a staging branch
165
- command(:stage) do |**params|
166
- feature_branch_name = GitReflow.current_branch
167
- staging_branch_name = GitReflow::Config.get('reflow.staging-branch', local: true)
168
-
169
- if staging_branch_name.empty?
170
- staging_branch_name = GitReflow.ask("What's the name of your staging branch? (default: 'staging') ")
171
- staging_branch_name = 'staging' if staging_branch_name.strip == ''
172
- GitReflow::Config.set('reflow.staging-branch', staging_branch_name, local: true)
173
- end
174
-
175
- GitReflow.run_command_with_label "git checkout #{staging_branch_name}"
176
- GitReflow.run_command_with_label "git pull origin #{staging_branch_name}"
177
-
178
- if GitReflow.run_command_with_label "git merge #{feature_branch_name}", with_system: true
179
- GitReflow.run_command_with_label "git push origin #{staging_branch_name}"
180
-
181
- staged = self.deploy(destination_server: :staging)
182
-
183
- if staged
184
- GitReflow.say "Deployed to Staging.", :success
185
- else
186
- GitReflow.say "There were issues deploying to staging.", :error
187
- end
188
- else
189
- GitReflow.say "There were issues merging your feature branch to staging.", :error
190
- end
191
- end
192
-
193
- # Deliver a feature branch to a base branch
194
- #
195
- # @option base [String] base branch to merge your feature branch into
196
- # @option force [Boolean] whether to force-deliver the feature branch, ignoring any QA checks
197
- command(:deliver, defaults: {base: 'master'}) do |**params|
198
- begin
199
- existing_pull_request = GitReflow.git_server.find_open_pull_request( from: GitReflow.current_branch, to: params[:base] )
200
-
201
- if existing_pull_request.nil?
202
- say "No pull request exists for #{GitReflow.remote_user}:#{GitReflow.current_branch}\nPlease submit your branch for review first with \`git reflow review\`", :deliver_halted
203
- else
204
-
205
- if existing_pull_request.good_to_merge?(force: params[:force])
206
- # displays current status and prompts user for confirmation
207
- self.status destination_branch: params[:base]
208
- # TODO: change name of this in the merge! method
209
- params[:skip_lgtm] = params[:force] if params[:force]
210
- existing_pull_request.merge!(params)
211
- else
212
- say existing_pull_request.rejection_message, :deliver_halted
213
- end
214
-
215
- end
216
-
217
- rescue Github::Error::UnprocessableEntity => e
218
- say "Github Error: #{e.inspect}", :error
219
- end
220
- end
221
-
222
-
223
- # Updates and synchronizes your base branch and feature branch.
224
- #
225
- # Performs the following:
226
- # $ git checkout <base_branch>
227
- # $ git pull <remote_location> <base_branch>
228
- # $ git checkout <current_branch>
229
- # $ git pull origin <current_branch>
230
- # $ git merge <base_branch>
231
- # @param remote [String] the name of the remote repository to fetch updates from (origin by default)
232
- # @param base [String] the branch that you want to fetch updates from (master by default)
233
- command(:refresh, defaults: {remote: 'origin', base: 'master'}) do |**params|
234
- GitReflow.update_feature_branch(params)
235
- end
236
- end
237
- end
238
- end
1
+ $: << File.expand_path(File.dirname(File.realpath(__FILE__)) + '/../..')
2
+ require 'git_reflow/workflow'
3
+
4
+ module GitReflow
5
+ module Workflows
6
+ # This class contains the core workflow for git-reflow. Going forward, this
7
+ # will act as the base class for customizing and extending git-reflow.
8
+ class Core
9
+ include GitReflow::Workflow
10
+
11
+ # Sets up the required git configurations that git-reflow depends on.
12
+ #
13
+ # @param local [Boolean] whether to configure git-reflow specific to the current project
14
+ # @param enterprise [Boolean] whether to configure git-reflow for use with Github Enterprise
15
+ command(:setup, defaults: {local: false, enterprise: false}) do |**params|
16
+ reflow_options = { project_only: params[:local], enterprise: params[:enterprise] }
17
+ existing_git_include_paths = GitReflow::Config.get('include.path', all: true).split("\n")
18
+
19
+ unless File.exist?(GitReflow::Config::CONFIG_FILE_PATH) or existing_git_include_paths.include?(GitReflow::Config::CONFIG_FILE_PATH)
20
+ GitReflow.say "We'll walk you through setting up git-reflow's defaults for all your projects.", :notice
21
+ GitReflow.say "In the future, you can run \`git-reflow setup --local\` from the root of any project you want to setup differently.", :notice
22
+ GitReflow.run "touch #{GitReflow::Config::CONFIG_FILE_PATH}"
23
+ GitReflow.say "Created #{GitReflow::Config::CONFIG_FILE_PATH} for git-reflow specific configurations.", :notice
24
+ GitReflow::Config.add "include.path", GitReflow::Config::CONFIG_FILE_PATH, global: true
25
+ GitReflow.say "Added #{GitReflow::Config::CONFIG_FILE_PATH} to include.path in $HOME/.gitconfig.", :notice
26
+ end
27
+
28
+ choose do |menu|
29
+ menu.header = "Available remote Git Server services"
30
+ menu.prompt = "Which service would you like to use for this project? "
31
+
32
+ menu.choice('GitHub') { GitReflow::GitServer.connect reflow_options.merge({ provider: 'GitHub', silent: false }) }
33
+ menu.choice('BitBucket (team-owned repos only)') { GitReflow::GitServer.connect reflow_options.merge({ provider: 'BitBucket', silent: false }) }
34
+ end
35
+
36
+ GitReflow::Config.set "constants.minimumApprovals", ask("Set the minimum number of approvals (leaving blank will require approval from all commenters): "), local: reflow_options[:project_only]
37
+ GitReflow::Config.set "constants.approvalRegex", GitReflow::GitServer::PullRequest::DEFAULT_APPROVAL_REGEX, local: reflow_options[:project_only]
38
+
39
+ if GitReflow::Config.get('core.editor').length <= 0
40
+ GitReflow::Config.set('core.editor', GitReflow.default_editor, local: reflow_options[:project_only])
41
+ GitReflow.say "Updated git's editor (via git config key 'core.editor') to: #{GitReflow.default_editor}.", :notice
42
+ end
43
+ end
44
+
45
+ # Start a new feature branch
46
+ #
47
+ # @param feature_branch [String] the name of the branch to create your feature on
48
+ # @option base [String] the name of the base branch you want to checkout your feature from
49
+ command(:start, defaults: {base: 'master'}) do |**params|
50
+ base_branch = params[:base]
51
+ feature_branch = params[:feature_branch]
52
+
53
+ if feature_branch.nil? or feature_branch.length <= 0
54
+ GitReflow.say "usage: git-reflow start [new-branch-name]", :error
55
+ else
56
+ GitReflow.run_command_with_label "git checkout #{base_branch}"
57
+ GitReflow.run_command_with_label "git pull origin #{base_branch}"
58
+ GitReflow.run_command_with_label "git push origin #{base_branch}:refs/heads/#{feature_branch}"
59
+ GitReflow.run_command_with_label "git checkout --track -b #{feature_branch} origin/#{feature_branch}"
60
+ end
61
+ end
62
+
63
+ # Submit a feature branch for review
64
+ #
65
+ # @option base [String] the name of the base branch you want to merge your feature into
66
+ # @option title [String] the title of your pull request
67
+ # @option body [String] the body of your pull request
68
+ command(:review, defaults: {base: 'master'}) do |**params|
69
+ base_branch = params[:base]
70
+ create_pull_request = true
71
+
72
+ GitReflow.fetch_destination base_branch
73
+ begin
74
+ GitReflow.push_current_branch
75
+
76
+ existing_pull_request = GitReflow.git_server.find_open_pull_request( from: GitReflow.current_branch, to: base_branch )
77
+ if existing_pull_request
78
+ say "A pull request already exists for these branches:", :notice
79
+ existing_pull_request.display_pull_request_summary
80
+ else
81
+ unless params[:title] || params[:body]
82
+ pull_request_msg_file = "#{GitReflow.git_root_dir}/.git/GIT_REFLOW_PR_MSG"
83
+
84
+ File.open(pull_request_msg_file, 'w') do |file|
85
+ file.write(params[:title] || GitReflow.pull_request_template || GitReflow.current_branch)
86
+ end
87
+
88
+ GitReflow.run("#{GitReflow.git_editor_command} #{pull_request_msg_file}", with_system: true)
89
+
90
+ pr_msg = File.read(pull_request_msg_file).split(/[\r\n]|\r\n/).map(&:strip)
91
+ title = pr_msg.shift
92
+
93
+ File.delete(pull_request_msg_file)
94
+
95
+ unless pr_msg.empty?
96
+ pr_msg.shift if pr_msg.first.empty?
97
+ end
98
+
99
+ params[:title] = title
100
+ params[:body] = "#{pr_msg.join("\n")}\n"
101
+
102
+ say "\nReview your PR:\n"
103
+ say "--------\n"
104
+ say "Title:\n#{params[:title]}\n\n"
105
+ say "Body:\n#{params[:body]}\n"
106
+ say "--------\n"
107
+
108
+ create_pull_request = ask("Submit pull request? (Y)") =~ /y/i
109
+ end
110
+
111
+ if create_pull_request
112
+ pull_request = GitReflow.git_server.create_pull_request(title: params[:title] || params[:body],
113
+ body: params[:body],
114
+ head: "#{GitReflow.remote_user}:#{GitReflow.current_branch}",
115
+ base: params[:base])
116
+
117
+ say "Successfully created pull request ##{pull_request.number}: #{pull_request.title}\nPull Request URL: #{pull_request.html_url}\n", :success
118
+ else
119
+ say "Review aborted. No pull request has been created.", :review_halted
120
+ end
121
+ end
122
+ rescue Github::Error::UnprocessableEntity => e
123
+ say "Github Error: #{e.to_s}", :error
124
+ rescue StandardError => e
125
+ say "\nError: #{e.inspect}", :error
126
+ end
127
+ end
128
+
129
+ # Checks the status of an existing pull request
130
+ #
131
+ # @option destination_branch [String] the branch you're merging your feature into ('master' is default)
132
+ command(:status, defaults: {destination_branch: 'master'}) do |**params|
133
+ pull_request = GitReflow.git_server.find_open_pull_request( :from => GitReflow.current_branch, :to => params[:destination_branch] )
134
+
135
+ if pull_request.nil?
136
+ say "No pull request exists for #{GitReflow.current_branch} -> #{params[:destination_branch]}", :notice
137
+ say "Run 'git reflow review #{params[:destination_branch]}' to start the review process", :notice
138
+ else
139
+ say "Here's the status of your review:"
140
+ pull_request.display_pull_request_summary
141
+ end
142
+ end
143
+
144
+ command(:deploy) do |**params|
145
+ destination_server = params[:destination_server] || 'default'
146
+ deploy_command = GitReflow::Config.get("reflow.deploy-to-#{destination_server}-command", local: true)
147
+
148
+ # first check is to allow for automated setup
149
+ if deploy_command.empty?
150
+ deploy_command = ask("Enter the command you use to deploy to #{destination_server} (leaving blank will skip deployment)")
151
+ end
152
+
153
+ # second check is to see if the user wants to skip
154
+ if deploy_command.empty?
155
+ say "Skipping deployment..."
156
+ false
157
+ else
158
+ GitReflow::Config.set("reflow.deploy-to-#{destination_server}-command", deploy_command, local: true)
159
+ run_command_with_label(deploy_command, with_system: true)
160
+ end
161
+ end
162
+
163
+ # Merge and deploy a feature branch to a staging branch
164
+ command(:stage) do |**params|
165
+ feature_branch_name = GitReflow.current_branch
166
+ staging_branch_name = GitReflow::Config.get('reflow.staging-branch', local: true)
167
+
168
+ if staging_branch_name.empty?
169
+ staging_branch_name = GitReflow.ask("What's the name of your staging branch? (default: 'staging') ")
170
+ staging_branch_name = 'staging' if staging_branch_name.strip == ''
171
+ GitReflow::Config.set('reflow.staging-branch', staging_branch_name, local: true)
172
+ end
173
+
174
+ GitReflow.run_command_with_label "git checkout #{staging_branch_name}"
175
+ GitReflow.run_command_with_label "git pull origin #{staging_branch_name}"
176
+
177
+ if GitReflow.run_command_with_label "git merge #{feature_branch_name}", with_system: true
178
+ GitReflow.run_command_with_label "git push origin #{staging_branch_name}"
179
+
180
+ staged = self.deploy(destination_server: :staging)
181
+
182
+ if staged
183
+ GitReflow.say "Deployed to Staging.", :success
184
+ else
185
+ GitReflow.say "There were issues deploying to staging.", :error
186
+ end
187
+ else
188
+ GitReflow.say "There were issues merging your feature branch to staging.", :error
189
+ end
190
+ end
191
+
192
+ # Deliver a feature branch to a base branch
193
+ #
194
+ # @option base [String] base branch to merge your feature branch into
195
+ # @option force [Boolean] whether to force-deliver the feature branch, ignoring any QA checks
196
+ command(:deliver, defaults: {base: 'master'}) do |**params|
197
+ begin
198
+ existing_pull_request = GitReflow.git_server.find_open_pull_request( from: GitReflow.current_branch, to: params[:base] )
199
+
200
+ if existing_pull_request.nil?
201
+ say "No pull request exists for #{GitReflow.remote_user}:#{GitReflow.current_branch}\nPlease submit your branch for review first with \`git reflow review\`", :deliver_halted
202
+ else
203
+
204
+ if existing_pull_request.good_to_merge?(force: params[:force])
205
+ # displays current status and prompts user for confirmation
206
+ self.status destination_branch: params[:base]
207
+ existing_pull_request.merge!(params)
208
+ else
209
+ say existing_pull_request.rejection_message, :deliver_halted
210
+ end
211
+
212
+ end
213
+
214
+ rescue Github::Error::UnprocessableEntity => e
215
+ say "Github Error: #{e.inspect}", :error
216
+ end
217
+ end
218
+
219
+
220
+ # Updates and synchronizes your base branch and feature branch.
221
+ #
222
+ # Performs the following:
223
+ # $ git checkout <base_branch>
224
+ # $ git pull <remote_location> <base_branch>
225
+ # $ git checkout <current_branch>
226
+ # $ git pull origin <current_branch>
227
+ # $ git merge <base_branch>
228
+ # @param remote [String] the name of the remote repository to fetch updates from (origin by default)
229
+ # @param base [String] the branch that you want to fetch updates from (master by default)
230
+ command(:refresh, defaults: {remote: 'origin', base: 'master'}) do |**params|
231
+ GitReflow.update_feature_branch(params)
232
+ end
233
+ end
234
+ end
235
+ end