qb 0.3.13 → 0.3.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/doc/getting_started.md +2 -0
- data/doc/qb_roles.md +4 -109
- data/doc/qb_roles/metadata.md +221 -0
- data/exe/qb +23 -11
- data/lib/qb.rb +1 -3
- data/lib/qb/cli.rb +97 -85
- data/lib/qb/options.rb +6 -6
- data/lib/qb/role/default_dir.rb +28 -28
- data/lib/qb/util.rb +3 -2
- data/lib/qb/version.rb +1 -1
- data/qb.gemspec +22 -9
- data/roles/nrser.rbenv_gem/tasks/main.yml +3 -3
- data/roles/qb/gem/build/defaults/main.yml +12 -0
- data/roles/{qb.build_gem → qb/gem/build}/meta/main.yml +0 -0
- data/roles/qb/gem/build/meta/qb.yml +42 -0
- data/roles/qb/gem/build/tasks/main.yml +61 -0
- data/roles/{qb.install_gem → qb/gem/install}/defaults/main.yml +1 -1
- data/roles/qb/gem/install/meta/main.yml +17 -0
- data/roles/{qb.install_gem → qb/gem/install}/meta/qb.yml +5 -2
- data/roles/{qb.install_gem → qb/gem/install}/tasks/main.yml +0 -0
- data/roles/qb/git/ignore/files/gitignore/Eagle.gitignore +9 -1
- data/roles/qb/git/ignore/files/gitignore/Global/Eclipse.gitignore +3 -0
- data/roles/qb/git/ignore/files/gitignore/Go.gitignore +1 -0
- data/roles/qb/git/ignore/files/gitignore/Node.gitignore +2 -0
- data/roles/qb/git/ignore/files/gitignore/Python.gitignore +7 -19
- data/roles/qb/git/ignore/files/gitignore/Python/Packaging.gitignore +25 -0
- data/roles/qb/git/ignore/files/gitignore/Ruby.gitignore +15 -5
- data/roles/qb/git/ignore/files/gitignore/Umbraco.gitignore +2 -2
- data/roles/qb/git/ignore/files/gitignore/VisualStudio.gitignore +4 -0
- data/roles/qb/role/qb/templates/qb.yml.j2 +19 -39
- data/roles/qb/role/templates/README.md.j2 +1 -1
- data/roles/qb/role/templates/defaults/main.yml.j2 +6 -1
- data/roles/qb/role/templates/filter_plugins/filters.py.j2 +5 -5
- data/roles/qb/role/templates/handlers/main.yml.j2 +3 -1
- data/roles/qb/role/templates/meta/main.yml.j2 +4 -2
- data/roles/qb/role/templates/tasks/main.yml.j2 +3 -1
- data/roles/qb/role/templates/vars/main.yml.j2 +3 -1
- metadata +43 -34
- data/roles/qb.build_gem/defaults/main.yml +0 -2
- data/roles/qb.build_gem/tasks/main.yml +0 -27
- data/roles/qb.install_gem/meta/main.yml +0 -12
data/lib/qb/cli.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Requirements
|
2
4
|
# =======================================================================
|
3
5
|
|
@@ -32,101 +34,111 @@ module QB::CLI
|
|
32
34
|
|
33
35
|
include SemanticLogger::Loggable
|
34
36
|
|
35
|
-
|
36
|
-
#
|
37
|
+
|
38
|
+
# Constants
|
39
|
+
# ============================================================================
|
40
|
+
|
41
|
+
# CLI args that common to all commands that enable debug output
|
37
42
|
#
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
if default
|
66
|
-
puts "DEFAULT #{ default.to_s }".indent
|
67
|
-
end
|
68
|
-
|
69
|
-
$stdout.write '> '
|
70
|
-
|
71
|
-
value = gets.chomp
|
72
|
-
|
73
|
-
QB.debug "User input", value
|
74
|
-
|
75
|
-
if value == '' && default != NRSER::NO_ARG
|
76
|
-
puts <<-END.dedent
|
77
|
-
|
78
|
-
Using default value #{ default.to_s }
|
79
|
-
|
80
|
-
END
|
81
|
-
|
82
|
-
return default
|
83
|
-
end
|
84
|
-
|
85
|
-
begin
|
86
|
-
type.from_s value
|
87
|
-
rescue TypeError => e
|
88
|
-
puts <<-END.dedent
|
89
|
-
Input value #{ value.inspect } failed to satisfy type
|
90
|
-
|
91
|
-
#{ type.to_s }
|
92
|
-
|
93
|
-
END
|
94
|
-
else
|
95
|
-
break value
|
96
|
-
end
|
97
|
-
|
98
|
-
end # loop
|
43
|
+
# @return [Array<String>]
|
44
|
+
#
|
45
|
+
DEBUG_ARGS = ['-D', '--DEBUG'].freeze
|
46
|
+
|
47
|
+
|
48
|
+
def self.set_debug! args
|
49
|
+
if DEBUG_ARGS.any? {|arg| args.include? arg}
|
50
|
+
QB::Util::Logging.setup level: :debug
|
51
|
+
DEBUG_ARGS.each {|arg| args.delete arg}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# @todo Document ask method.
|
57
|
+
#
|
58
|
+
# @param [type] arg_name
|
59
|
+
# @todo Add name param description.
|
60
|
+
#
|
61
|
+
# @return [return_type]
|
62
|
+
# @todo Document return value.
|
63
|
+
#
|
64
|
+
def self.ask name:,
|
65
|
+
description: nil,
|
66
|
+
type:,
|
67
|
+
default: NRSER::NO_ARG
|
68
|
+
puts
|
99
69
|
|
100
|
-
|
70
|
+
value = loop do
|
101
71
|
|
102
|
-
|
72
|
+
puts "Enter value for #{ name }"
|
103
73
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
74
|
+
if description
|
75
|
+
puts description.indent
|
76
|
+
end
|
77
|
+
|
78
|
+
puts "TYPE #{ type.to_s }".indent
|
79
|
+
|
80
|
+
if default
|
81
|
+
puts "DEFAULT #{ default.to_s }".indent
|
82
|
+
end
|
83
|
+
|
84
|
+
$stdout.write '> '
|
85
|
+
|
86
|
+
value = gets.chomp
|
87
|
+
|
88
|
+
QB.debug "User input", value
|
89
|
+
|
90
|
+
if value == '' && default != NRSER::NO_ARG
|
91
|
+
puts <<-END.dedent
|
92
|
+
|
93
|
+
Using default value #{ default.to_s }
|
94
|
+
|
95
|
+
END
|
96
|
+
|
97
|
+
return default
|
98
|
+
end
|
99
|
+
|
100
|
+
begin
|
101
|
+
type.from_s value
|
102
|
+
rescue TypeError => e
|
103
|
+
puts <<-END.dedent
|
104
|
+
Input value #{ value.inspect } failed to satisfy type
|
105
|
+
|
106
|
+
#{ type.to_s }
|
107
|
+
|
108
|
+
END
|
112
109
|
else
|
113
|
-
|
110
|
+
break value
|
114
111
|
end
|
115
112
|
|
116
|
-
|
117
|
-
description: option.description,
|
118
|
-
default: default
|
119
|
-
# type:
|
120
|
-
end
|
113
|
+
end # loop
|
121
114
|
|
115
|
+
puts "Using value #{ value.inspect }"
|
122
116
|
|
123
|
-
|
124
|
-
options.select { |opt| opt.value.nil? }.each { |option|
|
125
|
-
ask_for_option role: role, option: option
|
126
|
-
}
|
127
|
-
end # #ask_for_options
|
117
|
+
return value
|
128
118
|
|
119
|
+
end # .ask
|
120
|
+
|
121
|
+
|
122
|
+
def self.ask_for_option role:, option:
|
123
|
+
default = if role.defaults.key?(option.var_name)
|
124
|
+
role.defaults[option.var_name]
|
125
|
+
elsif option.required?
|
126
|
+
NRSER::NO_ARG
|
127
|
+
else
|
128
|
+
nil
|
129
|
+
end
|
129
130
|
|
130
|
-
|
131
|
+
ask name: option.name,
|
132
|
+
description: option.description,
|
133
|
+
default: default
|
134
|
+
# type:
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
def self.ask_for_options role:, options:
|
139
|
+
options.select { |opt| opt.value.nil? }.each { |option|
|
140
|
+
ask_for_option role: role, option: option
|
141
|
+
}
|
142
|
+
end # .ask_for_options
|
131
143
|
|
132
144
|
end # module QB::CLI
|
data/lib/qb/options.rb
CHANGED
@@ -20,13 +20,13 @@ module QB
|
|
20
20
|
# =======================================================================
|
21
21
|
|
22
22
|
QB_DEFAULTS = {
|
23
|
-
'hosts' => ['localhost'],
|
23
|
+
'hosts' => ['localhost'].freeze,
|
24
24
|
'facts' => true,
|
25
|
-
'print' => [
|
25
|
+
'print' => [].freeze,
|
26
26
|
'verbose' => false,
|
27
27
|
'run' => true,
|
28
28
|
'ask' => false,
|
29
|
-
}
|
29
|
+
}.freeze
|
30
30
|
|
31
31
|
# appended on the end of an `opts.on` call to create a newline after
|
32
32
|
# the option (making the help output a bit easier to read)
|
@@ -210,7 +210,7 @@ module QB
|
|
210
210
|
end
|
211
211
|
}
|
212
212
|
}
|
213
|
-
else
|
213
|
+
else
|
214
214
|
raise QB::Role::MetadataError,
|
215
215
|
"bad type for option #{ option.meta_name }: #{ option.meta['type'].inspect }"
|
216
216
|
end
|
@@ -284,7 +284,7 @@ module QB
|
|
284
284
|
options[option.cli_name] = option
|
285
285
|
end
|
286
286
|
end # each var
|
287
|
-
end # add
|
287
|
+
end # add
|
288
288
|
|
289
289
|
# destructively removes options from `@argv` and populates ansible, role,
|
290
290
|
# and qb option hashes.
|
@@ -531,4 +531,4 @@ module QB
|
|
531
531
|
# end protected
|
532
532
|
|
533
533
|
end # Options
|
534
|
-
end # QB
|
534
|
+
end # QB
|
data/lib/qb/role/default_dir.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
##
|
2
|
-
# {QB::Role} methods for finding the default directory for
|
2
|
+
# {QB::Role} methods for finding the default directory for
|
3
3
|
# running a role when one is not provided in the CLI.
|
4
4
|
#
|
5
|
-
# Broken out from the main `//lib/qb/role.rb` file because it was starting to
|
5
|
+
# Broken out from the main `//lib/qb/role.rb` file because it was starting to
|
6
6
|
# get long and unwieldy.
|
7
7
|
#
|
8
8
|
##
|
@@ -17,6 +17,7 @@ require 'pathname'
|
|
17
17
|
|
18
18
|
# Deps
|
19
19
|
# -----------------------------------------------------------------------
|
20
|
+
require 'nrser'
|
20
21
|
|
21
22
|
# Project / Package
|
22
23
|
# -----------------------------------------------------------------------
|
@@ -25,7 +26,6 @@ require 'pathname'
|
|
25
26
|
# Refinements
|
26
27
|
# =======================================================================
|
27
28
|
|
28
|
-
require 'nrser/refinements'
|
29
29
|
using NRSER
|
30
30
|
|
31
31
|
|
@@ -46,11 +46,11 @@ class QB::Role
|
|
46
46
|
# Gets the default `qb_dir` value, raising an error if the role doesn't
|
47
47
|
# define how to get one or there is a problem getting it.
|
48
48
|
#
|
49
|
-
# It uses a "strategy" value found at the 'default_dir' key in the role's
|
50
|
-
# QB metadata (in `<role_path>/meta/qb.yml` or returned by a
|
49
|
+
# It uses a "strategy" value found at the 'default_dir' key in the role's
|
50
|
+
# QB metadata (in `<role_path>/meta/qb.yml` or returned by a
|
51
51
|
# `<role_path>/meta/qb` executable).
|
52
52
|
#
|
53
|
-
# See the {file:doc/qb_roles/metadata/default_dir.md default_dir}
|
53
|
+
# See the {file:doc/qb_roles/metadata/default_dir.md default_dir}
|
54
54
|
# documentation for details on the accepted strategy values.
|
55
55
|
#
|
56
56
|
# @param [String | Pathname] cwd:
|
@@ -65,7 +65,7 @@ class QB::Role
|
|
65
65
|
# The directory to target.
|
66
66
|
#
|
67
67
|
# @raise
|
68
|
-
# When we can't determine a directory due to role meta settings or target
|
68
|
+
# When we can't determine a directory due to role meta settings or target
|
69
69
|
# system state.
|
70
70
|
#
|
71
71
|
def default_dir cwd, options
|
@@ -77,7 +77,7 @@ class QB::Role
|
|
77
77
|
options: options
|
78
78
|
|
79
79
|
default_dir_for(
|
80
|
-
|
80
|
+
strategy: self.meta['default_dir'],
|
81
81
|
cwd: cwd,
|
82
82
|
options: options
|
83
83
|
).to_pn
|
@@ -102,8 +102,8 @@ class QB::Role
|
|
102
102
|
# @return [return_type]
|
103
103
|
# @todo Document return value.
|
104
104
|
#
|
105
|
-
def default_dir_for
|
106
|
-
case
|
105
|
+
def default_dir_for strategy:, cwd:, options:
|
106
|
+
case strategy
|
107
107
|
when nil
|
108
108
|
# there is no get_dir info in meta/qb.yml, can't get the dir
|
109
109
|
raise QB::UserInputError.new binding.erb <<-END
|
@@ -116,7 +116,7 @@ class QB::Role
|
|
116
116
|
|
117
117
|
qb run <%= self.name %> DIRECTORY
|
118
118
|
|
119
|
-
or, if you are the developer of the <%= self.name %> role, set a
|
119
|
+
or, if you are the developer of the <%= self.name %> role, set a
|
120
120
|
non-null value for the 'default_dir' key in
|
121
121
|
|
122
122
|
<%= self.meta_path %>
|
@@ -124,8 +124,8 @@ class QB::Role
|
|
124
124
|
END
|
125
125
|
|
126
126
|
when false
|
127
|
-
# this method should not get called when the
|
128
|
-
# section is skipped in exe/qb when `default_dir = false`)
|
127
|
+
# this method should not get called when the strategy is `false` (an
|
128
|
+
# entire section is skipped in exe/qb when `default_dir = false`)
|
129
129
|
raise QB::StateError.squished <<-END
|
130
130
|
role does not use default directory (meta/qb.yml:default_dir = false)
|
131
131
|
END
|
@@ -141,11 +141,11 @@ class QB::Role
|
|
141
141
|
when Hash
|
142
142
|
logger.debug "qb meta option is a Hash"
|
143
143
|
|
144
|
-
unless
|
145
|
-
raise "#{ meta_path.to_s }:default_dir invalid: #{
|
144
|
+
unless strategy.length == 1
|
145
|
+
raise "#{ meta_path.to_s }:default_dir invalid: #{ strategy.inspect }"
|
146
146
|
end
|
147
147
|
|
148
|
-
hash_key, hash_value =
|
148
|
+
hash_key, hash_value = strategy.first
|
149
149
|
|
150
150
|
case hash_key
|
151
151
|
when 'exe'
|
@@ -172,21 +172,21 @@ class QB::Role
|
|
172
172
|
end
|
173
173
|
|
174
174
|
when 'find_up'
|
175
|
-
|
175
|
+
rel_path = hash_value
|
176
176
|
|
177
|
-
unless
|
178
|
-
raise "find_up
|
177
|
+
unless rel_path.is_a? String
|
178
|
+
raise "find_up relative path or glob must be string, found #{ rel_path.inspect }"
|
179
179
|
end
|
180
180
|
|
181
|
-
|
181
|
+
logger.debug "found 'find_up' strategy", rel_path: rel_path
|
182
182
|
|
183
|
-
|
183
|
+
cwd.to_pn.find_up! rel_path
|
184
184
|
|
185
185
|
when 'from_role'
|
186
186
|
# Get the value from another role, presumably one this role includes
|
187
187
|
|
188
188
|
default_dir_for \
|
189
|
-
|
189
|
+
strategy: QB::Role.require( hash_value ).meta['default_dir'],
|
190
190
|
cwd: cwd,
|
191
191
|
options: options
|
192
192
|
|
@@ -200,9 +200,9 @@ class QB::Role
|
|
200
200
|
|
201
201
|
contains an invalid default directory strategy
|
202
202
|
|
203
|
-
<%=
|
203
|
+
<%= strategy.pretty_inspect %>
|
204
204
|
|
205
|
-
The key <%= hash_key.inspect %> does not correspond to a recognized
|
205
|
+
The key <%= hash_key.inspect %> does not correspond to a recognized
|
206
206
|
form.
|
207
207
|
|
208
208
|
Valid forms are:
|
@@ -215,15 +215,15 @@ class QB::Role
|
|
215
215
|
end
|
216
216
|
|
217
217
|
when Array
|
218
|
-
|
219
|
-
default_dir_for
|
218
|
+
strategy.try_find do |candidate|
|
219
|
+
default_dir_for strategy: candidate, cwd: cwd, options: options
|
220
220
|
end
|
221
221
|
|
222
222
|
else
|
223
223
|
raise QB::Role::MetadataError.new binding.erb <<-END
|
224
|
-
bad default_dir
|
224
|
+
bad default_dir strategy: <%= strategy %>
|
225
225
|
END
|
226
|
-
end # case
|
226
|
+
end # case strategy
|
227
227
|
end # .default_dir_for
|
228
228
|
|
229
229
|
# end protected
|
data/lib/qb/util.rb
CHANGED
@@ -13,7 +13,7 @@ module QB
|
|
13
13
|
string.split(/[\W_\-\/]+/).reject {|w| w.empty?}
|
14
14
|
end # .words
|
15
15
|
|
16
|
-
# see if words from an input match words
|
16
|
+
# see if words from an input match words
|
17
17
|
def self.words_start_with? full_string, input
|
18
18
|
# QB.debug "does #{ input } match #{ full_string }?"
|
19
19
|
|
@@ -84,6 +84,7 @@ module QB
|
|
84
84
|
Pathname.new contracted
|
85
85
|
end
|
86
86
|
|
87
|
+
|
87
88
|
# find `filename` in `from` or closest parent directory.
|
88
89
|
#
|
89
90
|
# @param [String] filename
|
@@ -96,7 +97,7 @@ module QB
|
|
96
97
|
# When `true`, a {QB::FSStateError} will be raised if no file is found
|
97
98
|
# (default behavior).
|
98
99
|
#
|
99
|
-
# This is something of a legacy behavior - I think it would be better
|
100
|
+
# This is something of a legacy behavior - I think it would be better
|
100
101
|
# to have {find_up} return `nil` in that case and add a `find_up!`
|
101
102
|
# method that raises on not found. But I'm not going to do it right now.
|
102
103
|
#
|
data/lib/qb/version.rb
CHANGED
data/qb.gemspec
CHANGED
@@ -105,6 +105,8 @@ Gem::Specification.new do |spec|
|
|
105
105
|
spec.homepage = "https://github.com/nrser/qb"
|
106
106
|
spec.license = "MIT"
|
107
107
|
|
108
|
+
spec.required_ruby_version = '>= 2.3.0'
|
109
|
+
|
108
110
|
|
109
111
|
# Files
|
110
112
|
# ============================================================================
|
@@ -160,6 +162,7 @@ Gem::Specification.new do |spec|
|
|
160
162
|
spec.executables = spec.files.grep %r{^#{ spec.bindir }/[^\.]},
|
161
163
|
&File.method( :basename )
|
162
164
|
|
165
|
+
# Where that source be, standard `//lib` directory
|
163
166
|
spec.require_paths = ["lib"]
|
164
167
|
|
165
168
|
|
@@ -169,20 +172,30 @@ Gem::Specification.new do |spec|
|
|
169
172
|
# Development Dependencies
|
170
173
|
# ----------------------------------------------------------------------------
|
171
174
|
|
172
|
-
spec.add_development_dependency "bundler",
|
173
|
-
spec.add_development_dependency "rake",
|
174
|
-
|
175
|
-
|
176
|
-
spec.add_development_dependency "
|
177
|
-
|
178
|
-
|
175
|
+
spec.add_development_dependency "bundler", '~> 1.16', '>= 1.16.1'
|
176
|
+
spec.add_development_dependency "rake", '~> 12.3'
|
177
|
+
|
178
|
+
# Testing with `rspec`
|
179
|
+
spec.add_development_dependency "rspec", '~> 3.7'
|
180
|
+
|
181
|
+
# Doc site generation with `yard`
|
182
|
+
spec.add_development_dependency "yard", '~> 0.9.12'
|
183
|
+
|
184
|
+
# These, along with `//.yardopts` config, are *supposed to* result in
|
185
|
+
# rendering markdown files and doc comments using
|
186
|
+
# GitHub-Flavored Markdown (GFM), though I'm not sure if it's totally working
|
187
|
+
spec.add_development_dependency "redcarpet", '~> 3.4'
|
188
|
+
spec.add_development_dependency "github-markup", '~> 1.6'
|
189
|
+
|
190
|
+
# Nicer REPL experience
|
191
|
+
spec.add_development_dependency "pry", '~> 0.10.4'
|
179
192
|
|
180
193
|
|
181
194
|
# Runtime Dependencies
|
182
195
|
# ----------------------------------------------------------------------------
|
183
196
|
|
184
197
|
spec.add_dependency "cmds", '~> 0.0', ">= 0.2.4"
|
185
|
-
spec.add_dependency "nrser", '~> 0.
|
198
|
+
spec.add_dependency "nrser", '~> 0.1', ">= 0.1.0"
|
186
199
|
spec.add_dependency "nrser-extras", '~> 0.0', ">= 0.0.3"
|
187
200
|
spec.add_dependency "state_mate", '~> 0.0', ">= 0.1.0"
|
188
201
|
|
@@ -199,7 +212,7 @@ Gem::Specification.new do |spec|
|
|
199
212
|
spec.add_dependency 'awesome_print', '~> 1.8'
|
200
213
|
|
201
214
|
# Ruby lib wrapping `git` binary system calls for use in {QB::Repo::Git}
|
202
|
-
spec.add_dependency 'git',
|
215
|
+
spec.add_dependency 'git', '~> 1.3'
|
203
216
|
|
204
217
|
|
205
218
|
# Development-Only Extra Metadata
|