mixlib-versioning 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data/.gitignore +18 -0
  2. data/.yardopts +7 -0
  3. data/CHANGELOG.md +3 -0
  4. data/CONTRIBUTING.md +188 -0
  5. data/Gemfile +9 -0
  6. data/LICENSE +201 -0
  7. data/README.md +364 -0
  8. data/Rakefile +6 -0
  9. data/lib/mixlib/versioning.rb +194 -0
  10. data/lib/mixlib/versioning/exceptions.rb +28 -0
  11. data/lib/mixlib/versioning/format.rb +351 -0
  12. data/lib/mixlib/versioning/format/git_describe.rb +71 -0
  13. data/lib/mixlib/versioning/format/opscode_semver.rb +91 -0
  14. data/lib/mixlib/versioning/format/rubygems.rb +66 -0
  15. data/lib/mixlib/versioning/format/semver.rb +66 -0
  16. data/lib/mixlib/versioning/version.rb +23 -0
  17. data/mixlib-versioning.gemspec +22 -0
  18. data/spec/mixlib/versioning/format/git_describe_spec.rb +178 -0
  19. data/spec/mixlib/versioning/format/opscode_semver_spec.rb +113 -0
  20. data/spec/mixlib/versioning/format/rubygems_spec.rb +142 -0
  21. data/spec/mixlib/versioning/format/semver_spec.rb +107 -0
  22. data/spec/mixlib/versioning/format_spec.rb +69 -0
  23. data/spec/mixlib/versioning/versioning_spec.rb +259 -0
  24. data/spec/spec_helper.rb +43 -0
  25. data/spec/support/shared_examples/basic_semver.rb +42 -0
  26. data/spec/support/shared_examples/behaviors/filterable.rb +66 -0
  27. data/spec/support/shared_examples/behaviors/parses_valid_version_strings.rb +32 -0
  28. data/spec/support/shared_examples/behaviors/rejects_invalid_version_strings.rb +32 -0
  29. data/spec/support/shared_examples/behaviors/serializable.rb +51 -0
  30. data/spec/support/shared_examples/behaviors/sortable.rb +45 -0
  31. data/spec/support/shared_examples/semver.rb +105 -0
  32. metadata +127 -0
@@ -0,0 +1,71 @@
1
+ #
2
+ # Author:: Seth Chisamore (<schisamo@opscode.com>)
3
+ # Author:: Christopher Maier (<cm@opscode.com>)
4
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ module Mixlib
21
+ class Versioning
22
+ class Format
23
+ # Handles version strings based on
24
+ # {https://www.kernel.org/pub/software/scm/git/docs/git-describe.html git describe}
25
+ # output.
26
+ #
27
+ # SUPPORTED FORMATS
28
+ # -----------------
29
+ # ```text
30
+ # MAJOR.MINOR.PATCH-COMMITS_SINCE-gGIT_SHA1
31
+ # MAJOR.MINOR.PATCH.PRERELEASE-COMMITS_SINCE-gGIT_SHA1
32
+ # MAJOR.MINOR.PATCH-PRERELEASE-COMMITS_SINCE-gGIT_SHA1-ITERATION
33
+ # ```
34
+ #
35
+ # EXAMPLES
36
+ # --------
37
+ # ```text
38
+ # 10.16.2-49-g21353f0-1
39
+ # 10.16.2.rc.1-49-g21353f0-1
40
+ # 11.0.0-alpha-10-g642ffed
41
+ # 11.0.0-alpha.1-1-gcea071e
42
+ # ```
43
+ #
44
+ # @author Seth Chisamore (<schisamo@opscode.com>)
45
+ # @author Christopher Maier (<cm@opscode.com>)
46
+ class GitDescribe < Format
47
+
48
+ GIT_DESCRIBE_REGEX = /^(\d+)\.(\d+)\.(\d+)(?:\-|\.)?(.+)?\-(\d+)\-g([a-f0-9]{7,40})(?:\-)?(\d+)?$/
49
+
50
+ attr_reader :commits_since, :commit_sha
51
+
52
+ # @see Format#parse
53
+ def parse(version_string)
54
+ match = version_string.match(GIT_DESCRIBE_REGEX) rescue nil
55
+
56
+ unless match
57
+ raise Mixlib::Versioning::ParseError, "'#{version_string}' is not a valid #{self.class} version string!"
58
+ end
59
+
60
+ @major, @minor, @patch, @prerelease, @commits_since, @commit_sha, @iteration = match[1..7]
61
+ @major, @minor, @patch, @commits_since, @iteration = [@major, @minor, @patch, @commits_since, @iteration].map(&:to_i)
62
+
63
+ # Our comparison logic is built around SemVer semantics, so
64
+ # we'll store our internal information in that format
65
+ @build = "#{@commits_since}.g#{@commit_sha}.#{@iteration}"
66
+ end
67
+
68
+ end # class GitDescribe
69
+ end # class Format
70
+ end # module Versioning
71
+ end # module Mixlib
@@ -0,0 +1,91 @@
1
+ #
2
+ # Author:: Seth Chisamore (<schisamo@opscode.com>)
3
+ # Author:: Christopher Maier (<cm@opscode.com>)
4
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'mixlib/versioning/format/semver'
21
+
22
+ module Mixlib
23
+ class Versioning
24
+ class Format
25
+ # Defines the format of the semantic version scheme used for Opscode
26
+ # projects. They are SemVer-2.0.0-rc.1 compliant, but we further
27
+ # constrain the allowable strings for prerelease and build
28
+ # signifiers for our own internal standards.
29
+ #
30
+ # SUPPORTED FORMATS
31
+ # -----------------
32
+ # ```text
33
+ # MAJOR.MINOR.PATCH
34
+ # MAJOR.MINOR.PATCH-alpha.INDEX
35
+ # MAJOR.MINOR.PATCH-beta.INDEX
36
+ # MAJOR.MINOR.PATCH-rc.INDEX
37
+ # MAJOR.MINOR.PATCH-alpha.INDEX+YYYYMMDDHHMMSS
38
+ # MAJOR.MINOR.PATCH-beta.INDEX+YYYYMMDDHHMMSS
39
+ # MAJOR.MINOR.PATCH-rc.INDEX+YYYYMMDDHHMMSS
40
+ # MAJOR.MINOR.PATCH-alpha.INDEX+YYYYMMDDHHMMSS.git.COMMITS_SINCE.SHA1
41
+ # MAJOR.MINOR.PATCH-beta.INDEX+YYYYMMDDHHMMSS.git.COMMITS_SINCE.SHA1
42
+ # MAJOR.MINOR.PATCH-rc.INDEX+YYYYMMDDHHMMSS.git.COMMITS_SINCE.SHA1
43
+ # ```
44
+ #
45
+ # EXAMPLES
46
+ # --------
47
+ # ```text
48
+ # 11.0.0
49
+ # 11.0.0-alpha.1
50
+ # 11.0.0-alpha1+20121218164140
51
+ # 11.0.0-alpha1+20121218164140.git.207.694b062
52
+ # ```
53
+ #
54
+ # @author Seth Chisamore (<schisamo@opscode.com>)
55
+ # @author Christopher Maier (<cm@opscode.com>)
56
+ class OpscodeSemVer < SemVer
57
+
58
+ # The pattern is: `YYYYMMDDHHMMSS.git.COMMITS_SINCE.SHA1`
59
+ OPSCODE_BUILD_REGEX = /^\d{14}(\.git\.\d+\.[a-f0-9]{7})?$/
60
+
61
+ # Allows the following:
62
+ #
63
+ # ```text
64
+ # alpha, alpha.0, alpha.1, alpha.2, etc.
65
+ # beta, beta.0, beta.1, beta.2, etc.
66
+ # rc, rc.0, rc.1, rc.2, etc.
67
+ # ```
68
+ #
69
+ OPSCODE_PRERELEASE_REGEX = /^(alpha|beta|rc)(\.\d+)?$/
70
+
71
+ # @see SemVer#parse
72
+ def parse(version_string)
73
+ super(version_string)
74
+
75
+ unless @prerelease.nil?
76
+ unless @prerelease.match(OPSCODE_PRERELEASE_REGEX)
77
+ raise Mixlib::Versioning::ParseError, "'#{@prerelease}' is not a valid Opscode pre-release signifier!"
78
+ end
79
+ end
80
+
81
+ unless @build.nil?
82
+ unless @build.match(OPSCODE_BUILD_REGEX)
83
+ raise Mixlib::Versioning::ParseError, "'#{@build}' is not a valid Opscode build signifier!"
84
+ end
85
+ end
86
+ end
87
+
88
+ end # class OpscodeSemVer
89
+ end # class Format
90
+ end # module Versioning
91
+ end # module Mixlib
@@ -0,0 +1,66 @@
1
+ #
2
+ # Author:: Seth Chisamore (<schisamo@opscode.com>)
3
+ # Author:: Christopher Maier (<cm@opscode.com>)
4
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ module Mixlib
21
+ class Versioning
22
+ class Format
23
+ # Handles version strings based on {http://guides.rubygems.org/patterns/}
24
+ #
25
+ # SUPPORTED FORMATS
26
+ # -----------------
27
+ # ```text
28
+ # MAJOR.MINOR.PATCH.PRERELEASE
29
+ # MAJOR.MINOR.PATCH.PRERELEASE-ITERATION
30
+ # ```
31
+ #
32
+ # EXAMPLES
33
+ # --------
34
+ # ```text
35
+ # 10.1.1
36
+ # 10.1.1.alpha.1
37
+ # 10.1.1.beta.1
38
+ # 10.1.1.rc.0
39
+ # 10.16.2
40
+ # ```
41
+ #
42
+ # @author Seth Chisamore (<schisamo@opscode.com>)
43
+ # @author Christopher Maier (<cm@opscode.com>)
44
+ class Rubygems < Format
45
+
46
+ RUBYGEMS_REGEX = /^(\d+)\.(\d+)\.(\d+)(?:\.([[:alnum:]]+(?:\.[[:alnum:]]+)?))?(?:\-(\d+))?$/
47
+
48
+ # @see Format#parse
49
+ def parse(version_string)
50
+ match = version_string.match(RUBYGEMS_REGEX) rescue nil
51
+
52
+ unless match
53
+ raise Mixlib::Versioning::ParseError, "'#{version_string}' is not a valid #{self.class} version string!"
54
+ end
55
+
56
+ @major, @minor, @patch, @prerelease, @iteration = match[1..5]
57
+ @major, @minor, @patch, @iteration = [@major, @minor, @patch, @iteration].map(&:to_i)
58
+
59
+ # Do not convert @build to an integer; SemVer sorting logic will handle the conversion
60
+ @prerelease = nil if (@prerelease.nil? || @prerelease.empty?)
61
+ end
62
+
63
+ end # class Rubygems
64
+ end # class Format
65
+ end # module Versioning
66
+ end # module Mixlib
@@ -0,0 +1,66 @@
1
+ #
2
+ # Author:: Seth Chisamore (<schisamo@opscode.com>)
3
+ # Author:: Christopher Maier (<cm@opscode.com>)
4
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ module Mixlib
21
+ class Versioning
22
+ class Format
23
+ # Handles version strings based on {http://semver.org/ SemVer 2.0.0-rc.1}.
24
+ #
25
+ # SUPPORTED FORMATS
26
+ # -----------------
27
+ # ```text
28
+ # MAJOR.MINOR.PATCH
29
+ # MAJOR.MINOR.PATCH-PRERELEASE
30
+ # MAJOR.MINOR.PATCH-PRERELEASE+BUILD
31
+ #```
32
+ #
33
+ # EXAMPLES
34
+ # --------
35
+ # ```text
36
+ # 11.0.0
37
+ # 11.0.0-alpha.1
38
+ # 11.0.0-alpha1+20121218164140
39
+ # 11.0.0-alpha1+20121218164140.git.207.694b062
40
+ # ```
41
+ #
42
+ # @author Seth Chisamore (<schisamo@opscode.com>)
43
+ # @author Christopher Maier (<cm@opscode.com>)
44
+ class SemVer < Format
45
+
46
+ SEMVER_REGEX = /^(\d+)\.(\d+)\.(\d+)(?:\-([\dA-Za-z\-\.]+))?(?:\+([\dA-Za-z\-\.]+))?$/
47
+
48
+ # @see Format#parse
49
+ def parse(version_string)
50
+ match = version_string.match(SEMVER_REGEX) rescue nil
51
+
52
+ unless match
53
+ raise Mixlib::Versioning::ParseError, "'#{version_string}' is not a valid #{self.class} version string!"
54
+ end
55
+
56
+ @major, @minor, @patch, @prerelease, @build = match[1..5]
57
+ @major, @minor, @patch = [@major, @minor, @patch].map(&:to_i)
58
+
59
+ @prerelease = nil if (@prerelease.nil? || @prerelease.empty?)
60
+ @build = nil if (@build.nil? || @build.empty?)
61
+ end
62
+
63
+ end # class SemVer
64
+ end # class Format
65
+ end # module Versioning
66
+ end # module Mixlib
@@ -0,0 +1,23 @@
1
+ #
2
+ # Author:: Seth Chisamore (<schisamo@opscode.com>)
3
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ module Mixlib
20
+ class Versioning
21
+ VERSION = "1.0.0"
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mixlib/versioning/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "mixlib-versioning"
8
+ gem.version = Mixlib::Versioning::VERSION
9
+ gem.authors = ["Seth Chisamore", "Christopher Maier"]
10
+ gem.email = ["schisamo@opscode.com", "cm@opscode.com"]
11
+ gem.description = "General purpose Ruby library that allows you to parse, compare and manipulate version strings in multiple formats."
12
+ gem.summary = gem.description
13
+ gem.homepage = "https://github.com/opscode/mixlib-versioning"
14
+
15
+ gem.add_development_dependency "rspec"
16
+ gem.add_development_dependency "rspec_junit_formatter"
17
+
18
+ gem.files = `git ls-files`.split($/)
19
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
20
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
21
+ gem.require_paths = ["lib"]
22
+ end
@@ -0,0 +1,178 @@
1
+ #
2
+ # Author:: Seth Chisamore (<schisamo@opscode.com>)
3
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'spec_helper'
20
+
21
+ describe Mixlib::Versioning::Format::GitDescribe do
22
+
23
+ subject{ described_class.new(version_string) }
24
+
25
+ it_has_behavior "parses valid version strings", {
26
+ "0.10.8-231-g59d6185" => {
27
+ :major => 0,
28
+ :minor => 10,
29
+ :patch => 8,
30
+ :prerelease => nil,
31
+ :build => "231.g59d6185.0",
32
+ :release? => false,
33
+ :prerelease? => false,
34
+ :build? => true,
35
+ :release_build? => true,
36
+ :prerelease_build? => false,
37
+ :commits_since => 231,
38
+ :commit_sha => "59d6185",
39
+ :iteration => 0
40
+ },
41
+ "10.16.2-49-g21353f0-1" => {
42
+ :major => 10,
43
+ :minor => 16,
44
+ :patch => 2,
45
+ :prerelease => nil,
46
+ :build => "49.g21353f0.1",
47
+ :release? => false,
48
+ :prerelease? => false,
49
+ :build? => true,
50
+ :release_build? => true,
51
+ :prerelease_build? => false,
52
+ :commits_since => 49,
53
+ :commit_sha => "21353f0",
54
+ :iteration => 1
55
+ },
56
+ "10.16.2.rc.1-49-g21353f0-1" => {
57
+ :major => 10,
58
+ :minor => 16,
59
+ :patch => 2,
60
+ :prerelease => "rc.1",
61
+ :build => "49.g21353f0.1",
62
+ :release? => false,
63
+ :prerelease? => false,
64
+ :build? => true,
65
+ :release_build? => false,
66
+ :prerelease_build? => true,
67
+ :commits_since => 49,
68
+ :commit_sha => "21353f0",
69
+ :iteration => 1
70
+ },
71
+ "10.16.2-alpha-49-g21353f0-1" => {
72
+ :major => 10,
73
+ :minor => 16,
74
+ :patch => 2,
75
+ :prerelease => "alpha",
76
+ :build => "49.g21353f0.1",
77
+ :release? => false,
78
+ :prerelease? => false,
79
+ :build? => true,
80
+ :release_build? => false,
81
+ :prerelease_build? => true,
82
+ :commits_since => 49,
83
+ :commit_sha => "21353f0",
84
+ :iteration => 1
85
+ },
86
+ "10.16.2-alpha-49-g21353f0" => {
87
+ :major => 10,
88
+ :minor => 16,
89
+ :patch => 2,
90
+ :prerelease => "alpha",
91
+ :build => "49.g21353f0.0",
92
+ :release? => false,
93
+ :prerelease? => false,
94
+ :build? => true,
95
+ :release_build? => false,
96
+ :prerelease_build? => true,
97
+ :commits_since => 49,
98
+ :commit_sha => "21353f0",
99
+ :iteration => 0
100
+ }
101
+ }
102
+
103
+ it_has_behavior "rejects invalid version strings", {
104
+ "1.0.0" => "no git describe data",
105
+ "1.0.0-alpha.1" => "no git describe data",
106
+ "1.0.0-alpha.1+build.deadbeef" => "no git describe data",
107
+ "1.0.0-123-gfd0e3a65282cb5f6df3bab6a53f4fcb722340d499-1" => "too many SHA1 characters",
108
+ "1.0.0-123-gdeadbe-1" => "too few SHA1 characters",
109
+ "1.0.0-123-gNOTHEX1-1" => "illegal SHA1 characters",
110
+ "1.0.0-123-g1234567-alpha" => "non-numeric iteration",
111
+ "1.0.0-alpha-poop-g1234567-1" => "non-numeric 'commits_since'",
112
+ "1.0.0-g1234567-1" => "missing 'commits_since'",
113
+ "1.0.0-123-1" => "missing SHA1"
114
+ }
115
+
116
+ version_strings = %w{
117
+ 9.0.1-1-gdeadbee-1
118
+ 9.1.2-2-g1234567-1
119
+ 10.0.0-1-gabcdef3-1
120
+ 10.5.7-2-g21353f0-1
121
+ 10.20.2-2-gbbbbbbb-1
122
+ 10.20.2-3-gaaaaaaa-1
123
+ 9.0.1-2-gdeadbe1-1
124
+ 9.0.1-2-gdeadbe1-2
125
+ 9.0.1-2-gdeadbe2-1
126
+ 9.1.1-2-g1234567-1
127
+ }
128
+
129
+ it_has_behavior "serializable", version_strings
130
+
131
+ it_has_behavior "sortable" do
132
+ let(:unsorted_version_strings){ version_strings }
133
+ let(:sorted_version_strings){%w{
134
+ 9.0.1-1-gdeadbee-1
135
+ 9.0.1-2-gdeadbe1-1
136
+ 9.0.1-2-gdeadbe1-2
137
+ 9.0.1-2-gdeadbe2-1
138
+ 9.1.1-2-g1234567-1
139
+ 9.1.2-2-g1234567-1
140
+ 10.0.0-1-gabcdef3-1
141
+ 10.5.7-2-g21353f0-1
142
+ 10.20.2-2-gbbbbbbb-1
143
+ 10.20.2-3-gaaaaaaa-1
144
+ }}
145
+ let(:min){ "9.0.1-1-gdeadbee-1" }
146
+ let(:max){ "10.20.2-3-gaaaaaaa-1" }
147
+ end # it_has_behavior
148
+
149
+ # The +GitDescribe+ format only produces release build versions.
150
+ it_has_behavior "filterable" do
151
+ let(:unsorted_version_strings){ version_strings }
152
+ let(:build_versions){%w{
153
+ 9.0.1-1-gdeadbee-1
154
+ 9.1.2-2-g1234567-1
155
+ 10.0.0-1-gabcdef3-1
156
+ 10.5.7-2-g21353f0-1
157
+ 10.20.2-2-gbbbbbbb-1
158
+ 10.20.2-3-gaaaaaaa-1
159
+ 9.0.1-2-gdeadbe1-1
160
+ 9.0.1-2-gdeadbe1-2
161
+ 9.0.1-2-gdeadbe2-1
162
+ 9.1.1-2-g1234567-1
163
+ }}
164
+ let(:release_build_versions){%w{
165
+ 9.0.1-1-gdeadbee-1
166
+ 9.1.2-2-g1234567-1
167
+ 10.0.0-1-gabcdef3-1
168
+ 10.5.7-2-g21353f0-1
169
+ 10.20.2-2-gbbbbbbb-1
170
+ 10.20.2-3-gaaaaaaa-1
171
+ 9.0.1-2-gdeadbe1-1
172
+ 9.0.1-2-gdeadbe1-2
173
+ 9.0.1-2-gdeadbe2-1
174
+ 9.1.1-2-g1234567-1
175
+ }}
176
+ end # it_has_behavior
177
+
178
+ end # describe