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/path.rb
CHANGED
@@ -16,7 +16,7 @@ require 'nrser'
|
|
16
16
|
# Package
|
17
17
|
# -----------------------------------------------------------------------
|
18
18
|
|
19
|
-
|
19
|
+
require 'qb/repo/git'
|
20
20
|
|
21
21
|
|
22
22
|
# Refinements
|
@@ -278,7 +278,7 @@ class QB::Path < Pathname
|
|
278
278
|
|
279
279
|
def gem
|
280
280
|
unless instance_variable_defined? :@gem
|
281
|
-
@gem = QB::Package::Gem.from_root_path path
|
281
|
+
@gem = QB::Package::Gem.from_root_path path, repo: git
|
282
282
|
end
|
283
283
|
|
284
284
|
@gem
|
data/lib/qb/repo.rb
CHANGED
@@ -1 +1,137 @@
|
|
1
|
-
|
1
|
+
# Requirements
|
2
|
+
# =======================================================================
|
3
|
+
|
4
|
+
# Stdlib
|
5
|
+
# -----------------------------------------------------------------------
|
6
|
+
|
7
|
+
# Deps
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
|
10
|
+
# Project / Package
|
11
|
+
# -----------------------------------------------------------------------
|
12
|
+
|
13
|
+
|
14
|
+
# Refinements
|
15
|
+
# =======================================================================
|
16
|
+
|
17
|
+
require 'nrser/refinements'
|
18
|
+
using NRSER
|
19
|
+
|
20
|
+
require 'nrser/refinements/types'
|
21
|
+
using NRSER::Types
|
22
|
+
|
23
|
+
|
24
|
+
# Declarations
|
25
|
+
# =======================================================================
|
26
|
+
|
27
|
+
|
28
|
+
# Definitions
|
29
|
+
# =======================================================================
|
30
|
+
|
31
|
+
# @todo document QB::Repo class.
|
32
|
+
class QB::Repo < QB::Util::Resource
|
33
|
+
|
34
|
+
# Constants
|
35
|
+
# ======================================================================
|
36
|
+
|
37
|
+
|
38
|
+
# Class Methods
|
39
|
+
# ======================================================================
|
40
|
+
|
41
|
+
# Get an instance for whatever repo `path` is in.
|
42
|
+
#
|
43
|
+
# @param [String, Pathname] path
|
44
|
+
# A path that may be in a repo.
|
45
|
+
#
|
46
|
+
# @return [nil]
|
47
|
+
# If `path` *is not* a part of repo we can recognize (`git` only at the
|
48
|
+
# moment, sorry).
|
49
|
+
#
|
50
|
+
# @return [QB::Repo]
|
51
|
+
# If `path` *is* not a part of repo we can recognize.
|
52
|
+
#
|
53
|
+
def self.from_path path, git: {}
|
54
|
+
QB::Repo::Git.from_path path, **git
|
55
|
+
end # .from_path
|
56
|
+
|
57
|
+
|
58
|
+
# Instantiate a {QB::Repo} for the repo `path` is in or raise if it's not in
|
59
|
+
# any single recognizable repo.
|
60
|
+
#
|
61
|
+
# @param path see .from_path
|
62
|
+
# @param **opts see .from_path
|
63
|
+
#
|
64
|
+
# @return [QB::Repo]
|
65
|
+
#
|
66
|
+
# @raise [QB::FSStateError]
|
67
|
+
# If `path` is not in a repo.
|
68
|
+
#
|
69
|
+
def self.from_path! path, **opts
|
70
|
+
from_path( path, **opts ).tap { |repo|
|
71
|
+
if repo.nil?
|
72
|
+
raise QB::FSStateError,
|
73
|
+
"Path #{ path.inspect } does not appear to be in a repo."
|
74
|
+
end
|
75
|
+
}
|
76
|
+
end # .from_path!
|
77
|
+
|
78
|
+
|
79
|
+
# Properties
|
80
|
+
# ======================================================================
|
81
|
+
|
82
|
+
# @!attribute [r] ref_path
|
83
|
+
# User-provided path value used to construct the resource instance, if any.
|
84
|
+
#
|
85
|
+
# This may not be the same as a root path for the resource, such as with
|
86
|
+
# resource classes that can be constructed from any path *inside* the
|
87
|
+
# directory, like a {QB::Repo::Git}.
|
88
|
+
#
|
89
|
+
# @return [String | Pathname]
|
90
|
+
# If the resource instance was constructed based on a path argument.
|
91
|
+
#
|
92
|
+
# @return [nil]
|
93
|
+
# If the resource instance was *not* constructed based on a path
|
94
|
+
# argument.
|
95
|
+
#
|
96
|
+
prop :ref_path, type: t.maybe( t.path )
|
97
|
+
|
98
|
+
|
99
|
+
# @!attribute [r] root_path
|
100
|
+
# Absolute path to the gem's root directory.
|
101
|
+
#
|
102
|
+
# @return [Pathname]
|
103
|
+
#
|
104
|
+
prop :root_path, type: t.dir_path
|
105
|
+
|
106
|
+
|
107
|
+
# @!attribute [r] name
|
108
|
+
# The string name of the repo.
|
109
|
+
#
|
110
|
+
# @return [String]
|
111
|
+
# Non-empty string.
|
112
|
+
#
|
113
|
+
prop :name, type: t.maybe( t.non_empty_str )
|
114
|
+
|
115
|
+
|
116
|
+
# Instance Methods
|
117
|
+
# ======================================================================
|
118
|
+
|
119
|
+
# @todo Document tags method.
|
120
|
+
#
|
121
|
+
# @param [type] arg_name
|
122
|
+
# @todo Add name param description.
|
123
|
+
#
|
124
|
+
# @return [Array<String>]
|
125
|
+
#
|
126
|
+
def tags
|
127
|
+
raise NotImplementedError
|
128
|
+
end # #tags
|
129
|
+
|
130
|
+
|
131
|
+
end # class QB::Repo
|
132
|
+
|
133
|
+
|
134
|
+
# Post-Processing
|
135
|
+
# =======================================================================
|
136
|
+
|
137
|
+
require 'qb/repo/git'
|
data/lib/qb/repo/git.rb
CHANGED
@@ -7,9 +7,11 @@
|
|
7
7
|
# Deps
|
8
8
|
# -----------------------------------------------------------------------
|
9
9
|
require 'cmds'
|
10
|
+
require 'git'
|
10
11
|
|
11
12
|
# Project / Package
|
12
13
|
# -----------------------------------------------------------------------
|
14
|
+
require 'qb/util/resource'
|
13
15
|
|
14
16
|
|
15
17
|
# Refinements
|
@@ -26,7 +28,7 @@ using NRSER::Types
|
|
26
28
|
# =======================================================================
|
27
29
|
|
28
30
|
module QB; end
|
29
|
-
|
31
|
+
class QB::Repo < QB::Util::Resource; end
|
30
32
|
|
31
33
|
|
32
34
|
# Definitions
|
@@ -37,11 +39,11 @@ module QB::Repo; end
|
|
37
39
|
#
|
38
40
|
# The main entry point is {QB::Repo::Git.from_path}, which creates a
|
39
41
|
#
|
40
|
-
class QB::Repo::Git <
|
42
|
+
class QB::Repo::Git < QB::Repo
|
41
43
|
GITHUB_SSH_URL_RE = /^git@github\.com\:(?<owner>.*)\/(?<name>.*)\.git$/
|
42
44
|
GITHUB_HTTPS_URL_RE = /^https:\/\/github\.com\/(?<owner>.*)\/(?<name>.*)\.git$/
|
43
45
|
|
44
|
-
class User <
|
46
|
+
class User < QB::Util::Resource
|
45
47
|
prop :name, type: t.maybe(t.str), default: nil
|
46
48
|
prop :email, type: t.maybe(t.str), default: nil
|
47
49
|
end
|
@@ -119,6 +121,13 @@ class QB::Repo::Git < NRSER::Meta::Props::Base
|
|
119
121
|
# Class Methods
|
120
122
|
# =====================================================================
|
121
123
|
|
124
|
+
# Factories
|
125
|
+
# ---------------------------------------------------------------------
|
126
|
+
#
|
127
|
+
# Class methods that instantiate an instance of {QB::Repo::Git}, specializing
|
128
|
+
# it as a subclass when appropriate.
|
129
|
+
#
|
130
|
+
|
122
131
|
# Instantiate a {QB::Package::Git} resource for whatever Git repo `path`
|
123
132
|
# is in, or return `nil` if `path` is not in a Git repo.
|
124
133
|
#
|
@@ -145,10 +154,10 @@ class QB::Repo::Git < NRSER::Meta::Props::Base
|
|
145
154
|
# `input_path`.
|
146
155
|
#
|
147
156
|
def self.from_path path, use_github_api: false
|
148
|
-
|
157
|
+
ref_path = path
|
149
158
|
|
150
159
|
# Create a Pathname from the input
|
151
|
-
input_path = Pathname.new
|
160
|
+
input_path = Pathname.new ref_path
|
152
161
|
|
153
162
|
# input_path may point to a file, or something that doesn't even exist.
|
154
163
|
# We want to ascend until we find an existing directory that we can cd into.
|
@@ -158,7 +167,7 @@ class QB::Repo::Git < NRSER::Meta::Props::Base
|
|
158
167
|
if closest_dir.nil?
|
159
168
|
raise QB::FSStateError,
|
160
169
|
"Unable to find any existing directory from path " +
|
161
|
-
"#{
|
170
|
+
"#{ ref_path.inspect }"
|
162
171
|
end
|
163
172
|
|
164
173
|
# Change into the directory to make shell life easier
|
@@ -169,7 +178,7 @@ class QB::Repo::Git < NRSER::Meta::Props::Base
|
|
169
178
|
return nil
|
170
179
|
end
|
171
180
|
|
172
|
-
|
181
|
+
root_path = Pathname.new root_result.out.chomp
|
173
182
|
|
174
183
|
user = User.new **NRSER.map_values(User.props.keys) {|key, _|
|
175
184
|
begin
|
@@ -205,13 +214,9 @@ class QB::Repo::Git < NRSER::Meta::Props::Base
|
|
205
214
|
name = nil
|
206
215
|
github = nil
|
207
216
|
|
208
|
-
if origin &&
|
209
|
-
GITHUB_SSH_URL_RE.match(origin) ||
|
210
|
-
GITHUB_HTTPS_URL_RE.match(origin)
|
211
|
-
)
|
217
|
+
if origin && QB::Repo::Git::GitHub.url?( origin )
|
212
218
|
|
213
|
-
|
214
|
-
name = match['name']
|
219
|
+
repo_id = QB::Repo::Git::GitHub.parse_url origin
|
215
220
|
|
216
221
|
if use_github_api
|
217
222
|
github = OpenStruct.new
|
@@ -231,12 +236,27 @@ class QB::Repo::Git < NRSER::Meta::Props::Base
|
|
231
236
|
github = github.to_h
|
232
237
|
end
|
233
238
|
|
239
|
+
return QB::Repo::Git::GitHub.new(
|
240
|
+
ref_path: ref_path,
|
241
|
+
input_path: input_path,
|
242
|
+
root_path: root_path,
|
243
|
+
user: user,
|
244
|
+
is_clean: is_clean,
|
245
|
+
head: head,
|
246
|
+
branch: branch,
|
247
|
+
origin: origin,
|
248
|
+
repo_id: repo_id,
|
249
|
+
owner: repo_id.owner,
|
250
|
+
name: repo_id.name,
|
251
|
+
github: github,
|
252
|
+
)
|
253
|
+
|
234
254
|
end
|
235
255
|
|
236
256
|
new(
|
237
|
-
|
257
|
+
ref_path: ref_path,
|
238
258
|
input_path: input_path,
|
239
|
-
|
259
|
+
root_path: root_path,
|
240
260
|
user: user,
|
241
261
|
is_clean: is_clean,
|
242
262
|
head: head,
|
@@ -283,16 +303,13 @@ class QB::Repo::Git < NRSER::Meta::Props::Base
|
|
283
303
|
# Props
|
284
304
|
# =====================================================================
|
285
305
|
|
286
|
-
prop :raw_input_path, type: t.path, default: nil, to_data: :to_s
|
287
|
-
prop :root, type: t.pathname, to_data: :to_s
|
288
306
|
prop :user, type: User
|
289
307
|
prop :is_clean, type: t.bool
|
290
|
-
prop :head, type: t.maybe(t.str)
|
291
|
-
prop :branch, type: t.maybe(t.str)
|
292
|
-
prop :origin, type: t.maybe(t.str)
|
293
|
-
prop :owner, type: t.maybe(t.str)
|
294
|
-
prop :
|
295
|
-
prop :github, type: t.maybe(t.hash_), default: nil
|
308
|
+
prop :head, type: t.maybe(t.str)
|
309
|
+
prop :branch, type: t.maybe(t.str)
|
310
|
+
prop :origin, type: t.maybe(t.str)
|
311
|
+
prop :owner, type: t.maybe(t.str)
|
312
|
+
prop :github, type: t.maybe(t.hash_)
|
296
313
|
|
297
314
|
|
298
315
|
# Derived Properties
|
@@ -318,6 +335,10 @@ class QB::Repo::Git < NRSER::Meta::Props::Base
|
|
318
335
|
!github.nil?
|
319
336
|
end
|
320
337
|
|
338
|
+
def api
|
339
|
+
@api ||= ::Git.open root_path
|
340
|
+
end
|
341
|
+
|
321
342
|
|
322
343
|
# Reading Repo State
|
323
344
|
# ---------------------------------------------------------------------
|
@@ -329,4 +350,15 @@ class QB::Repo::Git < NRSER::Meta::Props::Base
|
|
329
350
|
is_clean
|
330
351
|
end
|
331
352
|
|
353
|
+
|
354
|
+
def tags
|
355
|
+
api.tags.map &:name
|
356
|
+
end
|
357
|
+
|
332
358
|
end # class QB::Repo::Git
|
359
|
+
|
360
|
+
|
361
|
+
# Post-Processing
|
362
|
+
# =======================================================================
|
363
|
+
|
364
|
+
require 'qb/repo/git/github'
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# Requirements
|
2
|
+
# =======================================================================
|
3
|
+
|
4
|
+
# Stdlib
|
5
|
+
# -----------------------------------------------------------------------
|
6
|
+
|
7
|
+
# Deps
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
|
10
|
+
# Project / Package
|
11
|
+
# -----------------------------------------------------------------------
|
12
|
+
require 'qb/github'
|
13
|
+
require 'qb/repo/git'
|
14
|
+
|
15
|
+
# Refinements
|
16
|
+
# =======================================================================
|
17
|
+
|
18
|
+
require 'nrser/refinements'
|
19
|
+
using NRSER
|
20
|
+
|
21
|
+
require 'nrser/refinements/types'
|
22
|
+
using NRSER::Types
|
23
|
+
|
24
|
+
|
25
|
+
# Definitions
|
26
|
+
# =======================================================================
|
27
|
+
|
28
|
+
# Git repo where the `origin` remote points to GitHub, which is used to
|
29
|
+
# determine it's owner and name.
|
30
|
+
#
|
31
|
+
class QB::Repo::Git::GitHub < QB::Repo::Git
|
32
|
+
|
33
|
+
# Constants
|
34
|
+
# ======================================================================
|
35
|
+
|
36
|
+
SSH_URL_RE = /^git@github\.com\:(?<owner>.*)\/(?<name>.*)\.git$/
|
37
|
+
HTTPS_URL_RE = /^https:\/\/github\.com\/(?<owner>.*)\/(?<name>.*)\.git$/
|
38
|
+
|
39
|
+
|
40
|
+
# Props
|
41
|
+
# ---------------------------------------------------------------------
|
42
|
+
|
43
|
+
### Primary Properties
|
44
|
+
|
45
|
+
prop :repo_id, type: QB::GitHub::RepoID
|
46
|
+
|
47
|
+
|
48
|
+
### Derived Properties
|
49
|
+
|
50
|
+
|
51
|
+
# Class Methods
|
52
|
+
# ======================================================================
|
53
|
+
|
54
|
+
# Helpers
|
55
|
+
# ---------------------------------------------------------------------
|
56
|
+
|
57
|
+
def self.ssh_url? string
|
58
|
+
SSH_URL_RE =~ string
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def self.https_url? string
|
63
|
+
HTTPS_URL_RE =~ string
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def self.url? string
|
68
|
+
ssh_url?( string ) || https_url?( string )
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
def self.parse_ssh_url string
|
73
|
+
parse_url_with SSH_URL_RE, string
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def self.parse_https_url string
|
78
|
+
parse_url_with HTTPS_URL_RE, string
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
# Extract owner and name from Git remote URL string pointing to GitHub.
|
83
|
+
#
|
84
|
+
# @return [nil]
|
85
|
+
# If the URL is not recognized.
|
86
|
+
#
|
87
|
+
# @return [QB::GitHub::RepoID]
|
88
|
+
# If the URL successfully parses.
|
89
|
+
#
|
90
|
+
def self.parse_url string
|
91
|
+
parse_ssh_url( string ) || parse_https_url( string )
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
# Eigenclass (Singleton Class)
|
96
|
+
# ========================================================================
|
97
|
+
#
|
98
|
+
class << self
|
99
|
+
protected
|
100
|
+
# ========================================================================
|
101
|
+
|
102
|
+
|
103
|
+
# @todo Document parse_url_with method.
|
104
|
+
#
|
105
|
+
# @param [type] arg_name
|
106
|
+
# @todo Add name param description.
|
107
|
+
#
|
108
|
+
# @return [return_type]
|
109
|
+
# @todo Document return value.
|
110
|
+
#
|
111
|
+
def parse_url_with regexp, string
|
112
|
+
if match = regexp.match( string )
|
113
|
+
QB::GitHub::RepoID.new owner: match['owner'], name: match['name']
|
114
|
+
end
|
115
|
+
end # #parse_url_with
|
116
|
+
|
117
|
+
|
118
|
+
# end protected
|
119
|
+
end # class << self (Eigenclass)
|
120
|
+
|
121
|
+
|
122
|
+
# Instance Methods
|
123
|
+
# ======================================================================
|
124
|
+
|
125
|
+
def api
|
126
|
+
QB::GitHub::API.client.repo repo_id.path
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
def issue number
|
131
|
+
# QB::GitHub::API.client.issue( repo_id.path, number ).to_h.stringify_keys
|
132
|
+
QB::GitHub::Issue.find_by repo_id: repo_id, number: number
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
end # class QB::Repo::Git::GitHub
|
137
|
+
|