From c7062dd5408a32bd78f5996282c8a020eb3eb12d Mon Sep 17 00:00:00 2001 From: Robert Waffen Date: Thu, 13 Aug 2026 10:04:48 +0200 Subject: [PATCH 1/8] chore: rename rake task to only ci, without the puppetlabs pl Signed-off-by: Robert Waffen --- .github/workflows/tests.yaml | 2 +- Rakefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 940b4661fa..b3df523f50 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -90,7 +90,7 @@ jobs: - name: Output Ruby Environment run: bundle env - name: Build gem for all platforms - run: bundle exec rake pl_ci:gem_build + run: bundle exec rake ci:gem_build # Windows tests fail if the gem is in the filesystem - name: Cleanup builds if: runner.os == 'Windows' diff --git a/Rakefile b/Rakefile index fe55f3057d..7d560aea29 100644 --- a/Rakefile +++ b/Rakefile @@ -56,7 +56,7 @@ task :default do sh %{rake -T} end -namespace :pl_ci do +namespace :ci do desc 'Build openvox gems' task :gem_build, [:gemspec] do |t, args| args.with_defaults(gemspec: 'openvox.gemspec') @@ -92,7 +92,7 @@ namespace :pl_ci do end end dst.flush - Rake::Task['pl_ci:gem_build'].invoke(dst.path) + Rake::Task['ci:gem_build'].invoke(dst.path) end end end From e547fa74c1c8a92061eed9e0d297f69f926e7f38 Mon Sep 17 00:00:00 2001 From: Robert Waffen Date: Thu, 13 Aug 2026 10:36:12 +0200 Subject: [PATCH 2/8] fix: move win32ole into platform block to add the dependency within crossbuils on ubnutu Signed-off-by: Robert Waffen --- openvox.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvox.gemspec b/openvox.gemspec index efad5f9330..02b276d917 100644 --- a/openvox.gemspec +++ b/openvox.gemspec @@ -43,7 +43,6 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency('racc', '~> 1.5') spec.add_runtime_dependency('scanf', '~> 1.0') spec.add_runtime_dependency('semantic_puppet', '~> 1.0') - spec.add_runtime_dependency('win32ole', '>= 1.8', '< 2.0') if Gem.win_platform? platform = spec.platform.to_s if platform == 'universal-darwin' @@ -54,5 +53,6 @@ Gem::Specification.new do |spec| # ffi 1.16.0 - 1.16.2 are broken on Windows spec.add_runtime_dependency('ffi', '>= 1.15.5', '< 2', '!= 1.16.0', '!= 1.16.1', '!= 1.16.2') spec.add_runtime_dependency('minitar', '~> 1.0') + spec.add_runtime_dependency('win32ole', '>= 1.8', '< 2.0') end end From 92c2a6f808b809c84bd0a25a8bbb742a590bd1d2 Mon Sep 17 00:00:00 2001 From: Robert Waffen Date: Thu, 13 Aug 2026 10:48:30 +0200 Subject: [PATCH 3/8] feat: do multi-platform crossbuilds. we have no native extensions, so build everything on linux runners Signed-off-by: Robert Waffen --- .github/workflows/gem_release.yaml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/gem_release.yaml b/.github/workflows/gem_release.yaml index eb48168c33..baa69ad13a 100644 --- a/.github/workflows/gem_release.yaml +++ b/.github/workflows/gem_release.yaml @@ -22,7 +22,7 @@ jobs: ruby-version: 'ruby' - name: Build gem shell: bash - run: gem build --verbose *.gemspec + run: bundle exec rake ci:gem_build - name: Upload gem to GitHub cache uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: @@ -46,6 +46,7 @@ jobs: shell: bash env: GH_TOKEN: ${{ github.token }} + # gh supports wildcards for release assets, so we can just upload all gem files in one command run: gh release create --repo ${{ github.repository }} ${{ github.ref_name }} --generate-notes *.gem release-to-github: @@ -60,9 +61,14 @@ jobs: with: name: gem-artifact - name: Publish gem to GitHub packages - run: gem push --host https://rubygems.pkg.github.com/${{ github.repository_owner }} *.gem env: GEM_HOST_API_KEY: ${{ secrets.GITHUB_TOKEN }} + # gem push does not support wildcards, so we have to loop through all gem files + # each combination of gem name, platform and version is a unique artifact, so we can have multiple gem files with the same name, version but different platforms + run: | + for gem_file in *.gem; do + gem push --host "https://rubygems.pkg.github.com/${{ github.repository_owner }}" "$gem_file" + done release-to-rubygems: needs: build-release @@ -79,7 +85,12 @@ jobs: - uses: rubygems/configure-rubygems-credentials@dc5a8d8553e6ee01fc26761a49e99e733d17954a # v2.1.0 - name: Publish gem to rubygems.org shell: bash - run: gem push *.gem + # gem push does not support wildcards, so we have to loop through all gem files + # each combination of gem name, platform and version is a unique artifact, so we can have multiple gem files with the same name, version but different platforms + run: | + for gem_file in *.gem; do + gem push "$gem_file" + done release-verification: name: Check that all releases are done @@ -101,6 +112,9 @@ jobs: ruby-version: 'ruby' - name: Wait for release to propagate shell: bash + # we upload different gem files for different platforms, so we have to wait for all of them to be available. run: | gem install rubygems-await - gem await *.gem + for gem_file in *.gem; do + gem await "$gem_file" + done From a72b0f531f5e82681f6921027e7125972e5ef4c4 Mon Sep 17 00:00:00 2001 From: Robert Waffen Date: Thu, 13 Aug 2026 14:10:32 +0200 Subject: [PATCH 4/8] ci: add gem build and installation tests to CI workflow Signed-off-by: Robert Waffen --- .github/workflows/tests.yaml | 93 ++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index b3df523f50..2f0ec61231 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -2,7 +2,9 @@ name: RSpec tests on: - pull_request: { branches: ['main'] } + pull_request: + branches: + - main push: branches: - main @@ -13,6 +15,10 @@ permissions: env: BUNDLE_SET: "without packaging documentation release" +concurrency: + group: rspec-tests-${{ github.ref }} + cancel-in-progress: true + jobs: validate_manpages: name: Validate man pages @@ -175,13 +181,94 @@ jobs: bundle exec rake -T | grep vox:upload working-directory: packaging + test_gem_build: + name: Test gem build + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Install Ruby + uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0 + with: + ruby-version: ruby + bundler-cache: true + + - name: Build gem for all platforms + run: bundle exec rake ci:gem_build + + - name: Upload gem to GitHub cache + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: gem-artifact + path: '*.gem' + retention-days: 1 + compression-level: 0 + + test_install: + name: Test gem install + needs: test_gem_build + strategy: + matrix: + include: + - os: ubuntu-24.04 + gem-platform: ruby + - os: macos-15 + gem-platform: universal-darwin + - os: windows-2025 + gem-platform: x64-mingw32 + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Download gem from GitHub cache + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: gem-artifact + + - name: Determine gem file + id: gem + shell: bash + env: + GEM_PLATFORM: ${{ matrix.gem-platform }} + run: | + gem_file="$( + ruby -rrubygems -e ' + spec = Gem::Specification.load("openvox.gemspec") + abort "Could not load openvox.gemspec" unless spec + spec.platform = ENV.fetch("GEM_PLATFORM") unless ENV["GEM_PLATFORM"] == "ruby" + puts spec.file_name + ' + )" + + test -f "$gem_file" + echo "file=$gem_file" >> "$GITHUB_OUTPUT" + + - name: Install Ruby + uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0 + with: + ruby-version: ruby + bundler-cache: true + + - name: Install gem + run: gem install "${{ steps.gem.outputs.file }}" --verbose + + - name: Smoke test + shell: bash + run: | + puppet --version + ruby -rpuppet -e 'puts Puppet.version' + tests: if: always() needs: - - validate_manpages - checks - - rspec_tests - rake_checks + - rspec_tests + - test_gem_build + - test_install + - validate_manpages runs-on: ubuntu-24.04 name: Test suite steps: From bee0eed30f5ad709b62fb5c85d6af695079b4be6 Mon Sep 17 00:00:00 2001 From: Robert Waffen Date: Thu, 13 Aug 2026 14:40:28 +0200 Subject: [PATCH 5/8] fix: filter gem-files in gemspec and remove path entries Signed-off-by: Robert Waffen --- openvox.gemspec | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/openvox.gemspec b/openvox.gemspec index 02b276d917..8c042da86d 100644 --- a/openvox.gemspec +++ b/openvox.gemspec @@ -22,7 +22,20 @@ Gem::Specification.new do |spec| EOF spec.email = "openvox@voxpupuli.org" spec.executables = ["puppet"] - spec.files = Dir['[A-Z]*'] + Dir['install.rb'] + Dir['bin/*'] + Dir['lib/**/*'] + Dir['conf/*'] + Dir['man/**/*'] + Dir['tasks/*'] + Dir['locales/**/*'] + Dir['ext/**/*'] + Dir['examples/**/*'] + spec.files = Dir.chdir(__dir__) do + Dir.glob(%w[ + [A-Z]* + install.rb + bin/* + lib/**/* + conf/* + man/**/* + tasks/* + locales/**/* + ext/**/* + examples/**/* + ]).reject { |path| File.directory?(path) || File.extname(path) == '.gem' } + end spec.license = "Apache-2.0" spec.homepage = "https://github.com/OpenVoxProject/openvox" spec.rdoc_options = ["--title", "OpenVox - Configuration Management", "--main", "README", "--line-numbers"] From 9ad9dc290423d98b848198a80982c647fb1f6de7 Mon Sep 17 00:00:00 2001 From: Robert Waffen Date: Fri, 14 Aug 2026 09:42:07 +0200 Subject: [PATCH 6/8] fix: target UCRT for 64-bit Windows gems RubyInstaller has used the x64-mingw-ucrt platform since Ruby 3.1, while OpenVox requires Ruby 3.2 or newer. Gems built for x64-mingw32 are incompatible with these supported Windows Rubies: RubyGems may install them, but cannot activate them afterwards. Replace the x64-mingw32 build and test target with x64-mingw-ucrt so the generated gem matches current RubyInstaller installations and includes the required Windows-specific dependencies. Keep x86-mingw32 for supported 32-bit Windows installations. Signed-off-by: Robert Waffen --- .github/workflows/tests.yaml | 2 +- Gemfile | 2 ++ Rakefile | 2 +- openvox.gemspec | 5 ++++- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 2f0ec61231..2f3a64e59b 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -216,7 +216,7 @@ jobs: - os: macos-15 gem-platform: universal-darwin - os: windows-2025 - gem-platform: x64-mingw32 + gem-platform: x64-mingw-ucrt runs-on: ${{ matrix.os }} steps: - name: Checkout diff --git a/Gemfile b/Gemfile index dfed2740b2..cd3b2fb542 100644 --- a/Gemfile +++ b/Gemfile @@ -55,6 +55,8 @@ group(:test) do gem 'webmock', '~> 3.0', require: false gem 'webrick', '~> 1.7', require: false gem 'yard', require: false + # The source gemspec has the generic ruby platform, so declare this explicitly for Windows development and CI. + gem 'win32ole', '>= 1.8', '< 2.0', require: false, platforms: [:windows] gem 'rubocop', '~> 1.89.0', require: false, platforms: [:ruby] gem 'rubocop-i18n', '~> 3.0', require: false, platforms: [:ruby] diff --git a/Rakefile b/Rakefile index 7d560aea29..d61bb185bd 100644 --- a/Rakefile +++ b/Rakefile @@ -62,7 +62,7 @@ namespace :ci do args.with_defaults(gemspec: 'openvox.gemspec') stdout, stderr, status = Open3.capture3(<<~END) gem build #{args.gemspec} --verbose --strict --platform x86-mingw32 && \ - gem build #{args.gemspec} --verbose --strict --platform x64-mingw32 && \ + gem build #{args.gemspec} --verbose --strict --platform x64-mingw-ucrt && \ gem build #{args.gemspec} --verbose --strict --platform universal-darwin && \ gem build #{args.gemspec} --verbose --strict END diff --git a/openvox.gemspec b/openvox.gemspec index 8c042da86d..0ce4483244 100644 --- a/openvox.gemspec +++ b/openvox.gemspec @@ -58,11 +58,14 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency('semantic_puppet', '~> 1.0') platform = spec.platform.to_s + windows_platforms = %w[x86-mingw32 x64-mingw-ucrt] + windows = windows_platforms.include?(platform) + if platform == 'universal-darwin' spec.add_runtime_dependency('CFPropertyList', ['>= 3.0.6', '< 5']) end - if platform == 'x64-mingw32' || platform == 'x86-mingw32' + if windows # ffi 1.16.0 - 1.16.2 are broken on Windows spec.add_runtime_dependency('ffi', '>= 1.15.5', '< 2', '!= 1.16.0', '!= 1.16.1', '!= 1.16.2') spec.add_runtime_dependency('minitar', '~> 1.0') From 88066569bb6b189e8bbf982f1be5ea1ecda4c8f7 Mon Sep 17 00:00:00 2001 From: Robert Waffen Date: Fri, 14 Aug 2026 09:50:04 +0200 Subject: [PATCH 7/8] feat: drop x86-mingw32 Signed-off-by: Robert Waffen --- Rakefile | 1 - openvox.gemspec | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index d61bb185bd..46f829f5f4 100644 --- a/Rakefile +++ b/Rakefile @@ -61,7 +61,6 @@ namespace :ci do task :gem_build, [:gemspec] do |t, args| args.with_defaults(gemspec: 'openvox.gemspec') stdout, stderr, status = Open3.capture3(<<~END) - gem build #{args.gemspec} --verbose --strict --platform x86-mingw32 && \ gem build #{args.gemspec} --verbose --strict --platform x64-mingw-ucrt && \ gem build #{args.gemspec} --verbose --strict --platform universal-darwin && \ gem build #{args.gemspec} --verbose --strict diff --git a/openvox.gemspec b/openvox.gemspec index 0ce4483244..d8701e4e12 100644 --- a/openvox.gemspec +++ b/openvox.gemspec @@ -58,7 +58,7 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency('semantic_puppet', '~> 1.0') platform = spec.platform.to_s - windows_platforms = %w[x86-mingw32 x64-mingw-ucrt] + windows_platforms = %w[x64-mingw-ucrt] windows = windows_platforms.include?(platform) if platform == 'universal-darwin' From 6f60964b1a272be412c2e432d9a0608eace8bd0d Mon Sep 17 00:00:00 2001 From: Robert Waffen Date: Fri, 14 Aug 2026 10:01:38 +0200 Subject: [PATCH 8/8] ci: remove redundant gem builds from RSpec jobs. It is now handled in test_gem_build and test_install Signed-off-by: Robert Waffen --- .github/workflows/tests.yaml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 2f3a64e59b..2ea8c15e33 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -93,14 +93,10 @@ jobs: with: ruby-version: ${{ matrix.cfg.ruby }} bundler-cache: true + - name: Output Ruby Environment run: bundle env - - name: Build gem for all platforms - run: bundle exec rake ci:gem_build - # Windows tests fail if the gem is in the filesystem - - name: Cleanup builds - if: runner.os == 'Windows' - run: Remove-Item -Path *.gem + - name: Run tests on Windows if: runner.os == 'Windows' run: |