qb 0.1.60 → 0.1.61

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/lib/qb/options.rb +6 -6
  3. data/lib/qb/role.rb +20 -33
  4. data/lib/qb/role/errors.rb +30 -0
  5. data/lib/qb/version.rb +1 -1
  6. data/library/path_facts +304 -0
  7. data/plugins/lookup_plugins/every.py +165 -0
  8. data/roles/qb.facts/defaults/main.yml +3 -0
  9. data/roles/{qb.yarn → qb.facts}/meta/main.yml +1 -1
  10. data/roles/{qb.yarn → qb.facts}/meta/qb.yml +21 -26
  11. data/roles/qb.facts/tasks/main.yml +10 -0
  12. data/roles/qb.git_repo/defaults/main.yml +1 -0
  13. data/roles/qb.git_repo/meta/main.yml +1 -9
  14. data/roles/qb.git_repo/tasks/main.yml +26 -1
  15. data/roles/qb.qb_role/templates/qb.yml.j2 +8 -0
  16. data/roles/qb.role/defaults/main.yml +1 -1
  17. data/roles/qb.role/tasks/main.yml +1 -1
  18. data/roles/qb.yarn_release/defaults/main.yml +4 -0
  19. data/roles/{qb.release_yarn → qb.yarn_release}/meta/main.yml +1 -1
  20. data/roles/{qb.release_yarn → qb.yarn_release}/meta/qb.yml +1 -1
  21. data/roles/qb.yarn_release/tasks/main.yml +73 -0
  22. data/roles/qb.yarn_setup/defaults/main.yml +11 -0
  23. data/roles/qb.yarn_setup/meta/main.yml +8 -0
  24. data/roles/qb.yarn_setup/meta/qb.yml +100 -0
  25. data/roles/qb.yarn_setup/tasks/distribution/MacOSX/brew_create.yml +59 -0
  26. data/roles/qb.yarn_setup/tasks/distribution/MacOSX/main.yml +42 -0
  27. data/roles/qb.yarn_setup/tasks/main.yml +11 -0
  28. data/roles/qb.yarn_setup/templates/yarn@M.m.p.rb.j2 +22 -0
  29. metadata +20 -12
  30. data/lib/qb/options/errors.rb +0 -11
  31. data/roles/qb.release_yarn/defaults/main.yml +0 -4
  32. data/roles/qb.release_yarn/tasks/main.yml +0 -73
  33. data/roles/qb.yarn/defaults/main.yml +0 -5
  34. data/roles/qb.yarn/tasks/distribution/MacOSX.yml +0 -7
  35. data/roles/qb.yarn/tasks/main.yml +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b47bdac25f6db4d1fea5cf3b018229d4b94a0987
4
- data.tar.gz: d3a4cdd1d235048c4f49dbbaf7824fe77706ce46
3
+ metadata.gz: ac5214f10fb124d147d91b4618033b426d389558
4
+ data.tar.gz: f051f2779ee56a8aa1747642080c99e08e567f02
5
5
  SHA512:
6
- metadata.gz: 95cc0afa926ddf49719cbe7b77effbeb99923dc7241430fa5adcf1ead739434662aca811d9978b9f077520a25095b6347887ea99b261bf763c178c23b27d1c62
7
- data.tar.gz: 46ab3b3bd3866aa64cb3982be5fdd126b5ba479dd550f4d7e05c292e3fc49c4506381e891ac951ef05e998e60f8ea21df2547b0b7e44919a9d28a0cfe9d12b85
6
+ metadata.gz: 2102fe8bf8be9a227dc3f5644c31c2e8d0ae57b9aa30dc4578914531c569afc05c71dbed9449f8ec0cda4c4a060203f0c1db91260fd9c423c1a3f6ede0a76323
7
+ data.tar.gz: c992b406840a86966b0b8d8b9e59c215255b23245c0f764db261dfb666639d24a9f30f30ecc5b6ca258ef8b80333bd93949f54023ccd944f68a3ab677cb1970b
@@ -1,6 +1,6 @@
1
1
  require 'optparse'
2
2
 
3
- require_relative "options/errors"
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::Options::MetadataError.new,
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::Options::MetadataError,
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::Options::MetadataError,
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::Options::MetadataError,
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::Options::MetadataError,
153
+ raise QB::Role::MetadataError,
154
154
  "bad type for option #{ option.meta_name }: #{ option.meta['type'].inspect }"
155
155
  end
156
156
 
@@ -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::Options::MetadataError.new,
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
- YAML.load(@meta_path.read) || {}
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
@@ -1,7 +1,7 @@
1
1
  module QB
2
2
  GEM_NAME = 'qb'
3
3
 
4
- VERSION = "0.1.60"
4
+ VERSION = "0.1.61"
5
5
 
6
6
  def self.gemspec
7
7
  Gem.loaded_specs[GEM_NAME]
@@ -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