qb 0.1.60 → 0.1.61
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 +4 -4
- data/lib/qb/options.rb +6 -6
- data/lib/qb/role.rb +20 -33
- data/lib/qb/role/errors.rb +30 -0
- data/lib/qb/version.rb +1 -1
- data/library/path_facts +304 -0
- data/plugins/lookup_plugins/every.py +165 -0
- data/roles/qb.facts/defaults/main.yml +3 -0
- data/roles/{qb.yarn → qb.facts}/meta/main.yml +1 -1
- data/roles/{qb.yarn → qb.facts}/meta/qb.yml +21 -26
- data/roles/qb.facts/tasks/main.yml +10 -0
- data/roles/qb.git_repo/defaults/main.yml +1 -0
- data/roles/qb.git_repo/meta/main.yml +1 -9
- data/roles/qb.git_repo/tasks/main.yml +26 -1
- data/roles/qb.qb_role/templates/qb.yml.j2 +8 -0
- data/roles/qb.role/defaults/main.yml +1 -1
- data/roles/qb.role/tasks/main.yml +1 -1
- data/roles/qb.yarn_release/defaults/main.yml +4 -0
- data/roles/{qb.release_yarn → qb.yarn_release}/meta/main.yml +1 -1
- data/roles/{qb.release_yarn → qb.yarn_release}/meta/qb.yml +1 -1
- data/roles/qb.yarn_release/tasks/main.yml +73 -0
- data/roles/qb.yarn_setup/defaults/main.yml +11 -0
- data/roles/qb.yarn_setup/meta/main.yml +8 -0
- data/roles/qb.yarn_setup/meta/qb.yml +100 -0
- data/roles/qb.yarn_setup/tasks/distribution/MacOSX/brew_create.yml +59 -0
- data/roles/qb.yarn_setup/tasks/distribution/MacOSX/main.yml +42 -0
- data/roles/qb.yarn_setup/tasks/main.yml +11 -0
- data/roles/qb.yarn_setup/templates/yarn@M.m.p.rb.j2 +22 -0
- metadata +20 -12
- data/lib/qb/options/errors.rb +0 -11
- data/roles/qb.release_yarn/defaults/main.yml +0 -4
- data/roles/qb.release_yarn/tasks/main.yml +0 -73
- data/roles/qb.yarn/defaults/main.yml +0 -5
- data/roles/qb.yarn/tasks/distribution/MacOSX.yml +0 -7
- data/roles/qb.yarn/tasks/main.yml +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac5214f10fb124d147d91b4618033b426d389558
|
4
|
+
data.tar.gz: f051f2779ee56a8aa1747642080c99e08e567f02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2102fe8bf8be9a227dc3f5644c31c2e8d0ae57b9aa30dc4578914531c569afc05c71dbed9449f8ec0cda4c4a060203f0c1db91260fd9c423c1a3f6ede0a76323
|
7
|
+
data.tar.gz: c992b406840a86966b0b8d8b9e59c215255b23245c0f764db261dfb666639d24a9f30f30ecc5b6ca258ef8b80333bd93949f54023ccd944f68a3ab677cb1970b
|
data/lib/qb/options.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'optparse'
|
2
2
|
|
3
|
-
require_relative "
|
3
|
+
require_relative "role/errors"
|
4
4
|
require_relative "options/option"
|
5
5
|
|
6
6
|
module QB
|
@@ -88,7 +88,7 @@ module QB
|
|
88
88
|
when String
|
89
89
|
include_path + [include_meta['as']]
|
90
90
|
else
|
91
|
-
raise QB::
|
91
|
+
raise QB::Role::MetadataError.new,
|
92
92
|
"bad 'as' value: #{ include_meta.inspect }"
|
93
93
|
end
|
94
94
|
else
|
@@ -125,7 +125,7 @@ module QB
|
|
125
125
|
else
|
126
126
|
ruby_type = case option.meta['type']
|
127
127
|
when nil
|
128
|
-
raise QB::
|
128
|
+
raise QB::Role::MetadataError,
|
129
129
|
"must provide type in qb metadata for option #{ option.meta_name }"
|
130
130
|
when 'string', 'str'
|
131
131
|
String
|
@@ -140,17 +140,17 @@ module QB
|
|
140
140
|
if option.meta['type']['one_of'].include? value
|
141
141
|
value
|
142
142
|
else
|
143
|
-
raise QB::
|
143
|
+
raise QB::Role::MetadataError,
|
144
144
|
"option '#{ option.cli_name }' must be one of: #{ option.meta['type']['one_of'].join(', ') }"
|
145
145
|
end
|
146
146
|
}
|
147
147
|
klass
|
148
148
|
else
|
149
|
-
raise QB::
|
149
|
+
raise QB::Role::MetadataError,
|
150
150
|
"bad type for option #{ option.meta_name }: #{ option.meta['type'].inspect }"
|
151
151
|
end
|
152
152
|
else
|
153
|
-
raise QB::
|
153
|
+
raise QB::Role::MetadataError,
|
154
154
|
"bad type for option #{ option.meta_name }: #{ option.meta['type'].inspect }"
|
155
155
|
end
|
156
156
|
|
data/lib/qb/role.rb
CHANGED
@@ -3,6 +3,8 @@ require 'cmds'
|
|
3
3
|
require 'parseconfig'
|
4
4
|
require 'nrser/refinements'
|
5
5
|
|
6
|
+
require_relative 'role/errors'
|
7
|
+
|
6
8
|
using NRSER
|
7
9
|
|
8
10
|
module QB
|
@@ -37,36 +39,7 @@ module QB
|
|
37
39
|
# the path qb metadata was load from. `nil` if it's never been loaded
|
38
40
|
# or doesn't exist.
|
39
41
|
attr_reader :meta_path
|
40
|
-
|
41
|
-
# errors
|
42
|
-
# =======================================================================
|
43
|
-
|
44
|
-
# base for errors in the module, extends QB:Error
|
45
|
-
class Error < QB::Error
|
46
|
-
end
|
47
|
-
|
48
|
-
# raised by `.require` when no roles match input
|
49
|
-
class NoMatchesError < Error
|
50
|
-
attr_accessor :input
|
51
|
-
|
52
|
-
def initialize input
|
53
|
-
@input = input
|
54
|
-
|
55
|
-
super "no roles match input #{ @input.inspect }"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# raised by `.require` when multiple roles match
|
60
|
-
class MultipleMatchesError < Error
|
61
|
-
attr_accessor :input, :matches
|
62
|
-
|
63
|
-
def initialize input, matches
|
64
|
-
@input = input
|
65
|
-
@matches = matches
|
66
|
-
|
67
|
-
super "mutiple roles match input #{ @input.inspect }:\n#{ @matches.join("\n") }"
|
68
|
-
end
|
69
|
-
end
|
42
|
+
|
70
43
|
|
71
44
|
# static role utils
|
72
45
|
# =======================================================================
|
@@ -280,7 +253,7 @@ module QB
|
|
280
253
|
when String
|
281
254
|
current_include_path + [option_meta['as']]
|
282
255
|
else
|
283
|
-
raise QB::
|
256
|
+
raise QB::Role::MetadataError.new,
|
284
257
|
"bad 'as' value: #{ option_meta.inspect }"
|
285
258
|
end
|
286
259
|
else
|
@@ -361,9 +334,23 @@ module QB
|
|
361
334
|
#
|
362
335
|
# if `cache` is true caches it as `@meta`
|
363
336
|
#
|
364
|
-
def load_meta cache = true
|
337
|
+
def load_meta cache = true
|
365
338
|
meta = if @meta_path.extname == '.yml'
|
366
|
-
|
339
|
+
contents = begin
|
340
|
+
@meta_path.read
|
341
|
+
rescue Exception => error
|
342
|
+
raise QB::Role::MetadataError,
|
343
|
+
"Failed to read metadata file at #{ @meta_path.to_s }, " +
|
344
|
+
"error: #{ error.inspect }"
|
345
|
+
end
|
346
|
+
|
347
|
+
begin
|
348
|
+
YAML.load(contents) || {}
|
349
|
+
rescue Exception => error
|
350
|
+
raise QB::Role::MetadataError,
|
351
|
+
"Failed to load metadata YAML from #{ @meta_path.to_s }, " +
|
352
|
+
"error: #{ error.inspect }"
|
353
|
+
end
|
367
354
|
else
|
368
355
|
YAML.load(Cmds.out!(@meta_path.realpath.to_s)) || {}
|
369
356
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module QB
|
2
|
+
class Role
|
3
|
+
# raised by `.require` when no roles match input
|
4
|
+
class NoMatchesError < QB::Error
|
5
|
+
attr_accessor :input
|
6
|
+
|
7
|
+
def initialize input
|
8
|
+
@input = input
|
9
|
+
|
10
|
+
super "no roles match input #{ @input.inspect }"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# raised by `.require` when multiple roles match
|
15
|
+
class MultipleMatchesError < QB::Error
|
16
|
+
attr_accessor :input, :matches
|
17
|
+
|
18
|
+
def initialize input, matches
|
19
|
+
@input = input
|
20
|
+
@matches = matches
|
21
|
+
|
22
|
+
super "mutiple roles match input #{ @input.inspect }:\n#{ @matches.join("\n") }"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# raised when there's bad metadata
|
27
|
+
class MetadataError < QB::Error
|
28
|
+
end
|
29
|
+
end # Role
|
30
|
+
end # QB
|
data/lib/qb/version.rb
CHANGED
data/library/path_facts
ADDED
@@ -0,0 +1,304 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# WANT_JSON
|
3
|
+
|
4
|
+
# init bundler in dev env
|
5
|
+
if ENV['QB_DEV_ENV']
|
6
|
+
ENV.each {|k, v|
|
7
|
+
if k.start_with? 'QB_DEV_ENV_'
|
8
|
+
ENV[k.sub('QB_DEV_ENV_', '')] = v
|
9
|
+
end
|
10
|
+
}
|
11
|
+
require 'bundler/setup'
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'ostruct'
|
15
|
+
|
16
|
+
require 'qb'
|
17
|
+
require 'cmds'
|
18
|
+
require 'pathname'
|
19
|
+
require 'uri'
|
20
|
+
require 'net/http'
|
21
|
+
|
22
|
+
class Result < OpenStruct
|
23
|
+
def to_json *args
|
24
|
+
to_h.to_json *args
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
GITHUB_SSH_URL_RE = /^git@github\.com\:(?<owner>.*)\/(?<name>.*)\.git$/
|
29
|
+
GITHUB_HTTPS_URL_RE = /^https:\/\/github\.com\/(?<owner>.*)\/(?<name>.*)\.git$/
|
30
|
+
|
31
|
+
# An attempt to unify NPM and Gem version schemes to a reasonable extend,
|
32
|
+
# and hopefully cover whatever else the cat may drag in.
|
33
|
+
class Version
|
34
|
+
# Create a Version instance from a Gem::Version
|
35
|
+
def self.from_gem_version version
|
36
|
+
release_segments = version.segments.take_while {|seg| !seg.is_a?(String)}
|
37
|
+
prerelease_segments = version.segments[release_segments.length..-1]
|
38
|
+
|
39
|
+
new raw: version.to_s,
|
40
|
+
major: release_segments[0],
|
41
|
+
minor: release_segments[1],
|
42
|
+
patch: release_segments[2],
|
43
|
+
prerelease: prerelease_segments,
|
44
|
+
build: [],
|
45
|
+
release: version.release
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.from_npm_version version
|
49
|
+
stmt = NRSER.squish <<-END
|
50
|
+
var Semver = require('semver');
|
51
|
+
|
52
|
+
console.log(
|
53
|
+
JSON.stringify(
|
54
|
+
Semver(#{ JSON.dump version })
|
55
|
+
)
|
56
|
+
);
|
57
|
+
END
|
58
|
+
|
59
|
+
parse = JSON.load Cmds.out!("node --eval %s", stmt)
|
60
|
+
|
61
|
+
new raw: version,
|
62
|
+
major: parse['major'],
|
63
|
+
minor: parse['minor'],
|
64
|
+
patch: parse['patch'],
|
65
|
+
prerelease: parse['prerelease'],
|
66
|
+
build: parse['build'],
|
67
|
+
release: [parse['major'], parse['minor'], parse['patch']].join(".")
|
68
|
+
end
|
69
|
+
|
70
|
+
# Construct a new Version
|
71
|
+
def initialize raw:, major:, minor:, patch:, prerelease:, build:, release:
|
72
|
+
@raw = raw
|
73
|
+
@major = major
|
74
|
+
@minor = minor
|
75
|
+
@patch = patch
|
76
|
+
@prerelease = prerelease
|
77
|
+
@build = build
|
78
|
+
@release = release
|
79
|
+
|
80
|
+
@level = @prerelease[0] || 'release'
|
81
|
+
|
82
|
+
@is_release = @prerelease.empty?
|
83
|
+
@is_dev = @prerelease[0] == 'dev'
|
84
|
+
@is_rc = @prerelease[0] == 'rc'
|
85
|
+
end
|
86
|
+
|
87
|
+
# Dump all instance variables in JSON serialization
|
88
|
+
def to_json *args
|
89
|
+
instance_variables.map {|var|
|
90
|
+
[var[1..-1].to_sym, instance_variable_get(var)]
|
91
|
+
}.to_h.to_json *args
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class PathFacts < QB::AnsibleModule
|
96
|
+
# Add a bunch of useful things to know about the path
|
97
|
+
def add_path_facts
|
98
|
+
@result.expanded = @path.expand_path
|
99
|
+
@result.exists = @path.exist?
|
100
|
+
@result.is_expanded = @result.expanded == @path
|
101
|
+
@result.is_absolute = @path.absolute?
|
102
|
+
@result.is_relative = @path.relative?
|
103
|
+
@result.is_dir = @path.directory?
|
104
|
+
@result.is_file = @path.file?
|
105
|
+
@result.is_cwd = @path == Pathname.getwd
|
106
|
+
|
107
|
+
# Will raise if there is no relative path between them, in which case
|
108
|
+
# 'relative' will be null.
|
109
|
+
@result.relative = begin
|
110
|
+
@path.relative_path_from Pathname.getwd
|
111
|
+
rescue ArgumentError => error
|
112
|
+
end
|
113
|
+
|
114
|
+
# Pathname#realpath will raise if the path doesn't exist
|
115
|
+
@result.realpath = begin
|
116
|
+
@path.realpath
|
117
|
+
rescue Exception => error
|
118
|
+
end
|
119
|
+
|
120
|
+
@result.is_realpath = @result.realpath == @path
|
121
|
+
end
|
122
|
+
|
123
|
+
# If the path is a Git repo (has a .git file in it's root) add useful
|
124
|
+
# Git facts.
|
125
|
+
def add_git_facts
|
126
|
+
git_file_path = @path.join('.git')
|
127
|
+
|
128
|
+
unless @path.directory? && git_file_path.exist?
|
129
|
+
@result.is_git = false
|
130
|
+
return
|
131
|
+
end
|
132
|
+
|
133
|
+
@result.is_git = true
|
134
|
+
|
135
|
+
Dir.chdir(@path) do
|
136
|
+
git = @result.git = Result.new
|
137
|
+
|
138
|
+
user = git.user = Result.new
|
139
|
+
|
140
|
+
['name', 'email'].each {|key|
|
141
|
+
user[key] = begin
|
142
|
+
Cmds.chomp! "git config user.#{ key }"
|
143
|
+
rescue
|
144
|
+
end
|
145
|
+
}
|
146
|
+
|
147
|
+
git.root = begin
|
148
|
+
Cmds.chomp! "git rev-parse --show-toplevel"
|
149
|
+
rescue
|
150
|
+
end
|
151
|
+
|
152
|
+
git.origin = begin
|
153
|
+
Cmds.chomp! "git remote get-url origin"
|
154
|
+
rescue
|
155
|
+
end
|
156
|
+
|
157
|
+
match = GITHUB_SSH_URL_RE.match(git.origin) ||
|
158
|
+
GITHUB_HTTPS_URL_RE.match(git.origin)
|
159
|
+
|
160
|
+
git.is_github = !! match
|
161
|
+
|
162
|
+
return unless match
|
163
|
+
|
164
|
+
git.owner = match['owner']
|
165
|
+
git.name = match['name']
|
166
|
+
git.full_name = "#{ git.owner }/#{ git.name }"
|
167
|
+
|
168
|
+
if true == @args['github_api']
|
169
|
+
github = git.github = Result.new
|
170
|
+
github.api_url = "https://api.github.com/repos/#{ git.owner }/#{ git.name }"
|
171
|
+
|
172
|
+
response = Net::HTTP.get_response URI(github.api_url)
|
173
|
+
|
174
|
+
if response.is_a? Net::HTTPSuccess
|
175
|
+
# parse response body and add everything to github result
|
176
|
+
parsed = JSON.parse response.body
|
177
|
+
parsed.each {|k, v| github[k] = v}
|
178
|
+
else
|
179
|
+
# assume it's private if we failed to find it
|
180
|
+
github.private = true
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# Find the only *.gemspec path in the `@path` directory. Warns and returns
|
189
|
+
# `nil` if there is more than one match.
|
190
|
+
def gemspec_path
|
191
|
+
paths = Pathname.glob(@path.join('*.gemspec'))
|
192
|
+
|
193
|
+
case paths.length
|
194
|
+
when 0
|
195
|
+
nil
|
196
|
+
when 1
|
197
|
+
paths[0]
|
198
|
+
else
|
199
|
+
warn "found multiple gemspecs: #{ paths }, unable to pick one."
|
200
|
+
nil
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# If `path` is a directory containing the source for a Ruby Gem, add
|
205
|
+
# useful information about it.
|
206
|
+
def add_gem_facts
|
207
|
+
unless @path.directory?
|
208
|
+
@result.is_gem = false
|
209
|
+
return
|
210
|
+
end
|
211
|
+
|
212
|
+
path = gemspec_path
|
213
|
+
|
214
|
+
if path.nil?
|
215
|
+
@result.is_gem = false
|
216
|
+
return
|
217
|
+
end
|
218
|
+
|
219
|
+
@result.is_gem = true
|
220
|
+
@result.package.types << 'gem'
|
221
|
+
|
222
|
+
gem = @result.gem = Result.new
|
223
|
+
|
224
|
+
gem.gemspec_path = gemspec_path.to_s
|
225
|
+
|
226
|
+
spec = Gem::Specification::load(gemspec_path.to_s)
|
227
|
+
gem.name = spec.name
|
228
|
+
gem.version = Version.from_gem_version spec.version
|
229
|
+
end
|
230
|
+
|
231
|
+
# Add facts about an NPM package based in `@path`, if any.
|
232
|
+
def add_npm_facts
|
233
|
+
package_json_path = @path.join('package.json')
|
234
|
+
|
235
|
+
unless @path.directory? && package_json_path.file?
|
236
|
+
@result.is_npm = false
|
237
|
+
return
|
238
|
+
end
|
239
|
+
|
240
|
+
@result.is_npm = true
|
241
|
+
@result.package.types << 'npm'
|
242
|
+
|
243
|
+
npm = @result.npm = Result.new
|
244
|
+
|
245
|
+
npm.package_json = JSON.load package_json_path.read
|
246
|
+
|
247
|
+
# To stay consistent with Gem
|
248
|
+
npm.name = npm.package_json['name']
|
249
|
+
npm.version = Version.from_npm_version npm.package_json['version']
|
250
|
+
end
|
251
|
+
|
252
|
+
# Run the module.
|
253
|
+
def main
|
254
|
+
# check the 'path' arg
|
255
|
+
unless @args['path'].is_a? String
|
256
|
+
raise ArgumentError,
|
257
|
+
"'path' arg must be a string, found #{ @args['path'].inspect }."
|
258
|
+
end
|
259
|
+
|
260
|
+
# We'll return the value of @result
|
261
|
+
@result = Result.new
|
262
|
+
|
263
|
+
# Default to signaling no change (we're not gonna change anything in this
|
264
|
+
# module either)
|
265
|
+
@result.changed = false
|
266
|
+
|
267
|
+
# String warnings that will be shown to the user
|
268
|
+
@result.warnings = []
|
269
|
+
|
270
|
+
@result.package = Result.new
|
271
|
+
@result.package.types = []
|
272
|
+
|
273
|
+
# Return the input as 'raw'
|
274
|
+
@result.raw = @args['path']
|
275
|
+
|
276
|
+
@path = Pathname.new @result.raw
|
277
|
+
|
278
|
+
add_path_facts
|
279
|
+
add_git_facts
|
280
|
+
add_gem_facts
|
281
|
+
add_npm_facts
|
282
|
+
|
283
|
+
# If we only have one type of package present, we set it's type and
|
284
|
+
# version as `package.type` and `package.version`, which makes it easy for
|
285
|
+
# code to 'auto-detect' the info.
|
286
|
+
#
|
287
|
+
# If there's more than one then we obviously can't guess what to do; the
|
288
|
+
# user needs to specify.
|
289
|
+
#
|
290
|
+
if @result.package.types.length == 1
|
291
|
+
@result.package.type = @result.package.types[0]
|
292
|
+
@result.package.name = @result[@result.package.type].name
|
293
|
+
@result.package.version = @result[@result.package.type].version
|
294
|
+
end
|
295
|
+
|
296
|
+
nil
|
297
|
+
end
|
298
|
+
|
299
|
+
def done
|
300
|
+
exit_json @result.to_h
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
PathFacts.new.run
|