bundle_update_interactive 0.8.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +22 -0
- data/lib/bundle_update_interactive/cli/options.rb +10 -2
- data/lib/bundle_update_interactive/cli.rb +7 -1
- data/lib/bundle_update_interactive/git_committer.rb +59 -0
- data/lib/bundle_update_interactive/updater.rb +10 -1
- data/lib/bundle_update_interactive/version.rb +1 -1
- 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: c5fa0d1bf9fc3114b352236559c7a91b460b6b2816b3cd0cd3b7bc848fd072b5
|
4
|
+
data.tar.gz: d70836e166741cf2efe13d188d393e094fe1adf50bb02e64f7e997a853dd65a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab496890f43f89d9519b3e14e32998fad0d888295419dd09ce2d69f546b09a8699e635c31a442aa3990d048dc09d0a864a488307c6f047213369c198aa8b3403
|
7
|
+
data.tar.gz: 4030b23f6982f0732f4a289d637ff94b1881e5b907377af69dcb0f5125c7fa19f29bb016a957c630a094268f30ecdda1d60f9978f1f9231a7e0cff4ca0b6ab23
|
data/README.md
CHANGED
@@ -42,6 +42,7 @@ bundle ui
|
|
42
42
|
|
43
43
|
## Options
|
44
44
|
|
45
|
+
- `--commit` [applies each gem update in a discrete git commit](#git-commits)
|
45
46
|
- `--latest` [modifies the Gemfile if necessary to allow the latest gem versions](#allow-latest-versions)
|
46
47
|
- `-D` / `--exclusively=GROUP` [limits updatable gems by Gemfile groups](#limit-impact-by-gemfile-groups)
|
47
48
|
|
@@ -69,6 +70,27 @@ Some gems, notably `rails`, are composed of smaller gems like `actionpack`, `act
|
|
69
70
|
|
70
71
|
Therefore, if any Rails component has a security vulnerability, `bundle update-interactive` will automatically roll up that information into a single `rails` line item, so you can select it and upgrade all of its components in one shot.
|
71
72
|
|
73
|
+
### Git commits
|
74
|
+
|
75
|
+
Sometimes, updating gems can lead to bugs or regressions. To facilitate troubleshooting, `update-interactive` offers the ability to commit each selected gem update in its own git commit, complete with a descriptive commit message. You can then make use of tools like `git bisect` to more easily find the update that introduced the problem.
|
76
|
+
|
77
|
+
To enable this behavior, pass the `--commit` option:
|
78
|
+
|
79
|
+
```
|
80
|
+
bundle update-interactive --commit
|
81
|
+
```
|
82
|
+
|
83
|
+
The gems you select to be updated will be applied in separate commits, like this:
|
84
|
+
|
85
|
+
```
|
86
|
+
* c9801382 Update activeadmin 3.2.2 → 3.2.3
|
87
|
+
* 9957254b Update rexml 3.3.5 → 3.3.6
|
88
|
+
* 4a4f2072 Update sass 1.77.6 → 1.77.8
|
89
|
+
```
|
90
|
+
|
91
|
+
> [!NOTE]
|
92
|
+
> In rare cases, Bundler may not be able to update a gem separately, due to interdependencies between gem versions. If this happens, you will see a message like "attempted to update [GEM] but its version stayed the same."
|
93
|
+
|
72
94
|
### Held back gems
|
73
95
|
|
74
96
|
When a newer version of a gem is available, but updating is not allowed due to a Gemfile requirement, `update-interactive` will report that the gem has been held back.
|
@@ -61,9 +61,12 @@ module BundleUpdateInteractive
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def build_parser(options) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
64
|
-
OptionParser.new do |parser|
|
64
|
+
OptionParser.new do |parser| # rubocop:disable Metrics/BlockLength
|
65
65
|
parser.summary_indent = " "
|
66
66
|
parser.summary_width = 24
|
67
|
+
parser.on("--commit", "Create a git commit for each selected gem update") do
|
68
|
+
options.commit = true
|
69
|
+
end
|
67
70
|
parser.on("--latest", "Modify the Gemfile to allow the latest gem versions") do
|
68
71
|
options.latest = true
|
69
72
|
end
|
@@ -90,13 +93,18 @@ module BundleUpdateInteractive
|
|
90
93
|
end
|
91
94
|
|
92
95
|
attr_accessor :exclusively
|
93
|
-
attr_writer :latest
|
96
|
+
attr_writer :commit, :latest
|
94
97
|
|
95
98
|
def initialize
|
96
99
|
@exclusively = []
|
100
|
+
@commit = false
|
97
101
|
@latest = false
|
98
102
|
end
|
99
103
|
|
104
|
+
def commit?
|
105
|
+
@commit
|
106
|
+
end
|
107
|
+
|
100
108
|
def latest?
|
101
109
|
@latest
|
102
110
|
end
|
@@ -17,7 +17,13 @@ module BundleUpdateInteractive
|
|
17
17
|
puts "Updating the following gems."
|
18
18
|
puts Table.updatable(selected_gems).render
|
19
19
|
puts
|
20
|
-
|
20
|
+
|
21
|
+
if options.commit?
|
22
|
+
GitCommitter.new(updater).apply_updates_as_individual_commits(*selected_gems.keys)
|
23
|
+
else
|
24
|
+
updater.apply_updates(*selected_gems.keys)
|
25
|
+
end
|
26
|
+
|
21
27
|
puts_gemfile_modified_notice if updater.modified_gemfile?
|
22
28
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
23
29
|
handle_exception(e)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "shellwords"
|
4
|
+
|
5
|
+
module BundleUpdateInteractive
|
6
|
+
class GitCommitter
|
7
|
+
def initialize(updater)
|
8
|
+
@updater = updater
|
9
|
+
end
|
10
|
+
|
11
|
+
def apply_updates_as_individual_commits(*gem_names)
|
12
|
+
assert_git_executable!
|
13
|
+
assert_working_directory_clean!
|
14
|
+
|
15
|
+
gem_names.flatten.each do |name|
|
16
|
+
updates = updater.apply_updates(name)
|
17
|
+
updated_gem = updates[name] || updates.values.first
|
18
|
+
next if updated_gem.nil?
|
19
|
+
|
20
|
+
commit_message = format_commit_message(updated_gem)
|
21
|
+
system "git add Gemfile Gemfile.lock", exception: true
|
22
|
+
system "git commit -m #{commit_message.shellescape}", exception: true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def format_commit_message(outdated_gem)
|
27
|
+
[
|
28
|
+
"Update",
|
29
|
+
outdated_gem.name,
|
30
|
+
outdated_gem.current_version.to_s,
|
31
|
+
outdated_gem.current_git_version,
|
32
|
+
"→",
|
33
|
+
outdated_gem.updated_version.to_s,
|
34
|
+
outdated_gem.updated_git_version
|
35
|
+
].compact.join(" ")
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
attr_reader :updater
|
41
|
+
|
42
|
+
def assert_git_executable!
|
43
|
+
success = begin
|
44
|
+
`git --version`
|
45
|
+
Process.last_status.success?
|
46
|
+
rescue SystemCallError
|
47
|
+
false
|
48
|
+
end
|
49
|
+
raise Error, "git could not be executed" unless success
|
50
|
+
end
|
51
|
+
|
52
|
+
def assert_working_directory_clean!
|
53
|
+
status = `git status --untracked-files=no --porcelain`.strip
|
54
|
+
return if status.empty?
|
55
|
+
|
56
|
+
raise Error, "`git status` reports uncommitted changes; please commit or stash them them first!\n#{status}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -18,6 +18,11 @@ module BundleUpdateInteractive
|
|
18
18
|
def apply_updates(*gem_names)
|
19
19
|
expanded_names = expand_gems_with_exact_dependencies(*gem_names)
|
20
20
|
BundlerCommands.update_gems_conservatively(*expanded_names)
|
21
|
+
|
22
|
+
# Return the gems that were actually updated based on observed changes to the lock file
|
23
|
+
updated_gems = build_outdated_gems(File.read("Gemfile.lock"))
|
24
|
+
@current_lockfile = Lockfile.parse
|
25
|
+
updated_gems
|
21
26
|
end
|
22
27
|
|
23
28
|
# Overridden by Latest::Updater subclass
|
@@ -32,7 +37,11 @@ module BundleUpdateInteractive
|
|
32
37
|
def find_updatable_gems
|
33
38
|
return {} if candidate_gems && candidate_gems.empty?
|
34
39
|
|
35
|
-
|
40
|
+
build_outdated_gems(BundlerCommands.read_updated_lockfile(*Array(candidate_gems)))
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_outdated_gems(lockfile_contents)
|
44
|
+
updated_lockfile = Lockfile.parse(lockfile_contents)
|
36
45
|
current_lockfile.entries.each_with_object({}) do |current_lockfile_entry, hash|
|
37
46
|
name = current_lockfile_entry.name
|
38
47
|
updated_lockfile_entry = updated_lockfile && updated_lockfile[name]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bundle_update_interactive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Brictson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-09-
|
11
|
+
date: 2024-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -131,6 +131,7 @@ files:
|
|
131
131
|
- lib/bundle_update_interactive/cli/table.rb
|
132
132
|
- lib/bundle_update_interactive/error.rb
|
133
133
|
- lib/bundle_update_interactive/gemfile.rb
|
134
|
+
- lib/bundle_update_interactive/git_committer.rb
|
134
135
|
- lib/bundle_update_interactive/http.rb
|
135
136
|
- lib/bundle_update_interactive/latest/gem_requirement.rb
|
136
137
|
- lib/bundle_update_interactive/latest/gemfile_editor.rb
|
@@ -167,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
168
|
- !ruby/object:Gem::Version
|
168
169
|
version: '0'
|
169
170
|
requirements: []
|
170
|
-
rubygems_version: 3.5.
|
171
|
+
rubygems_version: 3.5.19
|
171
172
|
signing_key:
|
172
173
|
specification_version: 4
|
173
174
|
summary: Adds an update-interactive command to Bundler
|