qb 0.3.8 → 0.3.9

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