smarter_bundler 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -3
- data/README.md +20 -2
- data/Vagrantfile +5 -1
- data/bin/test +10 -10
- data/exe/smarter_bundle +1 -1
- data/lib/smarter_bundler/bundle.rb +52 -17
- data/lib/smarter_bundler/gemfile.rb +5 -1
- data/lib/smarter_bundler/shell.rb +1 -1
- data/lib/smarter_bundler/version.rb +1 -1
- metadata +64 -87
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6fbba5a723688fabe832cd0ae312cb05a512185c
|
4
|
+
data.tar.gz: d8c649cad25c8f219b93065b8b508ac299fc88c7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3212fd4edcbc6064e82011b0b3d507334bc97323382ebe36dba899d48d8a87da94bfa8b409494012787b81618fe79501a47121e25d28486e9fad65a4230e0fbc
|
7
|
+
data.tar.gz: 6d3b40270cb45dc82afcb393ff3c5281aff40eef1f20b3153050ee80bd4a92eeb8c029d75f4f007b09fbe0ce78cc06f589e6e0623cebfd4a7eeb0a38c328b23d
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -22,12 +22,30 @@ A reasonable limit would be four to ten times the time it normally takes to inst
|
|
22
22
|
Once you hit that limit, then check your install log and incorporate the fixes it has found into your Gemfile
|
23
23
|
source to remove the need for it to run bundler multiple times whilst it fixes the Gemfile.
|
24
24
|
|
25
|
+
### Cleaning up afterwards
|
26
|
+
|
27
|
+
After smarter_bundle has updated the Gemfile, you should examine the changes, as some adjustments may be in order:
|
28
|
+
1. If a gem is not already referenced in the Gemfile, then look in Gemfile.lock for the gems that depend on it and place the new line in the same group as the related gems;
|
29
|
+
2. smarter_bundle does not backtrack and recheck earlier adjustments - this may result in a gem being restricted that is no longer needed because the gem that originally needed ended up being restricted to the point it no longer has so many prerequisites. In the Gemfile.lock you will see that the gem is not required by any other gems, nor was it a gem you directly need.
|
30
|
+
3. smarter_bundle does not know how to handle Gemfiles that are intended to be used with multiple ruby versions, so you will need to make a Gemfile that is intended for the ruby version you are checking it with and then incorporate the changes smarter_bundle makes back into the master Gemfile manually;
|
31
|
+
|
32
|
+
### Using in test scripts
|
33
|
+
|
34
|
+
If for some reason you do not use Gemfile.lock in automated testing (eg when testing gems with travis-ci), and you are testing against older ruby versions, then you may wish to consider using
|
35
|
+
smarter_bundler - instead of the test script failing, smarter_bundler will update the Gemfile on the fly. Of course you are swapping processing time for convienience,
|
36
|
+
so you should implement a time limit and manually update your Gemfile once the tests slow down too much.
|
37
|
+
|
38
|
+
I usually prefer to fail fast and fix it then and there rather than delay the issue, but sometimes delaying failure till later when it can be worked around is appropriate.
|
39
|
+
|
25
40
|
## Notes
|
26
41
|
|
27
|
-
If the error indicates a ruby version conflict,
|
42
|
+
If the error indicates a ruby version conflict,
|
43
|
+
then it will lookup the gem on rubygems to find the earliest version with the same ruby spec
|
28
44
|
and update the Gemfile to specify a version prior to that. If the lookup of rubygems fails, then it will simply check the next earlier version.
|
29
45
|
|
30
|
-
|
46
|
+
Syntax errors will trigger smarter_bundle to try the immediately earlier version, without looking up rubygems, because a syntax error indicates the gemspec doesn't correctly specify the required ruby versions.
|
47
|
+
|
48
|
+
If the error was not from a ruby version conflict or syntax error, it will attempt to install the gem directly once more.
|
31
49
|
|
32
50
|
It will attempt to fix the Gemfile up to 100 times before giving up as long as each attempt is making progress.
|
33
51
|
|
data/Vagrantfile
CHANGED
@@ -9,7 +9,11 @@ Vagrant.configure("2") do |config|
|
|
9
9
|
# provision with a shell script.
|
10
10
|
config.vm.provision "shell",
|
11
11
|
path: "https://raw.githubusercontent.com/ianheggie/provision_vagrant/master/provision?cache_bust=#{Process.pid}",
|
12
|
-
args: %w{ /vagrant
|
12
|
+
args: %w{ /vagrant /vagrant/test/rails30 /vagrant/test/rails31 /vagrant/test/rails32 /vagrant/test/rails40
|
13
|
+
/vagrant/test/rails41 /vagrant/test/rails42 /vagrant/test/rails50 /vagrant/test/rails51
|
14
|
+
/vagrant/test/special_cases }
|
15
|
+
|
16
|
+
|
13
17
|
|
14
18
|
# Stop nagging as this box changes daily...
|
15
19
|
config.vm.box_check_update = true
|
data/bin/test
CHANGED
@@ -6,30 +6,30 @@ ruby_version=`ruby -e 'puts RUBY_VERSION'`
|
|
6
6
|
psych_ver='< 3.0'
|
7
7
|
case "$ruby_version" in
|
8
8
|
1.8.7)
|
9
|
-
dirs='rails30 rails31 rails32'
|
9
|
+
dirs='rails30 rails31 rails32 special_cases'
|
10
10
|
psych_ver=''
|
11
11
|
;;
|
12
12
|
1.9.2)
|
13
|
-
dirs='rails30 rails31 rails32'
|
13
|
+
dirs='rails30 rails31 rails32 special_cases'
|
14
14
|
;;
|
15
15
|
1.9.3)
|
16
|
-
dirs='rails30 rails31 rails32 rails40 rails41 rails42'
|
16
|
+
dirs='rails30 rails31 rails32 rails40 rails41 rails42 special_cases'
|
17
17
|
;;
|
18
18
|
2.0*)
|
19
|
-
dirs='rails32 rails40 rails41 rails42'
|
19
|
+
dirs='rails32 rails40 rails41 rails42 special_cases'
|
20
20
|
;;
|
21
21
|
2.1*)
|
22
|
-
dirs='rails41 rails42'
|
22
|
+
dirs='rails41 rails42 special_cases'
|
23
23
|
;;
|
24
24
|
2.2.[01]*)
|
25
|
-
dirs='rails42'
|
25
|
+
dirs='rails42 special_cases'
|
26
26
|
;;
|
27
27
|
2.2.2)
|
28
|
-
dirs='rails32 rails42 rails50 rails51'
|
28
|
+
dirs='rails32 rails42 rails50 rails51 special_cases'
|
29
29
|
psych_ver='> 2.0'
|
30
30
|
;;
|
31
|
-
2.2.[2-9]*|2.[3-9]*)
|
32
|
-
dirs='rails50 rails51'
|
31
|
+
2.2.[2-9]*|2.[3-9]*|[3-9]*)
|
32
|
+
dirs='rails50 rails51 special_cases'
|
33
33
|
gem install psych
|
34
34
|
psych_ver='> 2.0'
|
35
35
|
;;
|
@@ -62,7 +62,7 @@ do
|
|
62
62
|
rm -f Gemfile.lock
|
63
63
|
cp -f Gemfile.default Gemfile
|
64
64
|
# Exclude debugger - it breaks for many varied reasons on travis
|
65
|
-
../../exe/smarter_bundle
|
65
|
+
../../exe/smarter_bundle --aggressive install --no-color --verbose --without debug
|
66
66
|
echo Gemfile changes:
|
67
67
|
diff Gemfile.default Gemfile
|
68
68
|
echo
|
data/exe/smarter_bundle
CHANGED
@@ -8,18 +8,20 @@ module SmarterBundler
|
|
8
8
|
class Bundle
|
9
9
|
include SmarterBundler::Shell
|
10
10
|
|
11
|
-
|
11
|
+
# Note the versions listed in KNOWN_SOLUTIONS are the first NON working version
|
12
|
+
# for the first ruby version listed (eg 1.8.7, 1.9.3, 2.2.2)
|
13
|
+
|
14
|
+
KNOWN_SOLUTIONS_187_192 = {
|
12
15
|
'unicorn' => '5.0',
|
13
16
|
'nokogiri' => '1.6.0',
|
14
17
|
'jbuilder' => '2.0.0',
|
15
18
|
'factory_girl' => '3.0',
|
16
19
|
'factory_bot' => '3.0',
|
20
|
+
'listen' => '3.1.2',
|
21
|
+
'css_parser' => '1.4.8', # syntax error
|
17
22
|
}
|
18
23
|
|
19
|
-
|
20
|
-
}
|
21
|
-
|
22
|
-
KNOWN_ISSUES_222_22x = {
|
24
|
+
KNOWN_SOLUTIONS_193_221 = {
|
23
25
|
'listen' => '3.1.2',
|
24
26
|
'acts-as-taggable-on' => '5.0.0',
|
25
27
|
'guard-rails' => '0.7.3',
|
@@ -27,13 +29,30 @@ module SmarterBundler
|
|
27
29
|
'ruby_dep' => '1.4.0',
|
28
30
|
}
|
29
31
|
|
32
|
+
KNOWN_SOLUTIONS_222_22x = {
|
33
|
+
}
|
34
|
+
|
30
35
|
|
31
36
|
def run(bundle_args)
|
37
|
+
@aggressive = bundle_args.first == '--aggressive'
|
38
|
+
if @aggressive
|
39
|
+
bundle_args = bundle_args.drop(1)
|
40
|
+
end
|
32
41
|
puts 'Smarter Bundler will recursively install your gems and output the successful bundler output. This may take a while.'
|
33
42
|
count = 0
|
34
43
|
gemfile = SmarterBundler::Gemfile.new
|
35
44
|
previous_failure = []
|
36
45
|
result = nil
|
46
|
+
if @aggressive
|
47
|
+
known_solutions.each do |gem, version|
|
48
|
+
if gemfile.mentions? gem
|
49
|
+
gemfile.restrict_gem_version(gem, version)
|
50
|
+
count += 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
puts "Made #{count} adjustments in Gemfile based on known solutions" if count > 0
|
54
|
+
end
|
55
|
+
|
37
56
|
while count < 100
|
38
57
|
result = call_bundle(bundle_args)
|
39
58
|
failed_gem_and_version = parse_output(result)
|
@@ -44,15 +63,15 @@ module SmarterBundler
|
|
44
63
|
end
|
45
64
|
previous_failure = failed_gem_and_version
|
46
65
|
gem, version = *failed_gem_and_version
|
47
|
-
if
|
48
|
-
puts 'Retrying seems to have fixed the problem'
|
49
|
-
elsif gemfile.restrict_gem_version(gem, known_issues(gem))
|
66
|
+
if gemfile.restrict_gem_version(gem, known_solution(gem))
|
50
67
|
gemfile.save
|
51
68
|
count += 1
|
52
|
-
elsif
|
69
|
+
elsif !fatal_error(result) && install_failed_gem(gem, version)
|
70
|
+
puts 'Retrying seems to have fixed the problem'
|
71
|
+
elsif ruby_version_error(result) && gemfile.restrict_gem_version(gem, rubygems_earlier_version(gem, version))
|
53
72
|
gemfile.save
|
54
73
|
count += 1
|
55
|
-
elsif
|
74
|
+
elsif fatal_error(result) && gemfile.restrict_gem_version(gem, version)
|
56
75
|
gemfile.save
|
57
76
|
count += 1
|
58
77
|
else
|
@@ -68,26 +87,38 @@ module SmarterBundler
|
|
68
87
|
end
|
69
88
|
|
70
89
|
def call_bundle(bundle_args)
|
71
|
-
shell "bundle #{bundle_args}"
|
90
|
+
shell "bundle #{bundle_args.join(' ')} && ruby -e 'puts \"Checking gems can be loaded ...\" ; require \"rubygems\" ; require \"bundler/setup\" ; Bundler.require(:default) ; puts \"PASSED GEM LOAD TEST\" ' "
|
72
91
|
end
|
73
92
|
|
74
93
|
def install_failed_gem(gem, version)
|
75
94
|
shell? "gem install '#{gem}' -v '#{version}'"
|
76
95
|
end
|
77
96
|
|
78
|
-
def
|
97
|
+
def fatal_error(result)
|
98
|
+
ruby_version_error(result) || syntax_error(result)
|
99
|
+
end
|
100
|
+
|
101
|
+
def ruby_version_error(result)
|
79
102
|
result.output.select { |l| l =~ /requires Ruby version/ }.any?
|
80
103
|
end
|
81
104
|
|
82
|
-
def
|
105
|
+
def syntax_error(result)
|
106
|
+
result.output.select { |l| l =~ /(: syntax error|SyntaxError: )/ }.any?
|
107
|
+
end
|
108
|
+
|
109
|
+
def known_solution(gem)
|
110
|
+
known_solutions[gem]
|
111
|
+
end
|
112
|
+
|
113
|
+
def known_solutions
|
83
114
|
if RUBY_VERSION <= '1.9.2'
|
84
|
-
|
115
|
+
KNOWN_SOLUTIONS_187_192
|
85
116
|
elsif RUBY_VERSION <= '2.2.1'
|
86
|
-
|
117
|
+
KNOWN_SOLUTIONS_193_221
|
87
118
|
elsif RUBY_VERSION <= '2.3'
|
88
|
-
|
119
|
+
KNOWN_SOLUTIONS_222_22x
|
89
120
|
else
|
90
|
-
|
121
|
+
{ }
|
91
122
|
end
|
92
123
|
end
|
93
124
|
|
@@ -95,6 +126,10 @@ module SmarterBundler
|
|
95
126
|
result.output.each do |line|
|
96
127
|
if line =~ /Make sure that `gem install (\S+) -v '(\S+)'`/
|
97
128
|
return [$1, $2]
|
129
|
+
elsif line =~ %r{SyntaxError: .*/ruby/[^/]*/gems/([^/]*)-(\d[^/]+)/}
|
130
|
+
return [$1, $2]
|
131
|
+
elsif line =~ %r{/ruby/[^/]*/gems/([^/]*)-(\d[^/]+)/\S+:\d+: syntax error}
|
132
|
+
return [$1, $2]
|
98
133
|
end
|
99
134
|
end
|
100
135
|
nil
|
@@ -14,9 +14,13 @@ module SmarterBundler
|
|
14
14
|
@changed = false
|
15
15
|
end
|
16
16
|
|
17
|
+
def mentions? gem
|
18
|
+
@contents.select { |line| line =~ /^\s*gem\s+['"]#{gem}['"]/ }.any?
|
19
|
+
end
|
20
|
+
|
17
21
|
def restrict_gem_version gem, version_limit
|
18
22
|
return false unless version_limit.to_s =~ /\d\.\d/
|
19
|
-
if
|
23
|
+
if ! mentions? gem
|
20
24
|
@contents << "gem '#{gem}', '>=0'"
|
21
25
|
end
|
22
26
|
adjusted = false
|
metadata
CHANGED
@@ -1,81 +1,69 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: smarter_bundler
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 3
|
10
|
-
version: 0.1.3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
6
|
+
authors:
|
13
7
|
- Ian Heggie
|
14
8
|
autorequire:
|
15
9
|
bindir: exe
|
16
10
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
22
|
-
version_requirements: &id001 !ruby/object:Gem::Requirement
|
23
|
-
none: false
|
24
|
-
requirements:
|
25
|
-
- - ~>
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
hash: 47
|
28
|
-
segments:
|
29
|
-
- 1
|
30
|
-
- 16
|
31
|
-
version: "1.16"
|
32
|
-
prerelease: false
|
33
|
-
type: :development
|
34
|
-
requirement: *id001
|
11
|
+
date: 2018-03-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
35
14
|
name: bundler
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
hash: 35
|
43
|
-
segments:
|
44
|
-
- 10
|
45
|
-
- 0
|
46
|
-
version: "10.0"
|
47
|
-
prerelease: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
48
20
|
type: :development
|
49
|
-
requirement: *id002
|
50
|
-
name: rake
|
51
|
-
- !ruby/object:Gem::Dependency
|
52
|
-
version_requirements: &id003 !ruby/object:Gem::Requirement
|
53
|
-
none: false
|
54
|
-
requirements:
|
55
|
-
- - ~>
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
hash: 31
|
58
|
-
segments:
|
59
|
-
- 5
|
60
|
-
- 0
|
61
|
-
version: "5.0"
|
62
21
|
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
63
34
|
type: :development
|
64
|
-
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
65
42
|
name: minitest
|
66
|
-
|
67
|
-
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
description: The smarter_bundle retries installing gems, and if that fails it tries
|
56
|
+
installing an earlier version by adjusting the Gemfile
|
57
|
+
email:
|
68
58
|
- ian@heggie.biz
|
69
|
-
executables:
|
59
|
+
executables:
|
70
60
|
- smarter_bundle
|
71
61
|
extensions: []
|
72
|
-
|
73
62
|
extra_rdoc_files: []
|
74
|
-
|
75
|
-
|
76
|
-
- .
|
77
|
-
- .
|
78
|
-
- .travis.yml
|
63
|
+
files:
|
64
|
+
- ".gitignore"
|
65
|
+
- ".ruby-versions"
|
66
|
+
- ".travis.yml"
|
79
67
|
- CHANGELOG
|
80
68
|
- Gemfile
|
81
69
|
- LICENSE.txt
|
@@ -92,39 +80,28 @@ files:
|
|
92
80
|
- lib/smarter_bundler/shell.rb
|
93
81
|
- lib/smarter_bundler/version.rb
|
94
82
|
- smarter_bundler.gemspec
|
95
|
-
has_rdoc: true
|
96
83
|
homepage: https://github.com/ianheggie/smarter_bundler
|
97
|
-
licenses:
|
84
|
+
licenses:
|
98
85
|
- MIT
|
86
|
+
metadata: {}
|
99
87
|
post_install_message:
|
100
88
|
rdoc_options: []
|
101
|
-
|
102
|
-
require_paths:
|
89
|
+
require_paths:
|
103
90
|
- lib
|
104
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
-
|
106
|
-
requirements:
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
107
93
|
- - ">="
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
version: "0"
|
113
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
-
none: false
|
115
|
-
requirements:
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
116
98
|
- - ">="
|
117
|
-
- !ruby/object:Gem::Version
|
118
|
-
|
119
|
-
segments:
|
120
|
-
- 0
|
121
|
-
version: "0"
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
122
101
|
requirements: []
|
123
|
-
|
124
102
|
rubyforge_project:
|
125
|
-
rubygems_version:
|
103
|
+
rubygems_version: 2.5.2
|
126
104
|
signing_key:
|
127
|
-
specification_version:
|
105
|
+
specification_version: 4
|
128
106
|
summary: Enhances bundler by adjusting Gemfile when correctable errors are found
|
129
107
|
test_files: []
|
130
|
-
|