bundler-resolutions 0.2.0 → 0.4.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 +4 -4
- data/README.md +19 -1
- data/lib/bundler/resolutions/config.rb +39 -0
- data/lib/bundler/resolutions/version.rb +3 -3
- data/lib/bundler/resolutions.rb +65 -33
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a4f090d8833033fef1949501d9b8876333cfbc8797c954306f4ee57d963981dc
|
4
|
+
data.tar.gz: 0400ae342a0e9b8c50f7644daf99b7642954fda1d2758e68b8b06041472244b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc78cd3cfacb3b56a160fe9a59acffb848360f082a2e326a647f2c547ddd31a692198fdcb13faf1ac50a224b6595c00cf11aa725f98cbfc98a0cd5453f95d263
|
7
|
+
data.tar.gz: 77cdeadf7f8fda11a215e8ab50d9c1506e400991a087b07e5edceef0d796c2faad2681979a2bbd41324ae5d99820377e8c710467895b21932b91990396756721
|
data/README.md
CHANGED
@@ -33,7 +33,7 @@ gems:
|
|
33
33
|
|
34
34
|
`Gemfile`:
|
35
35
|
```ruby
|
36
|
-
gem 'bundler-resolutions'
|
36
|
+
gem "bundler-resolutions", path: "../", install_if: -> { require Gem::Specification.find_by_name('bundler-resolutions').gem_dir + "/lib/bundler/resolutions"; true }
|
37
37
|
gem "rails"
|
38
38
|
```
|
39
39
|
|
@@ -53,6 +53,24 @@ gem 'bundler-resolutions'
|
|
53
53
|
gem "thor"
|
54
54
|
```
|
55
55
|
|
56
|
+
## Config file
|
57
|
+
|
58
|
+
The config file is a YAML file with a `gems` key that contains a mapping of gem names to version
|
59
|
+
requirements. The version requirements are the same as those used in the `Gemfile`.
|
60
|
+
|
61
|
+
Example:
|
62
|
+
|
63
|
+
```yaml
|
64
|
+
gems:
|
65
|
+
nokogiri: ">= 1.16.5" # CVE-2024-34459
|
66
|
+
thor: ">= 1.0.1, < 2.0"
|
67
|
+
```
|
68
|
+
|
69
|
+
By default, `bundler-resolutions` will look for a file named `.bundler-resolutions.yml` in the
|
70
|
+
current directory, or the parent, and continue looking up to the root dir.
|
71
|
+
|
72
|
+
You can also specify a file location by setting the `BUNDLER_RESOLUTIONS_CONFIG` ENV var.
|
73
|
+
|
56
74
|
## Detail
|
57
75
|
|
58
76
|
`bundler-resolutions` allows you to specify version requirements in a config file
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
module Bundler
|
6
|
+
class Resolutions
|
7
|
+
class Config
|
8
|
+
CONFIG_FILE_NAME = ".bundler-resolutions.yml"
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def load_config(config = nil)
|
12
|
+
raw_hash = if config.is_a?(Hash)
|
13
|
+
config
|
14
|
+
else
|
15
|
+
YAML.safe_load_file(find_config(config))
|
16
|
+
end
|
17
|
+
gems = raw_hash.fetch("gems")
|
18
|
+
gems.transform_values { |reqs| Array(reqs).map { |req| Gem::Requirement.new(req) } }
|
19
|
+
end
|
20
|
+
|
21
|
+
private def find_config(config = nil)
|
22
|
+
return config if config # If present, assume it is a location
|
23
|
+
|
24
|
+
# Use the ENV if present
|
25
|
+
env_file = ENV["BUNDLER_RESOLUTIONS_CONFIG"]
|
26
|
+
return env_file if env_file
|
27
|
+
|
28
|
+
# Otherwise find it above where `BUNDLE_GEMFILE` is located, or pwd if not set
|
29
|
+
dir = ENV["BUNDLE_GEMFILE"] ? File.dirname(ENV["BUNDLE_GEMFILE"]) : Dir.pwd
|
30
|
+
until File.exist?(File.join(dir, CONFIG_FILE_NAME))
|
31
|
+
dir = File.dirname(dir)
|
32
|
+
raise "Could not find #{CONFIG_FILE_NAME}" if dir == "/"
|
33
|
+
end
|
34
|
+
File.join(dir, CONFIG_FILE_NAME)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/bundler/resolutions.rb
CHANGED
@@ -1,20 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "yaml"
|
4
|
+
require_relative "resolutions/config"
|
5
|
+
require_relative "resolutions/version"
|
4
6
|
|
5
7
|
module Bundler
|
6
8
|
class Resolutions
|
7
|
-
|
9
|
+
DEFAULT_GEM_REQUIREMENT = Gem::Requirement.default
|
8
10
|
|
9
|
-
attr_reader :
|
11
|
+
attr_reader :config
|
10
12
|
|
11
13
|
def initialize(config = nil)
|
12
|
-
load_config(config)
|
14
|
+
@config = Bundler::Resolutions::Config.load_config(config)
|
13
15
|
end
|
14
16
|
|
15
17
|
class << self
|
16
18
|
def instance
|
17
|
-
@instance ||= new
|
19
|
+
@instance ||= new # rubocop:disable ThreadSafety/ClassInstanceVariable
|
20
|
+
end
|
21
|
+
|
22
|
+
# You can debug with BUNDLER_RESOLUTIONS_DEBUG=gem_name or BUNDLER_RESOLUTIONS_DEBUG=true
|
23
|
+
# to see all messages.
|
24
|
+
def log(message, gem = nil)
|
25
|
+
return if ENV["BUNDLER_RESOLUTIONS_DEBUG"].nil?
|
26
|
+
unless ENV["BUNDLER_RESOLUTIONS_DEBUG"] == "true" ||
|
27
|
+
ENV["BUNDLER_RESOLUTIONS_DEBUG"].split(",").include?(gem)
|
28
|
+
return
|
29
|
+
end
|
30
|
+
|
31
|
+
puts "bundler-resolutions: #{message}"
|
18
32
|
end
|
19
33
|
end
|
20
34
|
|
@@ -28,48 +42,66 @@ module Bundler
|
|
28
42
|
end
|
29
43
|
|
30
44
|
def constrain_versions_for(results, package)
|
45
|
+
log("Constraining versions for #{package} with results: #{results.map(&:to_s)}")
|
31
46
|
results.select do |pkg|
|
32
|
-
|
33
|
-
if
|
34
|
-
if ENV["BUNDLER_RESOLUTIONS_DEBUG"] == "true"
|
35
|
-
puts "bundler-resolutions making sure #{package} is satisfied by #{req}"
|
36
|
-
end
|
37
|
-
req.satisfied_by?(pkg.version)
|
38
|
-
else
|
47
|
+
reqs = resolutions_for(package.name)
|
48
|
+
if reqs.nil?
|
39
49
|
true
|
50
|
+
else
|
51
|
+
log("making sure #{package} / #{pkg} is satisfied by #{reqs.map(&:to_s)}")
|
52
|
+
reqs.all? { |req| req.satisfied_by?(pkg.version) }
|
40
53
|
end
|
41
54
|
end
|
42
55
|
end
|
43
56
|
|
44
|
-
|
45
|
-
|
46
|
-
# env given then work up dir hierarchy until found.
|
47
|
-
# The file should be called .bundler-resolutions.yml
|
48
|
-
raw_hash = if config.is_a?(Hash)
|
49
|
-
config
|
50
|
-
else
|
51
|
-
YAML.safe_load_file(find_config(config))
|
52
|
-
end
|
53
|
-
gems = raw_hash.fetch("gems")
|
54
|
-
@resolutions = gems.transform_values { |version| Gem::Requirement.new(version.split(",")) }
|
57
|
+
def resolutions_for(package_name)
|
58
|
+
config[package_name]
|
55
59
|
end
|
56
60
|
|
57
|
-
|
58
|
-
return config if config # If present, assume it is a location
|
61
|
+
def log(message, gem = nil) = self.class.log(message, gem)
|
59
62
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
+
module Definition
|
64
|
+
def check_lockfile
|
65
|
+
super
|
66
|
+
invalids = @locked_specs.to_a.select { |lazy_specification|
|
67
|
+
reqs = Bundler::Resolutions.instance.resolutions_for(lazy_specification.name)
|
68
|
+
next if reqs.nil?
|
63
69
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
70
|
+
# rubocop:disable Layout/LineLength
|
71
|
+
if reqs.all? { |req| req.satisfied_by?(lazy_specification.version) }
|
72
|
+
Bundler::Resolutions.log "#{lazy_specification.name} (#{lazy_specification.version}) is satisfied by the current lockfile version."
|
73
|
+
nil
|
74
|
+
else
|
75
|
+
Bundler::Resolutions.log "#{lazy_specification.name} (#{lazy_specification.version}) is NOT satisfied by the current lockfile version."
|
76
|
+
lazy_specification
|
77
|
+
end
|
78
|
+
# rubocop:enable Layout/LineLength
|
79
|
+
}
|
80
|
+
@locked_specs.delete(invalids)
|
69
81
|
end
|
70
|
-
File.join(dir, CONFIG_FILE_NAME)
|
71
82
|
end
|
72
83
|
end
|
73
84
|
end
|
74
85
|
|
86
|
+
# Check if the methods exists before we prepend them, to avoid issues with Bundler versions
|
87
|
+
# that do not have this method.
|
88
|
+
{
|
89
|
+
Bundler::Resolver => :filtered_versions_for,
|
90
|
+
Bundler::Definition => :nothing_changed?,
|
91
|
+
}.each do |klass, method|
|
92
|
+
next if klass.instance_methods.include?(method) || klass.private_instance_methods.include?(method)
|
93
|
+
|
94
|
+
raise <<~ERR
|
95
|
+
Bundler version #{Bundler::VERSION} is not compatible with bundler-resolutions #{Bundler::Resolutions::VERSION}
|
96
|
+
The method '#{method}' is not defined in '#{klass}'. This is likely due to a refactoring of a new
|
97
|
+
Bundler version. Please check the bundler-resolutions changelog and the Bundler changelog
|
98
|
+
to see if this is a known issue, or submit a bug report to bundler-resolutions.
|
99
|
+
ERR
|
100
|
+
end
|
101
|
+
|
102
|
+
# This is needed so we can trigger a rebuild of the lock file if just the yaml has changed.
|
103
|
+
Bundler::Definition.prepend(Bundler::Resolutions::Definition)
|
104
|
+
# This removes the transitive dependency versions that do not satisfy the yaml config.
|
75
105
|
Bundler::Resolver.prepend(Bundler::Resolutions::Resolver)
|
106
|
+
|
107
|
+
Bundler::Resolutions.log("bundler-resolutions #{Bundler::Resolutions::VERSION} loaded")
|
metadata
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bundler-resolutions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Harry Lascelles
|
8
|
+
autorequire:
|
8
9
|
bindir: bin
|
9
10
|
cert_chain: []
|
10
|
-
date: 2025-03
|
11
|
+
date: 2025-06-03 00:00:00.000000000 Z
|
11
12
|
dependencies: []
|
12
13
|
description: A bundler plugin to enforce resolutions without specifying a concrete
|
13
14
|
dependency
|
@@ -19,6 +20,7 @@ extra_rdoc_files: []
|
|
19
20
|
files:
|
20
21
|
- README.md
|
21
22
|
- lib/bundler/resolutions.rb
|
23
|
+
- lib/bundler/resolutions/config.rb
|
22
24
|
- lib/bundler/resolutions/version.rb
|
23
25
|
- plugins.rb
|
24
26
|
homepage: https://github.com/hlascelles/bundler-resolutions
|
@@ -31,6 +33,7 @@ metadata:
|
|
31
33
|
source_code_uri: https://github.com/hlascelles/bundler-resolutions/
|
32
34
|
bug_tracker_uri: https://github.com/hlascelles/bundler-resolutions/issues
|
33
35
|
rubygems_mfa_required: 'true'
|
36
|
+
post_install_message:
|
34
37
|
rdoc_options: []
|
35
38
|
require_paths:
|
36
39
|
- lib
|
@@ -38,14 +41,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
38
41
|
requirements:
|
39
42
|
- - ">="
|
40
43
|
- !ruby/object:Gem::Version
|
41
|
-
version: '
|
44
|
+
version: '3.2'
|
42
45
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
46
|
requirements:
|
44
47
|
- - ">="
|
45
48
|
- !ruby/object:Gem::Version
|
46
49
|
version: '0'
|
47
50
|
requirements: []
|
48
|
-
rubygems_version: 3.
|
51
|
+
rubygems_version: 3.5.22
|
52
|
+
signing_key:
|
49
53
|
specification_version: 4
|
50
54
|
summary: A bundler plugin to enforce resolutions without specifying a concrete dependency
|
51
55
|
test_files: []
|