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
@@ -0,0 +1,59 @@
1
+ # Requirements
2
+ # =======================================================================
3
+
4
+ # Stdlib
5
+ # -----------------------------------------------------------------------
6
+
7
+ # Deps
8
+ # -----------------------------------------------------------------------
9
+
10
+ # Project / Package
11
+ # -----------------------------------------------------------------------
12
+
13
+
14
+ # Refinements
15
+ # =======================================================================
16
+
17
+
18
+ # Declarations
19
+ # =======================================================================
20
+
21
+
22
+ # Definitions
23
+ # =======================================================================
24
+
25
+
26
+ # @todo document QB::GitHub::Resource class.
27
+ class QB::GitHub::Resource < QB::Util::Resource
28
+
29
+ # Constants
30
+ # ======================================================================
31
+
32
+
33
+ # Class Methods
34
+ # ======================================================================
35
+
36
+
37
+ # Attributes
38
+ # ======================================================================
39
+
40
+
41
+ # Constructor
42
+ # ======================================================================
43
+
44
+ # Instantiate a new `QB::GitHub::Resource`.
45
+ def initialize octokit_resource
46
+ @octokit_resource = octokit_resource
47
+ end # #initialize
48
+
49
+
50
+ # Instance Methods
51
+ # ======================================================================
52
+
53
+
54
+ end # class QB::GitHub::Resource
55
+
56
+
57
+
58
+ # Post-Processing
59
+ # =======================================================================
@@ -0,0 +1,45 @@
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
+ module QB; end
28
+ module QB::GitHub; end
29
+
30
+
31
+ # Definitions
32
+ # =======================================================================
33
+
34
+ module QB::GitHub::Types
35
+
36
+ def self.repo_name
37
+ t.path_seg name: 'GitHubRepoName(String)'
38
+ end
39
+
40
+ def self.repo_owner
41
+ t.path_seg name: 'GitHubRepoOwner(String)'
42
+ end
43
+
44
+ end # module QB::GitHub::Types
45
+
@@ -92,6 +92,137 @@ class QB::Package < QB::Util::Resource
92
92
  prop :name, type: t.non_empty_str
93
93
 
94
94
 
95
+ # @!attribute [r] repo_rel_path
96
+ # @todo Doc repo_rel_path property...
97
+ #
98
+ # @return [PropRubyType]
99
+ #
100
+ prop :repo_rel_path,
101
+ type: t.maybe( t.dir_path ),
102
+ source: :repo_rel_path
103
+
104
+
105
+ # Constructor
106
+ # =====================================================================
107
+
108
+ def initialize repo: NRSER::NO_ARG, **props
109
+ @repo = repo
110
+ super **props
111
+ end # #initialize
112
+
113
+
114
+ # Instance Methods
115
+ # =====================================================================
116
+
117
+ # Repository
118
+ # ---------------------------------------------------------------------
119
+
120
+ # @todo Document repo method.
121
+ #
122
+ # @param [type] arg_name
123
+ # @todo Add name param description.
124
+ #
125
+ # @return [return_type]
126
+ # @todo Document return value.
127
+ #
128
+ def repo
129
+ if @repo == NRSER::NO_ARG
130
+ @repo = QB::Repo.from_path root_path
131
+ end
132
+
133
+ @repo
134
+ end # #repo
135
+
136
+
137
+ # @return [Boolean]
138
+ # `true` if {#root_path} is in a repo type we recognize.
139
+ #
140
+ def in_repo?
141
+ !!repo
142
+ end # #in_repo?
143
+
144
+
145
+ # Relative path from the {#repo} root to the {#root_path}.
146
+ #
147
+ # Used as the version tag prefix (unless it's `.` - when the repo root is
148
+ # the root path).
149
+ #
150
+ # @return [Pathname]
151
+ #
152
+ def repo_rel_path
153
+ root_path.relative_path_from( repo.root_path ) if in_repo?
154
+ end
155
+
156
+
157
+ # Get the string prefix for tagging versions of this package.
158
+ #
159
+ # Only makes any sense if the package is in a recognized repo, and will error
160
+ # out if that's not the case.
161
+ #
162
+ # The most basic prefix is "v" for packages located at the root of the
163
+ # repository.
164
+ #
165
+ # @example
166
+ # repo_root = '.'
167
+ # package_root = repo_root
168
+ # QB::Package.from_path( package_root ).version_tag_prefix
169
+ # # => 'v'
170
+ # # (an actual tag would look like 'v0.1.2')
171
+ #
172
+ # To support "multi-package" repos - which is a way of dealing with apps that
173
+ # are composed of multiple versioned services without having to create a new
174
+ # submodule for every micro-service - packages that do not share the same
175
+ # root of the repo are prefixed by the relative path from the repo root to
176
+ # the package root.
177
+ #
178
+ # @example
179
+ # repo_root = Pathname.new '.'
180
+ # package_root = repo_root / 'services' / 'some-service'
181
+ # QB::Package.from_path( package_root ).version_tag_prefix
182
+ # # => 'services/some-service/v'
183
+ # # (an actual tag would look like 'services/some-service/v0.1.2')
184
+ #
185
+ # This creates a unique and intuitive namespace scheme for supporting
186
+ # multiple independent package versions in a single repo, which has proved
187
+ # handy for container-ized apps.
188
+ #
189
+ # Unless, of course, you change the package's path. Then it will get wonky.
190
+ # We'll burn that bridge when we come to it.
191
+ #
192
+ # @return [String]
193
+ #
194
+ def version_tag_prefix
195
+ if root_path == repo.root_path
196
+ 'v'
197
+ else
198
+ (repo_rel_path / 'v').to_s
199
+ end
200
+ end # #version_tag_prefix
201
+
202
+
203
+
204
+ #
205
+ #
206
+ # @return [String]
207
+ #
208
+ def version_tag
209
+ version_tag_prefix + version.semver
210
+ end # #version_tag
211
+
212
+
213
+ # @todo Document versions method.
214
+ #
215
+ # @param [type] arg_name
216
+ # @todo Add name param description.
217
+ #
218
+ # @return [return_type]
219
+ # @todo Document return value.
220
+ #
221
+ def versions
222
+ # method body...
223
+ end # #versions
224
+
225
+
95
226
  end # class QB::Package
96
227
 
97
228
 
@@ -71,9 +71,9 @@ class QB::Package::Gem < QB::Package
71
71
  # @raise [QB::FSStateError]
72
72
  # If `path` is not a directory.
73
73
  #
74
- def from_root_path path
74
+ def from_root_path path, repo: NRSER::NO_ARG
75
75
  # Values we will use to construct the resource instance.
76
- values = {}
76
+ values = {repo: repo}
77
77
 
78
78
  # Whatever we were passes is the reference path
79
79
  values[:ref_path] = path
@@ -129,8 +129,6 @@ class QB::Package::Gem < QB::Package
129
129
  }
130
130
  end # #from_root_path!
131
131
 
132
-
133
-
134
132
  end # class << self (Eigenclass)
135
133
 
136
134
 
@@ -17,6 +17,9 @@ require 'qb/util/resource'
17
17
  # Refinements
18
18
  # =======================================================================
19
19
 
20
+ require 'nrser/refinements'
21
+ using NRSER
22
+
20
23
  require 'nrser/refinements/types'
21
24
  using NRSER::Types
22
25
 
@@ -41,6 +44,7 @@ class QB::Package::Version < QB::Util::Resource
41
44
  # Mixins
42
45
  # =====================================================================
43
46
 
47
+ include Comparable
44
48
  include QB::Util::DockerMixin
45
49
 
46
50
 
@@ -52,6 +56,36 @@ class QB::Package::Version < QB::Util::Resource
52
56
  MIXED_SEGMENT = t.union NUMBER_SEGMENT, NAME_SEGMENT
53
57
 
54
58
 
59
+ # Reasonably simple regular expression to extract things that might be
60
+ # versions from strings.
61
+ #
62
+ # Intended for use on reasonably short strings like `git tag` output or
63
+ # what-not... probably not well suited for sifting through mountains of
64
+ # text.
65
+ #
66
+ # Structure:
67
+ #
68
+ # 1. The major version number, matched by a digit `1-9` followed by any
69
+ # number of digits.
70
+ # 2. A separator to the next segment, which is:
71
+ # 1. `.` separating to the minor version number
72
+ # 2. `-` separating to the prerelease
73
+ # 3. `+` separating to the build
74
+ # 3. One or more of `a-z`, `A-Z`, `0-9`, `.`, `-`, `_`, `+`
75
+ # 4. Ends with one of those that is *not* `.`, `_` or `+`, so `a-z`, `A-Z`,
76
+ # `0-9`.
77
+ #
78
+ # This will match *many* strings that are not versions, but it should not
79
+ # miss any that are. It cold obviously be refined and improve to reduce
80
+ # false positives at the cost of additional complexity, but I wanted to
81
+ # start simple and complicate it as needed.
82
+ #
83
+ # @return [Regexp]
84
+ #
85
+ POSSIBLE_VERSION_RE = \
86
+ /(?:0|[1-9]\d*)[\.\-\+][a-zA-Z0-9\.\-\_\+]*[a-zA-Z0-9\-]+/
87
+
88
+
55
89
  # Props
56
90
  # =====================================================================
57
91
 
@@ -89,9 +123,13 @@ class QB::Package::Version < QB::Util::Resource
89
123
  # Utilities
90
124
  # ---------------------------------------------------------------------
91
125
 
126
+ # Time formatted to be stuck in a version segment per [Semver][] spec.
127
+ # We also strip out '-' to avoid possible parsing weirdness.
128
+ #
129
+ # [Semver]: https://semver.org/
130
+ #
92
131
  # @return [String]
93
- # Time formatted to be stuck in a version segment per Semver spec.
94
- # We also strip out '-' to avoid possible parsing weirdness.
132
+ #
95
133
  def self.to_time_segment time
96
134
  time.utc.iso8601.gsub /[^0-9A-Za-z]/, ''
97
135
  end
@@ -131,6 +169,7 @@ class QB::Package::Version < QB::Util::Resource
131
169
  build: []
132
170
  end
133
171
 
172
+
134
173
  def self.from_npm_version version
135
174
  stmt = NRSER.squish <<-END
136
175
  var Semver = require('semver');
@@ -186,6 +225,27 @@ class QB::Package::Version < QB::Util::Resource
186
225
  end
187
226
  end
188
227
 
228
+ singleton_class.send :alias_method, :from_s, :from_string
229
+
230
+
231
+ # Extract version number from a string.
232
+ #
233
+ # @param [String] string
234
+ # String containing versions.
235
+ #
236
+ # @return [Array<QB::Package::Version]
237
+ # Any versions extracted from the string.
238
+ #
239
+ def self.extract string
240
+ string.scan( POSSIBLE_VERSION_RE ).map { |possible_version_string|
241
+ begin
242
+ from_string possible_version_string
243
+ rescue
244
+ nil
245
+ end
246
+ }.compact
247
+ end # .extract
248
+
189
249
 
190
250
  # Constructor
191
251
  # =====================================================================
@@ -388,6 +448,114 @@ class QB::Package::Version < QB::Util::Resource
388
448
  end # #prerelease_version
389
449
 
390
450
 
451
+ # Bumping
452
+ # ---------------------------------------------------------------------
453
+
454
+
455
+ # @todo Document bump_dev method.
456
+ #
457
+ # @param [type] arg_name
458
+ # @todo Add name param description.
459
+ #
460
+ # @return [return_type]
461
+ # @todo Document return value.
462
+ #
463
+ def bump_to_dev
464
+ props = { prerelease: ['dev'] }
465
+
466
+ case self.level
467
+ when 'release'
468
+ merge patch: patch.succ, **props
469
+ when 'rc'
470
+ merge **props
471
+ when 'dev'
472
+ self
473
+ end
474
+ end # #bump_dev
475
+
476
+
477
+ # Bump to next release-candidate version.
478
+ #
479
+ # This is a little tricky because we need to know what the *last* rc
480
+ # version was, which is not in the version in most cases.
481
+ #
482
+ # @param [type] arg_name
483
+ # @todo Add name param description.
484
+ #
485
+ # @return [return_type]
486
+ # @todo Document return value.
487
+ #
488
+ def bump_to_rc existing_versions: nil
489
+ case self.level
490
+ when 'release'
491
+ merge patch: patch.succ, prerelease: ['rc', 0]
492
+ when 'rc'
493
+ merge prerelease: ['rc', prerelease[1].succ]
494
+ when 'dev'
495
+ if existing_versions.nil?
496
+ raise ArgumentError.squished <<-END
497
+ Can't bump to next rc version without knowing what rc versions have
498
+ already been used.
499
+ END
500
+ elsif existing_versions.is_a? String
501
+ existing_versions = self.class.extract existing_versions
502
+ end
503
+
504
+ last_existing_rc = existing_versions.
505
+ select { |version|
506
+ version.rc? && version.release == release
507
+ }.
508
+ sort.
509
+ last
510
+
511
+ rc_number = if last_existing_rc.nil?
512
+ 0
513
+ else
514
+ last_existing_rc.prerelease[1].succ
515
+ end
516
+
517
+ merge prerelease: ['rc', rc_number]
518
+ end
519
+ end # #bump_rc
520
+
521
+
522
+ # @todo Document bump_to_release method.
523
+ #
524
+ # @param [type] arg_name
525
+ # @todo Add name param description.
526
+ #
527
+ # @return [return_type]
528
+ # @todo Document return value.
529
+ #
530
+ def bump_to_release
531
+ case self.level
532
+ when 'release'
533
+ # bump forward to next release, M.m.p -> M.m.(p+1)
534
+ merge patch: patch.succ
535
+ when 'rc', 'dev'
536
+ # bump forward to release version for rc or dev
537
+ release
538
+ end
539
+ end # #bump_to_release
540
+
541
+
542
+ # @todo Document bump method.
543
+ #
544
+ # @param [type] arg_name
545
+ # @todo Add name param description.
546
+ #
547
+ # @return [return_type]
548
+ # @todo Document return value.
549
+ #
550
+ def bump level:, **options
551
+ method_name = "bump_to_#{ level }"
552
+ if options.empty?
553
+ public_send method_name
554
+ else
555
+ public_send method_name, **options
556
+ end
557
+ end # #bump
558
+
391
559
 
392
560
  # Language Interface
393
561
  # =====================================================================
@@ -408,6 +576,11 @@ class QB::Package::Version < QB::Util::Resource
408
576
  end # #==
409
577
 
410
578
 
579
+ def <=> other
580
+ to_a <=> other.to_a
581
+ end
582
+
583
+
411
584
  # Return array of the version elements in order from greatest to least
412
585
  # precedence.
413
586
  #