qb 0.1.77 → 0.1.78
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.rb +5 -5
- data/lib/qb/package/version.rb +78 -103
- data/lib/qb/repo.rb +1 -0
- data/lib/qb/repo/git.rb +261 -0
- data/lib/qb/util.rb +4 -1
- data/lib/qb/util/interop.rb +51 -0
- data/lib/qb/version.rb +1 -1
- data/library/path_facts +7 -1
- data/plugins/filter_plugins/ruby_interop.py +85 -0
- data/plugins/filter_plugins/version.py +24 -0
- data/qb.gemspec +1 -1
- data/roles/nrser.rb/library/set_fact_with_ruby.rb +25 -6
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a116f7c56db4ada78655a13a0bd1082c1a0f3489
|
4
|
+
data.tar.gz: 62ef6a65bc735292b9e78232f698d34f59e3bedc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5dba83f32282f531f8e3cca01a78db53b1daac2025a9a9a8c2bb62688f7a70af894f0071cfdbbeba00b2e35372e011c63b7f44053250f5434489fc3a94db2e68
|
7
|
+
data.tar.gz: cdb4b31a280a269e6e344493f4969145f1217716be071481504b327dfaf05b2d5ec47dac93acd83e05095568441ea754dcb099790625bee5b12e0c74b26b1d31
|
data/lib/qb.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
require 'nrser/extras'
|
2
2
|
|
3
3
|
require_relative './qb/errors'
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative './qb/
|
7
|
-
require_relative "./qb/ansible_module"
|
4
|
+
require_relative './qb/version'
|
5
|
+
require_relative './qb/util'
|
6
|
+
require_relative './qb/ansible_module'
|
8
7
|
|
9
8
|
module QB
|
10
9
|
ROOT = (Pathname.new(__FILE__).dirname + '..').expand_path
|
@@ -38,4 +37,5 @@ end
|
|
38
37
|
|
39
38
|
# needs QB::*_ROLES_DIR
|
40
39
|
require 'qb/role'
|
41
|
-
require 'qb/options'
|
40
|
+
require 'qb/options'
|
41
|
+
require_relative './qb/repo'
|
data/lib/qb/package/version.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'time'
|
2
2
|
|
3
|
-
require 'nrser/types'
|
3
|
+
require 'nrser/refinements/types'
|
4
4
|
|
5
|
-
|
5
|
+
using NRSER::Types
|
6
6
|
|
7
|
-
|
7
|
+
require 'qb/util/docker_mixin'
|
8
8
|
|
9
9
|
module QB
|
10
10
|
module Package
|
@@ -13,9 +13,51 @@ module QB
|
|
13
13
|
#
|
14
14
|
# Intended to be immutable for practical purposes.
|
15
15
|
#
|
16
|
-
class Version
|
16
|
+
class Version < NRSER::Meta::Props::Base
|
17
|
+
|
18
|
+
# Mixins
|
19
|
+
# =====================================================================
|
20
|
+
|
17
21
|
include QB::Util::DockerMixin
|
18
22
|
|
23
|
+
|
24
|
+
# Constants
|
25
|
+
# =====================================================================
|
26
|
+
|
27
|
+
NUMBER_SEGMENT = t.non_neg_int
|
28
|
+
NAME_SEGMENT = t.str
|
29
|
+
MIXED_SEGMENT = t.union NUMBER_SEGMENT, NAME_SEGMENT
|
30
|
+
|
31
|
+
|
32
|
+
# Props
|
33
|
+
# =====================================================================
|
34
|
+
|
35
|
+
prop :raw, type: t.maybe(t.str), default: nil
|
36
|
+
prop :major, type: NUMBER_SEGMENT
|
37
|
+
prop :minor, type: NUMBER_SEGMENT, default: 0
|
38
|
+
prop :patch, type: NUMBER_SEGMENT, default: 0
|
39
|
+
prop :prerelease, type: t.array(MIXED_SEGMENT), default: []
|
40
|
+
prop :build, type: t.array(MIXED_SEGMENT), default: []
|
41
|
+
|
42
|
+
prop :release, type: t.str, source: :@release
|
43
|
+
prop :level, type: t.str, source: :@level
|
44
|
+
prop :is_release, type: t.bool, source: :release?
|
45
|
+
prop :is_prerelease, type: t.bool, source: :prerelease?
|
46
|
+
prop :is_build, type: t.bool, source: :build?
|
47
|
+
prop :is_dev, type: t.bool, source: :dev?
|
48
|
+
prop :is_rc, type: t.bool, source: :rc?
|
49
|
+
prop :has_level, type: t.bool, source: :level?
|
50
|
+
prop :semver, type: t.str, source: :semver
|
51
|
+
prop :docker_tag, type: t.str, source: :docker_tag
|
52
|
+
|
53
|
+
|
54
|
+
# Attributes
|
55
|
+
# =====================================================================
|
56
|
+
|
57
|
+
attr_reader :release,
|
58
|
+
:level
|
59
|
+
|
60
|
+
|
19
61
|
# Class Methods
|
20
62
|
# =====================================================================
|
21
63
|
|
@@ -116,79 +158,21 @@ module QB
|
|
116
158
|
end
|
117
159
|
|
118
160
|
|
119
|
-
# Instantiate from a hash. Slices out
|
120
|
-
#
|
121
|
-
# - `raw`
|
122
|
-
# - `major`
|
123
|
-
# - `minor`
|
124
|
-
# - `patch`
|
125
|
-
# - `prerelease`
|
126
|
-
# - `build`
|
127
|
-
#
|
128
|
-
# And passes their values to the constructor. Keys may be strings or
|
129
|
-
# symbols. All other key/values are ignored, allowing you to pass in
|
130
|
-
# the JSON encoding of a version instance.
|
131
|
-
#
|
132
|
-
# @param [Hash] hash
|
133
|
-
# Values to be passed to constructor.
|
134
|
-
#
|
135
|
-
# @return [QB::Package::Version]
|
136
|
-
#
|
137
|
-
def self.from_h hash
|
138
|
-
self.new(
|
139
|
-
NRSER.slice_keys(
|
140
|
-
NRSER.symbolize_keys(hash),
|
141
|
-
:raw,
|
142
|
-
:major,
|
143
|
-
:minor,
|
144
|
-
:patch,
|
145
|
-
:prerelease,
|
146
|
-
:build,
|
147
|
-
)
|
148
|
-
)
|
149
|
-
end # #from_h
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
# Attributes
|
154
|
-
# =====================================================================
|
155
|
-
|
156
|
-
attr_reader :raw,
|
157
|
-
:major,
|
158
|
-
:minor,
|
159
|
-
:patch,
|
160
|
-
:prerelease,
|
161
|
-
:build,
|
162
|
-
:release,
|
163
|
-
:level
|
164
|
-
|
165
|
-
|
166
161
|
# Constructor
|
167
162
|
# =====================================================================
|
168
163
|
|
169
164
|
# Construct a new Version
|
170
|
-
def initialize
|
171
|
-
|
172
|
-
|
173
|
-
minor: 0,
|
174
|
-
patch: 0,
|
175
|
-
prerelease: [],
|
176
|
-
build: []
|
177
|
-
)
|
178
|
-
@raw = T.maybe(T.str).check raw
|
179
|
-
@major = T.non_neg_int.check major
|
180
|
-
@minor = T.non_neg_int.check minor
|
181
|
-
@patch = T.non_neg_int.check patch
|
182
|
-
@prerelease = T.array(T.union(T.non_neg_int, T.str)).check prerelease
|
183
|
-
@build = T.array(T.union(T.non_neg_int, T.str)).check build
|
165
|
+
def initialize **values
|
166
|
+
super **values
|
167
|
+
|
184
168
|
@release = [major, minor, patch].join '.'
|
185
169
|
|
186
|
-
@level =
|
187
|
-
|
170
|
+
@level = t.match prerelease[0], {
|
171
|
+
t.is(nil) => ->(_) { nil },
|
188
172
|
|
189
|
-
|
173
|
+
NAME_SEGMENT => ->(str) { str },
|
190
174
|
|
191
|
-
|
175
|
+
NUMBER_SEGMENT => ->(int) { nil },
|
192
176
|
}
|
193
177
|
end
|
194
178
|
|
@@ -203,7 +187,7 @@ module QB
|
|
203
187
|
# True if this version is a release (no prerelease or build values).
|
204
188
|
#
|
205
189
|
def release?
|
206
|
-
|
190
|
+
prerelease.empty? && build.empty?
|
207
191
|
end
|
208
192
|
|
209
193
|
|
@@ -214,7 +198,7 @@ module QB
|
|
214
198
|
# empty.
|
215
199
|
#
|
216
200
|
def prerelease?
|
217
|
-
|
201
|
+
!prerelease.empty?
|
218
202
|
end
|
219
203
|
|
220
204
|
|
@@ -227,7 +211,7 @@ module QB
|
|
227
211
|
# Gem version.
|
228
212
|
#
|
229
213
|
def build?
|
230
|
-
|
214
|
+
!build.empty?
|
231
215
|
end
|
232
216
|
|
233
217
|
|
@@ -236,7 +220,7 @@ module QB
|
|
236
220
|
# we consider the 'level'.
|
237
221
|
#
|
238
222
|
def level?
|
239
|
-
|
223
|
+
!level.nil?
|
240
224
|
end
|
241
225
|
|
242
226
|
|
@@ -245,7 +229,7 @@ module QB
|
|
245
229
|
# is 'dev').
|
246
230
|
#
|
247
231
|
def dev?
|
248
|
-
|
232
|
+
level == 'dev'
|
249
233
|
end
|
250
234
|
|
251
235
|
|
@@ -254,7 +238,7 @@ module QB
|
|
254
238
|
# is 'rc').
|
255
239
|
#
|
256
240
|
def rc?
|
257
|
-
|
241
|
+
level == 'rc'
|
258
242
|
end
|
259
243
|
|
260
244
|
|
@@ -282,6 +266,14 @@ module QB
|
|
282
266
|
alias_method :normalized, :semver
|
283
267
|
|
284
268
|
|
269
|
+
|
270
|
+
# Related Versions
|
271
|
+
# ---------------------------------------------------------------------
|
272
|
+
#
|
273
|
+
# Functions that construct new version instances based on the current
|
274
|
+
# one as well as additional information provided.
|
275
|
+
#
|
276
|
+
|
285
277
|
# @return [QB::Package::Version]
|
286
278
|
# A new {QB::Package::Version} created from {#release}. Even if `self`
|
287
279
|
# *is* a release version already, still returns a new instance.
|
@@ -291,11 +283,6 @@ module QB
|
|
291
283
|
end # #release_version
|
292
284
|
|
293
285
|
|
294
|
-
def merge overrides = {}
|
295
|
-
self.class.from_h self.to_h.merge(overrides)
|
296
|
-
end
|
297
|
-
|
298
|
-
|
299
286
|
# Return a new {QB::Package::Version} with build information added.
|
300
287
|
#
|
301
288
|
# @return [QB::Package::Version]
|
@@ -318,6 +305,17 @@ module QB
|
|
318
305
|
merge raw: nil, build: segments
|
319
306
|
end
|
320
307
|
|
308
|
+
|
309
|
+
# @return [QB::Package::Version]
|
310
|
+
# A new {QB::Package::Version} created from {#release} and
|
311
|
+
# {#prerelease} data, but without any build information.
|
312
|
+
#
|
313
|
+
def prerelease_version
|
314
|
+
merge raw: nil, build: []
|
315
|
+
end # #prerelease_version
|
316
|
+
|
317
|
+
|
318
|
+
|
321
319
|
# Docker image tag for the version.
|
322
320
|
#
|
323
321
|
# See {QB::Util::DockerMixin::ClassMethods#to_docker_tag}.
|
@@ -391,29 +389,6 @@ module QB
|
|
391
389
|
end
|
392
390
|
|
393
391
|
|
394
|
-
# dump all instance variables into a hash
|
395
|
-
def to_h
|
396
|
-
instance_variables.map {|var|
|
397
|
-
[var[1..-1], instance_variable_get(var)]
|
398
|
-
}.to_h
|
399
|
-
end # #to_h
|
400
|
-
|
401
|
-
|
402
|
-
# Dump all instance variables in JSON serialization
|
403
|
-
def to_json *args
|
404
|
-
to_h.merge(
|
405
|
-
is_release: release?,
|
406
|
-
is_prerelease: prerelease?,
|
407
|
-
is_build: build?,
|
408
|
-
is_dev: dev?,
|
409
|
-
is_rc: rc?,
|
410
|
-
has_level: level?,
|
411
|
-
semver: semver,
|
412
|
-
docker_tag: docker_tag,
|
413
|
-
).to_json *args
|
414
|
-
end
|
415
|
-
|
416
|
-
|
417
392
|
def to_s
|
418
393
|
"#<QB::Package::Version #{ @raw }>"
|
419
394
|
end
|
data/lib/qb/repo.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative './repo/git'
|
data/lib/qb/repo/git.rb
ADDED
@@ -0,0 +1,261 @@
|
|
1
|
+
require 'cmds'
|
2
|
+
require 'nrser/refinements/types'
|
3
|
+
|
4
|
+
using NRSER::Types
|
5
|
+
|
6
|
+
module QB
|
7
|
+
module Repo
|
8
|
+
|
9
|
+
# Encapsulate information about a Git repository and expose useful operations as
|
10
|
+
# instance methods.
|
11
|
+
#
|
12
|
+
# The main entry point is {QB::Repo::Git.from_path}, which creates a
|
13
|
+
#
|
14
|
+
class Git < NRSER::Meta::Props::Base
|
15
|
+
GITHUB_SSH_URL_RE = /^git@github\.com\:(?<owner>.*)\/(?<name>.*)\.git$/
|
16
|
+
GITHUB_HTTPS_URL_RE = /^https:\/\/github\.com\/(?<owner>.*)\/(?<name>.*)\.git$/
|
17
|
+
|
18
|
+
class User < NRSER::Meta::Props::Base
|
19
|
+
prop :name, type: t.maybe(t.str), default: nil
|
20
|
+
prop :email, type: t.maybe(t.str), default: nil
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
# class GitHubRemote < NRSER::Meta::Props::Base
|
25
|
+
# SSH_URL_RE = /^git@github\.com\:(?<owner>.*)\/(?<name>.*)\.git$/
|
26
|
+
# HTTPS_URL_RE = /^https:\/\/github\.com\/(?<owner>.*)\/(?<name>.*)\.git$/
|
27
|
+
#
|
28
|
+
# prop :owner, type: t.str
|
29
|
+
# prop :name, type: t.str
|
30
|
+
# prop :api_response, type: t.maybe(t.hash)
|
31
|
+
#
|
32
|
+
# prop :full_name, type: t.str, source: :full_name
|
33
|
+
#
|
34
|
+
#
|
35
|
+
# # Class Methods
|
36
|
+
# # =====================================================================
|
37
|
+
#
|
38
|
+
# # Test if a Git SSH or HTTPS remote url points to GitHub.
|
39
|
+
# #
|
40
|
+
# # @param [String] url
|
41
|
+
# #
|
42
|
+
# # @return [Boolean]
|
43
|
+
# #
|
44
|
+
# def self.url? url
|
45
|
+
# SSH_URL_RE.match(url) || HTTPS_URL_RE.match(url)
|
46
|
+
# end # .url?
|
47
|
+
#
|
48
|
+
#
|
49
|
+
# # Instantiate an instance from a Git SSH or HTTPS remote url that points
|
50
|
+
# # to GitHub.
|
51
|
+
# #
|
52
|
+
# # @param [type] arg_name
|
53
|
+
# # @todo Add name param description.
|
54
|
+
# #
|
55
|
+
# # @return [QB::Repo::Git::GitHubRemote]
|
56
|
+
# # @todo Document return value.
|
57
|
+
# #
|
58
|
+
# def self.from_url url, use_api: false
|
59
|
+
# match = SSH_URL_RE.match(git.origin) ||
|
60
|
+
# HTTPS_URL_RE.match(git.origin)
|
61
|
+
#
|
62
|
+
# unless match
|
63
|
+
# raise ArgumentError.new NRSER.squish <<-END
|
64
|
+
# url #{ url.inspect } does not match GitHub SSH or HTTPS patterns.
|
65
|
+
# END
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# owner = match['owner']
|
69
|
+
# name = match['name']
|
70
|
+
#
|
71
|
+
# if use_api
|
72
|
+
#
|
73
|
+
# end
|
74
|
+
# end # .from_url
|
75
|
+
#
|
76
|
+
#
|
77
|
+
#
|
78
|
+
# # @todo Document full_name method.
|
79
|
+
# #
|
80
|
+
# # @param [type] arg_name
|
81
|
+
# # @todo Add name param description.
|
82
|
+
# #
|
83
|
+
# # @return [return_type]
|
84
|
+
# # @todo Document return value.
|
85
|
+
# #
|
86
|
+
# def full_name arg_name
|
87
|
+
# "#{ owner }/#{ name }"
|
88
|
+
# end # #full_name
|
89
|
+
#
|
90
|
+
# end
|
91
|
+
|
92
|
+
|
93
|
+
# Class Methods
|
94
|
+
# =====================================================================
|
95
|
+
|
96
|
+
# @todo Document from_path method.
|
97
|
+
#
|
98
|
+
# @param [String, Pathname] input_path
|
99
|
+
# A path that is in the Git repo.
|
100
|
+
#
|
101
|
+
# @return [QB::Repo::Git]
|
102
|
+
#
|
103
|
+
# @raise [QB::FSStateError]
|
104
|
+
# - If we can't find any existing directory to look in based on
|
105
|
+
# `input_path`.
|
106
|
+
#
|
107
|
+
# - If the directory we do find to look in does not seems to be part of
|
108
|
+
# a Git repo.
|
109
|
+
#
|
110
|
+
def self.from_path path, use_github_api: false
|
111
|
+
raw_input_path = path
|
112
|
+
|
113
|
+
# Create a Pathname from the input
|
114
|
+
input_path = Pathname.new raw_input_path
|
115
|
+
|
116
|
+
# input_path may point to a file, or something that doesn't even exist.
|
117
|
+
# We want to ascend until we find an existing directory that we can cd into.
|
118
|
+
closest_dir = input_path.ascend.find {|p| p.directory?}
|
119
|
+
|
120
|
+
# Make sure we found something
|
121
|
+
if closest_dir.nil?
|
122
|
+
raise QB::FSStateError,
|
123
|
+
"Unable to find any existing directory from path " +
|
124
|
+
"#{ raw_input_path.inspect }"
|
125
|
+
end
|
126
|
+
|
127
|
+
# Change into the directory to make shell life easier
|
128
|
+
Dir.chdir closest_dir do
|
129
|
+
root_result = Cmds.capture "git rev-parse --show-toplevel"
|
130
|
+
|
131
|
+
unless root_result.ok?
|
132
|
+
raise QB::FSStateError,
|
133
|
+
"Path #{ raw_input_path.inspect } does not appear to be in a " +
|
134
|
+
"Git repo (looked in #{ closest_dir.inspect })."
|
135
|
+
end
|
136
|
+
|
137
|
+
root = Pathname.new root_result.out.chomp
|
138
|
+
|
139
|
+
user = User.new **NRSER.map_values(User.props.keys) {|key, _|
|
140
|
+
begin
|
141
|
+
Cmds.chomp! "git config user.#{ key }"
|
142
|
+
rescue
|
143
|
+
end
|
144
|
+
}
|
145
|
+
|
146
|
+
is_clean = Cmds.chomp!('git status --porcelain 2>/dev/null').empty?
|
147
|
+
|
148
|
+
rev_parse = Cmds.capture 'git rev-parse HEAD'
|
149
|
+
|
150
|
+
head = if rev_parse.ok?
|
151
|
+
rev_parse.out.chomp
|
152
|
+
end
|
153
|
+
|
154
|
+
branch_result = Cmds.capture 'git branch --no-color 2> /dev/null'
|
155
|
+
|
156
|
+
branch = if branch_result.ok?
|
157
|
+
if line = branch_result.out.lines.find {|line| line.start_with? '*'}
|
158
|
+
if m = line.match(/\*\s+(\S+)/)
|
159
|
+
m[1]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
origin = begin
|
165
|
+
Cmds.chomp! "git remote get-url origin"
|
166
|
+
rescue
|
167
|
+
end
|
168
|
+
|
169
|
+
owner = nil
|
170
|
+
name = nil
|
171
|
+
github = nil
|
172
|
+
|
173
|
+
if origin && match = (
|
174
|
+
GITHUB_SSH_URL_RE.match(origin) ||
|
175
|
+
GITHUB_HTTPS_URL_RE.match(origin)
|
176
|
+
)
|
177
|
+
|
178
|
+
owner = match['owner']
|
179
|
+
name = match['name']
|
180
|
+
|
181
|
+
if use_github_api
|
182
|
+
github = OpenStruct.new
|
183
|
+
github.api_url = "https://api.github.com/repos/#{ owner }/#{ name }"
|
184
|
+
|
185
|
+
response = Net::HTTP.get_response URI(github.api_url)
|
186
|
+
|
187
|
+
if response.is_a? Net::HTTPSuccess
|
188
|
+
# parse response body and add everything to github result
|
189
|
+
parsed = JSON.parse response.body
|
190
|
+
parsed.each {|k, v| github[k] = v}
|
191
|
+
else
|
192
|
+
# assume it's private if we failed to find it
|
193
|
+
github.private = true
|
194
|
+
end
|
195
|
+
|
196
|
+
github = github.to_h
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
new(
|
202
|
+
raw_input_path: raw_input_path,
|
203
|
+
input_path: input_path,
|
204
|
+
root: root,
|
205
|
+
user: user,
|
206
|
+
is_clean: is_clean,
|
207
|
+
head: head,
|
208
|
+
branch: branch,
|
209
|
+
origin: origin,
|
210
|
+
owner: owner,
|
211
|
+
name: name,
|
212
|
+
github: github,
|
213
|
+
)
|
214
|
+
|
215
|
+
end # chdir
|
216
|
+
|
217
|
+
end # .from_path
|
218
|
+
|
219
|
+
|
220
|
+
# Props
|
221
|
+
# =====================================================================
|
222
|
+
|
223
|
+
prop :raw_input_path, type: t.maybe(t.union(Pathname, t.str)), default: nil
|
224
|
+
prop :root, type: Pathname
|
225
|
+
prop :user, type: User
|
226
|
+
prop :is_clean, type: t.bool
|
227
|
+
prop :head, type: t.maybe(t.str), default: nil
|
228
|
+
prop :branch, type: t.maybe(t.str), default: nil
|
229
|
+
prop :origin, type: t.maybe(t.str), default: nil
|
230
|
+
prop :owner, type: t.maybe(t.str), default: nil
|
231
|
+
prop :name, type: t.maybe(t.str), default: nil
|
232
|
+
prop :github, type: t.maybe(t.hash_), default: nil
|
233
|
+
|
234
|
+
prop :head_short, type: t.maybe(t.str), source: :head_short
|
235
|
+
prop :full_name, type: t.maybe(t.str), source: :full_name
|
236
|
+
prop :is_github, type: t.bool, source: :github?
|
237
|
+
|
238
|
+
|
239
|
+
# Instance Methods
|
240
|
+
# =====================================================================
|
241
|
+
|
242
|
+
def full_name
|
243
|
+
"#{ owner }/#{ name }" if owner && name
|
244
|
+
end
|
245
|
+
|
246
|
+
def head_short
|
247
|
+
head[0...7] if head
|
248
|
+
end
|
249
|
+
|
250
|
+
def github?
|
251
|
+
!github.nil?
|
252
|
+
end
|
253
|
+
|
254
|
+
def clean?
|
255
|
+
is_clean
|
256
|
+
end
|
257
|
+
|
258
|
+
end # class Git
|
259
|
+
|
260
|
+
end # module Repo
|
261
|
+
end # module QB
|
data/lib/qb/util.rb
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'nrser/refinements'
|
2
|
+
|
3
|
+
using NRSER
|
4
|
+
|
5
|
+
module QB
|
6
|
+
module Util
|
7
|
+
|
8
|
+
module Interop
|
9
|
+
class << self
|
10
|
+
|
11
|
+
# @todo Document receive method.
|
12
|
+
#
|
13
|
+
# @param [type] arg_name
|
14
|
+
# @todo Add name param description.
|
15
|
+
#
|
16
|
+
# @return [return_type]
|
17
|
+
# @todo Document return value.
|
18
|
+
#
|
19
|
+
def receive
|
20
|
+
# method body
|
21
|
+
yaml = $stdin.read
|
22
|
+
|
23
|
+
File.open('./receive.log', 'w') { |f|
|
24
|
+
f.write yaml
|
25
|
+
}
|
26
|
+
|
27
|
+
payload = YAML.load yaml
|
28
|
+
|
29
|
+
data = payload.fetch 'data'
|
30
|
+
method = payload.fetch 'method'
|
31
|
+
args = payload['args'] || []
|
32
|
+
kwds = payload['kwds'] || {}
|
33
|
+
args << kwds.symbolize_keys unless kwds.empty?
|
34
|
+
|
35
|
+
obj = if data.is_a?(Hash) && data.key?(NRSER::Meta::Props::CLASS_KEY)
|
36
|
+
NRSER::Meta::Props.from_data data
|
37
|
+
else
|
38
|
+
data
|
39
|
+
end
|
40
|
+
|
41
|
+
result = obj.send method, *args
|
42
|
+
|
43
|
+
$stdout.write result.to_yaml
|
44
|
+
|
45
|
+
end # #receive
|
46
|
+
|
47
|
+
end # class << self
|
48
|
+
end # module Interop
|
49
|
+
|
50
|
+
end # module Util
|
51
|
+
end # module QB
|
data/lib/qb/version.rb
CHANGED
data/library/path_facts
CHANGED
@@ -59,9 +59,15 @@ class PathFacts < QB::AnsibleModule
|
|
59
59
|
end
|
60
60
|
|
61
61
|
|
62
|
+
def add_git_facts
|
63
|
+
@result.git = QB::Repo::Git.from_path @path,
|
64
|
+
use_github_api: !!@args['github_api']
|
65
|
+
end
|
66
|
+
|
67
|
+
|
62
68
|
# If the path is part of a Git repo, as well as useful general
|
63
69
|
# Git environment facts.
|
64
|
-
def
|
70
|
+
def add_git_facts_old
|
65
71
|
# see if we're in a git repo. first, we need a directory that exists
|
66
72
|
dir = @path.expand_path.ascend.find {|p| p.directory? }
|
67
73
|
|
@@ -0,0 +1,85 @@
|
|
1
|
+
from __future__ import (absolute_import, division, print_function)
|
2
|
+
__metaclass__ = type
|
3
|
+
|
4
|
+
from ansible.errors import AnsibleError
|
5
|
+
|
6
|
+
import subprocess
|
7
|
+
import yaml
|
8
|
+
|
9
|
+
def qb_send(data, method, *args, **kwds):
|
10
|
+
'''
|
11
|
+
Load data as an object in ruby and send it a message (call a method).
|
12
|
+
'''
|
13
|
+
|
14
|
+
payload = {
|
15
|
+
'data': data,
|
16
|
+
'method': method,
|
17
|
+
'args': args,
|
18
|
+
'kwds': kwds,
|
19
|
+
}
|
20
|
+
|
21
|
+
input = yaml.safe_dump(payload)
|
22
|
+
|
23
|
+
ruby_code = '''
|
24
|
+
# init bundler in dev env
|
25
|
+
if ENV['QB_DEV_ENV']
|
26
|
+
ENV.each {|k, v|
|
27
|
+
if k.start_with? 'QB_DEV_ENV_'
|
28
|
+
ENV[k.sub('QB_DEV_ENV_', '')] = v
|
29
|
+
end
|
30
|
+
}
|
31
|
+
require 'bundler/setup'
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'qb'
|
35
|
+
|
36
|
+
QB::Util::Interop.receive
|
37
|
+
'''
|
38
|
+
|
39
|
+
process = subprocess.Popen(
|
40
|
+
['/usr/bin/env', 'ruby', '-e', ruby_code],
|
41
|
+
stdin=subprocess.PIPE,
|
42
|
+
stdout=subprocess.PIPE,
|
43
|
+
stderr=subprocess.PIPE,
|
44
|
+
)
|
45
|
+
|
46
|
+
out, err = process.communicate(input)
|
47
|
+
|
48
|
+
if process.returncode != 0:
|
49
|
+
raise AnsibleError('''
|
50
|
+
qb_send failed!
|
51
|
+
|
52
|
+
ERROR:
|
53
|
+
%s
|
54
|
+
''' % (err))
|
55
|
+
|
56
|
+
try:
|
57
|
+
result = yaml.load(out)
|
58
|
+
except Exception as error:
|
59
|
+
raise AnsibleError('''
|
60
|
+
qb_send failed to parse response:
|
61
|
+
|
62
|
+
%s
|
63
|
+
''' % out)
|
64
|
+
|
65
|
+
return result
|
66
|
+
|
67
|
+
|
68
|
+
class FilterModule(object):
|
69
|
+
'''
|
70
|
+
Ruby interop filters.
|
71
|
+
'''
|
72
|
+
|
73
|
+
def filters(self):
|
74
|
+
return {
|
75
|
+
'qb_send': qb_send,
|
76
|
+
}
|
77
|
+
# filters()
|
78
|
+
# FilterModule
|
79
|
+
|
80
|
+
|
81
|
+
# testing - call camel_case on first cli arg and print result
|
82
|
+
if __name__ == '__main__':
|
83
|
+
import doctest
|
84
|
+
doctest.testmod()
|
85
|
+
|
@@ -103,6 +103,29 @@ def semver_parse(version):
|
|
103
103
|
# semver_parse()
|
104
104
|
|
105
105
|
|
106
|
+
def qb_version_parse(version):
|
107
|
+
'''Parse version into QB::Package::Version
|
108
|
+
'''
|
109
|
+
|
110
|
+
ruby_code = (
|
111
|
+
'''
|
112
|
+
require 'qb'
|
113
|
+
|
114
|
+
puts JSON.parse(
|
115
|
+
QB::Package::Version.from_string %s
|
116
|
+
)
|
117
|
+
''' % json.dumps(version)
|
118
|
+
)
|
119
|
+
|
120
|
+
cmd = ['/usr/bin/env', 'ruby', '-e', ruby_code]
|
121
|
+
|
122
|
+
out = subprocess.check_output(cmd)
|
123
|
+
|
124
|
+
qb_version = json.loads(out)
|
125
|
+
|
126
|
+
return version
|
127
|
+
|
128
|
+
|
106
129
|
class FilterModule(object):
|
107
130
|
''' version manipulation filters '''
|
108
131
|
|
@@ -110,6 +133,7 @@ class FilterModule(object):
|
|
110
133
|
return {
|
111
134
|
'semver_inc': semver_inc,
|
112
135
|
'semver_parse': semver_parse,
|
136
|
+
'qb_version_parse': qb_version_parse,
|
113
137
|
}
|
114
138
|
# filters()
|
115
139
|
# FilterModule
|
data/qb.gemspec
CHANGED
@@ -94,7 +94,7 @@ Gem::Specification.new do |spec|
|
|
94
94
|
spec.add_development_dependency "yard"
|
95
95
|
|
96
96
|
spec.add_dependency "cmds",'~> 0.0', ">= 0.2.1"
|
97
|
-
spec.add_dependency "nrser",'~> 0.0', ">= 0.0.
|
97
|
+
spec.add_dependency "nrser",'~> 0.0', ">= 0.0.20"
|
98
98
|
spec.add_dependency "nrser-extras", '~> 0.0', ">= 0.0.3"
|
99
99
|
spec.add_dependency "state_mate", '~> 0.0', ">= 0.0.9"
|
100
100
|
spec.add_dependency 'parseconfig', '~> 1.0', '>= 1.0.8'
|
@@ -21,6 +21,11 @@ require 'json'
|
|
21
21
|
require 'shellwords'
|
22
22
|
require 'pp'
|
23
23
|
|
24
|
+
# We originally used the name 'vars', but switched to prefer 'bind'.
|
25
|
+
# However, we still support either, but doesn't make sense to provide
|
26
|
+
# both.
|
27
|
+
BIND_ARG_NAMES = ['bind', 'vars']
|
28
|
+
|
24
29
|
# Global var to append warning messages to.
|
25
30
|
$warnings = []
|
26
31
|
|
@@ -45,11 +50,14 @@ def main
|
|
45
50
|
|
46
51
|
args = JSON.load input
|
47
52
|
|
48
|
-
var_name = args.fetch 'var_name'
|
49
|
-
|
50
53
|
b = binding
|
51
54
|
|
52
|
-
|
55
|
+
if BIND_ARG_NAMES.count {|name| args.key? name } > 1
|
56
|
+
raise ArgumentError,
|
57
|
+
"Please provide exactly one of args #{ BIND_ARG_NAMES.join ', ' }"
|
58
|
+
end
|
59
|
+
|
60
|
+
BIND_ARG_NAMES.each do |key|
|
53
61
|
if args.key? key
|
54
62
|
args[key].each {|k, v|
|
55
63
|
# Ansible sends null/None values as empty strings, so convert those
|
@@ -62,12 +70,23 @@ def main
|
|
62
70
|
end
|
63
71
|
|
64
72
|
result = b.eval args.fetch('src')
|
73
|
+
|
74
|
+
ansible_facts = if args.key? 'var_name'
|
75
|
+
# We received a var_name, so we consider the result to be it's value
|
76
|
+
{args['var_name'] => result}
|
77
|
+
else
|
78
|
+
# The result should be a hash of variable names to value to set
|
79
|
+
unless result.is_a? Hash
|
80
|
+
raise "When var_name arg is not provided, result of evaluation must "
|
81
|
+
"be a Hash of variable names to value to set. " +
|
82
|
+
"Found #{ result.inspect }"
|
83
|
+
end
|
84
|
+
result
|
85
|
+
end
|
65
86
|
|
66
87
|
print JSON.dump({
|
67
88
|
'changed' => false,
|
68
|
-
'ansible_facts' =>
|
69
|
-
var_name => result,
|
70
|
-
},
|
89
|
+
'ansible_facts' => ansible_facts,
|
71
90
|
'warnings' => $warnings,
|
72
91
|
})
|
73
92
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.78
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nrser
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-08-
|
11
|
+
date: 2017-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -95,7 +95,7 @@ dependencies:
|
|
95
95
|
version: '0.0'
|
96
96
|
- - ">="
|
97
97
|
- !ruby/object:Gem::Version
|
98
|
-
version: 0.0.
|
98
|
+
version: 0.0.20
|
99
99
|
type: :runtime
|
100
100
|
prerelease: false
|
101
101
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -105,7 +105,7 @@ dependencies:
|
|
105
105
|
version: '0.0'
|
106
106
|
- - ">="
|
107
107
|
- !ruby/object:Gem::Version
|
108
|
-
version: 0.0.
|
108
|
+
version: 0.0.20
|
109
109
|
- !ruby/object:Gem::Dependency
|
110
110
|
name: nrser-extras
|
111
111
|
requirement: !ruby/object:Gem::Requirement
|
@@ -185,10 +185,13 @@ files:
|
|
185
185
|
- lib/qb/options.rb
|
186
186
|
- lib/qb/options/option.rb
|
187
187
|
- lib/qb/package/version.rb
|
188
|
+
- lib/qb/repo.rb
|
189
|
+
- lib/qb/repo/git.rb
|
188
190
|
- lib/qb/role.rb
|
189
191
|
- lib/qb/role/errors.rb
|
190
192
|
- lib/qb/util.rb
|
191
193
|
- lib/qb/util/docker_mixin.rb
|
194
|
+
- lib/qb/util/interop.rb
|
192
195
|
- lib/qb/util/stdio.rb
|
193
196
|
- lib/qb/version.rb
|
194
197
|
- library/git_mkdir.py
|
@@ -204,6 +207,7 @@ files:
|
|
204
207
|
- node_modules/semver/semver.js
|
205
208
|
- package.json
|
206
209
|
- plugins/filter_plugins/path.py
|
210
|
+
- plugins/filter_plugins/ruby_interop.py
|
207
211
|
- plugins/filter_plugins/string.py
|
208
212
|
- plugins/filter_plugins/version.py
|
209
213
|
- plugins/lookup_plugins/every.py
|