bundler-resolutions 0.2.0 → 0.3.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 +18 -0
- data/lib/bundler/resolutions/config.rb +39 -0
- data/lib/bundler/resolutions/version.rb +1 -1
- data/lib/bundler/resolutions.rb +68 -29
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a6def9961c77861086b6b58177a934945938362e2125ba5dc49b8a6c06efdff
|
4
|
+
data.tar.gz: ccef554f38761f9916843d675f70ef7189ef8a7070bdb3d9b2e466e2eed998de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '01507905d1b9402c1efc92f9509b5aeef2b858d18c3b3e8555af937e1b479dc4b2711f87eed3ef87b8d64bfb7285bb299322a5925d43013e6dac6afa2128b5ba'
|
7
|
+
data.tar.gz: c85660a42a9149ffcded4f649ef8b2d9413da63eb435d9c8231be3fcdf26dc6aebea0a6608bd1206298ac3caf47b01681a573cecc4e92b0dc3b6638a893b219d
|
data/README.md
CHANGED
@@ -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 { |version| Gem::Requirement.new(version.split(",")) }
|
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 in the file tree
|
29
|
+
dir = 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,15 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "yaml"
|
4
|
+
require_relative "resolutions/config"
|
4
5
|
|
5
6
|
module Bundler
|
6
7
|
class Resolutions
|
7
|
-
|
8
|
+
DEFAULT_GEM_REQUIREMENT = Gem::Requirement.default
|
8
9
|
|
9
|
-
attr_reader :
|
10
|
+
attr_reader :config
|
10
11
|
|
11
12
|
def initialize(config = nil)
|
12
|
-
load_config(config)
|
13
|
+
@config = Bundler::Resolutions::Config.load_config(config)
|
13
14
|
end
|
14
15
|
|
15
16
|
class << self
|
@@ -19,7 +20,14 @@ module Bundler
|
|
19
20
|
end
|
20
21
|
|
21
22
|
# A module we prepend to Bundler::Resolutions::Resolver
|
23
|
+
# :reek:ModuleInitialize
|
22
24
|
module Resolver
|
25
|
+
# Override the initializer in the resolver
|
26
|
+
def initialize(*args)
|
27
|
+
Bundler::Resolutions.instance.add_concrete_resolutions_for(args.first)
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
23
31
|
# This overrides the default behaviour of the resolver to filter out versions that don't
|
24
32
|
# satisfy the requirements specified in .bundler-resolutions.yml.
|
25
33
|
def filtered_versions_for(package)
|
@@ -29,11 +37,9 @@ module Bundler
|
|
29
37
|
|
30
38
|
def constrain_versions_for(results, package)
|
31
39
|
results.select do |pkg|
|
32
|
-
req =
|
40
|
+
req = resolutions_for(package.name)
|
33
41
|
if req
|
34
|
-
|
35
|
-
puts "bundler-resolutions making sure #{package} is satisfied by #{req}"
|
36
|
-
end
|
42
|
+
log("making sure #{package} is satisfied by #{req}")
|
37
43
|
req.satisfied_by?(pkg.version)
|
38
44
|
else
|
39
45
|
true
|
@@ -41,33 +47,66 @@ module Bundler
|
|
41
47
|
end
|
42
48
|
end
|
43
49
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
50
|
+
def add_concrete_resolutions_for(base)
|
51
|
+
base.requirements.each do |bundler_dependency|
|
52
|
+
requirement_name = bundler_dependency.name
|
53
|
+
resolutions = resolutions_for(requirement_name)
|
54
|
+
|
55
|
+
if resolutions
|
56
|
+
log(<<~MSG, requirement_name)
|
57
|
+
has resolutions for concrete dependency '#{requirement_name}': #{resolutions}
|
58
|
+
MSG
|
59
|
+
else
|
60
|
+
log("has no resolutions for concrete dependency '#{requirement_name}'", requirement_name)
|
61
|
+
next
|
62
|
+
end
|
63
|
+
|
64
|
+
bundler_resolutions_reqs = resolutions.requirements
|
65
|
+
apply_resolutions_for_concrete_gem(bundler_dependency, bundler_resolutions_reqs)
|
66
|
+
end
|
55
67
|
end
|
56
68
|
|
57
|
-
private def
|
58
|
-
|
69
|
+
private def resolutions_for(package_name)
|
70
|
+
config[package_name]
|
71
|
+
end
|
72
|
+
|
73
|
+
# You can debug with BUNDLER_RESOLUTIONS_DEBUG=gem_name or BUNDLER_RESOLUTIONS_DEBUG=true
|
74
|
+
# to see all messages.
|
75
|
+
private def log(message, gem = nil)
|
76
|
+
return unless ENV["BUNDLER_RESOLUTIONS_DEBUG"]
|
77
|
+
return if gem && !ENV["BUNDLER_RESOLUTIONS_DEBUG"].split(",").include?(gem)
|
78
|
+
|
79
|
+
puts "bundler-resolutions: #{message}"
|
80
|
+
end
|
81
|
+
|
82
|
+
private def apply_resolutions_for_concrete_gem(bundler_dependency, bundler_resolutions_reqs)
|
83
|
+
requirement_name = bundler_dependency.name
|
84
|
+
bundler_resolutions_reqs.each do |r|
|
85
|
+
# If the concrete requirement is already in the Gemfile, skip it
|
86
|
+
requirements = bundler_dependency.requirement.requirements
|
87
|
+
if requirements.include?(r)
|
88
|
+
# We don't want to double up / dupe the same requirements
|
89
|
+
log(<<~MSG, requirement_name)
|
90
|
+
Skipping adding requirements to gem concretely specified in Gemfile as it
|
91
|
+
was already present: #{requirement_name}: #{bundler_dependency}
|
92
|
+
MSG
|
93
|
+
next
|
94
|
+
end
|
59
95
|
|
60
|
-
|
61
|
-
|
62
|
-
|
96
|
+
# Otherwise add the additional requirement
|
97
|
+
before_req = bundler_dependency.to_s
|
98
|
+
# If there were no requirements before, there is a default one for ">= 0". We need to
|
99
|
+
# remove that so when we add the new one the implicit ">= 0" is not present, as it normally
|
100
|
+
# isn't written out to lockfiles.
|
101
|
+
requirements.clear if bundler_dependency.requirement == DEFAULT_GEM_REQUIREMENT
|
102
|
+
# Add the new requirement
|
103
|
+
requirements << r
|
104
|
+
after_req = bundler_dependency.to_s
|
63
105
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
dir = File.dirname(dir)
|
68
|
-
raise "Could not find #{CONFIG_FILE_NAME}" if dir == "/"
|
106
|
+
log(<<~MSG, requirement_name)
|
107
|
+
Adding concrete constraints for #{requirement_name}. Before: #{before_req}. After: #{after_req}.
|
108
|
+
MSG
|
69
109
|
end
|
70
|
-
File.join(dir, CONFIG_FILE_NAME)
|
71
110
|
end
|
72
111
|
end
|
73
112
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bundler-resolutions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Harry Lascelles
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-03
|
10
|
+
date: 2025-05-03 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
description: A bundler plugin to enforce resolutions without specifying a concrete
|
13
13
|
dependency
|
@@ -19,6 +19,7 @@ extra_rdoc_files: []
|
|
19
19
|
files:
|
20
20
|
- README.md
|
21
21
|
- lib/bundler/resolutions.rb
|
22
|
+
- lib/bundler/resolutions/config.rb
|
22
23
|
- lib/bundler/resolutions/version.rb
|
23
24
|
- plugins.rb
|
24
25
|
homepage: https://github.com/hlascelles/bundler-resolutions
|
@@ -38,7 +39,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
38
39
|
requirements:
|
39
40
|
- - ">="
|
40
41
|
- !ruby/object:Gem::Version
|
41
|
-
version: '
|
42
|
+
version: '3.2'
|
42
43
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
44
|
requirements:
|
44
45
|
- - ">="
|