qb 0.3.8 → 0.3.9
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/.yardopts +4 -0
- data/exe/.qb_interop_receive +39 -0
- data/exe/qb +8 -5
- data/lib/qb.rb +64 -19
- data/lib/qb/cli/run.rb +1 -1
- data/lib/qb/github.rb +4 -0
- data/lib/qb/github/api.rb +43 -0
- data/lib/qb/github/issue.rb +83 -0
- data/lib/qb/github/repo_id.rb +127 -0
- data/lib/qb/github/resource.rb +59 -0
- data/lib/qb/github/types.rb +45 -0
- data/lib/qb/package.rb +131 -0
- data/lib/qb/package/gem.rb +2 -4
- data/lib/qb/package/version.rb +175 -2
- data/lib/qb/path.rb +2 -2
- data/lib/qb/repo.rb +137 -1
- data/lib/qb/repo/git.rb +55 -23
- data/lib/qb/repo/git/github.rb +137 -0
- data/lib/qb/role.rb +74 -30
- data/lib/qb/util.rb +1 -4
- data/lib/qb/util/docker_mixin.rb +30 -2
- data/lib/qb/util/interop.rb +68 -7
- data/lib/qb/util/logging.rb +215 -0
- data/lib/qb/util/stdio.rb +25 -9
- data/lib/qb/version.rb +16 -28
- data/library/stream +2 -2
- data/plugins/filter_plugins/ruby_interop_plugins.py +49 -31
- data/qb.gemspec +16 -4
- data/roles/qb.role/defaults/main.yml +6 -2
- data/roles/{qb.bump → qb/pkg/bump}/.qb-options.yml +0 -0
- data/roles/{qb.bump → qb/pkg/bump}/README.md +0 -0
- data/roles/{qb.bump → qb/pkg/bump}/defaults/main.yml +0 -0
- data/roles/{qb.bump → qb/pkg/bump}/library/bump +0 -0
- data/roles/{qb.bump → qb/pkg/bump}/meta/main.yml +0 -0
- data/roles/{qb.bump → qb/pkg/bump}/meta/qb.yml +0 -0
- data/roles/{qb.bump → qb/pkg/bump}/tasks/frontend/level/dev.yml +0 -0
- data/roles/{qb.bump → qb/pkg/bump}/tasks/frontend/level/rc.yml +0 -0
- data/roles/{qb.bump → qb/pkg/bump}/tasks/frontend/level/release.yml +0 -0
- data/roles/{qb.bump → qb/pkg/bump}/tasks/frontend/main.yml +0 -0
- data/roles/{qb.bump → qb/pkg/bump}/tasks/main.yml +1 -1
- data/roles/{qb.qb_role → qb/role/qb}/.qb-options.yml +0 -0
- data/roles/{qb.qb_role → qb/role/qb}/defaults/main.yml +0 -0
- data/roles/{qb.qb_role → qb/role/qb}/meta/main.yml +0 -0
- data/roles/{qb.qb_role → qb/role/qb}/meta/qb.yml +0 -0
- data/roles/{qb.qb_role → qb/role/qb}/tasks/main.yml +0 -0
- data/roles/{qb.qb_role → qb/role/qb}/templates/.gitkeep +0 -0
- data/roles/{qb.qb_role → qb/role/qb}/templates/qb.yml.j2 +0 -0
- data/roles/qb/test/rspec/spec/issue/defaults/main.yml +2 -0
- data/roles/qb/test/rspec/spec/issue/meta/main.yml +8 -0
- data/roles/qb/test/rspec/spec/issue/meta/qb.yml +67 -0
- data/roles/qb/test/rspec/spec/issue/tasks/main.yml +21 -0
- metadata +95 -26
data/lib/qb/util/stdio.rb
CHANGED
@@ -68,6 +68,8 @@ module QB::Util::STDIO
|
|
68
68
|
# their output to it, which is in turn printed to the console `qb` is running
|
69
69
|
# in.
|
70
70
|
class Service
|
71
|
+
include SemanticLogger::Loggable
|
72
|
+
|
71
73
|
def initialize name
|
72
74
|
@name = name
|
73
75
|
@thread = nil
|
@@ -81,15 +83,25 @@ module QB::Util::STDIO
|
|
81
83
|
|
82
84
|
@path = SOCKET_DIR.join "#{ name }.#{ SecureRandom.uuid }.sock"
|
83
85
|
|
84
|
-
|
86
|
+
self.logger = SemanticLogger[
|
87
|
+
[
|
88
|
+
"#{ self.class.name } {",
|
89
|
+
" name: #{ name }",
|
90
|
+
" path: #{ @path.to_s }",
|
91
|
+
"}"
|
92
|
+
].join( "\n" )
|
93
|
+
]
|
94
|
+
|
95
|
+
logger.trace "Initialized"
|
85
96
|
end
|
86
97
|
|
87
98
|
def debug *args
|
88
|
-
|
99
|
+
# logger.debug "#{ @debug_header }", args
|
100
|
+
logger.debug *args
|
89
101
|
end
|
90
102
|
|
91
103
|
def open!
|
92
|
-
|
104
|
+
logger.trace "opening..."
|
93
105
|
|
94
106
|
# make sure env var is not already set (basically just prevents you from
|
95
107
|
# accidentally opening two instances with the same name)
|
@@ -100,7 +112,8 @@ module QB::Util::STDIO
|
|
100
112
|
end
|
101
113
|
|
102
114
|
@thread = Thread.new do
|
103
|
-
|
115
|
+
Thread.current.name = @name
|
116
|
+
logger.trace "thread started."
|
104
117
|
|
105
118
|
@server = UNIXServer.new @path.to_s
|
106
119
|
|
@@ -113,9 +126,9 @@ module QB::Util::STDIO
|
|
113
126
|
|
114
127
|
# set the env key so children can find the socket path
|
115
128
|
ENV[@env_key] = @path.to_s
|
116
|
-
|
129
|
+
logger.trace "set env var", @env_key => ENV[@env_key]
|
117
130
|
|
118
|
-
|
131
|
+
logger.trace "service open."
|
119
132
|
end # open
|
120
133
|
|
121
134
|
def close!
|
@@ -123,7 +136,7 @@ module QB::Util::STDIO
|
|
123
136
|
#
|
124
137
|
# TODO not sure how correct this is...
|
125
138
|
#
|
126
|
-
|
139
|
+
logger.trace "closing..."
|
127
140
|
|
128
141
|
@socket.close unless @socket.nil?
|
129
142
|
@socket = nil
|
@@ -132,7 +145,7 @@ module QB::Util::STDIO
|
|
132
145
|
FileUtils.rm(@path) if @path.exist?
|
133
146
|
@thread.kill unless @thread.nil?
|
134
147
|
|
135
|
-
|
148
|
+
logger.trace "closed."
|
136
149
|
end
|
137
150
|
end # Service
|
138
151
|
|
@@ -146,7 +159,10 @@ module QB::Util::STDIO
|
|
146
159
|
|
147
160
|
def work_in_thread
|
148
161
|
while (line = @socket.gets) do
|
149
|
-
|
162
|
+
logger.trace "received line",
|
163
|
+
line: line,
|
164
|
+
dest: @dest
|
165
|
+
|
150
166
|
@dest.puts line
|
151
167
|
end
|
152
168
|
end
|
data/lib/qb/version.rb
CHANGED
@@ -4,7 +4,7 @@ module QB
|
|
4
4
|
|
5
5
|
GEM_NAME = 'qb'
|
6
6
|
|
7
|
-
VERSION = "0.3.
|
7
|
+
VERSION = "0.3.9"
|
8
8
|
|
9
9
|
MIN_ANSIBLE_VERSION = Gem::Version.new '2.1.2'
|
10
10
|
|
@@ -27,12 +27,11 @@ module QB
|
|
27
27
|
end
|
28
28
|
|
29
29
|
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
# If the version of Ansible found is less than {QB::MIN_ANSIBLE_VERSION}.
|
30
|
+
# @return [Gem::Version]
|
31
|
+
# the Ansible executable version parsed into a Gem version so we can
|
32
|
+
# compare it.
|
34
33
|
#
|
35
|
-
def self.
|
34
|
+
def self.ansible_version
|
36
35
|
out = Cmds.out! 'ansible --version'
|
37
36
|
version_str = out[/ansible\ ([\d\.]+)/, 1]
|
38
37
|
|
@@ -44,36 +43,25 @@ module QB
|
|
44
43
|
END
|
45
44
|
end
|
46
45
|
|
47
|
-
|
48
|
-
|
49
|
-
if version < QB::MIN_ANSIBLE_VERSION
|
50
|
-
raise QB::AnsibleVersionError, NRSER.squish(
|
51
|
-
<<-END
|
52
|
-
QB #{ QB::VERSION } requires Ansible #{ QB::MIN_ANSIBLE_VERSION },
|
53
|
-
found version #{ version_str } at #{ `which ansible` }
|
54
|
-
END
|
55
|
-
)
|
56
|
-
end
|
57
|
-
end # .check_ansible_version
|
46
|
+
Gem::Version.new version_str
|
47
|
+
end # .ansible_version
|
58
48
|
|
59
49
|
|
60
|
-
#
|
61
|
-
# QB doesn't satisfy it.
|
50
|
+
# Check that the Ansible version is not less than {QB::MIN_ANSIBLE_VERSION}.
|
62
51
|
#
|
63
|
-
# @raise [QB::
|
64
|
-
# If
|
52
|
+
# @raise [QB::AnsibleVersionError]
|
53
|
+
# If the version of Ansible found is less than {QB::MIN_ANSIBLE_VERSION}.
|
65
54
|
#
|
66
|
-
def self.
|
67
|
-
|
68
|
-
|
69
|
-
raise QB::QBVersionError, NRSER.squish(
|
55
|
+
def self.check_ansible_version
|
56
|
+
if ansible_version < QB::MIN_ANSIBLE_VERSION
|
57
|
+
raise QB::AnsibleVersionError, NRSER.squish(
|
70
58
|
<<-END
|
71
|
-
|
72
|
-
#{
|
59
|
+
QB #{ QB::VERSION } requires Ansible #{ QB::MIN_ANSIBLE_VERSION },
|
60
|
+
found version #{ version_str } at #{ `which ansible` }
|
73
61
|
END
|
74
62
|
)
|
75
63
|
end
|
76
|
-
end # .
|
64
|
+
end # .check_ansible_version
|
77
65
|
|
78
66
|
|
79
67
|
end # module QB
|
data/library/stream
CHANGED
@@ -30,13 +30,13 @@ class Stream < QB::Ansible::Module
|
|
30
30
|
}
|
31
31
|
|
32
32
|
[:format, :env_mode].each { |key|
|
33
|
-
opts[key] = @args[key].to_sym if @args.key?(key.to_s)
|
33
|
+
opts[key] = @args[key.to_s].to_sym if @args.key?(key.to_s)
|
34
34
|
}
|
35
35
|
|
36
36
|
cmd = Cmds.new(template, **opts)
|
37
37
|
|
38
38
|
if @args['log']
|
39
|
-
info "STREAMING
|
39
|
+
info "STREAMING\n\n#{ cmd.prepare }\n\n"
|
40
40
|
end
|
41
41
|
|
42
42
|
cmd.stream!
|
@@ -5,46 +5,37 @@ from ansible.errors import AnsibleError
|
|
5
5
|
|
6
6
|
import subprocess
|
7
7
|
import yaml
|
8
|
+
import os
|
8
9
|
from ansible.parsing.yaml.dumper import AnsibleDumper
|
9
10
|
|
10
|
-
|
11
|
+
|
12
|
+
QB_ROOT = os.path.realpath(
|
13
|
+
os.path.join(
|
14
|
+
os.path.dirname(os.path.realpath(__file__)), # /plugins/filter_plugins
|
15
|
+
'..', # /plugins
|
16
|
+
'..', # /
|
17
|
+
)
|
18
|
+
)
|
19
|
+
|
20
|
+
INTEROP_RECEIVE_EXE = os.path.join( QB_ROOT, 'exe', '.qb_interop_receive' )
|
21
|
+
|
22
|
+
|
23
|
+
def send_to_interop( payload ):
|
11
24
|
'''
|
12
|
-
|
25
|
+
Send a payload to QB Ruby code via a subprocess.
|
13
26
|
'''
|
14
27
|
|
15
|
-
payload =
|
16
|
-
'data': data,
|
17
|
-
'method': method,
|
18
|
-
'args': args,
|
19
|
-
'kwds': kwds,
|
20
|
-
}
|
21
|
-
|
22
|
-
input = yaml.dump(payload, Dumper=AnsibleDumper)
|
23
|
-
|
24
|
-
ruby_code = '''
|
25
|
-
# init bundler in dev env
|
26
|
-
if ENV['QB_DEV_ENV']
|
27
|
-
ENV.each {|k, v|
|
28
|
-
if k.start_with? 'QB_DEV_ENV_'
|
29
|
-
ENV[k.sub('QB_DEV_ENV_', '')] = v
|
30
|
-
end
|
31
|
-
}
|
32
|
-
require 'bundler/setup'
|
33
|
-
end
|
34
|
-
|
35
|
-
require 'qb'
|
36
|
-
|
37
|
-
QB::Util::Interop.receive
|
38
|
-
'''
|
28
|
+
input = yaml.dump( payload, Dumper=AnsibleDumper )
|
39
29
|
|
40
30
|
process = subprocess.Popen(
|
41
|
-
[
|
31
|
+
[ INTEROP_RECEIVE_EXE ],
|
42
32
|
stdin=subprocess.PIPE,
|
43
33
|
stdout=subprocess.PIPE,
|
44
34
|
stderr=subprocess.PIPE,
|
35
|
+
env=os.environ,
|
45
36
|
)
|
46
37
|
|
47
|
-
out, err = process.communicate(input)
|
38
|
+
out, err = process.communicate( input )
|
48
39
|
|
49
40
|
if process.returncode != 0:
|
50
41
|
raise AnsibleError('''
|
@@ -64,16 +55,43 @@ def qb_send(data, method, *args, **kwds):
|
|
64
55
|
''' % out)
|
65
56
|
|
66
57
|
return result
|
58
|
+
|
59
|
+
|
60
|
+
def qb_send( data, method, *args, **kwds ):
|
61
|
+
'''
|
62
|
+
Load data as an object in ruby and send it a message (call a method).
|
63
|
+
'''
|
67
64
|
|
65
|
+
return send_to_interop({
|
66
|
+
'data': data,
|
67
|
+
'method': method,
|
68
|
+
'args': args,
|
69
|
+
'kwds': kwds,
|
70
|
+
})
|
71
|
+
|
72
|
+
|
73
|
+
def qb_send_const( name, method, *args, **kwds ):
|
74
|
+
'''
|
75
|
+
Send a message (call a method) to a Ruby constant by name.
|
76
|
+
'''
|
77
|
+
|
78
|
+
return send_to_interop({
|
79
|
+
'const': name,
|
80
|
+
'method': method,
|
81
|
+
'args': args,
|
82
|
+
'kwds': kwds,
|
83
|
+
})
|
84
|
+
|
68
85
|
|
69
|
-
class FilterModule(object):
|
86
|
+
class FilterModule( object ):
|
70
87
|
'''
|
71
88
|
Ruby interop filters.
|
72
89
|
'''
|
73
90
|
|
74
|
-
def filters(self):
|
91
|
+
def filters( self ):
|
75
92
|
return {
|
76
|
-
'qb_send':
|
93
|
+
'qb_send': qb_send,
|
94
|
+
'qb_send_const': qb_send_const,
|
77
95
|
}
|
78
96
|
# filters()
|
79
97
|
# FilterModule
|
data/qb.gemspec
CHANGED
@@ -85,20 +85,32 @@ Gem::Specification.new do |spec|
|
|
85
85
|
end
|
86
86
|
|
87
87
|
spec.bindir = "exe"
|
88
|
-
|
88
|
+
|
89
|
+
# All files in //exe that *do not* start with `.`:
|
90
|
+
spec.executables = spec.files.grep(%r{^exe/[^\.]}) { |f| File.basename(f) }
|
91
|
+
|
89
92
|
spec.require_paths = ["lib"]
|
90
93
|
|
91
94
|
spec.add_development_dependency "bundler", "~> 1.10"
|
92
95
|
spec.add_development_dependency "rake", "~> 10.0"
|
93
|
-
spec.add_development_dependency "rspec"
|
96
|
+
spec.add_development_dependency "rspec", "~> 3.7.0"
|
94
97
|
spec.add_development_dependency "yard"
|
95
98
|
spec.add_development_dependency "pry"
|
96
99
|
|
97
|
-
spec.add_dependency "cmds",'~> 0.0', ">= 0.2.2"
|
98
|
-
spec.add_dependency "nrser",'~> 0.0', ">= 0.0.
|
100
|
+
spec.add_dependency "cmds", '~> 0.0', ">= 0.2.2"
|
101
|
+
spec.add_dependency "nrser", '~> 0.0', ">= 0.0.28"
|
99
102
|
spec.add_dependency "nrser-extras", '~> 0.0', ">= 0.0.3"
|
100
103
|
spec.add_dependency "state_mate", '~> 0.0', ">= 0.0.9"
|
101
104
|
spec.add_dependency 'parseconfig', '~> 1.0', '>= 1.0.8'
|
105
|
+
spec.add_dependency "octokit", "~> 4.0"
|
106
|
+
|
107
|
+
# Much better logging
|
108
|
+
spec.add_dependency 'semantic_logger', '~> 4.2'
|
109
|
+
# With much more awesome printing!
|
110
|
+
spec.add_dependency 'awesome_print', '~> 1.8'
|
111
|
+
|
112
|
+
# Ruby lib wrapping `git` binary system calls for use in {QB::Repo::Git}
|
113
|
+
spec.add_dependency 'git', '~> 1.3.0'
|
102
114
|
|
103
115
|
|
104
116
|
if QB::VERSION.end_with? '.dev'
|
@@ -2,8 +2,12 @@
|
|
2
2
|
role_dest: "{{ qb_dir }}"
|
3
3
|
role_force: false
|
4
4
|
|
5
|
-
# can't be named `role_name` 'cause Ansible sets that?
|
6
|
-
|
5
|
+
# NOTE can't be named `role_name` 'cause Ansible sets that?
|
6
|
+
#
|
7
|
+
# Call `QB::Role.default_role_name role_dest` to get the default name
|
8
|
+
#
|
9
|
+
role_role_name: >-
|
10
|
+
{{ 'QB::Role' | qb_send_const( 'default_role_name', role_dest ) }}
|
7
11
|
|
8
12
|
role_defaults: true
|
9
13
|
role_files: false
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,67 @@
|
|
1
|
+
---
|
2
|
+
# meta/qb.yml file for qb/test/rspec/spec/issue
|
3
|
+
#
|
4
|
+
# qb settings for this role. see README.md for more info.
|
5
|
+
#
|
6
|
+
|
7
|
+
# description of the role to show in it's help output.
|
8
|
+
description: null
|
9
|
+
|
10
|
+
# Gemspec-style requirements. Right now only `gems:qb` is used, but plan to
|
11
|
+
# generalize in the future.
|
12
|
+
requirements:
|
13
|
+
gems:
|
14
|
+
qb: ~> 0.3.0
|
15
|
+
|
16
|
+
# prefix for role variables
|
17
|
+
var_prefix: null
|
18
|
+
|
19
|
+
# how to get a default for `dir` if it's not provided as the only
|
20
|
+
# positional argument. if a positional argument is provided it will
|
21
|
+
# override the method defined here.
|
22
|
+
#
|
23
|
+
# options:
|
24
|
+
#
|
25
|
+
# - null
|
26
|
+
# - require the value on the command line.
|
27
|
+
# - false
|
28
|
+
# - don't provide qb_dir (means doesn't load or save options either).
|
29
|
+
# - git_root
|
30
|
+
# - use the git root of the directory that the `qb` command is invoked
|
31
|
+
# from. useful for 'project-centric' commands so they can be invoked
|
32
|
+
# from anywhere in the repo.
|
33
|
+
# - cwd
|
34
|
+
# - use the directory the `qb` command is invoked form.
|
35
|
+
# - {exe: PATH}
|
36
|
+
# - invoke an executable, passing a JSON serialization of the options
|
37
|
+
# mapping their CLI names to values. path can be relative to role
|
38
|
+
# directory.
|
39
|
+
# - {find_up: FILENAME}
|
40
|
+
# - starting at the current directory and climbing up to parent
|
41
|
+
# directories, use the first one that contains FILENAME. error
|
42
|
+
# if none is found.
|
43
|
+
default_dir: null
|
44
|
+
|
45
|
+
# If `true`, QB will ensure the default dir exists before starting the play.
|
46
|
+
#
|
47
|
+
# For legacy reasons, this defaults to `true` if not present, but we want to
|
48
|
+
# default declare it as `false` here so new roles can turn it on only if
|
49
|
+
# they need it.
|
50
|
+
#
|
51
|
+
mkdir: false
|
52
|
+
|
53
|
+
# default user to become for play
|
54
|
+
default_user: null
|
55
|
+
|
56
|
+
# set to false to not save options in .qb-options.yml files
|
57
|
+
save_options: true
|
58
|
+
|
59
|
+
# options to pass to ansible-playbook
|
60
|
+
ansible_options: {}
|
61
|
+
|
62
|
+
options: []
|
63
|
+
# - name: example
|
64
|
+
# description: an example of a variable.
|
65
|
+
# required: false
|
66
|
+
# type: boolean # boolean (default) | string
|
67
|
+
# short: e
|