travis_check_rubies 0.2.5 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ab21a220cbfd5c324fed2b89437b745669ac522e
4
- data.tar.gz: 535c8f939a7d062574f920c0c1f42d28e06ed754
2
+ SHA256:
3
+ metadata.gz: 754293bfea3d3b93d0cca432c90b7b792ff7cf5634a670f8cdd8f82e4d3511b6
4
+ data.tar.gz: af8d4c0090e245130ac90dad26bd6068e08d340fe1c2a52f73352d3b0e15d1a7
5
5
  SHA512:
6
- metadata.gz: 849c73497444dfcf8e1aa7c0303e6169c8ee823d8ae072ec7190016468857cad59618cbdaaeb232b0e67c523a6eef3b3b5bcad03913baabfeb54aa88c98025ac
7
- data.tar.gz: 010526626e47ad0a788cf4b15acf2849318ba4c5f4d0936ee6d729679a0f496a5f180b8a8c104af8201e4f7e4c58ef04d9853de89c7ff1f7e347c2329d2c4988
6
+ metadata.gz: 73413645cbabaeea6f125258ad0df781e10f7dd2df886fdde4aac740cdd5651fa4bea375fb9860274a75b6a4100bd385ca1df3c3bd70ab7cab162c86b4e45cff
7
+ data.tar.gz: 026aec14d310b2b61bba7c34787c7159c6a11acc403af9cb4602f2d83b0559f03806ff7ad8ee97223315189cf9e3ee9b7223309ede98daf7f7b7df3fa96e7e04
data/.travis.yml CHANGED
@@ -1,23 +1,17 @@
1
- sudo: false
1
+ dist: xenial
2
2
  language: ruby
3
3
  rvm:
4
- - '2.0.0-p648'
5
- - '2.1.10'
6
- - '2.2.8'
7
- - '2.3.5'
8
- - '2.4.2'
9
- - 'jruby-9.0.5.0'
10
- - 'jruby-9.1.9.0'
4
+ - '2.3.8'
5
+ - '2.4.10'
6
+ - '2.5.9'
7
+ - '2.6.7'
8
+ - '2.7.3'
9
+ - '3.0.1'
10
+ - 'jruby-9.1.17.0'
11
+ - 'jruby-9.2.14.0'
11
12
  before_script:
12
13
  - env
13
14
  - rvm debug
14
15
  script:
15
16
  - bundle exec rspec
16
17
  - bundle exec travis_check_rubies
17
- matrix:
18
- allow_failures:
19
- - rvm: 'jruby-9.0.5.0'
20
- exclude:
21
- - rvm: 'jruby-9.0.5.0'
22
- include:
23
- - rvm: 'jruby-9.0.5.0'
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2017 Ivan Kuchin
1
+ Copyright (c) 2017-2021 Ivan Kuchin
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.markdown CHANGED
@@ -43,4 +43,4 @@ bundle exec travis_check_rubies
43
43
 
44
44
  ## Copyright
45
45
 
46
- Copyright (c) 2017 Ivan Kuchin. See [LICENSE.txt](LICENSE.txt) for details.
46
+ Copyright (c) 2017-2021 Ivan Kuchin. See [LICENSE.txt](LICENSE.txt) for details.
@@ -6,6 +6,8 @@ require 'yaml'
6
6
 
7
7
  CONFIG_FILE = '.travis_check_rubies.yml'
8
8
 
9
+ update = false
10
+
9
11
  options = if File.exist?(CONFIG_FILE)
10
12
  yaml = YAML.load_file(CONFIG_FILE) || {}
11
13
  fail "#{CONFIG_FILE} doesn't contain options hash" unless yaml.is_a?(Hash)
@@ -36,11 +38,21 @@ end
36
38
  op.on('--exclude V,V,V', Array, 'Exclude matching versions') do |exclude|
37
39
  options[:exclude] = exclude
38
40
  end
41
+ op.on('--conservative', 'Update to first instead of last possible version') do
42
+ options[:conservative] = true
43
+ end
44
+ op.on('-u', '--update', 'Update versions') do
45
+ update = true
46
+ end
39
47
  begin
40
48
  op.parse!
41
49
  rescue => e
42
50
  abort "#{e}\n\n#{op.help}"
43
51
  end
44
52
 
45
- suggestions = TravisCheckRubies::TravisYml.new.suggestions(options)
46
- abort suggestions if suggestions
53
+ travis_yml = TravisCheckRubies::TravisYml.new(options: options)
54
+ if update
55
+ abort unless travis_yml.update
56
+ else
57
+ abort unless travis_yml.suggest
58
+ end
@@ -1,4 +1,4 @@
1
- require 'travis_check_rubies/version'
1
+ require_relative 'travis_check_rubies/version'
2
2
 
3
3
  module TravisCheckRubies
4
4
  end
@@ -0,0 +1,44 @@
1
+ require 'digest'
2
+ require 'fspath'
3
+ require 'net/http'
4
+ require 'uri'
5
+
6
+ module TravisCheckRubies
7
+ class Fetcher
8
+ CACHE_TIME = 24 * 60 * 60
9
+
10
+ attr_reader :url
11
+
12
+ def initialize(url)
13
+ @url = url
14
+ end
15
+
16
+ def data
17
+ cached_data || fetch_data
18
+ end
19
+
20
+ private
21
+
22
+ def cache_path
23
+ @cache_path ||= FSPath(ENV['XDG_CACHE_HOME'] || '~/.cache').expand_path / "travis_check_rubies.#{Digest::SHA1.hexdigest url}"
24
+ end
25
+
26
+ def cached_data
27
+ return unless cache_path.size?
28
+ return unless cache_path.mtime + CACHE_TIME > Time.now
29
+ cache_path.read
30
+ end
31
+
32
+ def fetch_data
33
+ data = Net::HTTP.get(URI(url))
34
+
35
+ cache_path.dirname.mkpath
36
+ FSPath.temp_file('travis_check_rubies', cache_path.dirname) do |f|
37
+ f.write(data)
38
+ f.path.rename(cache_path)
39
+ end
40
+
41
+ data
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,11 @@
1
+ require_relative 'fetcher'
2
+
3
+ module TravisCheckRubies
4
+ class RvmIndex
5
+ URL = 'https://raw.githubusercontent.com/rvm/rvm/stable/config/known_strings'
6
+
7
+ def version_strings
8
+ TravisCheckRubies::Fetcher.new(URL).data.split("\n")
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,45 @@
1
+ require_relative 'fetcher'
2
+
3
+ require 'travis_check_rubies/travis_yml'
4
+
5
+ module TravisCheckRubies
6
+ class TravisIndex
7
+ ROOT_URL = 'https://rubies.travis-ci.org/'
8
+
9
+ LTS_VERSIONS = {
10
+ precise: '12.04',
11
+ trusty: '14.04',
12
+ xenial: '16.04',
13
+ bionic: '18.04',
14
+ focal: '20.04',
15
+ }
16
+
17
+ def version_strings
18
+ $stderr.puts "Using #{base_url}"
19
+ index_urls.select do |url|
20
+ url.start_with?(base_url)
21
+ end.map do |url|
22
+ url[%r{([^/]+)\.tar\.(?:gz|bz2)$}, 1]
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def index_urls
29
+ @index_urls ||= TravisCheckRubies::Fetcher.new(ROOT_URL + 'index.txt').data.split("\n")
30
+ end
31
+
32
+ def base_url
33
+ @base_url ||= begin
34
+ base_ubuntu_url = "#{ROOT_URL}ubuntu/"
35
+ dist = TravisYml.new.dist
36
+ version = LTS_VERSIONS[dist.to_sym]
37
+ if version
38
+ "#{base_ubuntu_url}#{version}/x86_64/"
39
+ else
40
+ fail "Unknown dist #{dist}"
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,66 +1,157 @@
1
+ require 'fspath'
1
2
  require 'yaml'
2
- require 'travis_check_rubies/version'
3
+
4
+ require_relative 'updater'
5
+ require_relative 'version'
3
6
 
4
7
  module TravisCheckRubies
5
8
  class TravisYml
6
- attr_reader :path
7
- attr_reader :versions, :allow_failures_versions, :exclude_versions, :include_versions
9
+ Suggestion = Struct.new(:section, :from, :choices, :to)
10
+
11
+ attr_reader :path, :options
8
12
 
9
- def initialize(path = '.travis.yml')
10
- @path = path
13
+ def initialize(path: '.travis.yml', options: {})
14
+ @path = FSPath(path)
15
+ @options = options
16
+ end
11
17
 
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')
18
+ def dist
19
+ original_object['dist'] || 'xenial'
17
20
  end
18
21
 
19
- def suggestions(options)
20
- suggestions = Hash.new{ |h, k| h[k] = [] }
22
+ def warnings
23
+ return @warnings if @warnings
21
24
 
22
- updates = Version.updates(versions, options)
25
+ @warnings = []
23
26
 
24
- versions.each do |version|
25
- next unless (for_version = updates[version])
26
- suggestions['rvm'] << "#{version} -> #{for_version.join(', ')}"
27
+ rvm_versions.group_by(&:itself).select{ |_, versions| versions.count > 1 }.each do |version, _|
28
+ @warnings << "#{version} in rvm is repeating"
27
29
  end
28
30
 
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"
31
+ (allow_failures_versions - rvm_versions - include_versions).each do |version|
32
+ @warnings << "#{version} in matrix.allow_failures is not in rvm or include list"
33
33
  end
34
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"
35
+ (exclude_versions - rvm_versions).each do |version|
36
+ @warnings << "#{version} in matrix.exclude is not in rvm list"
37
+ end
38
+
39
+ @warnings
40
+ end
41
+
42
+ def suggestions
43
+ return @suggestions if @suggestions
44
+
45
+ @suggestions = []
46
+
47
+ updates = Version.updates(rvm_versions, **options)
48
+ rvm_versions.each do |version|
49
+ next unless (suggestions = updates[version])
50
+ @suggestions << Suggestion.new('rvm', version, suggestions)
38
51
  end
39
52
 
40
53
  {
41
- 'matrix.allow_failures' => allow_failures_versions,
42
- 'matrix.exclude' => exclude_versions,
54
+ 'allow_failures' => allow_failures_versions,
55
+ 'exclude' => exclude_versions,
56
+ 'include' => include_versions,
43
57
  }.each do |section, versions|
44
58
  versions.each do |version|
45
- next unless (for_version = updates[version])
46
- suggestions[section] << "#{version} -> #{for_version.join(', ')}"
59
+ next unless (suggestions = Version.update(version, **options))
60
+ next if suggestions.include?(version)
61
+ to = section == 'include' && !options[:conservative] ? suggestions.last : suggestions.first
62
+ @suggestions << Suggestion.new(section, version, suggestions, to)
47
63
  end
48
64
  end
49
65
 
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(', ')}"
66
+ @suggestions
67
+ end
68
+
69
+ def suggest
70
+ puts warnings
71
+
72
+ suggestions.group_by(&:section).each do |section, section_suggestions|
73
+ puts "#{section}:"
74
+ section_suggestions.each do |suggestion|
75
+ puts " #{suggestion.from} -> #{suggestion.choices.join(', ')}"
76
+ end
77
+ end
78
+
79
+ warnings.empty? && suggestions.empty?
80
+ end
81
+
82
+ def update
83
+ unless warnings.empty?
84
+ puts warnings
85
+
86
+ return false
87
+ end
88
+
89
+ unless YAML.load(updated_content) == expected_object
90
+ puts updated_content
91
+
92
+ return false
93
+ end
94
+
95
+ FSPath.temp_file(path.basename, path.dirname) do |f|
96
+ f.write(updated_content)
97
+ f.path.rename(path)
54
98
  end
55
99
 
56
- return if suggestions.empty?
57
- suggestions.map do |section, lines|
58
- "#{section}:\n#{lines.map{ |line| " #{line}" }.join("\n")}"
59
- end.join("\n")
100
+ true
60
101
  end
61
102
 
62
103
  private
63
104
 
105
+ def original_content
106
+ @original_content ||= path.read
107
+ end
108
+
109
+ def original_object
110
+ @original_object ||= YAML.load(original_content)
111
+ end
112
+
113
+ def expected_object
114
+ @expected_object ||= YAML.load(original_content).tap do |expected|
115
+ suggestions.each do |suggestion|
116
+ if suggestion.section == 'rvm'
117
+ index = expected['rvm'].find_index{ |v| suggestion.from == v }
118
+ expected['rvm'][index, 1] = suggestion.choices.map(&:to_s)
119
+ else
120
+ entry = expected['matrix'][suggestion.section].find{ |attrs| suggestion.from == attrs['rvm'] }
121
+ entry['rvm'] = suggestion.to.to_s
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ def updated_content
128
+ return @updated_content if @updated_content
129
+
130
+ updater = Updater.new(original_content)
131
+
132
+ suggestions.each do |suggestion|
133
+ updater = updater.apply_suggestion(suggestion)
134
+ end
135
+
136
+ @updated_content = updater.content
137
+ end
138
+
139
+ def rvm_versions
140
+ @rvm_versions ||= Array(original_object['rvm']).map(&Version.method(:new))
141
+ end
142
+
143
+ def allow_failures_versions
144
+ @allow_failures_versions ||= matrix_versions(original_object, 'allow_failures')
145
+ end
146
+
147
+ def exclude_versions
148
+ @exclude_versions ||= matrix_versions(original_object, 'exclude')
149
+ end
150
+
151
+ def include_versions
152
+ @include_versions ||= matrix_versions(original_object, 'include')
153
+ end
154
+
64
155
  def matrix_versions(yaml, key)
65
156
  return [] unless (matrix = yaml['matrix'])
66
157
  return [] unless (list = matrix[key])
@@ -0,0 +1,98 @@
1
+ require 'psych'
2
+
3
+ module TravisCheckRubies
4
+ class Updater
5
+ attr_reader :content
6
+
7
+ def initialize(content)
8
+ @content = content
9
+ end
10
+
11
+ def apply_suggestion(suggestion)
12
+ lines = content.lines
13
+
14
+ if suggestion.section == 'rvm'
15
+ apply_rvm_suggestion(lines, suggestion)
16
+ else
17
+ apply_matrix_suggestion(lines, suggestion)
18
+ end
19
+
20
+ self.class.new lines.join('')
21
+ end
22
+
23
+ private
24
+
25
+ def apply_rvm_suggestion(lines, suggestion)
26
+ node = rvm_node.children.find{ |node| suggestion.from == node.to_ruby }
27
+
28
+ lines[node.start_line] = suggestion.choices.map do |version|
29
+ log_change suggestion.from, version, 'rvm'
30
+ line_with_version_change(lines, node, suggestion.from, version)
31
+ end.join('')
32
+ end
33
+
34
+ def apply_matrix_suggestion(lines, suggestion)
35
+ section_node = matrix_section_node(suggestion.section)
36
+
37
+ entry_node = section_node.children.find{ |node| suggestion.from == node.to_ruby['rvm'] }
38
+
39
+ node = fetch_node_mapping(entry_node, 'rvm')
40
+
41
+ log_change suggestion.from, suggestion.to, 'matrix'
42
+ lines[node.start_line] = line_with_version_change(lines, node, suggestion.from, suggestion.to)
43
+ end
44
+
45
+ def log_change(from, to, section)
46
+ puts "#{from} -> #{to} \# #{section} section"
47
+ end
48
+
49
+ def root
50
+ @root ||= Psych::Parser.new(Psych::TreeBuilder.new).parse(content).handler.root.children[0].children[0]
51
+ end
52
+
53
+ def rvm_node
54
+ fetch_node_mapping(root, 'rvm').tap do |rvm_node|
55
+ assert_type rvm_node, Psych::Nodes::Sequence
56
+ fail "Expected block style: #{rvm_node.to_ruby}" unless rvm_node.style == Psych::Nodes::Sequence::BLOCK
57
+ end
58
+ end
59
+
60
+ def matrix_section_node(section)
61
+ matrix_node = fetch_node_mapping(root, 'matrix')
62
+
63
+ fetch_node_mapping(matrix_node, section).tap do |section_node|
64
+ assert_type section_node, Psych::Nodes::Sequence
65
+ end
66
+ end
67
+
68
+ def fetch_node_mapping(mapping, key)
69
+ assert_type mapping, Psych::Nodes::Mapping
70
+
71
+ _, node = mapping.children.each_cons(2).find{ |key_node, _| key_node.to_ruby == key }
72
+
73
+ fail "Didn't find key #{key.inspect} in #{mapping.to_ruby}" unless node
74
+
75
+ node
76
+ end
77
+
78
+ def line_with_version_change(lines, node, from, to)
79
+ assert_type node, Psych::Nodes::Scalar
80
+
81
+ line = lines[node.start_line]
82
+
83
+ before = line[0...node.start_column]
84
+ excerpt = line[node.start_column...node.end_column]
85
+ after = line[node.end_column..-1]
86
+
87
+ fail "Didn't find #{from.to_s} in #{line}" unless excerpt.sub!(from.to_s, to.to_s)
88
+
89
+ "#{before}#{excerpt}#{after}"
90
+ end
91
+
92
+ def assert_type(node, expected_class)
93
+ return if node.is_a?(expected_class)
94
+
95
+ fail "Expected a #{expected_class}, got #{node.class}"
96
+ end
97
+ end
98
+ end
@@ -1,29 +1,20 @@
1
- require 'net/http'
2
- require 'fspath'
3
1
  require 'set'
4
- require 'uri'
2
+
3
+ require_relative 'rvm_index'
4
+ require_relative 'travis_index'
5
5
 
6
6
  module TravisCheckRubies
7
7
  class Version
8
- ROOT_URL = 'https://rubies.travis-ci.org/'
9
- CACHE_TIME = 24 * 60 * 60
10
-
11
8
  class << self
12
9
  def convert(version_or_string)
13
10
  version_or_string.is_a?(self) ? version_or_string : new(version_or_string)
14
11
  end
15
12
 
16
13
  def available
17
- @available ||= begin
18
- index_urls.select do |url|
19
- url.start_with?(base_url)
20
- end.map do |url|
21
- new(url[%r{([^/]+)\.tar\.(?:gz|bz2)$}, 1])
22
- end.sort
23
- end
14
+ @available ||= [TravisIndex, RvmIndex].map(&:new).map(&:version_strings).inject(:|).map{ |s| new(s) }.sort
24
15
  end
25
16
 
26
- def update(version, parts: 0..2, allow_pre: false, intermediary: true, exclude: [])
17
+ def update(version, parts: 0..2, allow_pre: false, intermediary: true, exclude: [], conservative: false)
27
18
  version = convert(version)
28
19
  return unless version.version_parts
29
20
 
@@ -66,53 +57,12 @@ module TravisCheckRubies
66
57
  updates = {}
67
58
  has = Set.new
68
59
  versions.uniq.sort.reverse_each do |version|
69
- deduplicated = (update(version, options) || [version]).select{ |v| has.add?(v) }
60
+ deduplicated = (update(version, **options) || [version]).select{ |v| has.add?(v) }
70
61
  updates[version] = [version] == deduplicated ? nil : deduplicated
71
62
  end
72
63
 
73
64
  Hash[versions.map{ |v| [v, updates[v]] }]
74
65
  end
75
-
76
- private
77
-
78
- def cache_path
79
- @cache_path ||= FSPath(ENV['XDG_CACHE_HOME'] || '~/.cache').expand_path / 'travis_check_rubies.txt'
80
- end
81
-
82
- def index_urls
83
- @index_urls ||= (cached_index_data || fetch_index_data).split("\n")
84
- end
85
-
86
- def cached_index_data
87
- return unless cache_path.size?
88
- return unless cache_path.mtime + CACHE_TIME > Time.now
89
- data = cache_path.read
90
- data if data.start_with?(ROOT_URL)
91
- end
92
-
93
- def fetch_index_data
94
- data = Net::HTTP.get(URI(ROOT_URL + 'index.txt'))
95
-
96
- cache_path.dirname.mkpath
97
- FSPath.temp_file('travis_check_rubies', cache_path.dirname) do |f|
98
- f.write(data)
99
- f.path.rename(cache_path)
100
- end
101
-
102
- data
103
- end
104
-
105
- def base_url
106
- @base_url ||= if ENV['TRAVIS']
107
- sys_path = `rvm debug`[/(?:system|remote.path):\s*"(.*?)"/, 1]
108
- "#{ROOT_URL}#{sys_path}/"
109
- else
110
- base_ubuntu_url = "#{ROOT_URL}ubuntu/"
111
- first_ubuntu_url = index_urls.sort.find{ |url| url.start_with?(base_ubuntu_url) }
112
- fail "First ubuntu url (#{ROOT_URL}ubuntu/*) not fount out of:\n#{index_urls.join("\n")}" unless first_ubuntu_url
113
- first_ubuntu_url[%r{^.*/}]
114
- end
115
- end
116
66
  end
117
67
 
118
68
  include Comparable
@@ -0,0 +1,48 @@
1
+ require 'rspec'
2
+ require 'travis_check_rubies/fetcher'
3
+
4
+ describe TravisCheckRubies::Fetcher do
5
+ describe '#data' do
6
+ subject{ described_class.new(url) }
7
+
8
+ let(:url){ 'https://example.com/index.txt' }
9
+ let(:cache_path){ FSPath.temp_file_path }
10
+
11
+ before do
12
+ allow(subject).to receive(:cache_path).and_return(cache_path)
13
+ end
14
+
15
+ it 'returns data from url' do
16
+ allow(Net::HTTP).to receive(:get).with(URI(url)).
17
+ and_return("one\ntwo\nthree")
18
+
19
+ expect(subject.data).to eq("one\ntwo\nthree")
20
+ end
21
+
22
+ it 'caches result' do
23
+ allow(Net::HTTP).to receive(:get).with(URI(url)).
24
+ once.and_return("a\nb\nc")
25
+
26
+ 3.times{ expect(subject.data).to eq("a\nb\nc") }
27
+ end
28
+
29
+ it 'reads cache from file if it is new' do
30
+ cache_path.write "foo\nbar"
31
+ allow(cache_path).to receive(:size?).and_return(616)
32
+ allow(cache_path).to receive(:mtime).and_return(Time.now - described_class::CACHE_TIME / 2)
33
+
34
+ expect(Net::HTTP).not_to receive(:get)
35
+ expect(subject.data).to eq("foo\nbar")
36
+ end
37
+
38
+ it 'writes cache file if it is stale' do
39
+ allow(cache_path).to receive(:size?).and_return(616)
40
+ allow(cache_path).to receive(:mtime).and_return(Time.now - described_class::CACHE_TIME * 2)
41
+ allow(Net::HTTP).to receive(:get).with(URI(url)).
42
+ once.and_return("brave\nnew\nworld")
43
+
44
+ expect(subject.data).to eq("brave\nnew\nworld")
45
+ expect(cache_path.read).to eq("brave\nnew\nworld")
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,31 @@
1
+ require 'rspec'
2
+ require 'travis_check_rubies/travis_index'
3
+
4
+ describe TravisCheckRubies::TravisIndex do
5
+ describe '#base_url' do
6
+ context 'when env variable TRAVIS is not set' do
7
+ let(:env_travis){ nil }
8
+
9
+ it 'gets base_url from first ubuntu url in index' do
10
+ allow(TravisCheckRubies::TravisYml).to receive(:new)
11
+ .and_return instance_double(TravisCheckRubies::TravisYml, dist: 'trusty')
12
+
13
+ expect(subject.send(:base_url)).to eq('https://rubies.travis-ci.org/ubuntu/14.04/x86_64/')
14
+ end
15
+ end
16
+ end
17
+
18
+ describe '#version_strings' do
19
+ it 'gets versions from index urls matching base_url' do
20
+ allow(subject).to receive(:index_urls).and_return(%w[
21
+ https://rubies.travis-ci.org/osx/AAA/1.tar.gz
22
+ https://rubies.travis-ci.org/ubuntu/ZZZ/2.tar.gz
23
+ https://rubies.travis-ci.org/ubuntu/BBB/4.tar.gz
24
+ https://rubies.travis-ci.org/ubuntu/BBB/3.tar.bz2
25
+ ])
26
+ allow(subject).to receive(:base_url).and_return('https://rubies.travis-ci.org/ubuntu/BBB/')
27
+
28
+ expect(subject.version_strings).to match_array(%w[3 4])
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,116 @@
1
+ require 'rspec'
2
+ require 'travis_check_rubies/updater'
3
+
4
+ describe TravisCheckRubies::Updater do
5
+ describe '#apply_suggestion' do
6
+ subject{ described_class.new(content).apply_suggestion(suggestion) }
7
+
8
+ context 'for rvm change suggestion' do
9
+ let(:content) do
10
+ <<~YAML
11
+ language: ruby
12
+ rvm: # rvm
13
+ - '2.1.3' # foo
14
+ - '2.2.8' # bar
15
+ - '2.5.0' # baz
16
+ before_script:
17
+ - env # env
18
+ YAML
19
+ end
20
+
21
+ context 'removing version' do
22
+ let(:suggestion){ double(section: 'rvm', from: '2.2.8', choices: []) }
23
+
24
+ let(:expected) do
25
+ <<~YAML
26
+ language: ruby
27
+ rvm: # rvm
28
+ - '2.1.3' # foo
29
+ - '2.5.0' # baz
30
+ before_script:
31
+ - env # env
32
+ YAML
33
+ end
34
+
35
+ it{ is_expected.to have_attributes(content: expected) }
36
+ end
37
+
38
+ context 'changing to one version' do
39
+ let(:suggestion){ double(section: 'rvm', from: '2.2.8', choices: [double(to_s: '2.2.9')]) }
40
+
41
+ let(:expected) do
42
+ <<~YAML
43
+ language: ruby
44
+ rvm: # rvm
45
+ - '2.1.3' # foo
46
+ - '2.2.9' # bar
47
+ - '2.5.0' # baz
48
+ before_script:
49
+ - env # env
50
+ YAML
51
+ end
52
+
53
+ it{ is_expected.to have_attributes(content: expected) }
54
+ end
55
+
56
+ context 'changing to multiple versions' do
57
+ let(:suggestion){ double(section: 'rvm', from: '2.2.8', choices: [double(to_s: '2.2.9'), double(to_s: '2.3.4')]) }
58
+
59
+ let(:expected) do
60
+ <<~YAML
61
+ language: ruby
62
+ rvm: # rvm
63
+ - '2.1.3' # foo
64
+ - '2.2.9' # bar
65
+ - '2.3.4' # bar
66
+ - '2.5.0' # baz
67
+ before_script:
68
+ - env # env
69
+ YAML
70
+ end
71
+
72
+ it{ is_expected.to have_attributes(content: expected) }
73
+ end
74
+ end
75
+
76
+ context 'for matrix change suggestion' do
77
+ let(:content) do
78
+ <<~YAML
79
+ language: ruby
80
+ before_script:
81
+ - env # env
82
+ matrix:
83
+ allow_failures:
84
+ - rvm: '2.2.8' # foo
85
+ exclude:
86
+ - rvm: '2.2.8' # bar
87
+ include:
88
+ - rvm: '2.1.3' # foo
89
+ - rvm: '2.2.8' # bar
90
+ - rvm: '2.2.8' # baz
91
+ YAML
92
+ end
93
+
94
+ let(:suggestion){ double(section: 'include', from: '2.2.8', to: double(to_s: '2.2.9')) }
95
+
96
+ let(:expected) do
97
+ <<~YAML
98
+ language: ruby
99
+ before_script:
100
+ - env # env
101
+ matrix:
102
+ allow_failures:
103
+ - rvm: '2.2.8' # foo
104
+ exclude:
105
+ - rvm: '2.2.8' # bar
106
+ include:
107
+ - rvm: '2.1.3' # foo
108
+ - rvm: '2.2.9' # bar
109
+ - rvm: '2.2.8' # baz
110
+ YAML
111
+ end
112
+
113
+ it{ is_expected.to have_attributes(content: expected) }
114
+ end
115
+ end
116
+ end
@@ -10,12 +10,6 @@ describe TravisCheckRubies::Version do
10
10
  strs.map{ |str| described_class.new(str) }
11
11
  end
12
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
13
  describe 'parsing' do
20
14
  {
21
15
  '1.2.3-pre1' => {
@@ -202,116 +196,12 @@ describe TravisCheckRubies::Version do
202
196
  end
203
197
  end
204
198
 
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('https://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('https://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
- cache_path.write "https://rubies.travis-ci.org/foo"
229
- allow(cache_path).to receive(:size?).and_return(616)
230
- allow(cache_path).to receive(:mtime).and_return(Time.now - described_class::CACHE_TIME / 2)
231
-
232
- expect(Net::HTTP).not_to receive(:get)
233
- expect(described_class.send(:index_urls)).to eq(%w[https://rubies.travis-ci.org/foo])
234
- end
235
-
236
- it 'ignores bad cache' do
237
- cache_path.write "http://rubies.travis-ci.org/foo"
238
- allow(cache_path).to receive(:size?).and_return(616)
239
- allow(cache_path).to receive(:mtime).and_return(Time.now - described_class::CACHE_TIME / 2)
240
-
241
- allow(Net::HTTP).to receive(:get).with(URI('https://rubies.travis-ci.org/index.txt')).
242
- once.and_return("brave\nnew\nworld")
243
- expect(described_class.send(:index_urls)).to eq(%w[brave new world])
244
- expect(cache_path.read).to eq("brave\nnew\nworld")
245
- end
246
-
247
- it 'writes cache file if it is stale' do
248
- allow(cache_path).to receive(:size?).and_return(616)
249
- allow(cache_path).to receive(:mtime).and_return(Time.now - described_class::CACHE_TIME * 2)
250
- allow(Net::HTTP).to receive(:get).with(URI('https://rubies.travis-ci.org/index.txt')).
251
- once.and_return("brave\nnew\nworld")
252
-
253
- expect(described_class.send(:index_urls)).to eq(%w[brave new world])
254
- expect(cache_path.read).to eq("brave\nnew\nworld")
255
- end
256
- end
257
-
258
- describe '.base_url' do
259
- before do
260
- cleanup_instance_variables(described_class)
261
- allow(ENV).to receive(:[]).with('TRAVIS').and_return(env_travis)
262
- end
263
-
264
- context 'when env variable TRAVIS is set' do
265
- let(:env_travis){ 'true' }
266
-
267
- it 'gets base_url from rvm debug' do
268
- allow(described_class).to receive(:`).with('rvm debug').
269
- and_return(%Q{ foo: "xxx" \n system: "XXX/YYY" \n bar: "yyy" })
270
-
271
- expect(described_class.send(:base_url)).to eq('https://rubies.travis-ci.org/XXX/YYY/')
272
- end
273
- end
274
-
275
- context 'when env variable TRAVIS is not set' do
276
- let(:env_travis){ nil }
277
-
278
- it 'gets base_url from first ubuntu url in index' do
279
- allow(described_class).to receive(:index_urls).and_return(%w[
280
- https://rubies.travis-ci.org/osx/AAA/1.tar.gz
281
- https://rubies.travis-ci.org/ubuntu/ZZZ/2.tar.gz
282
- https://rubies.travis-ci.org/ubuntu/BBB/3.tar.gz
283
- ])
284
-
285
- expect(described_class.send(:base_url)).to eq('https://rubies.travis-ci.org/ubuntu/BBB/')
286
- end
287
- end
288
- end
289
-
290
199
  describe '.available' do
291
- before do
292
- cleanup_instance_variables(described_class)
293
- end
294
-
295
- it 'gets sorted versions from index urls matching base_url' do
296
- allow(described_class).to receive(:index_urls).and_return(%w[
297
- https://rubies.travis-ci.org/osx/AAA/1.tar.gz
298
- https://rubies.travis-ci.org/ubuntu/ZZZ/2.tar.gz
299
- https://rubies.travis-ci.org/ubuntu/BBB/4.tar.gz
300
- https://rubies.travis-ci.org/ubuntu/BBB/3.tar.bz2
301
- ])
302
- allow(described_class).to receive(:base_url).and_return('https://rubies.travis-ci.org/ubuntu/BBB/')
303
-
304
- expect(described_class.available).to eq([v('3'), v('4')])
305
- end
306
-
307
- it 'caches result' do
308
- allow(described_class).to receive(:index_urls).once.and_return(%w[
309
- https://rubies.travis-ci.org/ubuntu/CCC/a.tar.gz
310
- https://rubies.travis-ci.org/ubuntu/CCC/b.tar.bz2
311
- ])
312
- allow(described_class).to receive(:base_url).and_return('https://rubies.travis-ci.org/ubuntu/CCC/')
200
+ it 'gets distinct sorted versions by combining indexes' do
201
+ allow(TravisCheckRubies::TravisIndex).to receive(:new).and_return(double(version_strings: %w[e d c b a]))
202
+ allow(TravisCheckRubies::RvmIndex).to receive(:new).and_return(double(version_strings: %w[d e f g h]))
313
203
 
314
- 3.times{ expect(described_class.available).to eq([v('a'), v('b')]) }
204
+ expect(described_class.available).to eq(vs(%w[a b c d e f g h]))
315
205
  end
316
206
  end
317
207
 
@@ -2,21 +2,28 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'travis_check_rubies'
5
- s.version = '0.2.5'
5
+ s.version = '0.6.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 https://rubies.travis-ci.org and propose changes'
8
- s.homepage = "http://github.com/toy/#{s.name}"
8
+ s.homepage = "https://github.com/toy/#{s.name}"
9
9
  s.authors = ['Ivan Kuchin']
10
10
  s.license = 'MIT'
11
11
 
12
+ s.metadata = {
13
+ 'bug_tracker_uri' => "https://github.com/toy/#{s.name}/issues",
14
+ 'documentation_uri' => "https://www.rubydoc.info/gems/#{s.name}/#{s.version}",
15
+ 'source_code_uri' => "https://github.com/toy/#{s.name}",
16
+ }
17
+
12
18
  s.files = `git ls-files`.split("\n")
13
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
20
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
15
21
  s.require_paths = %w[lib]
16
22
 
17
- s.required_ruby_version = '>= 2.0.0'
23
+ s.required_ruby_version = '>= 2.3.0'
18
24
 
19
25
  s.add_runtime_dependency 'fspath', '~> 3.0'
26
+ s.add_runtime_dependency 'psych', '~> 3.0'
20
27
 
21
28
  s.add_development_dependency 'rspec', '~> 3.0'
22
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: travis_check_rubies
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Kuchin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-13 00:00:00.000000000 Z
11
+ date: 2021-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fspath
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: psych
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rspec
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -40,7 +54,7 @@ dependencies:
40
54
  version: '3.0'
41
55
  description: Check if `.travis.yml` specifies latest available rubies from listed
42
56
  on https://rubies.travis-ci.org and propose changes
43
- email:
57
+ email:
44
58
  executables:
45
59
  - travis_check_rubies
46
60
  extensions: []
@@ -53,15 +67,25 @@ files:
53
67
  - README.markdown
54
68
  - bin/travis_check_rubies
55
69
  - lib/travis_check_rubies.rb
70
+ - lib/travis_check_rubies/fetcher.rb
71
+ - lib/travis_check_rubies/rvm_index.rb
72
+ - lib/travis_check_rubies/travis_index.rb
56
73
  - lib/travis_check_rubies/travis_yml.rb
74
+ - lib/travis_check_rubies/updater.rb
57
75
  - lib/travis_check_rubies/version.rb
76
+ - spec/travis_check_rubies/fetcher_spec.rb
77
+ - spec/travis_check_rubies/travis_index_spec.rb
78
+ - spec/travis_check_rubies/updater_spec.rb
58
79
  - spec/travis_check_rubies/version_spec.rb
59
80
  - travis_check_rubies.gemspec
60
- homepage: http://github.com/toy/travis_check_rubies
81
+ homepage: https://github.com/toy/travis_check_rubies
61
82
  licenses:
62
83
  - MIT
63
- metadata: {}
64
- post_install_message:
84
+ metadata:
85
+ bug_tracker_uri: https://github.com/toy/travis_check_rubies/issues
86
+ documentation_uri: https://www.rubydoc.info/gems/travis_check_rubies/0.6.0
87
+ source_code_uri: https://github.com/toy/travis_check_rubies
88
+ post_install_message:
65
89
  rdoc_options: []
66
90
  require_paths:
67
91
  - lib
@@ -69,17 +93,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
69
93
  requirements:
70
94
  - - ">="
71
95
  - !ruby/object:Gem::Version
72
- version: 2.0.0
96
+ version: 2.3.0
73
97
  required_rubygems_version: !ruby/object:Gem::Requirement
74
98
  requirements:
75
99
  - - ">="
76
100
  - !ruby/object:Gem::Version
77
101
  version: '0'
78
102
  requirements: []
79
- rubyforge_project:
80
- rubygems_version: 2.6.14
81
- signing_key:
103
+ rubygems_version: 3.1.5
104
+ signing_key:
82
105
  specification_version: 4
83
106
  summary: Are you using the latest rubies in .travis.yml?
84
107
  test_files:
108
+ - spec/travis_check_rubies/fetcher_spec.rb
109
+ - spec/travis_check_rubies/travis_index_spec.rb
110
+ - spec/travis_check_rubies/updater_spec.rb
85
111
  - spec/travis_check_rubies/version_spec.rb