travis_check_rubies 0.2.5 → 0.6.0

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 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