bundler-resolutions 0.1.0 → 0.2.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 +43 -42
- data/lib/bundler/resolutions/version.rb +1 -1
- data/lib/bundler/resolutions.rb +49 -21
- metadata +3 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 25173fc2b7df9fe3efd07150e315f38c6584199627bef4ea1ec44ec44e3fbb2d
|
4
|
+
data.tar.gz: 7728a62a42e3c9244932cb568e6a918d745a2bf9003f61d62bfb6402061610df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc87f9b2c8feea662f00ef0a7340aae3355c7b3e10864fb70214c970d600d7602e19745eb6882886b5fd84726371ce9caf2ef67ee5e8ff5e9b0f451ee3c4a2fc
|
7
|
+
data.tar.gz: 741b9f3f5b10ad0a896b0776a0d4807f6eef446e5941554f6b95c6530f0df99e4cfc50223f848f4371639abc1e0912b9c7f8ef9b440b22b1841e12fd6c8a7f59
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ bundler-resolutions
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
6
6
|
|
7
7
|
[bundler-resolutions](https://github.com/hlascelles/bundler-resolutions) is a [bundler](https://bundler.io/)
|
8
|
-
plugin that allows you to specify gem version requirements
|
8
|
+
plugin that allows you to specify gem version requirements for your `Gemfile` without explicitly declaring
|
9
9
|
a concrete dependency on those gems. It acts much like the
|
10
10
|
[resolutions](https://classic.yarnpkg.com/lang/en/docs/selective-version-resolutions/) feature in
|
11
11
|
[Yarn](https://yarnpkg.com/).
|
@@ -15,53 +15,49 @@ a concrete dependency on those gems. It acts much like the
|
|
15
15
|
|
16
16
|
## Usage
|
17
17
|
|
18
|
-
Add `bundler-resolutions` to your Gemfile, and add a
|
19
|
-
want to specify versions requirements for.
|
18
|
+
Add `bundler-resolutions` to your Gemfile, and add a `.bundler-resolutions.yml` file to
|
19
|
+
specify the gems you want to specify versions requirements for.
|
20
20
|
|
21
|
-
|
21
|
+
### Example 1
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
In this example the resulting `Gemfile.lock` will have nokogiri locked to `1.16.5` or above, but
|
24
|
+
nokogiri will not be present in the `DEPENDENCIES` section of the lock file. Also, if `rails` were
|
25
|
+
to change to a version that did not depend on nokogiri, then the resolution would not be used or
|
26
|
+
appear in the lock file at all.
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
`.bundler-resolutions.yml`:
|
29
|
+
```yaml
|
30
|
+
gems:
|
31
|
+
nokogiri: ">= 1.16.5" # CVE-2024-34459
|
31
32
|
```
|
32
33
|
|
33
|
-
|
34
|
-
explicitly declared, nor brought in as a transitive dependency.
|
35
|
-
|
34
|
+
`Gemfile`:
|
36
35
|
```ruby
|
37
|
-
|
38
|
-
|
39
|
-
group :resolutions do
|
40
|
-
gem "nokogiri", ">= 1.16.5" # CVE-2024-34459
|
41
|
-
end
|
36
|
+
gem 'bundler-resolutions'
|
37
|
+
gem "rails"
|
42
38
|
```
|
43
39
|
|
44
|
-
|
40
|
+
### Example 2
|
45
41
|
|
46
|
-
`
|
47
|
-
|
48
|
-
in as transitive dependencies, but that you don't depend on them yourself directly.
|
42
|
+
Here, the `Gemfile.lock` from this example will not have nokogiri at all, as it is neither
|
43
|
+
explicitly declared in the Gemfile, nor brought in as a transitive dependency.
|
49
44
|
|
50
|
-
|
51
|
-
|
52
|
-
|
45
|
+
`.bundler-resolutions.yml`:
|
46
|
+
```yaml
|
47
|
+
gems:
|
48
|
+
nokogiri: ">= 1.16.5" # CVE-2024-34459
|
49
|
+
```
|
53
50
|
|
54
51
|
```ruby
|
55
|
-
|
56
|
-
|
57
|
-
|
52
|
+
gem 'bundler-resolutions'
|
53
|
+
gem "thor"
|
54
|
+
```
|
58
55
|
|
59
|
-
|
56
|
+
## Detail
|
60
57
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
```
|
58
|
+
`bundler-resolutions` allows you to specify version requirements in a config file
|
59
|
+
to indicate that you have version requirements for those gems *if* they were to be brought
|
60
|
+
in as transitive dependencies, but that you don't depend on them yourself directly.
|
65
61
|
|
66
62
|
The big difference between doing this and just declaring it in your Gemfile is that it will only
|
67
63
|
be used in resolutions (and be written to your lock file) if the gems you do directly depend on
|
@@ -73,19 +69,24 @@ present in the `DEPENDENCIES` section of the lock file, as it is not a direct de
|
|
73
69
|
|
74
70
|
## Use cases
|
75
71
|
|
76
|
-
There are a number of reasons you may want to prevent the usage of some gem versions, without
|
77
|
-
direct use
|
72
|
+
There are a number of reasons you may want to prevent the usage of some gem versions, but without
|
73
|
+
declaring their direct use in Gemfiles. Also there are reasons to set versions across a monorepo
|
74
|
+
of many Gemfiles, but where not all apps use all blessed versions, such as:
|
78
75
|
|
79
76
|
1. You have learnt of a CVE of a gem.
|
80
|
-
|
81
|
-
|
82
|
-
|
77
|
+
1. You have internal processes that mandate the usage of certain gem versions for legal or sign off reasons.
|
78
|
+
1. You wish to take a paranoid approach to updating certain high value target gems. eg `devise`.
|
79
|
+
1. You want certain gem collections to move in lockstep. eg `sinatra`, `rack` and `rack-protection`, which are relatively tightly coupled.
|
80
|
+
1. You know of gems that are very slow to install and you have preinstalled them in internal base images. eg `rugged` or `sorbet`.
|
81
|
+
1. You know of gems that are tightly coupled to ruby itself that shouldn't be upgraded. eg `stringio` and `psych`.
|
82
|
+
1. You know of gem incompatibilities with your codebase in their later versions.
|
83
|
+
1. You know that different OS architectures do not work with some versions.
|
84
|
+
1. You wish to prevent unintentional downgrades of dependencies when using `bundle` commands.
|
83
85
|
|
84
86
|
## How it works
|
85
87
|
|
86
|
-
`bundler-resolutions` works by patching the
|
87
|
-
|
88
|
-
allow for the resolution restrictions from the versions specified in the `resolutions` group.
|
88
|
+
`bundler-resolutions` works by patching the `bundler` `Resolver` `filtered_versions_for` method to
|
89
|
+
allow for the resolution restrictions from the versions specified in the config file.
|
89
90
|
|
90
91
|
This is a very early version, and it should be considered experimental.
|
91
92
|
|
data/lib/bundler/resolutions.rb
CHANGED
@@ -1,47 +1,75 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "yaml"
|
4
|
+
|
3
5
|
module Bundler
|
4
6
|
class Resolutions
|
5
|
-
|
7
|
+
CONFIG_FILE_NAME = ".bundler-resolutions.yml"
|
6
8
|
|
7
9
|
attr_reader :resolutions
|
8
10
|
|
9
|
-
def initialize
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
# This method is called by the DSL to set the resolution for a given gem. It is effectively
|
14
|
-
# an override of the normal gem method.
|
15
|
-
def gem(name, requirements)
|
16
|
-
resolutions[name.to_sym] = requirements
|
11
|
+
def initialize(config = nil)
|
12
|
+
load_config(config)
|
17
13
|
end
|
18
14
|
|
19
15
|
class << self
|
20
|
-
def instance
|
16
|
+
def instance
|
17
|
+
@instance ||= new
|
18
|
+
end
|
21
19
|
end
|
22
20
|
|
23
21
|
# A module we prepend to Bundler::Resolutions::Resolver
|
24
22
|
module Resolver
|
25
23
|
# This overrides the default behaviour of the resolver to filter out versions that don't
|
26
|
-
# satisfy the requirements specified in
|
24
|
+
# satisfy the requirements specified in .bundler-resolutions.yml.
|
27
25
|
def filtered_versions_for(package)
|
28
|
-
super
|
29
|
-
|
30
|
-
|
26
|
+
Bundler::Resolutions.instance.constrain_versions_for(super, package)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def constrain_versions_for(results, package)
|
31
|
+
results.select do |pkg|
|
32
|
+
req = resolutions[package.name]
|
33
|
+
if req
|
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
|
39
|
+
true
|
31
40
|
end
|
32
41
|
end
|
33
42
|
end
|
34
43
|
|
35
|
-
|
36
|
-
|
37
|
-
#
|
38
|
-
#
|
39
|
-
|
40
|
-
|
44
|
+
private def load_config(config = nil)
|
45
|
+
# Safe load yaml file whose location is given by an argument, an ENV, and if no
|
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(",")) }
|
55
|
+
end
|
56
|
+
|
57
|
+
private def find_config(config = nil)
|
58
|
+
return config if config # If present, assume it is a location
|
59
|
+
|
60
|
+
# Use the ENV if present
|
61
|
+
env_file = ENV["BUNDLER_RESOLUTIONS_CONFIG"]
|
62
|
+
return env_file if env_file
|
63
|
+
|
64
|
+
# Otherwise find it in the file tree
|
65
|
+
dir = Dir.pwd
|
66
|
+
until File.exist?(File.join(dir, CONFIG_FILE_NAME))
|
67
|
+
dir = File.dirname(dir)
|
68
|
+
raise "Could not find #{CONFIG_FILE_NAME}" if dir == "/"
|
41
69
|
end
|
70
|
+
File.join(dir, CONFIG_FILE_NAME)
|
42
71
|
end
|
43
72
|
end
|
44
73
|
end
|
45
74
|
|
46
75
|
Bundler::Resolver.prepend(Bundler::Resolutions::Resolver)
|
47
|
-
Bundler::Dsl.prepend(Bundler::Resolutions::Dsl)
|
metadata
CHANGED
@@ -1,14 +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.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Harry Lascelles
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-03-23 00:00:00.000000000 Z
|
12
11
|
dependencies: []
|
13
12
|
description: A bundler plugin to enforce resolutions without specifying a concrete
|
14
13
|
dependency
|
@@ -32,7 +31,6 @@ metadata:
|
|
32
31
|
source_code_uri: https://github.com/hlascelles/bundler-resolutions/
|
33
32
|
bug_tracker_uri: https://github.com/hlascelles/bundler-resolutions/issues
|
34
33
|
rubygems_mfa_required: 'true'
|
35
|
-
post_install_message:
|
36
34
|
rdoc_options: []
|
37
35
|
require_paths:
|
38
36
|
- lib
|
@@ -47,8 +45,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
47
45
|
- !ruby/object:Gem::Version
|
48
46
|
version: '0'
|
49
47
|
requirements: []
|
50
|
-
rubygems_version: 3.
|
51
|
-
signing_key:
|
48
|
+
rubygems_version: 3.6.6
|
52
49
|
specification_version: 4
|
53
50
|
summary: A bundler plugin to enforce resolutions without specifying a concrete dependency
|
54
51
|
test_files: []
|