git_reflow 0.8.9 → 0.9.3

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.
Files changed (87) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/multi-ruby-tests.yml +33 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +2 -0
  5. data/.ruby-version +1 -0
  6. data/Appraisals +1 -6
  7. data/CHANGELOG.md +466 -348
  8. data/Gemfile.lock +99 -72
  9. data/LICENSE +20 -20
  10. data/README.md +481 -0
  11. data/Rakefile +15 -8
  12. data/Workflow +3 -0
  13. data/_config.yml +1 -0
  14. data/bin/console +7 -7
  15. data/bin/setup +6 -6
  16. data/exe/git-reflow +20 -36
  17. data/git_reflow.gemspec +26 -30
  18. data/lib/git_reflow.rb +3 -15
  19. data/lib/git_reflow/config.rb +48 -13
  20. data/lib/git_reflow/git_helpers.rb +69 -22
  21. data/lib/git_reflow/git_server.rb +63 -63
  22. data/lib/git_reflow/git_server/base.rb +68 -68
  23. data/lib/git_reflow/git_server/bit_bucket.rb +101 -101
  24. data/lib/git_reflow/git_server/bit_bucket/pull_request.rb +84 -84
  25. data/lib/git_reflow/git_server/git_hub.rb +53 -41
  26. data/lib/git_reflow/git_server/git_hub/pull_request.rb +16 -14
  27. data/lib/git_reflow/git_server/pull_request.rb +4 -2
  28. data/lib/git_reflow/merge_error.rb +9 -9
  29. data/lib/git_reflow/rspec.rb +3 -2
  30. data/lib/git_reflow/rspec/command_line_helpers.rb +23 -6
  31. data/lib/git_reflow/rspec/stub_helpers.rb +13 -13
  32. data/lib/git_reflow/rspec/workflow_helpers.rb +18 -0
  33. data/lib/git_reflow/sandbox.rb +16 -6
  34. data/lib/git_reflow/version.rb +1 -1
  35. data/lib/git_reflow/workflow.rb +304 -9
  36. data/lib/git_reflow/workflows/FlatMergeWorkflow +38 -0
  37. data/lib/git_reflow/workflows/core.rb +364 -238
  38. data/spec/fixtures/authentication_failure.json +3 -0
  39. data/spec/fixtures/awesome_workflow.rb +3 -7
  40. data/spec/fixtures/git/git_config +7 -7
  41. data/spec/fixtures/issues/comment.json.erb +27 -27
  42. data/spec/fixtures/issues/comments.json +29 -29
  43. data/spec/fixtures/issues/comments.json.erb +15 -15
  44. data/spec/fixtures/pull_requests/comment.json.erb +45 -45
  45. data/spec/fixtures/pull_requests/comments.json +47 -47
  46. data/spec/fixtures/pull_requests/comments.json.erb +15 -15
  47. data/spec/fixtures/pull_requests/commits.json +29 -29
  48. data/spec/fixtures/pull_requests/external_pull_request.json +145 -145
  49. data/spec/fixtures/pull_requests/pull_request.json +142 -142
  50. data/spec/fixtures/pull_requests/pull_request.json.erb +142 -142
  51. data/spec/fixtures/pull_requests/pull_request_branch_nonexistent_error.json +32 -0
  52. data/spec/fixtures/pull_requests/pull_request_exists_error.json +32 -32
  53. data/spec/fixtures/pull_requests/pull_requests.json +136 -136
  54. data/spec/fixtures/repositories/commit.json +53 -53
  55. data/spec/fixtures/repositories/commit.json.erb +53 -53
  56. data/spec/fixtures/repositories/commits.json.erb +13 -13
  57. data/spec/fixtures/repositories/statuses.json +31 -31
  58. data/spec/fixtures/users/user.json +32 -0
  59. data/spec/lib/git_reflow/git_helpers_spec.rb +115 -12
  60. data/spec/lib/git_reflow/git_server/bit_bucket_spec.rb +81 -81
  61. data/spec/lib/git_reflow/git_server/git_hub/pull_request_spec.rb +10 -10
  62. data/spec/lib/git_reflow/git_server/git_hub_spec.rb +77 -3
  63. data/spec/lib/git_reflow/git_server/pull_request_spec.rb +9 -3
  64. data/spec/lib/git_reflow/git_server_spec.rb +101 -101
  65. data/spec/lib/git_reflow/sandbox_spec.rb +1 -1
  66. data/spec/lib/git_reflow/workflow_spec.rb +304 -59
  67. data/spec/lib/git_reflow/workflows/core_spec.rb +225 -67
  68. data/spec/lib/git_reflow/workflows/flat_merge_spec.rb +71 -59
  69. data/spec/lib/git_reflow_spec.rb +2 -25
  70. data/spec/spec_helper.rb +3 -0
  71. data/spec/support/fixtures.rb +54 -54
  72. data/spec/support/github_helpers.rb +99 -109
  73. data/spec/support/mock_pull_request.rb +17 -17
  74. data/spec/support/web_mocks.rb +39 -39
  75. metadata +51 -74
  76. data/README.rdoc +0 -461
  77. data/circle.yml +0 -26
  78. data/lib/git_reflow/commands/deliver.rb +0 -10
  79. data/lib/git_reflow/commands/refresh.rb +0 -20
  80. data/lib/git_reflow/commands/review.rb +0 -13
  81. data/lib/git_reflow/commands/setup.rb +0 -11
  82. data/lib/git_reflow/commands/stage.rb +0 -9
  83. data/lib/git_reflow/commands/start.rb +0 -18
  84. data/lib/git_reflow/commands/status.rb +0 -7
  85. data/lib/git_reflow/os_detector.rb +0 -23
  86. data/lib/git_reflow/workflows/flat_merge.rb +0 -10
  87. data/spec/fixtures/workflow_with_super.rb +0 -8
@@ -1,13 +1,13 @@
1
- module GitReflow
2
- module RSpec
3
- module StubHelpers
4
-
5
- def stub_with_fallback(obj, method)
6
- original_method = obj.method(method)
7
- allow(obj).to receive(method).with(anything()) { |*args| original_method.call(*args) }
8
- return allow(obj).to receive(method)
9
- end
10
-
11
- end
12
- end
13
- end
1
+ module GitReflow
2
+ module RSpec
3
+ module StubHelpers
4
+
5
+ def stub_with_fallback(obj, method)
6
+ original_method = obj.method(method)
7
+ allow(obj).to receive(method).with(anything()) { |*args| original_method.call(*args) }
8
+ return allow(obj).to receive(method)
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ module GitReflow
2
+ module RSpec
3
+ # @nodoc
4
+ module WorkflowHelpers
5
+ def use_workflow(path)
6
+ allow(GitReflow::Workflows::Core).to receive(:load_workflow).and_return(
7
+ GitReflow::Workflows::Core.load_raw_workflow(File.read(path))
8
+ )
9
+ end
10
+
11
+ def suppress_loading_of_external_workflows
12
+ allow(GitReflow::Workflows::Core).to receive(:load__workflow).with("#{GitReflow.git_root_dir}/Workflow").and_return(false)
13
+ return if GitReflow::Config.get('reflow.workflow').to_s.empty?
14
+ allow(GitReflow::Workflows::Core).to receive(:load_workflow).with(GitReflow::Config.get('reflow.workflow')).and_return(false)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -4,6 +4,7 @@ module GitReflow
4
4
 
5
5
  COLOR_FOR_LABEL = {
6
6
  notice: :yellow,
7
+ info: :yellow,
7
8
  error: :red,
8
9
  deliver_halted: :red,
9
10
  review_halted: :red,
@@ -11,8 +12,16 @@ module GitReflow
11
12
  plain: :white
12
13
  }
13
14
 
15
+ class CommandError < StandardError;
16
+ attr_reader :output
17
+ def initialize(output, *args)
18
+ @output = output
19
+ super(*args)
20
+ end
21
+ end
22
+
14
23
  def run(command, options = {})
15
- options = { loud: true, blocking: true }.merge(options)
24
+ options = { loud: true, blocking: true, raise: false }.merge(options)
16
25
 
17
26
  GitReflow.logger.debug "Running... #{command}"
18
27
 
@@ -21,12 +30,13 @@ module GitReflow
21
30
  else
22
31
  output = %x{#{command}}
23
32
 
24
- if options[:blocking] == true && !$?.success?
25
- abort "\"#{command}\" failed to run."
26
- else
27
- puts output if options[:loud] == true
28
- output
33
+ if !$?.success?
34
+ raise CommandError.new(output, "\"#{command}\" failed to run.") if options[:raise] == true
35
+ abort "\"#{command}\" failed to run." if options[:blocking] == true
29
36
  end
37
+
38
+ puts output if options[:loud] == true
39
+ output
30
40
  end
31
41
  end
32
42
 
@@ -1,3 +1,3 @@
1
1
  module GitReflow
2
- VERSION = "0.8.9"
2
+ VERSION = "0.9.3"
3
3
  end
@@ -1,5 +1,6 @@
1
1
  require 'git_reflow/sandbox'
2
2
  require 'git_reflow/git_helpers'
3
+ require 'bundler/inline'
3
4
 
4
5
  module GitReflow
5
6
  module Workflow
@@ -9,20 +10,128 @@ module GitReflow
9
10
 
10
11
  # @nodoc
11
12
  def self.current
12
- workflow_file = GitReflow::Config.get('reflow.workflow')
13
- if workflow_file.length > 0 and File.exists?(workflow_file)
14
- GitReflow.logger.debug "Using workflow: #{workflow_file}"
15
- eval(File.read(workflow_file))
16
- else
17
- GitReflow.logger.debug "Using core workflow..."
18
- GitReflow::Workflows::Core
13
+ return @current unless @current.nil?
14
+ # First look for a "Workflow" file in the current directory, then check
15
+ # for a global Workflow file stored in git-reflow git config.
16
+ loaded_local_workflow = GitReflow::Workflows::Core.load_workflow "#{GitReflow.git_root_dir}/Workflow"
17
+ loaded_global_workflow = false
18
+
19
+ unless loaded_local_workflow
20
+ loaded_global_workflow = GitReflow::Workflows::Core.load_workflow GitReflow::Config.get('reflow.workflow')
19
21
  end
22
+
23
+ @current = GitReflow::Workflows::Core
24
+ end
25
+
26
+ # @nodoc
27
+ # This is primarily a helper method for tests. Due to the nature of how the
28
+ # tests load many different workflows, this helps start fresh and isolate
29
+ # the scenario at hand.
30
+ def self.reset!
31
+ GitReflow.logger.debug "Resetting GitReflow workflow..."
32
+ current.commands = {}
33
+ current.callbacks = { before: {}, after: {}}
34
+ @current = nil
35
+ # We'll need to reload the core class again in order to clear previously
36
+ # eval'd content in the context of the class
37
+ load File.expand_path('../workflows/core.rb', __FILE__)
20
38
  end
21
39
 
22
40
  module ClassMethods
23
41
  include GitReflow::Sandbox
24
42
  include GitReflow::GitHelpers
25
43
 
44
+ def commands
45
+ @commands ||= {}
46
+ end
47
+
48
+ def commands=(command_hash)
49
+ @commands = command_hash
50
+ end
51
+
52
+ def command_docs
53
+ @command_docs ||= {}
54
+ end
55
+
56
+ def command_docs=(command_doc_hash)
57
+ @command_docs = command_doc_hash
58
+ end
59
+
60
+ def callbacks
61
+ @callbacks ||= {
62
+ before: {},
63
+ after: {}
64
+ }
65
+ end
66
+
67
+ def callbacks=(callback_hash)
68
+ @callbacks = callback_hash
69
+ end
70
+
71
+ # Proxy our Config class so that it's available in workflow files
72
+ def git_config
73
+ GitReflow::Config
74
+ end
75
+
76
+ def git_server
77
+ GitReflow.git_server
78
+ end
79
+
80
+ def logger
81
+ GitReflow.logger
82
+ end
83
+
84
+ # Checks for an installed gem, and if none is installed use bundler's
85
+ # inline gemfile to install it.
86
+ #
87
+ # @param name [String] the name of the gem to require as a dependency
88
+ def use_gem(name, *args)
89
+ run("gem list -ie #{name}", loud: false, raise: true)
90
+ logger.info "Using installed gem '#{name}' with options: #{args.inspect}"
91
+ rescue ::GitReflow::Sandbox::CommandError => e
92
+ abort e.message unless e.output =~ /\Afalse/
93
+ logger.info "Installing gem '#{name}' with options: #{args.inspect}"
94
+ say "Installing gem '#{name}'...", :notice
95
+ gemfile do
96
+ source "https://rubygems.org"
97
+ gem name, *args
98
+ end
99
+ end
100
+
101
+ # Use bundler's inline gemfile to install dependencies.
102
+ # See: https://bundler.io/v1.16/guides/bundler_in_a_single_file_ruby_script.html
103
+ #
104
+ # @yield A block to be executed in the context of Bundler's `gemfile` DSL
105
+ def use_gemfile(&block)
106
+ logger.info "Using a custom gemfile"
107
+ gemfile(true, &block)
108
+ end
109
+
110
+ # Loads a pre-defined workflow (FlatMergeWorkflow) from within another
111
+ # Workflow file
112
+ #
113
+ # @param name [String] the name of the Workflow file to use as a basis
114
+ def use(workflow_name)
115
+ if workflows.key?(workflow_name)
116
+ GitReflow.logger.debug "Using Workflow: #{workflow_name}"
117
+ GitReflow::Workflows::Core.load_workflow(workflows[workflow_name])
118
+ else
119
+ GitReflow.logger.error "Tried to use non-existent Workflow: #{workflow_name}"
120
+ end
121
+ end
122
+
123
+ # Keeps track of available workflows when using `.use(workflow_name)`
124
+ # Workflow file
125
+ #
126
+ # @return [Hash, nil] A hash with [workflow_name, workflow_path] as key/value pairs
127
+ def workflows
128
+ return @workflows if @workflows
129
+ workflow_paths = Dir["#{File.dirname(__FILE__)}/workflows/*Workflow"]
130
+ @workflows = {}
131
+ workflow_paths.each { |p| @workflows[File.basename(p)] = p }
132
+ @workflows
133
+ end
134
+
26
135
  # Creates a singleton method on the inlcuded class
27
136
  #
28
137
  # This method will take any number of keyword parameters. If @defaults keyword is provided, and the given
@@ -34,11 +143,24 @@ module GitReflow
34
143
  #
35
144
  # @yield [a:, b:, c:, ...] Invokes the block with an arbitrary number of keyword arguments
36
145
  def command(name, **params, &block)
37
- defaults = params[:defaults] || {}
146
+ params[:flags] ||= {}
147
+ params[:switches] ||= {}
148
+ params[:arguments] ||= {}
149
+ defaults ||= params[:arguments].merge(params[:flags]).merge(params[:switches])
150
+
151
+ # Ensure flags and switches use kebab-case
152
+ kebab_case_keys!(params[:flags])
153
+ kebab_case_keys!(params[:switches])
154
+
155
+ # Register the command with the workflow so that we can properly handle
156
+ # option parsing from the command line
157
+ self.commands[name] = params
158
+ self.command_docs[name] = params
159
+
38
160
  self.define_singleton_method(name) do |**args|
39
161
  args_with_defaults = {}
40
162
  args.each do |name, value|
41
- if "#{value}".length <= 0
163
+ if "#{value}".length <= 0 && !defaults[name].nil?
42
164
  args_with_defaults[name] = defaults[name]
43
165
  else
44
166
  args_with_defaults[name] = value
@@ -51,9 +173,182 @@ module GitReflow
51
173
  end
52
174
  end
53
175
 
176
+ GitReflow.logger.debug "callbacks: #{callbacks.inspect}"
177
+ Array(callbacks[:before][name]).each do |block|
178
+ GitReflow.logger.debug "(before) callback running for `#{name}` command..."
179
+ argument_overrides = block.call(**args_with_defaults) || {}
180
+ args_with_defaults.merge!(argument_overrides) if argument_overrides.is_a?(Hash)
181
+ end
182
+
183
+ GitReflow.logger.info "Running command `#{name}` with args: #{args_with_defaults.inspect}..."
54
184
  block.call(**args_with_defaults)
185
+
186
+ Array(callbacks[:after][name]).each do |block|
187
+ GitReflow.logger.debug "(after) callback running for `#{name}` command..."
188
+ block.call(**args_with_defaults)
189
+ end
190
+ end
191
+ end
192
+
193
+ # Stores a Proc to be called once the command successfully finishes
194
+ #
195
+ # Procs declared with `before` are executed sequentially in the order they are defined in a custom Workflow
196
+ # file.
197
+ #
198
+ # @param name [Symbol] the name of the method to create
199
+ #
200
+ # @yield A block to be executed before the given command. These blocks
201
+ # are executed in the context of `GitReflow::Workflows::Core`
202
+ def before(name, &block)
203
+ name = name.to_sym
204
+ if commands[name].nil?
205
+ GitReflow.logger.error "Attempted to register (before) callback for non-existing command: #{name}"
206
+ else
207
+ GitReflow.logger.debug "(before) callback registered for: #{name}"
208
+ callbacks[:before][name] ||= []
209
+ callbacks[:before][name] << block
55
210
  end
56
211
  end
212
+
213
+ # Stores a Proc to be called once the command successfully finishes
214
+ #
215
+ # Procs declared with `after` are executed sequentially in the order they are defined in a custom Workflow
216
+ # file.
217
+ #
218
+ # @param name [Symbol] the name of the method to create
219
+ #
220
+ # @yield A block to be executed after the given command. These blocks
221
+ # are executed in the context of `GitReflow::Workflows::Core`
222
+ def after(name, &block)
223
+ name = name.to_sym
224
+ if commands[name].nil?
225
+ GitReflow.logger.error "Attempted to register (after) callback for non-existing command: #{name}"
226
+ else
227
+ GitReflow.logger.debug "(after) callback registered for: #{name}"
228
+ callbacks[:after][name] ||= []
229
+ callbacks[:after][name] << block
230
+ end
231
+ end
232
+
233
+ # Creates a singleton method on the inlcuded class
234
+ #
235
+ # This method updates the help text associated with the provided command.
236
+ #
237
+ # @param name [Symbol] the name of the command to add/update help text for
238
+ # @param defaults [Hash] keyword arguments to provide fallbacks for
239
+ def command_help(name, summary:, arguments: {}, flags: {}, switches: {}, description: "")
240
+ command_docs[name] = {
241
+ summary: summary,
242
+ description: description,
243
+ arguments: arguments,
244
+ flags: kebab_case_keys!(flags),
245
+ switches: kebab_case_keys!(switches)
246
+ }
247
+ end
248
+
249
+ # Outputs documentation for the provided command
250
+ #
251
+ # @param name [Symbol] the name of the command to output help text for
252
+ def documentation_for_command(name)
253
+ name = name.to_sym
254
+ docs = command_docs[name]
255
+ if !docs.nil?
256
+ GitReflow.say "USAGE"
257
+ GitReflow.say " git-reflow #{name} [command options] #{docs[:arguments].keys.map {|arg| "[#{arg}]" }.join(' ')}"
258
+ if docs[:arguments].any?
259
+ GitReflow.say "ARGUMENTS"
260
+ docs[:arguments].each do |arg_name, arg_desc|
261
+ default_text = commands[name][:arguments][arg_name].nil? ? "" : "(default: #{commands[name][:arguments][arg_name]}) "
262
+ GitReflow.say " #{arg_name} – #{default_text}#{arg_desc}"
263
+ end
264
+ end
265
+ if docs[:flags].any? || docs[:switches].any?
266
+ cmd = commands[name.to_sym]
267
+ GitReflow.say "COMMAND OPTIONS"
268
+ docs[:flags].each do |flag_name, flag_desc|
269
+ flag_names = ["-#{flag_name.to_s[0]}", "--#{flag_name}"]
270
+ flag_default = cmd[:flags][flag_name]
271
+
272
+ GitReflow.say " #{flag_names} – #{!flag_default.nil? ? "(default: #{flag_default}) " : ""}#{flag_desc}"
273
+ end
274
+ docs[:switches].each do |switch_name, switch_desc|
275
+ switch_names = [switch_name.to_s[0], "-#{switch_name}"].map {|s| "-#{s}" }.join(', ')
276
+ switch_default = cmd[:switches][switch_name]
277
+
278
+ GitReflow.say " #{switch_names} – #{!switch_default.nil? ? "(default: #{switch_default}) " : ""}#{switch_desc}"
279
+ end
280
+ end
281
+ else
282
+ help
283
+ end
284
+ end
285
+
286
+ # Outputs documentation for git-reflow
287
+ def help
288
+ GitReflow.say "NAME"
289
+ GitReflow.say " git-reflow – Git Reflow manages your git workflow."
290
+ GitReflow.say "VERSION"
291
+ GitReflow.say " #{GitReflow::VERSION}"
292
+ GitReflow.say "USAGE"
293
+ GitReflow.say " git-reflow command [command options] [arguments...]"
294
+ GitReflow.say "COMMANDS"
295
+ command_docs.each do |command_name, command_doc|
296
+ GitReflow.say " #{command_name}\t– #{command_doc[:summary]}"
297
+ end
298
+ end
299
+
300
+ # Parses ARGV for the provided git-reflow command name
301
+ #
302
+ # @param name [Symbol, String] the name of the git-reflow command to parse from ARGV
303
+ def parse_command_options!(name)
304
+ name = name.to_sym
305
+ options = {}
306
+ docs = command_docs[name]
307
+ OptionParser.new do |opts|
308
+ opts.banner = "USAGE:\n git-reflow #{name} [command options] #{docs[:arguments].keys.map {|arg| "[#{arg}]" }.join(' ')}"
309
+ opts.separator ""
310
+ opts.separator "COMMAND OPTIONS:" if docs[:flags].any? || docs[:switches].any?
311
+
312
+ self.commands[name][:flags].each do |flag_name, flag_default|
313
+ opts.on("-#{flag_name[0]}", "--#{flag_name} #{flag_name.upcase}", command_docs[name][:flags][flag_name]) do |f|
314
+ options[kebab_to_underscore(flag_name)] = f || flag_default
315
+ end
316
+ end
317
+
318
+ self.commands[name][:switches].each do |switch_name, switch_default|
319
+ opts.on("-#{switch_name[0]}", "--[no-]#{switch_name}", command_docs[name][:switches][switch_name]) do |s|
320
+ options[kebab_to_underscore(switch_name)] = s || switch_default
321
+ end
322
+ end
323
+ end.parse!
324
+
325
+ # Add arguments to optiosn to pass to defined commands
326
+ commands[name][:arguments].each do |arg_name, arg_default|
327
+ options[arg_name] = ARGV.shift || arg_default
328
+ end
329
+ options
330
+ rescue OptionParser::InvalidOption
331
+ documentation_for_command(name)
332
+ exit 1
333
+ end
334
+
335
+ private
336
+
337
+ def kebab_case_keys!(hsh)
338
+ hsh.keys.each do |key_to_update|
339
+ hsh[underscore_to_kebab(key_to_update)] = hsh.delete(key_to_update) if key_to_update =~ /_/
340
+ end
341
+
342
+ hsh
343
+ end
344
+
345
+ def kebab_to_underscore(sym_or_string)
346
+ sym_or_string.to_s.gsub('-', '_').to_sym
347
+ end
348
+
349
+ def underscore_to_kebab(sym_or_string)
350
+ sym_or_string.to_s.gsub('_', '-').to_sym
351
+ end
57
352
  end
58
353
  end
59
354
  end
@@ -0,0 +1,38 @@
1
+ command(:deliver, arguments: { base: "master" }, flags: { merge_method: "merge" }, switches: { force: false, skip_lgtm: false }) do |**params|
2
+ params[:force] = params[:force] || params[:skip_lgtm]
3
+ begin
4
+ existing_pull_request = git_server.find_open_pull_request( from: current_branch, to: params[:base] )
5
+
6
+ if existing_pull_request.nil?
7
+ say "No pull request exists for #{remote_user}:#{current_branch}\nPlease submit your branch for review first with \`git reflow review\`", :deliver_halted
8
+ else
9
+
10
+ if existing_pull_request.good_to_merge?(force: params[:force])
11
+ # displays current status and prompts user for confirmation
12
+ self.status destination_branch: params[:base]
13
+ existing_pull_request.merge!(params)
14
+ else
15
+ say existing_pull_request.rejection_message, :deliver_halted
16
+ end
17
+
18
+ end
19
+
20
+ rescue Github::Error::UnprocessableEntity => e
21
+ say "Github Error: #{e.inspect}", :error
22
+ end
23
+ end
24
+ command_help(
25
+ :deliver,
26
+ summary: "deliver your feature branch",
27
+ arguments: {
28
+ base: "the branch to merge this feature into"
29
+ },
30
+ flags: {
31
+ merge_method: "how you want your feature branch merged ('merge', 'squash', 'rebase')"
32
+ },
33
+ switches: {
34
+ force: "skip the lgtm checks and deliver your feature branch",
35
+ skip_lgtm: "skip the lgtm checks and deliver your feature branch"
36
+ },
37
+ description: "merge your feature branch down to your base branch, and cleanup your feature branch"
38
+ )