(CAT-2589) Add Ruby 4.0 / Puppet 9 lane, source gems from puppetcore - #385
Open
LukasAud wants to merge 15 commits into
Open
(CAT-2589) Add Ruby 4.0 / Puppet 9 lane, source gems from puppetcore#385LukasAud wants to merge 15 commits into
LukasAud wants to merge 15 commits into
Conversation
Adds a ruby_version: '4.0' / puppet_version: '~> 9.0' matrix entry to the spec and acceptance jobs in ci.yml and nightly.yml, alongside the existing 3.2 / puppet 8 lane. Updates the Gemfile to source the puppet gem from rubygems-puppetcore.puppet.com when PUPPET_FORGE_TOKEN is set, and bumps puppetlabs_spec_helper to ~> 9.0 to pick up the CVE-fixed puppetlabs-syntax fork. Mirrors puppetlabs_spec_helper@3bfa7d21.
The reusable gem_ci.yml workflow injects PUPPET_FORGE_TOKEN as an empty string (not omitted) when the secret isn't configured. Ruby treats "" as truthy, so the bare `if ENV['PUPPET_FORGE_TOKEN']` check routed puppet resolution to the private puppetcore gem source with no actual credentials, failing bundle install with "Bad username or password" on every CI lane.
puppetlabs_spec_helper >= 9.0.0 depends on puppet-lint ~> 5.0, which conflicts with the previously pinned voxpupuli-puppet-lint-plugins ~> 5.0 (depends on puppet-lint ~> 4.0). voxpupuli-puppet-lint-plugins 7.0.0 depends on puppet-lint ~> 5.1, which resolves cleanly. Verified locally: `bundle lock` now succeeds for the existing ruby 3.2 / puppet ~> 8.0 lane.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #385 +/- ##
==========================================
- Coverage 90.99% 88.98% -2.02%
==========================================
Files 6 6
Lines 733 853 +120
==========================================
+ Hits 667 759 +92
- Misses 66 94 +28 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
rspec-puppet-facts < 5.4.0 depends on puppet >= 7, < 9, which conflicts with the new Gemfile's puppet ~> 9.0 branch. 6.x dropped the direct puppet dependency entirely (now depends on facterdb >= 3.1, < 5.0 and openfact ~> 5.0 instead), so bumping clears the conflict. facterdb bumped to ~> 4.0 to satisfy 6.x's floor; not referenced directly anywhere in ruby-pwsh's own spec code. Verified locally: `bundle lock` resolves cleanly for the ruby 3.2 / puppet ~> 8.0 lane with these versions.
puppet_litmus ~> 1.0 pulled in an old bolt (4.0.0 via orchestrator_client 0.7.2 -> faraday 1.9.0 -> faraday-patron -> patron), whose native C extension (patron, a libcurl wrapper) fails to build on Ruby 4.0. puppet_litmus is not referenced anywhere in this repo's own spec code or Rakefile (dead weight in the system_tests group), so bumping is low-risk. 2.8.0 resolves via a modern orchestrator_client/faraday 2.x stack with no native-extension dependency. Verified locally: `bundle lock` resolves cleanly for the ruby 3.2 / puppet ~> 8.0 lane, and the puppet ~> 9.0 lane no longer conflicts on anything other than requiring the private puppetcore gem source.
orchestrator_client (pulled in via bolt <- puppet_litmus) allows faraday >= 1.4, < 3.0. When resolving alongside a real puppet ~> 9.0 candidate from puppetcore, Bundler's resolver backtracks to faraday 1.9.0 instead of 2.x. Faraday 1.x's gemspec bundles faraday-patron (a native libcurl-wrapping extension) as a hard runtime dependency, which fails to build on Ruby 4.0. Pinning faraday directly forces the resolver onto the 2.x branch regardless of solver ordering; faraday 2.x's adapters are fully optional, so faraday-patron/patron never enters the graph. Local `bundle lock` can't fully validate this against real puppet 9.x metadata (only available via the private puppetcore source), so this is verified against the ruby 3.2 / puppet ~> 8.0 lane locally and relies on CI for confirmation on the ruby 4.0 / puppet ~> 9.0 lane.
puppet_litmus is not referenced anywhere in this repo's code, specs, or Rakefile -- the actual acceptance task (spec/acceptance/dsc/*.rb, namespace :acceptance in Rakefile) uses plain RSpec with a hand-rolled DSC-module vendoring step, not litmus/bolt provisioning. puppet_litmus -> bolt -> r10k -> puppet_forge forms an intractable dependency conflict on Ruby 4.0: bolt's r10k/puppet_forge chain forces faraday < 2.0 unless a newer puppet_forge (>= 4.0.0) is used, but that newer puppet_forge hard-pins faraday-follow_redirects ~> 0.3.0, and versions of faraday-follow_redirects below 0.5.0 refuse to run on Ruby 4.0 at all. No combination of version pins satisfies this. Since the gem is unused, removing it (and the now-unnecessary faraday pin from the previous commit) is simpler and more correct than trying to force a resolution through an unused dependency's broken chain. Verified locally: `bundle lock` resolves cleanly for the ruby 3.2 / puppet ~> 8.0 lane, with bolt/r10k/patron/puppet_litmus fully absent from the graph.
lib/pwsh.rb requires 'rexml/document' directly, but rexml was never declared as a dependency anywhere -- it was only ever satisfied as an accidental transitive dependency pulled in via puppet_litmus's bolt/ r10k chain. Removing puppet_litmus in the previous commit surfaced this: `cannot load such file -- rexml/document` on every spec run, since rexml is a Ruby "default gem" that Bundler's isolation won't fall back to unless explicitly declared. Added to both: - ruby-pwsh.gemspec (spec.add_dependency), so real consumers of the published gem get it resolved correctly - Gemfile directly, since this Gemfile doesn't call `gemspec` and so never pulls in the gemspec's runtime dependencies on its own Verified locally: `bundle exec rspec spec/unit/pwsh_spec.rb` no longer raises LoadError on rexml/document (fails locally only on "No pwsh discovered!", because this machine has no local PowerShell install -- unrelated to this change, and not something CI hits).
The "export environment" step had a misplaced closing quote, putting
">> \$GITHUB_ENV" inside the echoed string instead of using it as
shell redirection:
echo "PUPPET_GEM_VERSION=${{ inputs.puppet_version }} >> $GITHUB_ENV"
PUPPET_GEM_VERSION was therefore never actually set for the acceptance
job, on any lane. This was silently harmless when there was only one
ruby/puppet pairing to test (unconstrained puppet resolution happened
to work fine on Ruby 3.x), but surfaces as a real Bundler version-
solving failure on the new Ruby 4.0 lane: with no PUPPET_GEM_VERSION,
the Gemfile can't scope puppet to ~> 9.0, so Bundler falls back to
puppetlabs_spec_helper's own broad puppet >= 8, < 10 constraint (via
puppetlabs-syntax) -- which pulls in a facter version that caps
Ruby at < 4.0, conflicting with the actual Ruby 4.0.6 runtime.
The acceptance job's matrix strategy had no fail-fast setting (unlike spec, which already sets fail-fast: false), so it defaulted to true: whenever one lane (e.g. ruby 4.0 | puppet ~> 9.0) failed, GitHub Actions auto-cancelled the sibling lane (ruby 3.2 | puppet ~> 8.0) mid-run, masking its true pass/fail status as "canceled" instead.
facter's latest public RubyGems release (4.10.0) declares required_ruby_version '>= 2.5', '< 4.0' -- no version on public RubyGems supports Ruby 4.0 at all, which blocked bundle install entirely for the ruby 4.0 / puppet ~> 9.0 lane (needed transitively via puppet's own facter >= 4.3.0, < 5 dependency). Mirrors puppetlabs-motd's Gemfile: route facter through gemsource_puppetcore unconditionally, the same way puppet already is, so it resolves against the private puppetcore build (which supports Ruby 4.0) instead of the public gem when PUPPET_FORGE_TOKEN is set.
custom_acceptance.yml never exposed PUPPET_FORGE_TOKEN or the puppetcore bundler source credential as environment variables, unlike cat-github-actions' gem_ci.yml (used by the spec job). This meant bundle install in the acceptance job only ever consulted public rubygems.org, silently ignoring gemsource_puppetcore entirely -- confirmed by the log only showing "Fetching gem metadata from https://rubygems.org/", never rubygems-puppetcore.puppet.com. Mirrors gem_ci.yml's env block, including the PUPPET_FORGE_TOKEN_PUBLIC fallback since ruby-pwsh is a public repo.
Ruby 3.4 changed Hash#inspect's default output from {:key=>"value"}
to {key: "value"}. These four assertions hardcoded the pre-3.4 format,
so they failed under the new Ruby 4.0 lane even though the actual DSC
resource application succeeded correctly (confirmed via the debug
probes added in a prior commit -- the real puppet apply output was
present, just in the new hash format the regex didn't expect).
Since the 3.2 lane still runs pre-3.4 Ruby and would produce the old
format, made the regexes match either style rather than picking one.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Ruby 4.0 / Puppet 9 CI coverage to
ruby-pwsh, mirroring the same update already carried out on other repos (e.g.puppetlabs_spec_helper@3bfa7d21,bolt-private#120):ruby_version: '4.0'/puppet_version: '~> 9.0'matrix entry to thespecandacceptancejobs inci.ymlandnightly.yml, alongside the existing3.2/~> 8.0lane.Gemfileto source thepuppetgem fromrubygems-puppetcore.puppet.comwhenPUPPET_FORGE_TOKENis set (falls back toGEM_SOURCE_PUPPETCOREor the default gem source otherwise).puppetlabs_spec_helperfrom~> 8.0to~> 9.0to pick up the CVE-fixedpuppetlabs-syntaxfork.ruby-pwshdoesn't carry bolt's Gemfile Ruby-version-conditional/canary-spec workaround for the Puppet 8.x FrozenError-on-Ruby-4.0 bug, since its CI already explicitly pinspuppet_versionper matrix lane rather than resolving puppet dynamically from the runtime Ruby version — so that part of the bolt-private pattern doesn't apply here.Test plan
ruby 3.2 | puppet ~> 8.0lane and the newruby 4.0 | puppet ~> 9.0lane, for bothspecandacceptancejobs.