diff --git a/moduleroot/Gemfile.erb b/moduleroot/Gemfile.erb index ecaf7da939f26279b8b69457c95b32d57cb45dbb..d7fb69ea8d9bdad0b92d0c59c41bcf9cc9a1363e 100644 --- a/moduleroot/Gemfile.erb +++ b/moduleroot/Gemfile.erb @@ -58,16 +58,31 @@ end -%> source ENV['GEM_SOURCE'] || 'https://rubygems.org' -def location_for(place_or_version, fake_version = nil) +def location_for(place_or_version, fake_version = nil, gem_name = nil) git_url_regex = %r{\A(?<url>(https?|git)[:@][^#]*)(#(?<branch>.*))?} file_url_regex = %r{\Afile:\/\/(?<path>.*)} - if place_or_version && (git_url = place_or_version.match(git_url_regex)) + version = place_or_version || '>= 0' + + # Configure private source for puppet-related gems when auth token is available + is_puppet_gem = ['puppet', 'facter'].include?(gem_name) + has_auth_token = !ENV['PUPPET_AUTH_TOKEN'].to_s.empty? + + if is_puppet_gem && has_auth_token + # When using puppet gem with private source and no specific version requested, + # enforce the version constraint + if gem_name == 'puppet' && version == '>= 0' + version = '~> 8.11' + end + + [version, { require: false, source: 'https://rubygems-puppetcore.puppet.com' }] + elsif place_or_version && (git_url = place_or_version.match(git_url_regex)) [fake_version, { git: git_url[:url], branch: git_url[:branch], require: false }].compact elsif place_or_version && (file_url = place_or_version.match(file_url_regex)) ['>= 0', { path: File.expand_path(file_url[:path]), require: false }] else - [place_or_version, { require: false }] + # Default to rubygems.org when PUPPET_AUTH_TOKEN is not set + [version, { require: false }] end end @@ -110,13 +125,11 @@ hiera_version = ENV['HIERA_GEM_VERSION'] gems = {} -gems['puppet'] = location_for(puppet_version) - -# If facter or hiera versions have been specified via the environment -# variables +gems['puppet'] = location_for(puppet_version, nil, 'puppet') -gems['facter'] = location_for(facter_version) if facter_version -gems['hiera'] = location_for(hiera_version) if hiera_version +# If facter or hiera versions have been specified via the environment variables +gems['facter'] = location_for(facter_version, nil, 'facter') +gems['hiera'] = location_for(hiera_version, nil, 'hiera') if hiera_version gems.each do |gem_name, gem_params| gem gem_name, *gem_params diff --git a/moduleroot/spec/support/gemfile_spec.rb.erb b/moduleroot/spec/support/gemfile_spec.rb.erb new file mode 100644 index 0000000000000000000000000000000000000000..12db74265ce7693763d07e55fa5e6c3c597c1886 --- /dev/null +++ b/moduleroot/spec/support/gemfile_spec.rb.erb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'bundler' + +RSpec.describe 'Gemfile.lock verification' do + let(:parser) { Bundler::LockfileParser.new(Bundler.read_file(Bundler.default_lockfile)) } + let(:private_source) { 'https://rubygems-puppetcore.puppet.com/' } + let(:public_source) { 'https://rubygems.org/' } + let(:auth_token_present?) { !ENV['PUPPET_AUTH_TOKEN'].nil? } + + # Helper method to get source remotes for a specific gem + def get_gem_source_remotes(gem_name) + spec = parser.specs.find { |s| s.name == gem_name } + return [] unless spec + + source = spec.source + return [] unless source.is_a?(Bundler::Source::Rubygems) + + source.remotes.map(&:to_s) + end + + context 'when PUPPET_AUTH_TOKEN is present' do + before do + skip "Skipping private source tests - PUPPET_AUTH_TOKEN not present" unless auth_token_present? + end + + it 'has puppet under private source' do + remotes = get_gem_source_remotes('puppet') + expect(remotes).to eq([private_source]), + "Expected puppet to use private source #{private_source}, got: #{remotes.join(', ')}" + expect(remotes).not_to eq([public_source]), + "Expected puppet to not use public source #{public_source}, got: #{remotes.join(', ')}" + end + + it 'has facter under private source' do + remotes = get_gem_source_remotes('facter') + expect(remotes).to eq([private_source]), + "Expected facter to use private source #{private_source}, got: #{remotes.join(', ')}" + expect(remotes).not_to eq([public_source]), + "Expected facter to not use public source #{public_source}, got: #{remotes.join(', ')}" + end + end + + context 'when PUPPET_AUTH_TOKEN is not present' do + before do + skip "Skipping public source tests - PUPPET_AUTH_TOKEN is present" if auth_token_present? + end + + it 'has puppet under public source' do + remotes = get_gem_source_remotes('puppet') + expect(remotes).to eq([public_source]), + "Expected puppet to use public source #{public_source}, got: #{remotes.join(', ')}" + expect(remotes).not_to eq([private_source]), + "Expected puppet to not use private source #{private_source}, got: #{remotes.join(', ')}" + end + + it 'has facter under public source' do + remotes = get_gem_source_remotes('facter') + expect(remotes).to eq([public_source]), + "Expected facter to use public source #{public_source}, got: #{remotes.join(', ')}" + expect(remotes).not_to eq([private_source]), + "Expected facter to not use private source #{private_source}, got: #{remotes.join(', ')}" + end + end +end