travis_check_rubies 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.travis.yml +10 -4
- data/README.markdown +1 -1
- data/bin/travis_check_rubies +31 -19
- data/lib/travis_check_rubies/travis_yml.rb +70 -0
- data/lib/travis_check_rubies/version.rb +74 -20
- data/spec/travis_check_rubies/version_spec.rb +425 -0
- data/travis_check_rubies.gemspec +7 -1
- metadata +41 -11
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
YzMyMGIwYzk2NzM4NzI3NjUxMGE0MmU0NmVkOTEzN2U3NmU4YzkwOQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bfd262c7e986d7ca949f6811db98ef99f2aab55e
|
4
|
+
data.tar.gz: 65c395fa0c08ae67e8e0c35f526891091f02ab8d
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
MTE3YmI3NjkxYzE2YjBlYzg5ZjFjYzQyZjVlZmJmYTViMGRiODUxNjg1MGRj
|
11
|
-
YWQ4Mzk0YmFjNDgzMDZlMDAyOGUyZmZhNzEyMWQxMWYzMmY3OWU=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NWM2YzI5YTExMzdkZmEyM2Y4ZTdjOGY5NjBkZDk4Mzc0YzJhNGFhMjc5NzE1
|
14
|
-
MmI4YTU2MTZjNGJmZDM5NDdhMWNiMGZmZGFjNTBjZjRhODQxOGVjNjI3YTNl
|
15
|
-
NmVlNTEzMWQwMjBiNmY1MTIzMzk5NzJjNmViODhmMjdjNjdjOWY=
|
6
|
+
metadata.gz: 86c99d9aa7055c649b3611d29181429f25b4997c253504c4af5740973606f8838eeb466355d9cb961f07e1e79556d76ef6accb3bc2ad42abcd5767a2054a6b44
|
7
|
+
data.tar.gz: d71305cf683e36b261330a182b2c77de094e4f6be19b795aed62908091323abb8ad319b3dd37db1b09a9f0879f30d576787be107815fe6e0f9ffd50f2ba7a8f4
|
data/.travis.yml
CHANGED
@@ -1,14 +1,20 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
-
- '1.8.7-p371'
|
5
|
-
- '1.9.3-p551'
|
6
4
|
- '2.0.0-p648'
|
7
5
|
- '2.1.10'
|
8
6
|
- '2.2.6'
|
9
7
|
- '2.3.3'
|
10
8
|
- '2.4.0'
|
11
|
-
- 'jruby-1.7.26'
|
12
9
|
- 'jruby-9.0.5.0'
|
13
10
|
- 'jruby-9.1.5.0'
|
14
|
-
script:
|
11
|
+
script:
|
12
|
+
- bundle exec rspec
|
13
|
+
- bundle exec travis_check_rubies
|
14
|
+
matrix:
|
15
|
+
allow_failures:
|
16
|
+
- rvm: 'jruby-9.0.5.0'
|
17
|
+
exclude:
|
18
|
+
- rvm: 'jruby-9.0.5.0'
|
19
|
+
include:
|
20
|
+
- rvm: 'jruby-9.0.5.0'
|
data/README.markdown
CHANGED
data/bin/travis_check_rubies
CHANGED
@@ -1,24 +1,36 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require 'travis_check_rubies/
|
3
|
+
require 'travis_check_rubies/travis_yml'
|
4
|
+
require 'optparse'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
17
|
-
if matched_versions
|
18
|
-
(matched_versions - [version]).each do |matched_version|
|
19
|
-
puts "#{ansi_green}+#{matched_version}#{ansi_reset}"
|
20
|
-
end
|
21
|
-
end
|
6
|
+
options = {}
|
7
|
+
|
8
|
+
op = OptionParser.new
|
9
|
+
op.on('--parts N|M..N', 'Match updates by how many parts (0..2 by default)') do |parts|
|
10
|
+
options[:parts] = case parts
|
11
|
+
when /\A\d+\z/
|
12
|
+
parts.to_i
|
13
|
+
when /\A(\d+)..(\d+)\z/
|
14
|
+
$1.to_i..$2.to_i
|
15
|
+
else
|
16
|
+
fail "Expected number N or range M..N, got #{parts}"
|
22
17
|
end
|
23
|
-
abort
|
24
18
|
end
|
19
|
+
op.on('--[no-]allow-pre', 'Allow matching pre releases (false by default)') do |allow_pre|
|
20
|
+
options[:allow_pre] = allow_pre
|
21
|
+
end
|
22
|
+
op.on('--[no-]intermediary', 'Include all latest version distinct by maximum matchable '\
|
23
|
+
'parts, like 2.3.X when current is 2.2.X and latest is 2.4.X (true by default)') do |intermediary|
|
24
|
+
options[:intermediary] = intermediary
|
25
|
+
end
|
26
|
+
op.on('--exclude V,V,V', Array, 'Exclude matching versions') do |exclude|
|
27
|
+
options[:exclude] = exclude
|
28
|
+
end
|
29
|
+
begin
|
30
|
+
op.parse!
|
31
|
+
rescue => e
|
32
|
+
abort "#{e}\n\n#{op.help}"
|
33
|
+
end
|
34
|
+
|
35
|
+
suggestions = TravisCheckRubies::TravisYml.new.suggestions(options)
|
36
|
+
abort suggestions if suggestions
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'travis_check_rubies/version'
|
3
|
+
|
4
|
+
module TravisCheckRubies
|
5
|
+
class TravisYml
|
6
|
+
attr_reader :path
|
7
|
+
attr_reader :versions, :allow_failures_versions, :exclude_versions, :include_versions
|
8
|
+
|
9
|
+
def initialize(path = '.travis.yml')
|
10
|
+
@path = path
|
11
|
+
|
12
|
+
yaml = YAML.load_file(path)
|
13
|
+
@versions = Array(yaml['rvm']).map(&Version.method(:new))
|
14
|
+
@allow_failures_versions = matrix_versions(yaml, 'allow_failures')
|
15
|
+
@exclude_versions = matrix_versions(yaml, 'exclude')
|
16
|
+
@include_versions = matrix_versions(yaml, 'include')
|
17
|
+
end
|
18
|
+
|
19
|
+
def suggestions(options)
|
20
|
+
suggestions = Hash.new{ |h, k| h[k] = [] }
|
21
|
+
|
22
|
+
updates = Version.updates(versions, options)
|
23
|
+
|
24
|
+
versions.each do |version|
|
25
|
+
next unless (for_version = updates[version])
|
26
|
+
suggestions['rvm'] << "#{version} -> #{for_version.join(', ')}"
|
27
|
+
end
|
28
|
+
|
29
|
+
allow_failures_versions.each do |version|
|
30
|
+
next if versions.include?(version)
|
31
|
+
next if include_versions.include?(version)
|
32
|
+
suggestions['matrix.allow_failures'] << "#{version} in matrix.allow_failures is not in rvm or include list"
|
33
|
+
end
|
34
|
+
|
35
|
+
exclude_versions.each do |version|
|
36
|
+
next if versions.include?(version)
|
37
|
+
suggestions['matrix.exclude'] << "#{version} in matrix.exclude is not in rvm list"
|
38
|
+
end
|
39
|
+
|
40
|
+
{
|
41
|
+
'matrix.allow_failures' => allow_failures_versions,
|
42
|
+
'matrix.exclude' => exclude_versions,
|
43
|
+
}.each do |section, versions|
|
44
|
+
versions.each do |version|
|
45
|
+
next unless (for_version = updates[version])
|
46
|
+
suggestions[section] << "#{version} -> #{for_version.join(', ')}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
include_versions.each do |version|
|
51
|
+
next unless (for_version = Version.update(version, options))
|
52
|
+
next if for_version.include?(version)
|
53
|
+
suggestions['matrix.include'] << "#{version} -> #{for_version.join(', ')}"
|
54
|
+
end
|
55
|
+
|
56
|
+
return if suggestions.empty?
|
57
|
+
suggestions.map do |section, lines|
|
58
|
+
"#{section}:\n#{lines.map{ |line| " #{line}" }.join("\n")}"
|
59
|
+
end.join("\n")
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def matrix_versions(yaml, key)
|
65
|
+
return [] unless (matrix = yaml['matrix'])
|
66
|
+
return [] unless (list = matrix[key])
|
67
|
+
Array(list).map{ |attrs| attrs['rvm'] }.compact.map(&Version.method(:new))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -1,12 +1,17 @@
|
|
1
1
|
require 'net/http'
|
2
|
+
require 'fspath'
|
2
3
|
require 'set'
|
3
4
|
require 'uri'
|
4
|
-
require 'yaml'
|
5
5
|
|
6
6
|
module TravisCheckRubies
|
7
7
|
class Version
|
8
|
+
ROOT_URL = 'http://rubies.travis-ci.org/'
|
9
|
+
CACHE_TIME = 24 * 60 * 60
|
10
|
+
|
8
11
|
class << self
|
9
|
-
|
12
|
+
def convert(version_or_string)
|
13
|
+
version_or_string.is_a?(self) ? version_or_string : new(version_or_string)
|
14
|
+
end
|
10
15
|
|
11
16
|
def available
|
12
17
|
@available ||= begin
|
@@ -14,36 +19,81 @@ module TravisCheckRubies
|
|
14
19
|
url.start_with?(base_url)
|
15
20
|
end.map do |url|
|
16
21
|
new(url[%r{([^/]+)\.tar\.(?:gz|bz2)$}, 1])
|
17
|
-
end
|
22
|
+
end.sort
|
18
23
|
end
|
19
24
|
end
|
20
25
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
26
|
+
def update(version, parts: 0..2, allow_pre: false, intermediary: true, exclude: [])
|
27
|
+
version = convert(version)
|
28
|
+
return unless version.version_parts
|
29
|
+
|
30
|
+
parts = Array(parts)
|
31
|
+
exclude = exclude.map{ |ev| convert(ev) }
|
32
|
+
ordered = allow_pre ? available : available.partition(&:pre).inject(:+)
|
33
|
+
candidates = ordered.reverse.select do |v|
|
34
|
+
next unless v.version_parts
|
35
|
+
next unless v.match?(version, parts.min)
|
36
|
+
next unless v >= version
|
37
|
+
next if exclude.any?{ |ev| ev.match?(v, ev.version_parts.length) }
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
41
|
+
updates = if intermediary
|
42
|
+
candidates.group_by do |v|
|
43
|
+
v.version_parts.take(parts.max)
|
44
|
+
end.flat_map do |_, group|
|
45
|
+
parts.map do |n|
|
46
|
+
group.find{ |v| v.match?(version, n) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
else
|
50
|
+
parts.map do |n|
|
51
|
+
candidates.find{ |v| v.match?(version, n) }
|
25
52
|
end
|
26
53
|
end
|
54
|
+
|
55
|
+
updates.compact!
|
56
|
+
updates.uniq!
|
57
|
+
updates.sort!
|
58
|
+
|
59
|
+
updates unless [version] == updates
|
27
60
|
end
|
28
61
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
62
|
+
def updates(versions, **options)
|
63
|
+
versions = versions.map{ |v| convert(v) }
|
64
|
+
|
65
|
+
updates = {}
|
66
|
+
has = Set.new
|
67
|
+
versions.uniq.sort.reverse_each do |version|
|
68
|
+
deduplicated = (update(version, options) || [version]).select{ |v| has.add?(v) }
|
69
|
+
updates[version] = [version] == deduplicated ? nil : deduplicated
|
37
70
|
end
|
38
|
-
|
39
|
-
|
40
|
-
end]
|
71
|
+
|
72
|
+
Hash[versions.map{ |v| [v, updates[v]] }]
|
41
73
|
end
|
42
74
|
|
43
75
|
private
|
44
76
|
|
77
|
+
def cache_path
|
78
|
+
@cache_path ||= FSPath(ENV['XDG_CACHE_HOME'] || '~/.cache').expand_path / 'travis_check_rubies.txt'
|
79
|
+
end
|
80
|
+
|
45
81
|
def index_urls
|
46
|
-
@index_urls ||=
|
82
|
+
@index_urls ||= begin
|
83
|
+
if cache_path.size? && cache_path.mtime + CACHE_TIME > Time.now
|
84
|
+
cache_path.read
|
85
|
+
else
|
86
|
+
data = Net::HTTP.get(URI(ROOT_URL + 'index.txt'))
|
87
|
+
|
88
|
+
cache_path.dirname.mkpath
|
89
|
+
FSPath.temp_file('travis_check_rubies', cache_path.dirname) do |f|
|
90
|
+
f.write(data)
|
91
|
+
f.path.rename(cache_path)
|
92
|
+
end
|
93
|
+
|
94
|
+
data
|
95
|
+
end
|
96
|
+
end.split("\n")
|
47
97
|
end
|
48
98
|
|
49
99
|
def base_url
|
@@ -91,6 +141,10 @@ module TravisCheckRubies
|
|
91
141
|
match_by(n) == other.match_by(n)
|
92
142
|
end
|
93
143
|
|
144
|
+
def inspect
|
145
|
+
"#<#{self.class.name} #{str}>"
|
146
|
+
end
|
147
|
+
|
94
148
|
protected
|
95
149
|
|
96
150
|
def compare_by
|
@@ -103,7 +157,7 @@ module TravisCheckRubies
|
|
103
157
|
end
|
104
158
|
|
105
159
|
def match_by(n)
|
106
|
-
[type, variant, version_parts.take(n)]
|
160
|
+
[type, variant, version_parts && version_parts.take(n)]
|
107
161
|
end
|
108
162
|
end
|
109
163
|
end
|
@@ -0,0 +1,425 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'travis_check_rubies/version'
|
3
|
+
|
4
|
+
describe TravisCheckRubies::Version do
|
5
|
+
def v(str)
|
6
|
+
described_class.new(str)
|
7
|
+
end
|
8
|
+
|
9
|
+
def vs(strs)
|
10
|
+
strs.map{ |str| described_class.new(str) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def cleanup_instance_variables(o)
|
14
|
+
o.instance_variables.each do |name|
|
15
|
+
o.remove_instance_variable(name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'parsing' do
|
20
|
+
{
|
21
|
+
'1.2.3-pre1' => {
|
22
|
+
version_parts: [1, 2, 3],
|
23
|
+
pre: 'pre1',
|
24
|
+
},
|
25
|
+
'jruby' => {
|
26
|
+
type: 'jruby',
|
27
|
+
},
|
28
|
+
'ruby-2.3.4.5-clang' => {
|
29
|
+
str: '2.3.4.5-clang',
|
30
|
+
version_parts: [2, 3, 4, 5],
|
31
|
+
variant: 'clang',
|
32
|
+
},
|
33
|
+
'xrb-1000' => {
|
34
|
+
type: 'xrb',
|
35
|
+
version_parts: [1000],
|
36
|
+
},
|
37
|
+
'1.5' => {
|
38
|
+
version_parts: [1, 5],
|
39
|
+
},
|
40
|
+
'1.8.4-p616' => {
|
41
|
+
version_parts: [1, 8, 4, 616],
|
42
|
+
},
|
43
|
+
}.each do |version_string, defined_attributes|
|
44
|
+
context "of #{version_string}" do
|
45
|
+
subject{ v(version_string) }
|
46
|
+
|
47
|
+
let(:default_attributes) do
|
48
|
+
{
|
49
|
+
str: version_string,
|
50
|
+
type: 'ruby',
|
51
|
+
version_parts: nil,
|
52
|
+
pre: nil,
|
53
|
+
variant: nil,
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
it{ is_expected.to have_attributes(default_attributes.merge(defined_attributes)) }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#eql?' do
|
63
|
+
it 'returns false for different version' do
|
64
|
+
expect(v('1.8')).not_to eql(v('1.9'))
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'returns true for equal versions' do
|
68
|
+
expect(v('1.8')).to eql(v('1.8'))
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'returns true for same version in different format' do
|
72
|
+
expect(v('1.8')).to eql(v('ruby-1.8'))
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'returns true for same version string' do
|
76
|
+
expect(v('1.8')).to eql('1.8')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#<=>' do
|
81
|
+
let(:versions) do
|
82
|
+
vs(%w[
|
83
|
+
jruby-head
|
84
|
+
jruby-1.7.7
|
85
|
+
jruby-1.7.26
|
86
|
+
jruby-9.0.0.0.pre1
|
87
|
+
jruby-9.0.0.0.pre2
|
88
|
+
jruby-9.0.0.0
|
89
|
+
ruby-1.8.7
|
90
|
+
ruby-1.8.7-p371
|
91
|
+
ruby-2.0.0-p645
|
92
|
+
ruby-2.0.0-p647
|
93
|
+
ruby-2.0.0-p647-clang
|
94
|
+
])
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'oders versions using all parts' do
|
98
|
+
expect(versions.reverse.sort).to eq(versions)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#match?' do
|
103
|
+
subject{ v('ruby-1.7.7') }
|
104
|
+
|
105
|
+
context 'for same version' do
|
106
|
+
let(:version){ v('ruby-1.7.7') }
|
107
|
+
|
108
|
+
it 'matches with any number of parts' do
|
109
|
+
(0..4).each{ |n| is_expected.to be_match(version, n) }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'for different patch version' do
|
114
|
+
let(:version){ v('ruby-1.7.8') }
|
115
|
+
|
116
|
+
it 'matches with 0..2 parts' do
|
117
|
+
(0..2).each{ |n| is_expected.to be_match(version, n) }
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'does not match with more parts' do
|
121
|
+
(3..4).each{ |n| is_expected.not_to be_match(version, n) }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'for different minor version' do
|
126
|
+
let(:version){ v('ruby-1.8.7') }
|
127
|
+
|
128
|
+
it 'matches with 0..1 parts' do
|
129
|
+
(0..1).each{ |n| is_expected.to be_match(version, n) }
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'does not match with more parts' do
|
133
|
+
(2..4).each{ |n| is_expected.not_to be_match(version, n) }
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'for different major version' do
|
138
|
+
let(:version){ v('ruby-2.7.7') }
|
139
|
+
|
140
|
+
it 'matches with 0 parts' do
|
141
|
+
is_expected.to be_match(version, 0)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'does not match with more parts' do
|
145
|
+
(1..4).each{ |n| is_expected.not_to be_match(version, n) }
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context 'for version with additional part' do
|
150
|
+
let(:version){ v('ruby-1.7.7.1') }
|
151
|
+
|
152
|
+
it 'matches with 0..3 parts' do
|
153
|
+
(0..3).each{ |n| is_expected.to be_match(version, n) }
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'does not match with more parts' do
|
157
|
+
is_expected.not_to be_match(version, 4)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context 'for pre release of same version' do
|
162
|
+
let(:version){ v('ruby-1.7.7-pre1') }
|
163
|
+
|
164
|
+
it 'matches with any number of parts' do
|
165
|
+
(0..4).each{ |n| is_expected.to be_match(version, n) }
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'for different type of same version' do
|
170
|
+
let(:version){ v('jruby-1.7.7') }
|
171
|
+
|
172
|
+
it 'does not match' do
|
173
|
+
(0..4).each{ |n| is_expected.not_to be_match(version, n) }
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context 'for different variant of same version' do
|
178
|
+
let(:version){ v('ruby-1.7.7-clang') }
|
179
|
+
|
180
|
+
it 'does not match' do
|
181
|
+
(0..4).each{ |n| is_expected.not_to be_match(version, n) }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context 'for version without version parts' do
|
186
|
+
let(:version){ v('ruby') }
|
187
|
+
|
188
|
+
it 'does not match' do
|
189
|
+
(0..4).each{ |n| is_expected.not_to be_match(version, n) }
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe '#inspect' do
|
195
|
+
{
|
196
|
+
'1.2.3-pre1' => '#<TravisCheckRubies::Version 1.2.3-pre1>',
|
197
|
+
'jruby' => '#<TravisCheckRubies::Version jruby>',
|
198
|
+
}.each do |version_string, inspect|
|
199
|
+
context "for #{version_string}" do
|
200
|
+
it{ expect(v(version_string).inspect).to eq(inspect) }
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe '.index_urls' do
|
206
|
+
let(:cache_path){ FSPath.temp_file_path }
|
207
|
+
|
208
|
+
before do
|
209
|
+
cleanup_instance_variables(described_class)
|
210
|
+
allow(described_class).to receive(:cache_path).and_return(cache_path)
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'returns urls from text index of rubies.travis-ci.org' do
|
214
|
+
allow(Net::HTTP).to receive(:get).with(URI('http://rubies.travis-ci.org/index.txt')).
|
215
|
+
and_return("one\ntwo\nthree")
|
216
|
+
|
217
|
+
expect(described_class.send(:index_urls)).to eq(%w[one two three])
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'caches result' do
|
221
|
+
allow(Net::HTTP).to receive(:get).with(URI('http://rubies.travis-ci.org/index.txt')).
|
222
|
+
once.and_return("a\nb\nc")
|
223
|
+
|
224
|
+
3.times{ expect(described_class.send(:index_urls)).to eq(%w[a b c]) }
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'reads cache from file if it is new' do
|
228
|
+
allow(cache_path).to receive(:size?).and_return(616)
|
229
|
+
allow(cache_path).to receive(:mtime).and_return(Time.now - described_class::CACHE_TIME / 2)
|
230
|
+
allow(cache_path).to receive(:read).and_return("foo\nbar")
|
231
|
+
|
232
|
+
expect(Net::HTTP).not_to receive(:get)
|
233
|
+
expect(described_class.send(:index_urls)).to eq(%w[foo bar])
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'writes cache file if it is stale' do
|
237
|
+
allow(cache_path).to receive(:size?).and_return(616)
|
238
|
+
allow(cache_path).to receive(:mtime).and_return(Time.now - described_class::CACHE_TIME * 2)
|
239
|
+
allow(Net::HTTP).to receive(:get).with(URI('http://rubies.travis-ci.org/index.txt')).
|
240
|
+
once.and_return("brave\nnew\nworld")
|
241
|
+
|
242
|
+
expect(described_class.send(:index_urls)).to eq(%w[brave new world])
|
243
|
+
expect(cache_path.read).to eq("brave\nnew\nworld")
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe '.base_url' do
|
248
|
+
before do
|
249
|
+
cleanup_instance_variables(described_class)
|
250
|
+
allow(ENV).to receive(:[]).with('TRAVIS').and_return(env_travis)
|
251
|
+
end
|
252
|
+
|
253
|
+
context 'when env variable TRAVIS is set' do
|
254
|
+
let(:env_travis){ 'true' }
|
255
|
+
|
256
|
+
it 'gets base_url from rvm debug' do
|
257
|
+
allow(described_class).to receive(:`).with('rvm debug').
|
258
|
+
and_return(%Q{ foo: "xxx" \n system: "XXX/YYY" \n bar: "yyy" })
|
259
|
+
|
260
|
+
expect(described_class.send(:base_url)).to eq('http://rubies.travis-ci.org/XXX/YYY/')
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
context 'when env variable TRAVIS is not set' do
|
265
|
+
let(:env_travis){ nil }
|
266
|
+
|
267
|
+
it 'gets base_url from first ubuntu url in index' do
|
268
|
+
allow(described_class).to receive(:index_urls).and_return(%w[
|
269
|
+
http://rubies.travis-ci.org/osx/AAA/1.tar.gz
|
270
|
+
http://rubies.travis-ci.org/ubuntu/ZZZ/2.tar.gz
|
271
|
+
http://rubies.travis-ci.org/ubuntu/BBB/3.tar.gz
|
272
|
+
])
|
273
|
+
|
274
|
+
expect(described_class.send(:base_url)).to eq('http://rubies.travis-ci.org/ubuntu/BBB/')
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
describe '.available' do
|
280
|
+
before do
|
281
|
+
cleanup_instance_variables(described_class)
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'gets sorted versions from index urls matching base_url' do
|
285
|
+
allow(described_class).to receive(:index_urls).and_return(%w[
|
286
|
+
http://rubies.travis-ci.org/osx/AAA/1.tar.gz
|
287
|
+
http://rubies.travis-ci.org/ubuntu/ZZZ/2.tar.gz
|
288
|
+
http://rubies.travis-ci.org/ubuntu/BBB/4.tar.gz
|
289
|
+
http://rubies.travis-ci.org/ubuntu/BBB/3.tar.bz2
|
290
|
+
])
|
291
|
+
allow(described_class).to receive(:base_url).and_return('http://rubies.travis-ci.org/ubuntu/BBB/')
|
292
|
+
|
293
|
+
expect(described_class.available).to eq([v('3'), v('4')])
|
294
|
+
end
|
295
|
+
|
296
|
+
it 'caches result' do
|
297
|
+
allow(described_class).to receive(:index_urls).once.and_return(%w[
|
298
|
+
http://rubies.travis-ci.org/ubuntu/CCC/a.tar.gz
|
299
|
+
http://rubies.travis-ci.org/ubuntu/CCC/b.tar.bz2
|
300
|
+
])
|
301
|
+
allow(described_class).to receive(:base_url).and_return('http://rubies.travis-ci.org/ubuntu/CCC/')
|
302
|
+
|
303
|
+
3.times{ expect(described_class.available).to eq([v('a'), v('b')]) }
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
describe '.update' do
|
308
|
+
before do
|
309
|
+
allow(described_class).to receive(:available).and_return(vs(available_strs).sort)
|
310
|
+
end
|
311
|
+
|
312
|
+
context 'for version without version parts' do
|
313
|
+
let(:available_strs){ %w[ruby 1.2.3 2.3.4] }
|
314
|
+
|
315
|
+
it{ expect(described_class.update(v('ruby'))).to eq nil }
|
316
|
+
end
|
317
|
+
|
318
|
+
context 'when there are no updates' do
|
319
|
+
let(:available_strs){ %w[ruby 1.2.3 2.3.4] }
|
320
|
+
|
321
|
+
it{ expect(described_class.update(v('2.3.4'))).to eq nil }
|
322
|
+
end
|
323
|
+
|
324
|
+
context 'when version is not present' do
|
325
|
+
let(:available_strs){ %w[ruby 1.2.3 2.3.4] }
|
326
|
+
|
327
|
+
it{ expect(described_class.update(v('3.4.5'))).to eq [] }
|
328
|
+
end
|
329
|
+
|
330
|
+
describe 'parts and intermediary' do
|
331
|
+
let(:version){ v('1.7.1') }
|
332
|
+
|
333
|
+
let(:available_strs){ %w[
|
334
|
+
1.7.1 1.7.2 1.8.6 1.8.7 1.9.2 1.9.3
|
335
|
+
2.0.8 2.0.9 2.1.6 2.1.7 2.2.4 2.2.5
|
336
|
+
3.0.4 3.0.5 3.1.2 3.1.3 3.2.0 3.2.1
|
337
|
+
] }
|
338
|
+
|
339
|
+
context 'when intermediary is true' do
|
340
|
+
it 'returns all latest with distinct 0..2 (by default) matching version parts' do
|
341
|
+
expect(described_class.update(version)).to eq vs(%w[1.7.2 1.8.7 1.9.3 2.0.9 2.1.7 2.2.5 3.0.5 3.1.3 3.2.1])
|
342
|
+
end
|
343
|
+
|
344
|
+
{
|
345
|
+
0 => %w[3.2.1],
|
346
|
+
0..1 => %w[1.9.3 2.2.5 3.2.1],
|
347
|
+
0..2 => %w[1.7.2 1.8.7 1.9.3 2.0.9 2.1.7 2.2.5 3.0.5 3.1.3 3.2.1],
|
348
|
+
1..2 => %w[1.7.2 1.8.7 1.9.3],
|
349
|
+
2 => %w[1.7.2],
|
350
|
+
}.each do |parts, expected|
|
351
|
+
it "returns all latest with distinct #{parts} matching version parts" do
|
352
|
+
expect(described_class.update(version, parts: parts)).to eq vs(expected)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
context 'when intermediary is false' do
|
358
|
+
it 'returns latest for each 0..2 (by default) matching version parts' do
|
359
|
+
expect(described_class.update(version, intermediary: false)).to eq vs(%w[1.7.2 1.9.3 3.2.1])
|
360
|
+
end
|
361
|
+
|
362
|
+
{
|
363
|
+
0 => %w[3.2.1],
|
364
|
+
0..1 => %w[1.9.3 3.2.1],
|
365
|
+
0..2 => %w[1.7.2 1.9.3 3.2.1],
|
366
|
+
1..2 => %w[1.7.2 1.9.3],
|
367
|
+
2 => %w[1.7.2],
|
368
|
+
}.each do |parts, expected|
|
369
|
+
it "returns latest for each #{parts} matching version parts" do
|
370
|
+
expect(described_class.update(version, parts: parts, intermediary: false)).to eq vs(expected)
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
describe 'pre releases' do
|
377
|
+
let(:available_strs){ %w[2.4.0-pre 2.4.0 2.4.1 2.4.2-pre1 2.4.2-pre2] }
|
378
|
+
|
379
|
+
context 'when for pre release there is only newer pre release' do
|
380
|
+
it 'returns next pre release' do
|
381
|
+
expect(described_class.update(v('2.4.2-pre1'))).to eq [v('2.4.2-pre2')]
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
context 'when there is a newer release and even newer pre release' do
|
386
|
+
context 'for release' do
|
387
|
+
it 'returns newer release when allow_pre is false' do
|
388
|
+
expect(described_class.update(v('2.4.0'))).to eq [v('2.4.1')]
|
389
|
+
end
|
390
|
+
|
391
|
+
it 'returns even newer pre release when allow_pre is true' do
|
392
|
+
expect(described_class.update(v('2.4.0'), allow_pre: true)).to eq [v('2.4.2-pre2')]
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
context 'for pre release' do
|
397
|
+
it 'returns release when allow_pre is false' do
|
398
|
+
expect(described_class.update(v('2.4.0-pre'))).to eq [v('2.4.1')]
|
399
|
+
end
|
400
|
+
|
401
|
+
it 'returns even newer pre release when allow_pre is true' do
|
402
|
+
expect(described_class.update(v('2.4.0-pre'), allow_pre: true)).to eq [v('2.4.2-pre2')]
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
describe '.updates' do
|
410
|
+
before do
|
411
|
+
allow(described_class).to receive(:available).
|
412
|
+
and_return(vs(%w[1.8.7 1.9.3 2.0.9 2.1.7]).sort)
|
413
|
+
end
|
414
|
+
|
415
|
+
it 'returns a hash with updates for higher versions removed from updates for lower versions' do
|
416
|
+
expect(described_class.updates(vs(%w[2.0.8 2.1.7 1.8.6 1.9.3])).to_a).
|
417
|
+
to eq({
|
418
|
+
v('2.0.8') => vs(%w[2.0.9]),
|
419
|
+
v('2.1.7') => nil,
|
420
|
+
v('1.8.6') => vs(%w[1.8.7]),
|
421
|
+
v('1.9.3') => nil,
|
422
|
+
}.to_a)
|
423
|
+
end
|
424
|
+
end
|
425
|
+
end
|
data/travis_check_rubies.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'travis_check_rubies'
|
5
|
-
s.version = '0.
|
5
|
+
s.version = '0.2.0'
|
6
6
|
s.summary = 'Are you using the latest rubies in .travis.yml?'
|
7
7
|
s.description = 'Check if `.travis.yml` specifies latest available rubies from listed on http://rubies.travis-ci.org and propose changes'
|
8
8
|
s.homepage = "http://github.com/toy/#{s.name}"
|
@@ -13,4 +13,10 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
14
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
15
15
|
s.require_paths = %w[lib]
|
16
|
+
|
17
|
+
s.required_ruby_version = '>= 2.0.0'
|
18
|
+
|
19
|
+
s.add_runtime_dependency 'fspath', '~> 3.0'
|
20
|
+
|
21
|
+
s.add_development_dependency 'rspec', '~> 3.0'
|
16
22
|
end
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: travis_check_rubies
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Kuchin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
12
|
-
dependencies:
|
11
|
+
date: 2017-03-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: fspath
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
13
41
|
description: Check if `.travis.yml` specifies latest available rubies from listed
|
14
42
|
on http://rubies.travis-ci.org and propose changes
|
15
43
|
email:
|
@@ -18,14 +46,16 @@ executables:
|
|
18
46
|
extensions: []
|
19
47
|
extra_rdoc_files: []
|
20
48
|
files:
|
21
|
-
- .gitignore
|
22
|
-
- .travis.yml
|
49
|
+
- ".gitignore"
|
50
|
+
- ".travis.yml"
|
23
51
|
- Gemfile
|
24
52
|
- LICENSE.txt
|
25
53
|
- README.markdown
|
26
54
|
- bin/travis_check_rubies
|
27
55
|
- lib/travis_check_rubies.rb
|
56
|
+
- lib/travis_check_rubies/travis_yml.rb
|
28
57
|
- lib/travis_check_rubies/version.rb
|
58
|
+
- spec/travis_check_rubies/version_spec.rb
|
29
59
|
- travis_check_rubies.gemspec
|
30
60
|
homepage: http://github.com/toy/travis_check_rubies
|
31
61
|
licenses:
|
@@ -37,19 +67,19 @@ require_paths:
|
|
37
67
|
- lib
|
38
68
|
required_ruby_version: !ruby/object:Gem::Requirement
|
39
69
|
requirements:
|
40
|
-
- -
|
70
|
+
- - ">="
|
41
71
|
- !ruby/object:Gem::Version
|
42
|
-
version:
|
72
|
+
version: 2.0.0
|
43
73
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
74
|
requirements:
|
45
|
-
- -
|
75
|
+
- - ">="
|
46
76
|
- !ruby/object:Gem::Version
|
47
77
|
version: '0'
|
48
78
|
requirements: []
|
49
79
|
rubyforge_project:
|
50
|
-
rubygems_version: 2.6.
|
80
|
+
rubygems_version: 2.6.10
|
51
81
|
signing_key:
|
52
82
|
specification_version: 4
|
53
83
|
summary: Are you using the latest rubies in .travis.yml?
|
54
|
-
test_files:
|
55
|
-
|
84
|
+
test_files:
|
85
|
+
- spec/travis_check_rubies/version_spec.rb
|