metasploit-version 0.1.2-java
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.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +32 -0
- data/.simplecov +60 -0
- data/.travis.yml +26 -0
- data/.yardopts +7 -0
- data/CONTRIBUTING.md +156 -0
- data/Gemfile +17 -0
- data/LICENSE.txt +22 -0
- data/README.md +133 -0
- data/Rakefile +20 -0
- data/features/shared/examples/metasploit/version/gem_version_constant.feature +215 -0
- data/features/shared/examples/metasploit/version/version_constant.feature +183 -0
- data/features/shared/examples/metasploit/version/version_module.feature +275 -0
- data/features/shared/examples/metasploit/version/version_module/prerelease/git/branch.feature +234 -0
- data/features/shared/examples/metasploit/version/version_module/prerelease/git/detached_head.feature +97 -0
- data/features/shared/examples/metasploit/version/version_module/prerelease/git/master.feature +94 -0
- data/features/shared/examples/metasploit/version/version_module/prerelease/git/step_definitions/environment_variable_steps.rb +13 -0
- data/features/shared/examples/metasploit/version/version_module/prerelease/git/step_definitions/git_steps.rb +30 -0
- data/features/shared/examples/metasploit/version/version_module/prerelease/travis_ci/branch.feature +173 -0
- data/features/shared/examples/metasploit/version/version_module/prerelease/travis_ci/master.feature +90 -0
- data/features/shared/examples/metasploit/version/version_module/prerelease/travis_ci/pull_request.feature +99 -0
- data/features/shared/examples/metasploit/version/version_module/prerelease/travis_ci/tag.feature +277 -0
- data/features/support/env.rb +41 -0
- data/features/support/simplecov_setup.rb +12 -0
- data/lib/metasploit/version.rb +19 -0
- data/lib/metasploit/version/branch.rb +172 -0
- data/lib/metasploit/version/version.rb +57 -0
- data/metasploit-version.gemspec +41 -0
- data/spec/lib/metasploit/version/branch_spec.rb +660 -0
- data/spec/lib/metasploit/version/version_spec.rb +5 -0
- data/spec/lib/metasploit/version_spec.rb +6 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/shared/examples/metasploit/version/gem_version_constant.rb +17 -0
- data/spec/support/shared/examples/metasploit/version/version_constant.rb +17 -0
- data/spec/support/shared/examples/metasploit/version/version_module.rb +226 -0
- metadata +173 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
# Has to be the first file required so that all other files show coverage information
|
2
|
+
require 'simplecov'
|
3
|
+
|
4
|
+
#
|
5
|
+
# Standard Library
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'pathname'
|
9
|
+
|
10
|
+
#
|
11
|
+
# Gems
|
12
|
+
#
|
13
|
+
|
14
|
+
require 'aruba/cucumber'
|
15
|
+
# only does jruby customization if actually in JRuby
|
16
|
+
require 'aruba/jruby'
|
17
|
+
|
18
|
+
Before do |scenario|
|
19
|
+
command_name = case scenario
|
20
|
+
when Cucumber::Ast::Scenario, Cucumber::Ast::ScenarioOutline
|
21
|
+
"#{scenario.feature.title} #{scenario.name}"
|
22
|
+
when Cucumber::Ast::OutlineTable::ExampleRow
|
23
|
+
scenario_outline = scenario.scenario_outline
|
24
|
+
|
25
|
+
"#{scenario_outline.feature.title} #{scenario_outline.name} #{scenario.name}"
|
26
|
+
else
|
27
|
+
raise TypeError, "Don't know how to extract command name from #{scenario.class}"
|
28
|
+
end
|
29
|
+
|
30
|
+
# Used in simplecov_setup so that each scenario has a different name and their coverage results are merged instead
|
31
|
+
# of overwriting each other as 'Cucumber Features'
|
32
|
+
set_env('SIMPLECOV_COMMAND_NAME', command_name)
|
33
|
+
|
34
|
+
simplecov_setup_pathname = Pathname.new(__FILE__).expand_path.parent.join('simplecov_setup')
|
35
|
+
# set environment variable so child processes will merge their coverage data with parent process's coverage data.
|
36
|
+
set_env('RUBYOPT', "-r#{simplecov_setup_pathname} #{ENV['RUBYOPT']}")
|
37
|
+
end
|
38
|
+
|
39
|
+
Before do
|
40
|
+
@aruba_timeout_seconds = 10 * 60
|
41
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# @note this file is loaded in env.rb to setup simplecov using RUBYOPTs for child processes
|
2
|
+
|
3
|
+
require 'simplecov'
|
4
|
+
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
root = Pathname(__FILE__).expand_path.parent.parent.parent
|
8
|
+
|
9
|
+
SimpleCov.command_name(ENV['SIMPLECOV_COMMAND_NAME'])
|
10
|
+
SimpleCov.root(root)
|
11
|
+
load root.join('.simplecov')
|
12
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#
|
2
|
+
# Standard Library
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
#
|
8
|
+
# Project
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'metasploit/version/version'
|
12
|
+
|
13
|
+
# Namespace used across all metasploit gems
|
14
|
+
module Metasploit
|
15
|
+
# Namespace for this gem.
|
16
|
+
module Version
|
17
|
+
autoload :Branch, 'metasploit/version/branch'
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'metasploit/version'
|
2
|
+
|
3
|
+
# Regular expressions for parsing the branch name into its component parts
|
4
|
+
module Metasploit::Version::Branch
|
5
|
+
#
|
6
|
+
# CONSTANTS
|
7
|
+
#
|
8
|
+
|
9
|
+
# Regular expression that matches, but does not capture an optional prefix of `ref/remotes` for when a branch name is
|
10
|
+
# fully qualified on Jenkins. Remote name after `ref/remotes` is captured in `:remote` group.
|
11
|
+
JENKINS_PREFIX_REGEXP = %r{(?:ref/remotes/(?<remote>[^/]+)/)?}
|
12
|
+
|
13
|
+
# Matches runs of alphanumeric characters that are valid in prerelease segments. Prerelease segments must be
|
14
|
+
# separated by `.` or `-`.
|
15
|
+
PRERELEASE_SEGMENT_REGEXP = /[0-9a-zA-Z]+/
|
16
|
+
|
17
|
+
# Version pattern allowed by Rubygems for pre-release: runs of alphanumeric characters separated by `.` or `-`.
|
18
|
+
# Group is captured to `:prerelease` name.
|
19
|
+
PRERELEASE_REGEXP = /(?<prerelease>#{PRERELEASE_SEGMENT_REGEXP}([-.]#{PRERELEASE_SEGMENT_REGEXP})*)/
|
20
|
+
|
21
|
+
# Regular expression that matches exactly a staging branch. It may
|
22
|
+
# {JENKINS_PREFIX_REGEXP optionally start with `ref/remotes`}, followed by a type of `staging`, no story ID, and a
|
23
|
+
# {PRERELEASE_REGEXP pre-release name}.
|
24
|
+
#
|
25
|
+
# @example Staging Branch
|
26
|
+
# 'staging/long-running'
|
27
|
+
#
|
28
|
+
# @example Staging Branch on Jenkins
|
29
|
+
# 'ref/remotes/origin/staging/long-running'
|
30
|
+
STAGING_REGEXP = %r{
|
31
|
+
\A
|
32
|
+
#{JENKINS_PREFIX_REGEXP}
|
33
|
+
(?<type>staging)
|
34
|
+
/
|
35
|
+
#{PRERELEASE_REGEXP}
|
36
|
+
\z
|
37
|
+
}x
|
38
|
+
|
39
|
+
# Regular expression that matches exactly a chore, feature or bug branch. It may
|
40
|
+
# {JENKINS_PREFIX_REGEXP optionally start with `ref/remotes`}, followed by a type of `staging`, story ID, and a
|
41
|
+
# {PRERELEASE_REGEXP pre-release name}.
|
42
|
+
#
|
43
|
+
# @example Bug Branch
|
44
|
+
# 'bug/MSP-666/nasty'
|
45
|
+
#
|
46
|
+
# @example Bug Branch on Jenkins
|
47
|
+
# 'ref/remotes/origin/bug/MSP-666/nasty'
|
48
|
+
#
|
49
|
+
# @example Chore Branch
|
50
|
+
# 'chore/MSP-1234/recurring'
|
51
|
+
#
|
52
|
+
# @example Chore Branch on Jenkins
|
53
|
+
# 'ref/remotes/origin/chore/MSP-1234/recurring'
|
54
|
+
#
|
55
|
+
# @example Feature Branch
|
56
|
+
# 'feature/MSP-31337/cool'
|
57
|
+
#
|
58
|
+
# @example Feature Branch on Jenkins
|
59
|
+
# 'ref/remotes/origin/feature/MSP-31337/cool'
|
60
|
+
#
|
61
|
+
STORY_REGEXP = %r{
|
62
|
+
\A
|
63
|
+
#{JENKINS_PREFIX_REGEXP}
|
64
|
+
(?<type>bug|chore|feature)
|
65
|
+
/
|
66
|
+
(?<story>[^/]+)
|
67
|
+
/
|
68
|
+
#{PRERELEASE_REGEXP}
|
69
|
+
\z
|
70
|
+
}x
|
71
|
+
|
72
|
+
# Regular expression that matches separator used between {PRERELEASE_SEGMENT_REGEXP prerelease segments} for gem
|
73
|
+
# versions and tag versions.
|
74
|
+
VERSION_PRERELEASE_SEGMENT_SEPARATOR_REGEXP = /\.pre\./
|
75
|
+
|
76
|
+
# Regular expression that exactly matches a release or pre-release version tag prefixed with `v` and followed by
|
77
|
+
# the major, minor, and patch numbers separated by '.' with an optional prerelease version suffix.
|
78
|
+
#
|
79
|
+
# @example Releease Tag
|
80
|
+
# 'v1.2.3'
|
81
|
+
#
|
82
|
+
# @example Prerelease Tag
|
83
|
+
# 'v1.2.3.pre.cool'
|
84
|
+
#
|
85
|
+
VERSION_REGEXP = %r{
|
86
|
+
\A
|
87
|
+
v(?<major>\d+)
|
88
|
+
\.
|
89
|
+
(?<minor>\d+)
|
90
|
+
\.
|
91
|
+
(?<patch>\d+)
|
92
|
+
(?:
|
93
|
+
#{VERSION_PRERELEASE_SEGMENT_SEPARATOR_REGEXP}
|
94
|
+
(?<gem_version_prerelease>
|
95
|
+
#{PRERELEASE_SEGMENT_REGEXP}
|
96
|
+
(#{VERSION_PRERELEASE_SEGMENT_SEPARATOR_REGEXP}#{PRERELEASE_SEGMENT_REGEXP})*
|
97
|
+
)
|
98
|
+
)?
|
99
|
+
\z
|
100
|
+
}x
|
101
|
+
|
102
|
+
# The current branch name from travis-ci or git.
|
103
|
+
#
|
104
|
+
# @return [String]
|
105
|
+
def self.current
|
106
|
+
branch = ENV['TRAVIS_BRANCH']
|
107
|
+
|
108
|
+
if branch.nil? || branch.empty?
|
109
|
+
branch = `git rev-parse --abbrev-ref HEAD`.strip
|
110
|
+
end
|
111
|
+
|
112
|
+
branch
|
113
|
+
end
|
114
|
+
|
115
|
+
# Parses the branch
|
116
|
+
#
|
117
|
+
# @param branch [String] the branch name
|
118
|
+
# @return ['HEAD'] if `branch` is 'HEAD' (such as in a detached head state for git)
|
119
|
+
# @return ['master'] if `branch` is `master`
|
120
|
+
# @return [Hash{type: 'staging', prerelease: String}] if a staging branch
|
121
|
+
# @return [Hash{type: String, story: String, prerelease: String}] if not a staging branch
|
122
|
+
# @return [Hash{major: Integer, minor: Integer, patch: Integer, prerelease: String}]
|
123
|
+
# @return [nil] if `branch` does not match any of the formats
|
124
|
+
def self.parse(branch)
|
125
|
+
if ['HEAD', 'master'].include? branch
|
126
|
+
branch
|
127
|
+
else
|
128
|
+
match = branch.match(STAGING_REGEXP)
|
129
|
+
|
130
|
+
if match
|
131
|
+
{
|
132
|
+
prerelease: match[:prerelease],
|
133
|
+
type: match[:type]
|
134
|
+
}
|
135
|
+
else
|
136
|
+
match = branch.match(STORY_REGEXP)
|
137
|
+
|
138
|
+
if match
|
139
|
+
{
|
140
|
+
prerelease: match[:prerelease],
|
141
|
+
story: match[:story],
|
142
|
+
type: match[:type]
|
143
|
+
}
|
144
|
+
else
|
145
|
+
match = branch.match(VERSION_REGEXP)
|
146
|
+
|
147
|
+
if match
|
148
|
+
prerelease = prerelease(match[:gem_version_prerelease])
|
149
|
+
|
150
|
+
{
|
151
|
+
major: match[:major].to_i,
|
152
|
+
minor: match[:minor].to_i,
|
153
|
+
patch: match[:patch].to_i,
|
154
|
+
prerelease: prerelease
|
155
|
+
}
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Replaces `.pre.` in `gem_version_prerelease` with `-` to undo conversion to rubygems 1.8.6 compatible pre-release
|
163
|
+
# version.
|
164
|
+
#
|
165
|
+
# @return [String] unless `gem_version_prerelease` is `nil`.
|
166
|
+
# @return [nil] if `gem_version_prerelease` is `nil`.
|
167
|
+
def self.prerelease(gem_version_prerelease)
|
168
|
+
unless gem_version_prerelease.nil?
|
169
|
+
gem_version_prerelease.gsub('.pre.', '-')
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Metasploit
|
2
|
+
module Version
|
3
|
+
# Holds components of {VERSION} as defined by {http://semver.org/spec/v2.0.0.html semantic versioning v2.0.0}.
|
4
|
+
module Version
|
5
|
+
#
|
6
|
+
# Constants
|
7
|
+
#
|
8
|
+
|
9
|
+
# The major version number.
|
10
|
+
MAJOR = 0
|
11
|
+
# The minor version number, scoped to the {MAJOR} version number.
|
12
|
+
MINOR = 1
|
13
|
+
# The patch number, scoped to the {MINOR} version number.
|
14
|
+
PATCH = 2
|
15
|
+
|
16
|
+
#
|
17
|
+
# Module Methods
|
18
|
+
#
|
19
|
+
|
20
|
+
# The full version string, including the {Metasploit::Version::Version::MAJOR},
|
21
|
+
# {Metasploit::Version::Version::MINOR}, {Metasploit::Version::Version::PATCH}, and optionally, the
|
22
|
+
# `Metasploit::Version::Version::PRERELEASE` in the
|
23
|
+
# {http://semver.org/spec/v2.0.0.html semantic versioning v2.0.0} format.
|
24
|
+
#
|
25
|
+
# @return [String] '{Metasploit::Version::Version::MAJOR}.{Metasploit::Version::Version::MINOR}.{Metasploit::Version::Version::PATCH}' on master.
|
26
|
+
# '{Metasploit::Version::Version::MAJOR}.{Metasploit::Version::Version::MINOR}.{Metasploit::Version::Version::PATCH}-PRERELEASE'
|
27
|
+
# on any branch other than master.
|
28
|
+
def self.full
|
29
|
+
version = "#{MAJOR}.#{MINOR}.#{PATCH}"
|
30
|
+
|
31
|
+
if defined? PRERELEASE
|
32
|
+
version = "#{version}-#{PRERELEASE}"
|
33
|
+
end
|
34
|
+
|
35
|
+
version
|
36
|
+
end
|
37
|
+
|
38
|
+
# The full gem version string, including the {Metasploit::Version::Version::MAJOR},
|
39
|
+
# {Metasploit::Version::Version::MINOR}, {Metasploit::Version::Version::PATCH}, and optionally, the
|
40
|
+
# `Metasploit::Version::Version::PRERELEASE` in the
|
41
|
+
# {http://guides.rubygems.org/specification-reference/#version RubyGems versioning} format.
|
42
|
+
#
|
43
|
+
# @return [String] '{Metasploit::Version::Version::MAJOR}.{Metasploit::Version::Version::MINOR}.{Metasploit::Version::Version::PATCH}'
|
44
|
+
# on master. '{Metasploit::Version::Version::MAJOR}.{Metasploit::Version::Version::MINOR}.{Metasploit::Version::Version::PATCH}.PRERELEASE'
|
45
|
+
# on any branch other than master.
|
46
|
+
def self.gem
|
47
|
+
full.gsub('-', '.pre.')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# (see Version.gem)
|
52
|
+
GEM_VERSION = Version.gem
|
53
|
+
|
54
|
+
# (see Version.full)
|
55
|
+
VERSION = Version.full
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'metasploit/version/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'metasploit-version'
|
8
|
+
spec.version = Metasploit::Version::GEM_VERSION
|
9
|
+
spec.authors = ['Luke Imhoff']
|
10
|
+
spec.email = ['luke_imhoff@rapid7.com']
|
11
|
+
spec.summary = 'Semantic versioning helpers and shared examples'
|
12
|
+
spec.description = "Metasploit::Version::Full for deriving String VERSION from constants in Version module and " \
|
13
|
+
"shared examples: 'Metasploit::Version VERSION constant' to check VERSION and " \
|
14
|
+
"'Metasploit::Version Version Module' to check Version."
|
15
|
+
spec.homepage = 'https://github.com/rapid7/metasploit-version'
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
spec.files = `git ls-files`.split($/)
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
24
|
+
spec.add_development_dependency 'metasploit-yard', '~> 1.0'
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
|
27
|
+
|
28
|
+
if RUBY_PLATFORM =~ /java/
|
29
|
+
# markdown library for YARD to enable proper parsing of README.md and CONTRIBUTING.md
|
30
|
+
spec.add_development_dependency 'kramdown'
|
31
|
+
|
32
|
+
spec.platform = Gem::Platform::JAVA
|
33
|
+
else
|
34
|
+
# markdown library for YARD to enable proper parsing of README.md and CONTRIBUTING.md
|
35
|
+
spec.add_development_dependency 'redcarpet'
|
36
|
+
|
37
|
+
spec.platform = Gem::Platform::RUBY
|
38
|
+
end
|
39
|
+
|
40
|
+
spec.add_runtime_dependency 'rspec'
|
41
|
+
end
|
@@ -0,0 +1,660 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Metasploit::Version::Branch do
|
4
|
+
context 'CONSTANTS' do
|
5
|
+
context 'JENKINS_PREFIX_REGEXP' do
|
6
|
+
subject(:jenkins_prefix_regexp) {
|
7
|
+
described_class::JENKINS_PREFIX_REGEXP
|
8
|
+
}
|
9
|
+
|
10
|
+
it "matches 'ref/remotes/' by itself" do
|
11
|
+
expect(jenkins_prefix_regexp).to match('ref/remotes/')
|
12
|
+
end
|
13
|
+
|
14
|
+
it "matches 'ref/remotes/' prefix" do
|
15
|
+
expect(jenkins_prefix_regexp).to match('ref/remotes/remote-name')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'matches nothing' do
|
19
|
+
expect(jenkins_prefix_regexp).to match('')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'PRERELEASE_REGEXP' do
|
24
|
+
subject(:prerelease_regexp) {
|
25
|
+
described_class::PRERELEASE_REGEXP
|
26
|
+
}
|
27
|
+
|
28
|
+
it 'matches a single segment' do
|
29
|
+
expected_prerelease = 'singlesegment'
|
30
|
+
match = prerelease_regexp.match(expected_prerelease)
|
31
|
+
|
32
|
+
expect(match).not_to be_nil
|
33
|
+
expect(match[:prerelease]).to eq(expected_prerelease)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "matches segments separated by '-'" do
|
37
|
+
expected_prerelease = 'first-second'
|
38
|
+
match = prerelease_regexp.match(expected_prerelease)
|
39
|
+
|
40
|
+
expect(match).not_to be_nil
|
41
|
+
expect(match[:prerelease]).to eq(expected_prerelease)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "matches segmented separated by '.'" do
|
45
|
+
expected_prerelease = 'first.second'
|
46
|
+
match = prerelease_regexp.match(expected_prerelease)
|
47
|
+
|
48
|
+
expect(match).not_to be_nil
|
49
|
+
expect(match[:prerelease]).to eq(expected_prerelease)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "matches segmented separated by a mix of '.' and '-'" do
|
53
|
+
expected_prerelease = 'first.second-third'
|
54
|
+
match = prerelease_regexp.match(expected_prerelease)
|
55
|
+
|
56
|
+
expect(match).not_to be_nil
|
57
|
+
expect(match[:prerelease]).to eq(expected_prerelease)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'PRERELEASE_SEGMENT_REGEXP' do
|
62
|
+
subject(:prerelease_segment_regexp) {
|
63
|
+
described_class::PRERELEASE_SEGMENT_REGEXP
|
64
|
+
}
|
65
|
+
|
66
|
+
it 'does not match an empty string' do
|
67
|
+
expect(prerelease_segment_regexp).not_to match('')
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'matches 0-9, a-z, and A-Z' do
|
71
|
+
ranges = [
|
72
|
+
'0'..'9',
|
73
|
+
'a'..'z',
|
74
|
+
'A'..'Z'
|
75
|
+
]
|
76
|
+
string = ranges.map(&:to_a).map(&:join).join
|
77
|
+
|
78
|
+
expect(prerelease_segment_regexp).to match(string)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'STAGING_REGEXP' do
|
83
|
+
subject(:staging_regexp) {
|
84
|
+
described_class::STAGING_REGEXP
|
85
|
+
}
|
86
|
+
|
87
|
+
it 'matches staging branch' do
|
88
|
+
expect(staging_regexp).to match('staging/long-running')
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'does not match bug branch' do
|
92
|
+
expect(staging_regexp).not_to match('bug/MSP-1234/nasty')
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'does not match chore branch' do
|
96
|
+
expect(staging_regexp).not_to match('chore/MSP-1234/repeating')
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'does not match feature branch' do
|
100
|
+
expect(staging_regexp).not_to match('feature/MSP-1234/new-feature')
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'does not match pre-release tag' do
|
104
|
+
expect(staging_regexp).not_to match('v1.2.3.pre.release')
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'does not match release tag' do
|
108
|
+
expect(staging_regexp).not_to match('v1.2.3')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'STORY_REGEXP' do
|
113
|
+
subject(:story_regexp) {
|
114
|
+
described_class::STORY_REGEXP
|
115
|
+
}
|
116
|
+
|
117
|
+
it 'does not match staging branch' do
|
118
|
+
expect(story_regexp).not_to match('staging/long-running')
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'type' do
|
122
|
+
context 'bug' do
|
123
|
+
let(:type) {
|
124
|
+
'bug'
|
125
|
+
}
|
126
|
+
|
127
|
+
context 'with story' do
|
128
|
+
it 'matches' do
|
129
|
+
expect(story_regexp).to match("#{type}/MSP-1234/nasty")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'without story' do
|
134
|
+
it 'does not match' do
|
135
|
+
expect(story_regexp).not_to match("#{type}/nasty")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'chore' do
|
141
|
+
let(:type) {
|
142
|
+
'chore'
|
143
|
+
}
|
144
|
+
|
145
|
+
context 'with story' do
|
146
|
+
it 'matches' do
|
147
|
+
expect(story_regexp).to match("#{type}/MSP-1234/repeating")
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'without story' do
|
152
|
+
it 'does not match' do
|
153
|
+
expect(story_regexp).not_to match("#{type}/repeating")
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'feature' do
|
159
|
+
let(:type) {
|
160
|
+
'feature'
|
161
|
+
}
|
162
|
+
|
163
|
+
context 'with story' do
|
164
|
+
it 'matches' do
|
165
|
+
expect(story_regexp).to match("#{type}/MSP-1234/cool")
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'without story' do
|
170
|
+
it 'does not match' do
|
171
|
+
expect(story_regexp).not_to match("#{type}/cool")
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'does not match pre-release tag' do
|
178
|
+
expect(story_regexp).not_to match('v1.2.3.pre.release')
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'does not match release tag' do
|
182
|
+
expect(story_regexp).not_to match('v1.2.3')
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
context 'VERSION_PRERELEASE_SEGMENT_SEPARATOR_REGEXP' do
|
187
|
+
subject(:version_prerelease_segment_separator_regexp) {
|
188
|
+
described_class::VERSION_PRERELEASE_SEGMENT_SEPARATOR_REGEXP
|
189
|
+
}
|
190
|
+
|
191
|
+
it { is_expected.to match('.pre.') }
|
192
|
+
|
193
|
+
it "escapes '.' around 'pre'" do
|
194
|
+
expect(version_prerelease_segment_separator_regexp).not_to match('aprea')
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context 'VERSION_REGEXP' do
|
199
|
+
subject(:version_regexp) {
|
200
|
+
described_class::VERSION_REGEXP
|
201
|
+
}
|
202
|
+
|
203
|
+
it "does not match tag without 'v' prefix" do
|
204
|
+
expect(version_regexp).not_to match('1.2.3')
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'matches release tag' do
|
208
|
+
expect(version_regexp).to match('v1.2.3')
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'matches prerelease tag' do
|
212
|
+
expect(version_regexp).to match('v1.2.3.pre.release')
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'does not match staging branch' do
|
216
|
+
expect(version_regexp).not_to match('staging/long-running')
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'does not match bug branch' do
|
220
|
+
expect(version_regexp).not_to match('bug/MSP-1234/nasty')
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'does not match chore branch' do
|
224
|
+
expect(version_regexp).not_to match('chore/MSP-1234/recurring')
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'does not match feature branch' do
|
228
|
+
expect(version_regexp).not_to match('feature/MSP-1234/cool')
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
context 'current' do
|
234
|
+
subject(:current) {
|
235
|
+
described_class.current
|
236
|
+
}
|
237
|
+
|
238
|
+
around(:each) do |example|
|
239
|
+
env_before = ENV.to_hash
|
240
|
+
|
241
|
+
begin
|
242
|
+
example.run
|
243
|
+
ensure
|
244
|
+
ENV.replace(env_before)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context 'with TRAVIS_BRANCH' do
|
249
|
+
before(:each) do
|
250
|
+
ENV['TRAVIS_BRANCH'] = travis_branch
|
251
|
+
end
|
252
|
+
|
253
|
+
context 'that is empty' do
|
254
|
+
let(:travis_branch) {
|
255
|
+
''
|
256
|
+
}
|
257
|
+
|
258
|
+
it 'parses git abbreviated ref' do
|
259
|
+
expect(current).to eq(`git rev-parse --abbrev-ref HEAD`.strip)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
context 'that is not empty' do
|
264
|
+
let(:travis_branch) {
|
265
|
+
'feature/MSP-1234/travis-ci'
|
266
|
+
}
|
267
|
+
|
268
|
+
it 'is TRAVIS_BRANCH' do
|
269
|
+
expect(current).to eq(travis_branch)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
context 'without TRAVIS_BRANCH' do
|
275
|
+
before(:each) do
|
276
|
+
ENV.delete('TRAVIS_BRANCH')
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'parses git abbreviated ref' do
|
280
|
+
expect(current).to eq(`git rev-parse --abbrev-ref HEAD`.strip)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
context 'parse' do
|
286
|
+
subject(:parse) {
|
287
|
+
described_class.parse(branch)
|
288
|
+
}
|
289
|
+
|
290
|
+
context 'with HEAD' do
|
291
|
+
let(:branch) {
|
292
|
+
'HEAD'
|
293
|
+
}
|
294
|
+
|
295
|
+
it { is_expected.to eq('HEAD') }
|
296
|
+
end
|
297
|
+
|
298
|
+
context 'with master' do
|
299
|
+
let(:branch) {
|
300
|
+
'master'
|
301
|
+
}
|
302
|
+
|
303
|
+
it { is_expected.to eq('master') }
|
304
|
+
end
|
305
|
+
|
306
|
+
context 'with staging branch' do
|
307
|
+
#
|
308
|
+
# Shared examples
|
309
|
+
#
|
310
|
+
|
311
|
+
shared_examples_for 'staging branch' do
|
312
|
+
it { is_expected.to be_a(Hash) }
|
313
|
+
|
314
|
+
context '[:prerelease]' do
|
315
|
+
subject(:prerelease) {
|
316
|
+
parse[:prerelease]
|
317
|
+
}
|
318
|
+
|
319
|
+
it "is name after 'staging/'" do
|
320
|
+
expect(prerelease).to eq(expected_prerelease)
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
context '[:type]' do
|
325
|
+
subject(:type) {
|
326
|
+
parse[:type]
|
327
|
+
}
|
328
|
+
|
329
|
+
it { is_expected.to eq(expected_type) }
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
#
|
334
|
+
# lets
|
335
|
+
#
|
336
|
+
|
337
|
+
let(:branch) {
|
338
|
+
"#{jenkins_prefix}#{expected_type}/#{expected_prerelease}"
|
339
|
+
}
|
340
|
+
|
341
|
+
let(:expected_prerelease) {
|
342
|
+
'long-running'
|
343
|
+
}
|
344
|
+
|
345
|
+
let(:expected_type) {
|
346
|
+
'staging'
|
347
|
+
}
|
348
|
+
|
349
|
+
context 'with Jenkins prefix' do
|
350
|
+
let(:jenkins_prefix) {
|
351
|
+
'ref/remotes/origin/'
|
352
|
+
}
|
353
|
+
|
354
|
+
it_should_behave_like 'staging branch'
|
355
|
+
end
|
356
|
+
|
357
|
+
context 'without Jenkins prefix' do
|
358
|
+
let(:jenkins_prefix) {
|
359
|
+
''
|
360
|
+
}
|
361
|
+
|
362
|
+
it_should_behave_like 'staging branch'
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
context 'with story branch' do
|
367
|
+
shared_examples_for 'story branch' do
|
368
|
+
context 'with story' do
|
369
|
+
shared_examples_for 'with story' do
|
370
|
+
it { should be_a Hash }
|
371
|
+
|
372
|
+
context '[:prerelease]' do
|
373
|
+
subject(:prerelease) {
|
374
|
+
parse[:prerelease]
|
375
|
+
}
|
376
|
+
|
377
|
+
it "is name after last '/'" do
|
378
|
+
expect(prerelease).to eq(expected_prerelease)
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
context '[:story]' do
|
383
|
+
subject(:story) {
|
384
|
+
parse[:story]
|
385
|
+
}
|
386
|
+
|
387
|
+
it 'is middle name' do
|
388
|
+
expect(story).to eq(expected_story)
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
context '[:type]' do
|
393
|
+
subject(:type) {
|
394
|
+
parse[:type]
|
395
|
+
}
|
396
|
+
|
397
|
+
it { is_expected.to eq(expected_type) }
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
let(:expected_story) {
|
402
|
+
'MSP-1234'
|
403
|
+
}
|
404
|
+
|
405
|
+
let(:branch) {
|
406
|
+
"#{jenkins_prefix}#{expected_type}/#{expected_story}/#{expected_prerelease}"
|
407
|
+
}
|
408
|
+
|
409
|
+
context 'with Jenkins prefix' do
|
410
|
+
let(:jenkins_prefix) {
|
411
|
+
'ref/remotes/upstream/'
|
412
|
+
}
|
413
|
+
|
414
|
+
it_should_behave_like 'with story'
|
415
|
+
end
|
416
|
+
|
417
|
+
context 'without Jenkins prefix' do
|
418
|
+
let(:jenkins_prefix) {
|
419
|
+
''
|
420
|
+
}
|
421
|
+
|
422
|
+
it_should_behave_like 'with story'
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
context 'without story' do
|
427
|
+
let(:branch) {
|
428
|
+
"#{expected_type}/#{expected_prerelease}"
|
429
|
+
}
|
430
|
+
|
431
|
+
it { is_expected.to be_nil }
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
context 'for a bug' do
|
436
|
+
let(:expected_prerelease) {
|
437
|
+
'nasty'
|
438
|
+
}
|
439
|
+
|
440
|
+
let(:expected_type) {
|
441
|
+
'bug'
|
442
|
+
}
|
443
|
+
|
444
|
+
it_should_behave_like 'story branch'
|
445
|
+
end
|
446
|
+
|
447
|
+
context 'for a chore' do
|
448
|
+
let(:expected_prerelease) {
|
449
|
+
'recurring'
|
450
|
+
}
|
451
|
+
|
452
|
+
let(:expected_type) {
|
453
|
+
'chore'
|
454
|
+
}
|
455
|
+
|
456
|
+
it_should_behave_like 'story branch'
|
457
|
+
end
|
458
|
+
|
459
|
+
context 'for a bug' do
|
460
|
+
let(:expected_prerelease) {
|
461
|
+
'cool-new'
|
462
|
+
}
|
463
|
+
|
464
|
+
let(:expected_type) {
|
465
|
+
'feature'
|
466
|
+
}
|
467
|
+
|
468
|
+
it_should_behave_like 'story branch'
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
context 'with version tag' do
|
473
|
+
let(:expected_major) {
|
474
|
+
10
|
475
|
+
}
|
476
|
+
|
477
|
+
let(:expected_minor) {
|
478
|
+
20
|
479
|
+
}
|
480
|
+
|
481
|
+
let(:expected_patch) {
|
482
|
+
30
|
483
|
+
}
|
484
|
+
|
485
|
+
context 'for pre-release' do
|
486
|
+
let(:branch) {
|
487
|
+
"v#{expected_major}.#{expected_minor}.#{expected_patch}.pre.early.pre.release"
|
488
|
+
}
|
489
|
+
|
490
|
+
it { is_expected.to be_a Hash }
|
491
|
+
|
492
|
+
context '[:major]' do
|
493
|
+
subject(:major) {
|
494
|
+
parse[:major]
|
495
|
+
}
|
496
|
+
|
497
|
+
it { is_expected.to be_an Integer }
|
498
|
+
|
499
|
+
it 'is first number in dotted version' do
|
500
|
+
expect(major).to eq(expected_major)
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
504
|
+
context '[:minor]' do
|
505
|
+
subject(:minor) {
|
506
|
+
parse[:minor]
|
507
|
+
}
|
508
|
+
|
509
|
+
it { is_expected.to be_an Integer }
|
510
|
+
|
511
|
+
it 'is second number in dotted version' do
|
512
|
+
expect(minor).to eq(expected_minor)
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
context '[:patch]' do
|
517
|
+
subject(:patch) {
|
518
|
+
parse[:patch]
|
519
|
+
}
|
520
|
+
|
521
|
+
it { is_expected.to be_an Integer }
|
522
|
+
|
523
|
+
it 'is third number in dotted version' do
|
524
|
+
expect(patch).to eq(expected_patch)
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
context '[:prerelease]' do
|
529
|
+
subject(:prerelease) {
|
530
|
+
parse[:prerelease]
|
531
|
+
}
|
532
|
+
|
533
|
+
it "converts '.pre.' separators from prerelease back to '-'" do
|
534
|
+
expect(prerelease).to eq('early-release')
|
535
|
+
end
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
context 'for release' do
|
540
|
+
let(:branch) {
|
541
|
+
"v#{expected_major}.#{expected_minor}.#{expected_patch}"
|
542
|
+
}
|
543
|
+
|
544
|
+
it { is_expected.to be_a Hash }
|
545
|
+
|
546
|
+
context '[:major]' do
|
547
|
+
subject(:major) {
|
548
|
+
parse[:major]
|
549
|
+
}
|
550
|
+
|
551
|
+
it { is_expected.to be_an Integer }
|
552
|
+
|
553
|
+
it 'is first number in dotted version' do
|
554
|
+
expect(major).to eq(expected_major)
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
context '[:minor]' do
|
559
|
+
subject(:minor) {
|
560
|
+
parse[:minor]
|
561
|
+
}
|
562
|
+
|
563
|
+
it { is_expected.to be_an Integer }
|
564
|
+
|
565
|
+
it 'is second number in dotted version' do
|
566
|
+
expect(minor).to eq(expected_minor)
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
context '[:patch]' do
|
571
|
+
subject(:patch) {
|
572
|
+
parse[:patch]
|
573
|
+
}
|
574
|
+
|
575
|
+
it { is_expected.to be_an Integer }
|
576
|
+
|
577
|
+
it 'is third number in dotted version' do
|
578
|
+
expect(patch).to eq(expected_patch)
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
context '[:prerelease]' do
|
583
|
+
subject(:prerelease) {
|
584
|
+
parse[:prerelease]
|
585
|
+
}
|
586
|
+
|
587
|
+
it { is_expected.to be_nil }
|
588
|
+
end
|
589
|
+
end
|
590
|
+
end
|
591
|
+
|
592
|
+
context 'with malformed bug branch' do
|
593
|
+
let(:branch) {
|
594
|
+
'bug/without-story'
|
595
|
+
}
|
596
|
+
|
597
|
+
it { is_expected.to be_nil }
|
598
|
+
end
|
599
|
+
|
600
|
+
context 'with malformed chore branch' do
|
601
|
+
let(:branch) {
|
602
|
+
'chore/without-story'
|
603
|
+
}
|
604
|
+
|
605
|
+
it { is_expected.to be_nil }
|
606
|
+
end
|
607
|
+
|
608
|
+
context 'with malformed feature branch' do
|
609
|
+
let(:branch) {
|
610
|
+
'feature/without-story'
|
611
|
+
}
|
612
|
+
|
613
|
+
it { is_expected.to be_nil }
|
614
|
+
end
|
615
|
+
|
616
|
+
context 'with malformed version tag' do
|
617
|
+
let(:branch) {
|
618
|
+
'1.2.3.pre.without.pre.v'
|
619
|
+
}
|
620
|
+
|
621
|
+
it { is_expected.to be_nil }
|
622
|
+
end
|
623
|
+
end
|
624
|
+
|
625
|
+
context 'prerelease' do
|
626
|
+
subject(:prerelease) {
|
627
|
+
described_class.prerelease(gem_version_prerelease)
|
628
|
+
}
|
629
|
+
|
630
|
+
context 'with nil' do
|
631
|
+
let(:gem_version_prerelease) {
|
632
|
+
nil
|
633
|
+
}
|
634
|
+
|
635
|
+
it { is_expected.to be_nil }
|
636
|
+
end
|
637
|
+
|
638
|
+
context 'without nil' do
|
639
|
+
context "with '.pre.'" do
|
640
|
+
let(:gem_version_prerelease) {
|
641
|
+
'second.pre.early.pre.release'
|
642
|
+
}
|
643
|
+
|
644
|
+
it "replaces '.pre.' with '-'" do
|
645
|
+
expect(prerelease).to eq('second-early-release')
|
646
|
+
end
|
647
|
+
end
|
648
|
+
|
649
|
+
context "without '.pre.'" do
|
650
|
+
let(:gem_version_prerelease) {
|
651
|
+
'prerelease'
|
652
|
+
}
|
653
|
+
|
654
|
+
it 'is unchanged' do
|
655
|
+
expect(prerelease).to eq(gem_version_prerelease)
|
656
|
+
end
|
657
|
+
end
|
658
|
+
end
|
659
|
+
end
|
660
|
+
end
|