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.
- checksums.yaml +5 -5
- data/.github/workflows/multi-ruby-tests.yml +33 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +2 -0
- data/.ruby-version +1 -0
- data/Appraisals +1 -6
- data/CHANGELOG.md +466 -348
- data/Gemfile.lock +99 -72
- data/LICENSE +20 -20
- data/README.md +481 -0
- data/Rakefile +15 -8
- data/Workflow +3 -0
- data/_config.yml +1 -0
- data/bin/console +7 -7
- data/bin/setup +6 -6
- data/exe/git-reflow +20 -36
- data/git_reflow.gemspec +26 -30
- data/lib/git_reflow.rb +3 -15
- data/lib/git_reflow/config.rb +48 -13
- data/lib/git_reflow/git_helpers.rb +69 -22
- data/lib/git_reflow/git_server.rb +63 -63
- data/lib/git_reflow/git_server/base.rb +68 -68
- data/lib/git_reflow/git_server/bit_bucket.rb +101 -101
- data/lib/git_reflow/git_server/bit_bucket/pull_request.rb +84 -84
- data/lib/git_reflow/git_server/git_hub.rb +53 -41
- data/lib/git_reflow/git_server/git_hub/pull_request.rb +16 -14
- data/lib/git_reflow/git_server/pull_request.rb +4 -2
- data/lib/git_reflow/merge_error.rb +9 -9
- data/lib/git_reflow/rspec.rb +3 -2
- data/lib/git_reflow/rspec/command_line_helpers.rb +23 -6
- data/lib/git_reflow/rspec/stub_helpers.rb +13 -13
- data/lib/git_reflow/rspec/workflow_helpers.rb +18 -0
- data/lib/git_reflow/sandbox.rb +16 -6
- data/lib/git_reflow/version.rb +1 -1
- data/lib/git_reflow/workflow.rb +304 -9
- data/lib/git_reflow/workflows/FlatMergeWorkflow +38 -0
- data/lib/git_reflow/workflows/core.rb +364 -238
- data/spec/fixtures/authentication_failure.json +3 -0
- data/spec/fixtures/awesome_workflow.rb +3 -7
- data/spec/fixtures/git/git_config +7 -7
- data/spec/fixtures/issues/comment.json.erb +27 -27
- data/spec/fixtures/issues/comments.json +29 -29
- data/spec/fixtures/issues/comments.json.erb +15 -15
- data/spec/fixtures/pull_requests/comment.json.erb +45 -45
- data/spec/fixtures/pull_requests/comments.json +47 -47
- data/spec/fixtures/pull_requests/comments.json.erb +15 -15
- data/spec/fixtures/pull_requests/commits.json +29 -29
- data/spec/fixtures/pull_requests/external_pull_request.json +145 -145
- data/spec/fixtures/pull_requests/pull_request.json +142 -142
- data/spec/fixtures/pull_requests/pull_request.json.erb +142 -142
- data/spec/fixtures/pull_requests/pull_request_branch_nonexistent_error.json +32 -0
- data/spec/fixtures/pull_requests/pull_request_exists_error.json +32 -32
- data/spec/fixtures/pull_requests/pull_requests.json +136 -136
- data/spec/fixtures/repositories/commit.json +53 -53
- data/spec/fixtures/repositories/commit.json.erb +53 -53
- data/spec/fixtures/repositories/commits.json.erb +13 -13
- data/spec/fixtures/repositories/statuses.json +31 -31
- data/spec/fixtures/users/user.json +32 -0
- data/spec/lib/git_reflow/git_helpers_spec.rb +115 -12
- data/spec/lib/git_reflow/git_server/bit_bucket_spec.rb +81 -81
- data/spec/lib/git_reflow/git_server/git_hub/pull_request_spec.rb +10 -10
- data/spec/lib/git_reflow/git_server/git_hub_spec.rb +77 -3
- data/spec/lib/git_reflow/git_server/pull_request_spec.rb +9 -3
- data/spec/lib/git_reflow/git_server_spec.rb +101 -101
- data/spec/lib/git_reflow/sandbox_spec.rb +1 -1
- data/spec/lib/git_reflow/workflow_spec.rb +304 -59
- data/spec/lib/git_reflow/workflows/core_spec.rb +225 -67
- data/spec/lib/git_reflow/workflows/flat_merge_spec.rb +71 -59
- data/spec/lib/git_reflow_spec.rb +2 -25
- data/spec/spec_helper.rb +3 -0
- data/spec/support/fixtures.rb +54 -54
- data/spec/support/github_helpers.rb +99 -109
- data/spec/support/mock_pull_request.rb +17 -17
- data/spec/support/web_mocks.rb +39 -39
- metadata +51 -74
- data/README.rdoc +0 -461
- data/circle.yml +0 -26
- data/lib/git_reflow/commands/deliver.rb +0 -10
- data/lib/git_reflow/commands/refresh.rb +0 -20
- data/lib/git_reflow/commands/review.rb +0 -13
- data/lib/git_reflow/commands/setup.rb +0 -11
- data/lib/git_reflow/commands/stage.rb +0 -9
- data/lib/git_reflow/commands/start.rb +0 -18
- data/lib/git_reflow/commands/status.rb +0 -7
- data/lib/git_reflow/os_detector.rb +0 -23
- data/lib/git_reflow/workflows/flat_merge.rb +0 -10
- 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
|
data/lib/git_reflow/sandbox.rb
CHANGED
@@ -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
|
25
|
-
|
26
|
-
|
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
|
|
data/lib/git_reflow/version.rb
CHANGED
data/lib/git_reflow/workflow.rb
CHANGED
@@ -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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
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
|
+
)
|