ra10ke 4.5.0 → 4.5.1

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: ea18d86c034c89c78111ffadc6f2a3612332c9a8715275b957e3367d5c4a3d06
4
- data.tar.gz: d7e12ba7bbc9a444c5a94d95c2e7421e0e632316ad6ce920a0152397510504c9
3
+ metadata.gz: e89462c238286812deefe1c66b23bd3458f10f68545f19394cda6e5cae239fa3
4
+ data.tar.gz: be70614d1b793aaae4e3e9151186709b70d68506687b3a3590f6e79ed6fe4298
5
5
  SHA512:
6
- metadata.gz: 862eff9a48ac411815d92e71c01f12448d8d2b8d348ec0de709a8026d6617a8f7688161a15f294bb08dad75325853884fea3abd0e847d13a16129593f8438149
7
- data.tar.gz: 756ad73f768fdd94ef42268769fbb4fe37b47e342e3ecfa811ceda820276bd787aaaaf381131f49e54961562fcade747f7e1784e209933ff569a96060ff5e462
6
+ metadata.gz: 95bbe0ab0fea1b2598c75f4e0f7cfee5c1b77acc457574bd55627bd584d9a9ae2b0360f6bb70fcafb8b4df03559b05d63db2ee5abc1f8364276e126ddfaae047
7
+ data.tar.gz: 0c1d340000c757922d5929b27f61d814c4d7a1b8c1c7220d2a4bd50ba30f42c66bec026eb959bb03b74169ff567a6ec409a0c0c2ac357aa5744e86fbe2dce287
@@ -15,7 +15,7 @@ jobs:
15
15
  name: Build the gem
16
16
  runs-on: ubuntu-24.04
17
17
  steps:
18
- - uses: actions/checkout@v5
18
+ - uses: actions/checkout@v6
19
19
  - name: Install Ruby
20
20
  uses: ruby/setup-ruby@v1
21
21
  with:
@@ -24,7 +24,7 @@ jobs:
24
24
  shell: bash
25
25
  run: gem build --verbose *.gemspec
26
26
  - name: Upload gem to GitHub cache
27
- uses: actions/upload-artifact@v4
27
+ uses: actions/upload-artifact@v7
28
28
  with:
29
29
  name: gem-artifact
30
30
  path: '*.gem'
@@ -39,7 +39,7 @@ jobs:
39
39
  contents: write # clone repo and create release
40
40
  steps:
41
41
  - name: Download gem from GitHub cache
42
- uses: actions/download-artifact@v5
42
+ uses: actions/download-artifact@v8
43
43
  with:
44
44
  name: gem-artifact
45
45
  - name: Create Release
@@ -56,7 +56,7 @@ jobs:
56
56
  packages: write # publish to rubygems.pkg.github.com
57
57
  steps:
58
58
  - name: Download gem from GitHub cache
59
- uses: actions/download-artifact@v5
59
+ uses: actions/download-artifact@v8
60
60
  with:
61
61
  name: gem-artifact
62
62
  - name: Publish gem to GitHub packages
@@ -73,10 +73,10 @@ jobs:
73
73
  id-token: write # rubygems.org authentication
74
74
  steps:
75
75
  - name: Download gem from GitHub cache
76
- uses: actions/download-artifact@v5
76
+ uses: actions/download-artifact@v8
77
77
  with:
78
78
  name: gem-artifact
79
- - uses: rubygems/configure-rubygems-credentials@v1.0.0
79
+ - uses: rubygems/configure-rubygems-credentials@v2.0.0
80
80
  - name: Publish gem to rubygems.org
81
81
  shell: bash
82
82
  run: gem push *.gem
@@ -92,7 +92,7 @@ jobs:
92
92
  - release-to-rubygems
93
93
  steps:
94
94
  - name: Download gem from GitHub cache
95
- uses: actions/download-artifact@v5
95
+ uses: actions/download-artifact@v8
96
96
  with:
97
97
  name: gem-artifact
98
98
  - name: Install Ruby
@@ -16,7 +16,7 @@ jobs:
16
16
  outputs:
17
17
  ruby: ${{ steps.ruby.outputs.versions }}
18
18
  steps:
19
- - uses: actions/checkout@v5
19
+ - uses: actions/checkout@v6
20
20
  - name: Install Ruby ${{ matrix.ruby }}
21
21
  uses: ruby/setup-ruby@v1
22
22
  with:
@@ -25,7 +25,7 @@ jobs:
25
25
  - name: Run Rubocop
26
26
  run: bundle exec rake rubocop
27
27
  - id: ruby
28
- uses: voxpupuli/ruby-version@v1
28
+ uses: voxpupuli/ruby-version@v2
29
29
  test:
30
30
  runs-on: ubuntu-latest
31
31
  needs: rubocop_and_matrix
@@ -35,7 +35,7 @@ jobs:
35
35
  ruby: ${{ fromJSON(needs.rubocop_and_matrix.outputs.ruby) }}
36
36
  name: Ruby ${{ matrix.ruby }}
37
37
  steps:
38
- - uses: actions/checkout@v5
38
+ - uses: actions/checkout@v6
39
39
  - name: Install Ruby ${{ matrix.ruby }}
40
40
  uses: ruby/setup-ruby@v1
41
41
  with:
data/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [v4.5.1](https://github.com/voxpupuli/ra10ke/tree/v4.5.1) (2026-05-11)
6
+
7
+ [Full Changelog](https://github.com/voxpupuli/ra10ke/compare/v4.5.0...v4.5.1)
8
+
9
+ **Fixed bugs:**
10
+
11
+ - fix: process git modules before Forge modules to prevent dependency conflicts [\#145](https://github.com/voxpupuli/ra10ke/pull/145) ([bastelfreak](https://github.com/bastelfreak))
12
+
13
+ **Closed issues:**
14
+
15
+ - r10k:solve\_dependencies pulls in outdated constraints from last forge release as implicit dependency instead of explicit git module [\#128](https://github.com/voxpupuli/ra10ke/issues/128)
16
+
5
17
  ## [v4.5.0](https://github.com/voxpupuli/ra10ke/tree/v4.5.0) (2025-10-16)
6
18
 
7
19
  [Full Changelog](https://github.com/voxpupuli/ra10ke/compare/v4.4.0...v4.5.0)
data/Gemfile CHANGED
@@ -5,5 +5,5 @@ gemspec
5
5
 
6
6
  group :release, optional: true do
7
7
  gem 'faraday-retry', '~> 2.1', require: false
8
- gem 'github_changelog_generator', '~> 1.16.4', require: false
8
+ gem 'github_changelog_generator', '~> 1.18', require: false
9
9
  end
data/lib/ra10ke/solve.rb CHANGED
@@ -50,38 +50,26 @@ module Ra10ke::Solve
50
50
  # List of modules we have in the Puppetfile, as [name, version] pairs
51
51
  @current_modules = []
52
52
 
53
+ # Single pass: partition modules into git/Forge arrays and simultaneously seed
54
+ # @processed_modules with all git module names. Seeding upfront prevents
55
+ # add_reqs_to_graph from fetching Forge releases for any git module encountered
56
+ # as a transitive dependency, regardless of declaration order in the Puppetfile.
57
+ git_modules = []
58
+ forge_modules = []
53
59
  puppetfile.modules.each do |puppet_module|
54
60
  next if ignore_modules.include? puppet_module.title
55
61
 
56
62
  if puppet_module.instance_of?(R10K::Module::Forge)
57
- module_name = puppet_module.title.tr('/', '-')
58
- installed_version = puppet_module.expected_version
59
- puts "Processing Forge module #{module_name}-#{installed_version}"
60
- @current_modules << [module_name, installed_version]
61
- @graph.artifact(module_name, installed_version)
62
- constraint = '>=0.0.0'
63
- unless allow_major_bump
64
- ver = Semverse::Version.new installed_version
65
- if ver.major.zero?
66
- constraint = "~>#{installed_version}"
67
- else
68
- nver = Semverse::Version.new([ver.major + 1, 0, 0])
69
- constraint = "<#{nver}"
70
- end
71
- end
72
- puts "...Adding a demand: #{module_name} #{constraint}"
73
-
74
- @demands.add([module_name, constraint])
75
- puts '...Fetching latest release version information'
76
- forge_rel = PuppetForge::Module.find(module_name).current_release
77
- mod = @graph.artifact(module_name, forge_rel.version)
78
- puts '...Adding its requirements to the graph'
79
- meta = get_release_metadata(module_name, forge_rel)
80
- add_reqs_to_graph(mod, meta)
63
+ forge_modules << puppet_module
64
+ elsif puppet_module.instance_of?(R10K::Module::Git)
65
+ @processed_modules.add(puppet_module.title.tr('/', '-'))
66
+ git_modules << puppet_module
81
67
  end
68
+ end
82
69
 
83
- next unless puppet_module.instance_of?(R10K::Module::Git)
84
-
70
+ # Process git modules first so their metadata populates the graph before
71
+ # any Forge module's transitive dependencies are resolved.
72
+ git_modules.each do |puppet_module|
85
73
  # This downloads the git module to modules/modulename
86
74
  meta = fetch_git_metadata(puppet_module)
87
75
  version = get_key_or_sym(meta, :version)
@@ -95,6 +83,35 @@ module Ra10ke::Solve
95
83
  puts "...Adding requirements for git module #{module_name}-#{version}"
96
84
  add_reqs_to_graph(mod, meta)
97
85
  end
86
+
87
+ # Process Forge modules. Any git module already in @processed_modules will
88
+ # be skipped by add_reqs_to_graph when encountered as a transitive dependency.
89
+ forge_modules.each do |puppet_module|
90
+ module_name = puppet_module.title.tr('/', '-')
91
+ installed_version = puppet_module.expected_version
92
+ puts "Processing Forge module #{module_name}-#{installed_version}"
93
+ @current_modules << [module_name, installed_version]
94
+ @graph.artifact(module_name, installed_version)
95
+ constraint = '>=0.0.0'
96
+ unless allow_major_bump
97
+ ver = Semverse::Version.new installed_version
98
+ if ver.major.zero?
99
+ constraint = "~>#{installed_version}"
100
+ else
101
+ nver = Semverse::Version.new([ver.major + 1, 0, 0])
102
+ constraint = "<#{nver}"
103
+ end
104
+ end
105
+ puts "...Adding a demand: #{module_name} #{constraint}"
106
+
107
+ @demands.add([module_name, constraint])
108
+ puts '...Fetching latest release version information'
109
+ forge_rel = PuppetForge::Module.find(module_name).current_release
110
+ mod = @graph.artifact(module_name, forge_rel.version)
111
+ puts '...Adding its requirements to the graph'
112
+ meta = get_release_metadata(module_name, forge_rel)
113
+ add_reqs_to_graph(mod, meta)
114
+ end
98
115
  puts
99
116
  puts 'Resolving dependencies...'
100
117
  puts 'WARNING: Potentially breaking updates are allowed for this resolution' if allow_major_bump
@@ -1,3 +1,3 @@
1
1
  module Ra10ke
2
- VERSION = '4.5.0'
2
+ VERSION = '4.5.1'
3
3
  end
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec::Mocks.configuration.allow_message_expectations_on_nil = true
6
+
7
+ RSpec.describe Ra10ke::Solve do
8
+ # Minimal helper class that mixes in the module so we can test its private methods.
9
+ let(:instance) do
10
+ klass = Class.new do
11
+ include Ra10ke::Solve
12
+
13
+ # Expose private helpers for direct testing.
14
+ public :get_key_or_sym, :get_version_req, :print_module_diff, :add_reqs_to_graph
15
+
16
+ def initialize
17
+ @graph = Solve::Graph.new
18
+ @processed_modules = Set.new
19
+ @demands = Set.new
20
+ # @metadata_cache is intentionally left nil here; tests that need it
21
+ # set it via instance_variable_set in a before block.
22
+ end
23
+ end
24
+ klass.new
25
+ end
26
+
27
+ let(:processed_modules) { instance.instance_variable_get(:@processed_modules) }
28
+ let(:demands) { instance.instance_variable_get(:@demands) }
29
+ let(:graph) { instance.instance_variable_get(:@graph) }
30
+
31
+ # -------------------------------------------------------------------------
32
+ describe '#get_key_or_sym' do
33
+ it 'fetches a value by symbol key' do
34
+ expect(instance.get_key_or_sym({ version: '1.0.0' }, :version)).to eq('1.0.0')
35
+ end
36
+
37
+ it 'fetches a value by string key when only the string form is present' do
38
+ expect(instance.get_key_or_sym({ 'version' => '2.0.0' }, :version)).to eq('2.0.0')
39
+ end
40
+
41
+ it 'prefers the symbol key over the string key when both are present' do
42
+ expect(instance.get_key_or_sym({ version: 'sym', 'version' => 'str' }, :version)).to eq('sym')
43
+ end
44
+
45
+ it 'returns nil when the key is absent in both forms' do
46
+ expect(instance.get_key_or_sym({}, :version)).to be_nil
47
+ end
48
+ end
49
+
50
+ # -------------------------------------------------------------------------
51
+ describe '#get_version_req' do
52
+ it 'returns version_requirement when present' do
53
+ expect(instance.get_version_req({ version_requirement: '>= 1.0.0' })).to eq('>= 1.0.0')
54
+ end
55
+
56
+ it 'falls back to version_range when version_requirement is absent' do
57
+ expect(instance.get_version_req({ version_range: '>= 2.0.0' })).to eq('>= 2.0.0')
58
+ end
59
+
60
+ it 'returns nil when neither key is present' do
61
+ expect(instance.get_version_req({})).to be_nil
62
+ end
63
+
64
+ it 'works with string keys' do
65
+ expect(instance.get_version_req({ 'version_requirement' => '~> 3.0' })).to eq('~> 3.0')
66
+ end
67
+ end
68
+
69
+ # -------------------------------------------------------------------------
70
+ describe '#print_module_diff' do
71
+ it 'reports OUTDATED for a module whose version has changed' do
72
+ expect do
73
+ instance.print_module_diff([['foo-bar', '1.0.0']], [['foo-bar', '2.0.0']])
74
+ end.to output(/OUTDATED.*foo-bar.*1\.0\.0.*2\.0\.0/).to_stdout
75
+ end
76
+
77
+ it 'reports MISSING for a module present in the resolution but not in current' do
78
+ expect do
79
+ instance.print_module_diff([], [['missing-mod', '1.2.3']])
80
+ end.to output(/MISSING.*missing-mod.*1\.2\.3/).to_stdout
81
+ end
82
+
83
+ it 'produces no output when all modules are up to date' do
84
+ expect do
85
+ instance.print_module_diff([['foo-bar', '1.0.0']], [['foo-bar', '1.0.0']])
86
+ end.not_to output.to_stdout
87
+ end
88
+
89
+ it 'reports all outdated modules in a single pass' do
90
+ current = [['aaa-one', '1.0.0'], ['bbb-two', '2.0.0']]
91
+ resolution = [['aaa-one', '1.1.0'], ['bbb-two', '2.1.0']]
92
+ expect do
93
+ instance.print_module_diff(current, resolution)
94
+ end.to output(/aaa-one.*bbb-two/m).to_stdout
95
+ end
96
+ end
97
+
98
+ # -------------------------------------------------------------------------
99
+ describe '#add_reqs_to_graph' do
100
+ let(:artifact) { graph.artifact('mymod', '1.0.0') }
101
+
102
+ context 'when the dependency is already in @processed_modules' do
103
+ before { processed_modules.add('puppetlabs-stdlib') }
104
+
105
+ it 'does not attempt a Forge lookup' do
106
+ meta = { name: 'mymod', dependencies: [{ name: 'puppetlabs/stdlib', version_requirement: '>= 4.0.0' }] }
107
+ expect(PuppetForge::Module).not_to receive(:find)
108
+ instance.add_reqs_to_graph(artifact, meta)
109
+ end
110
+
111
+ it 'adds the dependency name to @demands' do
112
+ meta = { name: 'mymod', dependencies: [{ name: 'puppetlabs/stdlib', version_requirement: '>= 4.0.0' }] }
113
+ instance.add_reqs_to_graph(artifact, meta)
114
+ expect(demands).to include('puppetlabs-stdlib')
115
+ end
116
+
117
+ it 'records the version constraint on the artifact' do
118
+ meta = { name: 'mymod', dependencies: [{ name: 'puppetlabs/stdlib', version_requirement: '>= 4.0.0' }] }
119
+ instance.add_reqs_to_graph(artifact, meta)
120
+ dep = artifact.dependencies.find { |d| d.name == 'puppetlabs-stdlib' }
121
+ expect(dep).not_to be_nil
122
+ expect(dep.constraint.to_s).to eq('>= 4.0.0')
123
+ end
124
+ end
125
+
126
+ context 'when no_demands flag is set' do
127
+ before { processed_modules.add('puppetlabs-stdlib') }
128
+
129
+ it 'does not add the dependency to @demands' do
130
+ meta = { name: 'mymod', dependencies: [{ name: 'puppetlabs/stdlib', version_requirement: '>= 4.0.0' }] }
131
+ instance.add_reqs_to_graph(artifact, meta, :no_demands)
132
+ expect(demands).not_to include('puppetlabs-stdlib')
133
+ end
134
+ end
135
+
136
+ context 'when dependency has an invalid version constraint' do
137
+ before { processed_modules.add('puppetlabs-badmod') }
138
+
139
+ it 'prints a warning and continues without raising' do
140
+ meta = { name: 'mymod', dependencies: [{ name: 'puppetlabs/badmod', version_requirement: 'not_valid' }] }
141
+ expect do
142
+ instance.add_reqs_to_graph(artifact, meta)
143
+ end.to output(/WARNING.*Invalid version constraint/).to_stdout
144
+ end
145
+ end
146
+
147
+ context 'when dependency has no version constraint' do
148
+ before { processed_modules.add('puppetlabs-nover') }
149
+
150
+ it 'falls back to >=0.0.0 and does not raise' do
151
+ meta = { name: 'mymod', dependencies: [{ name: 'puppetlabs/nover' }] }
152
+ expect { instance.add_reqs_to_graph(artifact, meta) }.not_to raise_error
153
+ dep = artifact.dependencies.find { |d| d.name == 'puppetlabs-nover' }
154
+ expect(dep.constraint.to_s).to eq('>= 0.0.0')
155
+ end
156
+ end
157
+
158
+ context 'when dependency has a compound constraint (>=x <y)' do
159
+ before { processed_modules.add('puppetlabs-compound') }
160
+
161
+ it 'records both bounds on the artifact' do
162
+ meta = {
163
+ name: 'mymod',
164
+ dependencies: [{ name: 'puppetlabs/compound', version_requirement: '>= 4.0.0 <9.0.0' }],
165
+ }
166
+ instance.add_reqs_to_graph(artifact, meta)
167
+ constraints = artifact.dependencies.select { |d| d.name == 'puppetlabs-compound' }
168
+ .map { |d| d.constraint.to_s }
169
+ expect(constraints).to include('>= 4.0.0')
170
+ expect(constraints).to include('< 9.0.0')
171
+ end
172
+ end
173
+ end
174
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ra10ke
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.5.0
4
+ version: 4.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Theo Chatzimichos
@@ -213,6 +213,7 @@ files:
213
213
  - spec/ra10ke/duplicates_spec.rb
214
214
  - spec/ra10ke/git_repo_spec.rb
215
215
  - spec/ra10ke/puppetfile_parser_spec.rb
216
+ - spec/ra10ke/solve_spec.rb
216
217
  - spec/ra10ke/validate_spec.rb
217
218
  - spec/ra10ke_spec.rb
218
219
  - spec/spec_helper.rb
@@ -234,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
234
235
  - !ruby/object:Gem::Version
235
236
  version: '0'
236
237
  requirements: []
237
- rubygems_version: 3.6.9
238
+ rubygems_version: 4.0.6
238
239
  specification_version: 4
239
240
  summary: Syntax check for the Puppetfile, check for outdated installed puppet modules
240
241
  test_files: []