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