qb 0.1.77 → 0.1.78
Sign up to get free protection for your applications and to get access to all the features.
- 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
|