bundler-resolutions 0.1.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 +7 -0
- data/README.md +93 -0
- data/lib/bundler/resolutions/version.rb +9 -0
- data/lib/bundler/resolutions.rb +47 -0
- data/plugins.rb +3 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5a9bc7c0b4191b262edcc52111b78fb8c67b74b0c9642ddec0036142d46c2989
|
4
|
+
data.tar.gz: bb5c955b6db7a14e56e8d5048c98709a36f634f25364a14cbe22d6606d3faeab
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2d0f016d3a21dd98fe3d175d015fd4e526a514f32acf8283205db330ac9e52df4444e59a12e761882580790c8bccc1599739d3375291f598b810b4e7800b0705
|
7
|
+
data.tar.gz: cf1c8bee485fa053ec3de1ac094638381d9153796de7e77f5add4ee31953f41889f3563f6413830a5351633cb2f7960d5557447f66d52aca69ac175293696646
|
data/README.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
bundler-resolutions
|
2
|
+
===================
|
3
|
+
|
4
|
+
[](https://rubygems.org/gems/bundler-resolutions)
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
6
|
+
|
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 in your `Gemfile` without explicitly declaring
|
9
|
+
a concrete dependency on those gems. It acts much like the
|
10
|
+
[resolutions](https://classic.yarnpkg.com/lang/en/docs/selective-version-resolutions/) feature in
|
11
|
+
[Yarn](https://yarnpkg.com/).
|
12
|
+
|
13
|
+
> [!WARNING]
|
14
|
+
> This is an experimental project and neither its API stability nor correctness should be assumed
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
Add `bundler-resolutions` to your Gemfile, and add a `resolutions` group to specify the gems you
|
19
|
+
want to specify versions requirements for.
|
20
|
+
|
21
|
+
The resulting `Gemfile.lock` in this example will have nokogiri locked to `1.16.5` or above.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
plugin 'bundler-resolutions'
|
25
|
+
|
26
|
+
gem "rails"
|
27
|
+
|
28
|
+
group :resolutions do
|
29
|
+
gem "nokogiri", ">= 1.16.5" # CVE-2024-34459
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
However the `Gemfile.lock` from this example will not have nokogiri at all, as it is neither
|
34
|
+
explicitly declared, nor brought in as a transitive dependency.
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
plugin 'bundler-resolutions'
|
38
|
+
|
39
|
+
group :resolutions do
|
40
|
+
gem "nokogiri", ">= 1.16.5" # CVE-2024-34459
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
## Detail
|
45
|
+
|
46
|
+
`bundler-resolutions` allows you to specify version requirements using standard gem syntax in your
|
47
|
+
Gemfile to indicate that you have version requirements for those gems *if* they were to be brought
|
48
|
+
in as transitive dependencies, but that you don't depend on them yourself directly.
|
49
|
+
|
50
|
+
An example use case is in the Gemfile given below. Here we are saying that although we do not use nokogiri
|
51
|
+
specifically ourselves, we want to ensure that if it is pulled in by other gems then it will
|
52
|
+
always be above the know version with a CVE.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
source "https://rubygems.org"
|
56
|
+
|
57
|
+
plugin 'bundler-resolutions'
|
58
|
+
|
59
|
+
gem "rails"
|
60
|
+
|
61
|
+
group :resolutions do
|
62
|
+
gem "nokogiri", ">= 1.16.5" # CVE-2024-34459
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
The big difference between doing this and just declaring it in your Gemfile is that it will only
|
67
|
+
be used in resolutions (and be written to your lock file) if the gems you do directly depend on
|
68
|
+
continue to use it. If they stop using it, then your resolutions will take no part in the
|
69
|
+
bundler lock resolution.
|
70
|
+
|
71
|
+
The other difference is that even if it does take part in the resolutions, it will not be
|
72
|
+
present in the `DEPENDENCIES` section of the lock file, as it is not a direct dependency.
|
73
|
+
|
74
|
+
## Use cases
|
75
|
+
|
76
|
+
There are a number of reasons you may want to prevent the usage of some gem versions, without
|
77
|
+
direct use, such as:
|
78
|
+
|
79
|
+
1. You have learnt of a CVE of a gem.
|
80
|
+
2. You have internal processes that mandate the usage of certain gem versions for legal or sign off reasons.
|
81
|
+
3. You know of gem incompatibilities in later versions.
|
82
|
+
4. You know that different OS architectures do not work with some versions.
|
83
|
+
|
84
|
+
## How it works
|
85
|
+
|
86
|
+
`bundler-resolutions` works by patching the Gemfile DSL to allow for special processing
|
87
|
+
of the `resolutions` group. It also patches the bundler `filtered_versions_for` method to
|
88
|
+
allow for the resolution restrictions from the versions specified in the `resolutions` group.
|
89
|
+
|
90
|
+
This is a very early version, and it should be considered experimental.
|
91
|
+
|
92
|
+
Future work may include relating this to bundler-audit, and other security tools, so you
|
93
|
+
will automatically gain version restrictions against known CVEs.
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bundler
|
4
|
+
class Resolutions
|
5
|
+
GROUP_NAME = :resolutions
|
6
|
+
|
7
|
+
attr_reader :resolutions
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@resolutions = {}
|
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
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def instance = @instance ||= new
|
21
|
+
end
|
22
|
+
|
23
|
+
# A module we prepend to Bundler::Resolutions::Resolver
|
24
|
+
module Resolver
|
25
|
+
# This overrides the default behaviour of the resolver to filter out versions that don't
|
26
|
+
# satisfy the requirements specified in RESOLVER_RESOLUTIONS.
|
27
|
+
def filtered_versions_for(package)
|
28
|
+
super.select do |pkg|
|
29
|
+
req = Bundler::Resolutions.instance.resolutions[package.name.to_sym]
|
30
|
+
req ? Gem::Requirement.new(*req.split(",")).satisfied_by?(pkg.version) : true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# A module we prepend to Bundler::Dsl
|
36
|
+
module Dsl
|
37
|
+
# Here we override the normal group function to capture the resolutions, and ensure any
|
38
|
+
# gem calls are effectively a no-op as regards to adding them to dependencies.
|
39
|
+
def group(*args, &blk)
|
40
|
+
args.first == GROUP_NAME ? Bundler::Resolutions.instance.instance_eval(&blk) : super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
Bundler::Resolver.prepend(Bundler::Resolutions::Resolver)
|
47
|
+
Bundler::Dsl.prepend(Bundler::Resolutions::Dsl)
|
data/plugins.rb
ADDED
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bundler-resolutions
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Harry Lascelles
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-10-02 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A bundler plugin to enforce resolutions without specifying a concrete
|
14
|
+
dependency
|
15
|
+
email:
|
16
|
+
- harry@harrylascelles.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- README.md
|
22
|
+
- lib/bundler/resolutions.rb
|
23
|
+
- lib/bundler/resolutions/version.rb
|
24
|
+
- plugins.rb
|
25
|
+
homepage: https://github.com/hlascelles/bundler-resolutions
|
26
|
+
licenses:
|
27
|
+
- MIT
|
28
|
+
metadata:
|
29
|
+
homepage_uri: https://github.com/hlascelles/bundler-resolutions
|
30
|
+
documentation_uri: https://github.com/hlascelles/bundler-resolutions
|
31
|
+
changelog_uri: https://github.com/hlascelles/bundler-resolutions/blob/master/CHANGELOG.md
|
32
|
+
source_code_uri: https://github.com/hlascelles/bundler-resolutions/
|
33
|
+
bug_tracker_uri: https://github.com/hlascelles/bundler-resolutions/issues
|
34
|
+
rubygems_mfa_required: 'true'
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubygems_version: 3.5.11
|
51
|
+
signing_key:
|
52
|
+
specification_version: 4
|
53
|
+
summary: A bundler plugin to enforce resolutions without specifying a concrete dependency
|
54
|
+
test_files: []
|