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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +4 -0
  3. data/exe/.qb_interop_receive +39 -0
  4. data/exe/qb +8 -5
  5. data/lib/qb.rb +64 -19
  6. data/lib/qb/cli/run.rb +1 -1
  7. data/lib/qb/github.rb +4 -0
  8. data/lib/qb/github/api.rb +43 -0
  9. data/lib/qb/github/issue.rb +83 -0
  10. data/lib/qb/github/repo_id.rb +127 -0
  11. data/lib/qb/github/resource.rb +59 -0
  12. data/lib/qb/github/types.rb +45 -0
  13. data/lib/qb/package.rb +131 -0
  14. data/lib/qb/package/gem.rb +2 -4
  15. data/lib/qb/package/version.rb +175 -2
  16. data/lib/qb/path.rb +2 -2
  17. data/lib/qb/repo.rb +137 -1
  18. data/lib/qb/repo/git.rb +55 -23
  19. data/lib/qb/repo/git/github.rb +137 -0
  20. data/lib/qb/role.rb +74 -30
  21. data/lib/qb/util.rb +1 -4
  22. data/lib/qb/util/docker_mixin.rb +30 -2
  23. data/lib/qb/util/interop.rb +68 -7
  24. data/lib/qb/util/logging.rb +215 -0
  25. data/lib/qb/util/stdio.rb +25 -9
  26. data/lib/qb/version.rb +16 -28
  27. data/library/stream +2 -2
  28. data/plugins/filter_plugins/ruby_interop_plugins.py +49 -31
  29. data/qb.gemspec +16 -4
  30. data/roles/qb.role/defaults/main.yml +6 -2
  31. data/roles/{qb.bump → qb/pkg/bump}/.qb-options.yml +0 -0
  32. data/roles/{qb.bump → qb/pkg/bump}/README.md +0 -0
  33. data/roles/{qb.bump → qb/pkg/bump}/defaults/main.yml +0 -0
  34. data/roles/{qb.bump → qb/pkg/bump}/library/bump +0 -0
  35. data/roles/{qb.bump → qb/pkg/bump}/meta/main.yml +0 -0
  36. data/roles/{qb.bump → qb/pkg/bump}/meta/qb.yml +0 -0
  37. data/roles/{qb.bump → qb/pkg/bump}/tasks/frontend/level/dev.yml +0 -0
  38. data/roles/{qb.bump → qb/pkg/bump}/tasks/frontend/level/rc.yml +0 -0
  39. data/roles/{qb.bump → qb/pkg/bump}/tasks/frontend/level/release.yml +0 -0
  40. data/roles/{qb.bump → qb/pkg/bump}/tasks/frontend/main.yml +0 -0
  41. data/roles/{qb.bump → qb/pkg/bump}/tasks/main.yml +1 -1
  42. data/roles/{qb.qb_role → qb/role/qb}/.qb-options.yml +0 -0
  43. data/roles/{qb.qb_role → qb/role/qb}/defaults/main.yml +0 -0
  44. data/roles/{qb.qb_role → qb/role/qb}/meta/main.yml +0 -0
  45. data/roles/{qb.qb_role → qb/role/qb}/meta/qb.yml +0 -0
  46. data/roles/{qb.qb_role → qb/role/qb}/tasks/main.yml +0 -0
  47. data/roles/{qb.qb_role → qb/role/qb}/templates/.gitkeep +0 -0
  48. data/roles/{qb.qb_role → qb/role/qb}/templates/qb.yml.j2 +0 -0
  49. data/roles/qb/test/rspec/spec/issue/defaults/main.yml +2 -0
  50. data/roles/qb/test/rspec/spec/issue/meta/main.yml +8 -0
  51. data/roles/qb/test/rspec/spec/issue/meta/qb.yml +67 -0
  52. data/roles/qb/test/rspec/spec/issue/tasks/main.yml +21 -0
  53. metadata +95 -26
@@ -16,7 +16,7 @@ require 'nrser'
16
16
  # Package
17
17
  # -----------------------------------------------------------------------
18
18
 
19
- require_relative './repo/git'
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
@@ -1 +1,137 @@
1
- require_relative './repo/git'
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'
@@ -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
- module QB::Repo; end
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 < NRSER::Meta::Props::Base
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 < NRSER::Meta::Props::Base
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
- raw_input_path = path
157
+ ref_path = path
149
158
 
150
159
  # Create a Pathname from the input
151
- input_path = Pathname.new raw_input_path
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
- "#{ raw_input_path.inspect }"
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
- root = Pathname.new root_result.out.chomp
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 && match = (
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
- owner = match['owner']
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
- raw_input_path: raw_input_path,
257
+ ref_path: ref_path,
238
258
  input_path: input_path,
239
- root: root,
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), default: nil
291
- prop :branch, type: t.maybe(t.str), default: nil
292
- prop :origin, type: t.maybe(t.str), default: nil
293
- prop :owner, type: t.maybe(t.str), default: nil
294
- prop :name, type: t.maybe(t.str), default: nil
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
+