gem_changelog_diff 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 05a598faafc36b6f7a81836a1454668ab885425c63f8efa6b019190efc3c1614
4
- data.tar.gz: 4f9eeeb3664f4ebde09921007292a2ad1af06caa0a2d738de04e6d6b28b67551
3
+ metadata.gz: 47e69603bad8c0641ed060fc572632c76d014dcc09f98d75322cafceefa4a1a2
4
+ data.tar.gz: beb52279aac1a12e5da0e19ce981d5b7bfa497a385130de9a7503cc4ac871742
5
5
  SHA512:
6
- metadata.gz: 1544e2ec1db09d8dc3f34a7a24e69d55b9f7b7cbd8a5730aaa85faa94778e87de3551686912e0c83554204af3926b4b358eef0b86b5533ad952d8a11a170b88c
7
- data.tar.gz: bdfe56aa40447f182fa846015d653570990308a3375d4edb25f8398dcbc5caa90abfbcf4d37383f391a93ba6b446a48f123410fa55e18e4a33fb47ed075d34f7
6
+ metadata.gz: e5fa45dae9504354720cafa62e7e05768b58de06d1b0376496ba3e38b74b05dc7a23b10b3ca00338acca5e38ce2f29f17495d040d508fe6f14e03515cdf33a02
7
+ data.tar.gz: 537bea10e8961bff3b2d2c55530afcbe0de4fd0ab422c224b4d7b821edfe264821cb683e3d2a242d29cd551779d15a6c480e4269795347a25f190b59e56e886d
data/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.0] - 2026-06-18
11
+
12
+ ### Added
13
+
14
+ - `Gemfile.lock` parsing via `Bundler::LockfileParser` with RubyGems API version lookup
15
+ - Automatic fallback to lockfile parsing when `bundle outdated` is unavailable
16
+ - `--strategy` flag: `auto` (default), `outdated`, or `lockfile`
17
+ - `--lockfile` flag for custom lockfile path
18
+ - Positional arguments to inspect specific gems: `gem_changelog_diff check rails sidekiq`
19
+ - `--group` flag to filter by Bundler group
20
+ - `--ignore` flag to exclude specific gems
21
+
10
22
  ## [0.3.0] - 2026-06-18
11
23
 
12
24
  ### Added
@@ -41,7 +53,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
41
53
  - Plain text formatter for changelog output
42
54
  - Full end-to-end pipeline: detect → lookup → fetch → format
43
55
 
44
- [Unreleased]: https://github.com/eclectic-coding/gem_changelog_diff/compare/v0.3.0...HEAD
56
+ [Unreleased]: https://github.com/eclectic-coding/gem_changelog_diff/compare/v0.4.0...HEAD
57
+ [0.4.0]: https://github.com/eclectic-coding/gem_changelog_diff/releases/tag/v0.4.0
45
58
  [0.3.0]: https://github.com/eclectic-coding/gem_changelog_diff/releases/tag/v0.3.0
46
59
  [0.2.0]: https://github.com/eclectic-coding/gem_changelog_diff/releases/tag/v0.2.0
47
60
  [0.1.0]: https://github.com/eclectic-coding/gem_changelog_diff/releases/tag/v0.1.0
data/README.md CHANGED
@@ -14,6 +14,8 @@ CLI that shows you the changelog diff for each gem before you `bundle update`, p
14
14
  - [Usage](#usage)
15
15
  - [GitHub Authentication](#github-authentication)
16
16
  - [Output Control](#output-control)
17
+ - [Detection Strategy](#detection-strategy)
18
+ - [Filtering](#filtering)
17
19
  - [Development](#development)
18
20
  - [Contributing](#contributing)
19
21
  - [License](#license)
@@ -68,6 +70,23 @@ gem_changelog_diff --no-color # Disable colored output
68
70
 
69
71
  The tool also respects the `$NO_COLOR` environment variable.
70
72
 
73
+ ### Detection Strategy
74
+
75
+ ```bash
76
+ gem_changelog_diff --strategy lockfile # Parse Gemfile.lock directly
77
+ gem_changelog_diff --strategy outdated # Use bundle outdated only
78
+ gem_changelog_diff --strategy auto # Try bundle outdated, fallback to lockfile (default)
79
+ gem_changelog_diff --lockfile path/to/Gemfile.lock # Custom lockfile path
80
+ ```
81
+
82
+ ### Filtering
83
+
84
+ ```bash
85
+ gem_changelog_diff check rails sidekiq # Only check specific gems
86
+ gem_changelog_diff --group development # Filter by Bundler group
87
+ gem_changelog_diff --ignore rails rake # Exclude specific gems
88
+ ```
89
+
71
90
  [Back to top](#gemchangelogdiff)
72
91
 
73
92
  ## Development
data/ROADMAP.md CHANGED
@@ -2,19 +2,6 @@
2
2
 
3
3
  Feature roadmap for gem_changelog_diff. Each section is auto-pruned by `bin/release` when that version ships.
4
4
 
5
- ## 0.4.0 -- Lockfile Parsing Fallback & Filtering
6
-
7
- Support environments where `bundle outdated` is unavailable. Let users narrow which gems to inspect.
8
-
9
- - Parse `Gemfile.lock` directly via `Bundler::LockfileParser` and query RubyGems API for latest versions
10
- - Automatic fallback when `bundle outdated` fails
11
- - Positional args to inspect specific gems: `gem_changelog_diff check rails sidekiq`
12
- - `--group`, `--ignore`, `--lockfile`, `--strategy` flags
13
-
14
- **New files:** `lockfile_parser.rb`
15
-
16
- ---
17
-
18
5
  ## 0.5.0 -- Caching & Performance
19
6
 
20
7
  Avoid redundant API calls. Make repeated runs fast on large dependency trees.
@@ -14,11 +14,16 @@ module GemChangelogDiff
14
14
  class_option :verbose, type: :boolean, default: false, desc: "Show detailed output"
15
15
  class_option :quiet, type: :boolean, default: false, desc: "Suppress warnings"
16
16
  class_option :no_color, type: :boolean, default: false, desc: "Disable colored output"
17
+ class_option :lockfile, type: :string, desc: "Path to Gemfile.lock"
18
+ class_option :strategy, type: :string, default: "auto", desc: "Detection strategy (auto, outdated, lockfile)"
19
+ class_option :group, type: :string, desc: "Filter by Bundler group"
20
+ class_option :ignore, type: :array, desc: "Gems to skip"
17
21
 
18
- desc "check", "Show changelog diffs for outdated gems"
19
- def check
22
+ desc "check [GEM...]", "Show changelog diffs for outdated gems"
23
+ def check(*gem_names)
20
24
  configure_token
21
- gems = Detector.new.detect
25
+ gems = detect_gems
26
+ gems = filter_gems(gems, gem_names)
22
27
 
23
28
  if gems.empty?
24
29
  say "All gems are up to date!"
@@ -44,6 +49,39 @@ module GemChangelogDiff
44
49
  GemChangelogDiff.configuration.github_token = token if token
45
50
  end
46
51
 
52
+ def detect_gems
53
+ case options[:strategy]
54
+ when "lockfile"
55
+ detect_via_lockfile
56
+ when "outdated"
57
+ Detector.new(group: options[:group]).detect
58
+ else
59
+ detect_with_fallback
60
+ end
61
+ end
62
+
63
+ def detect_with_fallback
64
+ Detector.new(group: options[:group]).detect
65
+ rescue Error
66
+ log_warning " bundle outdated failed, falling back to lockfile parsing..."
67
+ detect_via_lockfile
68
+ end
69
+
70
+ def detect_via_lockfile
71
+ lockfile_path = options[:lockfile] || "Gemfile.lock"
72
+ LockfileParser.new.detect(lockfile_path: lockfile_path)
73
+ end
74
+
75
+ def filter_gems(gems, gem_names)
76
+ gems = gems.select { |g| gem_names.include?(g.name) } if gem_names.any?
77
+ gems = gems.reject { |g| ignore_list.include?(g.name) } if ignore_list.any?
78
+ gems
79
+ end
80
+
81
+ def ignore_list
82
+ @ignore_list ||= options[:ignore] || []
83
+ end
84
+
47
85
  def build_reports(gems)
48
86
  rubygems_client = RubygemsClient.new
49
87
  source_resolver = SourceResolver.new
@@ -13,8 +13,15 @@ module GemChangelogDiff
13
13
 
14
14
  private
15
15
 
16
+ def initialize(group: nil)
17
+ @group = group
18
+ end
19
+
16
20
  def run_bundle_outdated
17
- output, status = Open3.capture2("bundle", "outdated", "--parseable")
21
+ cmd = ["bundle", "outdated", "--parseable"]
22
+ cmd.push("--group", @group) if @group
23
+
24
+ output, status = Open3.capture2(*cmd)
18
25
  raise Error, "bundle outdated failed (exit #{status.exitstatus})" unless [0, 1].include?(status.exitstatus)
19
26
 
20
27
  output
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler"
4
+
5
+ module GemChangelogDiff
6
+ class LockfileParser
7
+ def initialize(rubygems_client: RubygemsClient.new)
8
+ @rubygems_client = rubygems_client
9
+ end
10
+
11
+ def detect(lockfile_path: "Gemfile.lock")
12
+ content = File.read(lockfile_path)
13
+ parser = Bundler::LockfileParser.new(content)
14
+ find_outdated(parser.specs)
15
+ rescue Errno::ENOENT
16
+ raise Error, "Lockfile not found: #{lockfile_path}"
17
+ end
18
+
19
+ private
20
+
21
+ def find_outdated(specs)
22
+ specs.filter_map { |spec| check_gem(spec) }
23
+ end
24
+
25
+ def check_gem(spec)
26
+ latest = @rubygems_client.latest_version(spec.name)
27
+ return nil unless latest
28
+
29
+ latest_version = Gem::Version.new(latest)
30
+ return nil unless latest_version > spec.version
31
+
32
+ OutdatedGem.new(
33
+ name: spec.name,
34
+ current_version: spec.version.to_s,
35
+ newest_version: latest
36
+ )
37
+ end
38
+ end
39
+ end
@@ -9,19 +9,30 @@ module GemChangelogDiff
9
9
  GITHUB_REPO_REGEX = %r{github\.com/([^/]+)/([^/]+)}
10
10
 
11
11
  def repo_url(gem_name)
12
+ data = fetch_gem_data(gem_name)
13
+ return nil unless data
14
+
15
+ extract_github_repo(data)
16
+ end
17
+
18
+ def latest_version(gem_name)
19
+ data = fetch_gem_data(gem_name)
20
+ data&.dig("version")
21
+ end
22
+
23
+ private
24
+
25
+ def fetch_gem_data(gem_name)
12
26
  uri = URI(format(RUBYGEMS_API, name: gem_name))
13
27
  response = Net::HTTP.get_response(uri)
14
28
  return nil unless response.is_a?(Net::HTTPSuccess)
15
29
 
16
- data = JSON.parse(response.body)
17
- extract_github_repo(data)
30
+ JSON.parse(response.body)
18
31
  rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH,
19
32
  Net::OpenTimeout, Net::ReadTimeout => e
20
33
  raise NetworkError, "RubyGems API request failed: #{e.message}"
21
34
  end
22
35
 
23
- private
24
-
25
36
  def extract_github_repo(data)
26
37
  %w[source_code_uri homepage_uri bug_tracker_uri].each do |field|
27
38
  url = data[field]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GemChangelogDiff
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -11,6 +11,7 @@ require_relative "gem_changelog_diff/errors"
11
11
  require_relative "gem_changelog_diff/outdated_gem"
12
12
  require_relative "gem_changelog_diff/detector"
13
13
  require_relative "gem_changelog_diff/rubygems_client"
14
+ require_relative "gem_changelog_diff/lockfile_parser"
14
15
  require_relative "gem_changelog_diff/github_client"
15
16
  require_relative "gem_changelog_diff/changelog_parser"
16
17
  require_relative "gem_changelog_diff/source_resolver"
@@ -37,6 +37,7 @@ module GemChangelogDiff
37
37
  class Detector
38
38
  PARSEABLE_REGEX: Regexp
39
39
 
40
+ def initialize: (?group: String?) -> void
40
41
  def detect: () -> Array[OutdatedGem]
41
42
 
42
43
  private
@@ -50,12 +51,24 @@ module GemChangelogDiff
50
51
  GITHUB_REPO_REGEX: Regexp
51
52
 
52
53
  def repo_url: (String gem_name) -> String?
54
+ def latest_version: (String gem_name) -> String?
53
55
 
54
56
  private
55
57
 
58
+ def fetch_gem_data: (String gem_name) -> Hash[String, untyped]?
56
59
  def extract_github_repo: (Hash[String, untyped] data) -> String?
57
60
  end
58
61
 
62
+ class LockfileParser
63
+ def initialize: (?rubygems_client: RubygemsClient) -> void
64
+ def detect: (?lockfile_path: String) -> Array[OutdatedGem]
65
+
66
+ private
67
+
68
+ def find_outdated: (Array[untyped] specs) -> Array[OutdatedGem]
69
+ def check_gem: (untyped spec) -> OutdatedGem?
70
+ end
71
+
59
72
  type release_hash = {
60
73
  tag_name: String,
61
74
  name: String?,
@@ -143,6 +156,11 @@ module GemChangelogDiff
143
156
 
144
157
  def color_enabled?: () -> bool
145
158
  def configure_token: () -> void
159
+ def detect_gems: () -> Array[OutdatedGem]
160
+ def detect_with_fallback: () -> Array[OutdatedGem]
161
+ def detect_via_lockfile: () -> Array[OutdatedGem]
162
+ def filter_gems: (Array[OutdatedGem] gems, Array[String] gem_names) -> Array[OutdatedGem]
163
+ def ignore_list: () -> Array[String]
146
164
  def build_reports: (Array[OutdatedGem] gems) -> Array[gem_report]
147
165
  def build_gem_report: (OutdatedGem gem, RubygemsClient rubygems_client, SourceResolver source_resolver) -> gem_report
148
166
  def log: (String message) -> void
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gem_changelog_diff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chuck Smith
@@ -64,6 +64,7 @@ files:
64
64
  - lib/gem_changelog_diff/errors.rb
65
65
  - lib/gem_changelog_diff/formatter.rb
66
66
  - lib/gem_changelog_diff/github_client.rb
67
+ - lib/gem_changelog_diff/lockfile_parser.rb
67
68
  - lib/gem_changelog_diff/outdated_gem.rb
68
69
  - lib/gem_changelog_diff/rubygems_client.rb
69
70
  - lib/gem_changelog_diff/source_resolver.rb