From 1efd8834eed5eda788c6177671554b7c7f391e9d Mon Sep 17 00:00:00 2001 From: Julien Godin <40758407+JGodin-C2C@users.noreply.github.com> Date: Wed, 11 Oct 2023 16:03:58 +0200 Subject: [PATCH 1/2] Create puppet-lint.yml --- .github/workflows/puppet-lint.yml | 55 +++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .github/workflows/puppet-lint.yml diff --git a/.github/workflows/puppet-lint.yml b/.github/workflows/puppet-lint.yml new file mode 100644 index 0000000..221adab --- /dev/null +++ b/.github/workflows/puppet-lint.yml @@ -0,0 +1,55 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# Puppet Lint tests Puppet code against the recommended Puppet language style guide. +# https://puppet.com/docs/puppet/7/style_guide.html +# Puppet Lint validates only code style; it does not validate syntax. +# To test syntax, use Puppet's puppet parser validate command. +# More details at https://github.com/puppetlabs/puppet-lint/ + +name: puppet-lint + +on: + push: + branches: [ "master" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "master" ] + schedule: + - cron: '39 14 * * 1' + +permissions: + contents: read + +jobs: + puppet-lint: + name: Run puppet-lint scanning + runs-on: ubuntu-latest + permissions: + contents: read # for checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Ruby + uses: ruby/setup-ruby@d37167af451eb51448db3354e1057b75c4b268f7 + with: + ruby-version: 3.0 + bundler-cache: true + + - name: Install puppet-lint + run: gem install puppet-lint + + - name: Run puppet-lint + run: puppet-lint . --sarif > puppet-lint-results.sarif + continue-on-error: true + + - name: Upload analysis results to GitHub + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: puppet-lint-results.sarif + wait-for-processing: true From 525db68c2f22f39960f5f7ec6a0957084e2573ba Mon Sep 17 00:00:00 2001 From: Julien Godin Date: Wed, 11 Oct 2023 16:27:53 +0200 Subject: [PATCH 2/2] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20upgrade=20using=20late?= =?UTF-8?q?st=20pdk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julien Godin --- .gitignore | 38 +++++++++++----- .puppet-lint.rc | 4 -- Gemfile | 103 ++++++++++++++++++++++++++++---------------- Rakefile | 93 ++++++++++++++++++++++++++++++++++----- metadata.json | 17 +++++--- spec/spec_helper.rb | 90 +++++++++++++++++++++++++------------- 6 files changed, 246 insertions(+), 99 deletions(-) diff --git a/.gitignore b/.gitignore index 65839fa..3f15512 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,28 @@ -pkg/ -Gemfile.lock -vendor/ -spec/fixtures/ -.vagrant/ -.bundle/ -coverage/ -log/ -.*.swp -*~ +.git/ +.*.sw[op] +.metadata +.yardoc +.yardwarns +*.iml +/.bundle/ +/.idea/ +/.vagrant/ +/coverage/ +/bin/ +/doc/ +/Gemfile.local +/Gemfile.lock +/junit/ +/log/ +/pkg/ +/spec/fixtures/manifests/ +/spec/fixtures/modules/* +/tmp/ +/vendor/ +/convert_report.txt +/update_report.txt +.DS_Store +.project +.envrc +/inventory.yaml +/spec/fixtures/litmus_inventory.yaml diff --git a/.puppet-lint.rc b/.puppet-lint.rc index e09d52f..cc96ece 100644 --- a/.puppet-lint.rc +++ b/.puppet-lint.rc @@ -1,5 +1 @@ ---fail-on-warnings --relative ---no-140chars ---no-documentation ---no-class_inherits_from_params_class-check diff --git a/Gemfile b/Gemfile index 15d5d9d..add1873 100644 --- a/Gemfile +++ b/Gemfile @@ -1,46 +1,73 @@ -source ENV['GEM_SOURCE'] || "https://rubygems.org" - -ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments -minor_version = ruby_version_segments[0..1].join('.') - -group :development, :unit_tests do - gem "rake", :require => false - gem "rspec", :require => false - gem "rspec-puppet", :require => false - gem "puppetlabs_spec_helper", :require => false - gem "metadata-json-lint", :require => false - gem "puppet-lint", :require => false - gem "puppet-lint-unquoted_string-check", :require => false - gem "puppet-lint-empty_string-check", :require => false - gem "puppet-lint-spaceship_operator_without_tag-check", :require => false - gem "puppet-lint-undef_in_function-check", :require => false - gem "puppet-lint-leading_zero-check", :require => false - gem "puppet-lint-trailing_comma-check", :require => false - gem "puppet-lint-file_ensure-check", :require => false - gem "puppet-lint-version_comparison-check", :require => false - gem "puppet-lint-file_source_rights-check", :require => false - gem "puppet-lint-alias-check", :require => false - gem "rspec-puppet-facts", :require => false - gem "ruby-augeas", :require => false - gem "puppet-blacksmith", :require => false if RUBY_VERSION !~ /^1\./ - gem "json_pure", '< 2.0.2', :require => false +source ENV['GEM_SOURCE'] || 'https://rubygems.org' + +def location_for(place_or_version, fake_version = nil) + git_url_regex = %r{\A(?(https?|git)[:@][^#]*)(#(?.*))?} + file_url_regex = %r{\Afile:\/\/(?.*)} + + if 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 }] + end end +group :development do + gem "json", '= 2.1.0', require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.3.0', require: false if Gem::Requirement.create(['>= 2.7.0', '< 3.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.5.1', require: false if Gem::Requirement.create(['>= 3.0.0', '< 3.0.5']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.6.1', require: false if Gem::Requirement.create(['>= 3.1.0', '< 3.1.3']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.6.3', require: false if Gem::Requirement.create(['>= 3.2.0', '< 4.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "racc", '~> 1.4.0', require: false if Gem::Requirement.create(['>= 2.7.0', '< 3.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "voxpupuli-puppet-lint-plugins", '~> 5.0', require: false + gem "facterdb", '~> 1.18', require: false + gem "metadata-json-lint", '~> 3.0', require: false + gem "puppetlabs_spec_helper", '~> 6.0', require: false + gem "rspec-puppet-facts", '~> 2.0', require: false + gem "codecov", '~> 0.2', require: false + gem "dependency_checker", '~> 1.0.0', require: false + gem "parallel_tests", '= 3.12.1', require: false + gem "pry", '~> 0.10', require: false + gem "simplecov-console", '~> 0.5', require: false + gem "puppet-debugger", '~> 1.0', require: false + gem "rubocop", '= 1.48.1', require: false + gem "rubocop-performance", '= 1.16.0', require: false + gem "rubocop-rspec", '= 2.19.0', require: false + gem "rb-readline", '= 0.5.5', require: false, platforms: [:mswin, :mingw, :x64_mingw] +end group :system_tests do - gem "puppet-module-posix-system-r#{minor_version}", :require => false - gem "beaker-hostgenerator", :require => false, :git => 'https://github.com/mcanevet/beaker-hostgenerator.git', :branch => 'fix_debian9' + gem "puppet_litmus", '~> 1.0', require: false, platforms: [:ruby, :x64_mingw] + gem "serverspec", '~> 2.41', require: false end -if facterversion = ENV['FACTER_GEM_VERSION'] - gem 'facter', facterversion, :require => false -else - gem 'facter', :require => false -end +puppet_version = ENV['PUPPET_GEM_VERSION'] +facter_version = ENV['FACTER_GEM_VERSION'] +hiera_version = ENV['HIERA_GEM_VERSION'] + +gems = {} -if puppetversion = ENV['PUPPET_GEM_VERSION'] - gem 'puppet', puppetversion, :require => false -else - gem 'puppet', :require => false +gems['puppet'] = location_for(puppet_version) + +# If facter or hiera versions have been specified via the environment +# variables + +gems['facter'] = location_for(facter_version) if facter_version +gems['hiera'] = location_for(hiera_version) if hiera_version + +gems.each do |gem_name, gem_params| + gem gem_name, *gem_params end -# vim:ft=ruby +# Evaluate Gemfile.local and ~/.gemfile if they exist +extra_gemfiles = [ + "#{__FILE__}.local", + File.join(Dir.home, '.gemfile'), +] + +extra_gemfiles.each do |gemfile| + if File.file?(gemfile) && File.readable?(gemfile) + eval(File.read(gemfile), binding) + end +end +# vim: syntax=ruby diff --git a/Rakefile b/Rakefile index aa7b8a1..74415a9 100644 --- a/Rakefile +++ b/Rakefile @@ -1,17 +1,88 @@ +# frozen_string_literal: true + +require 'bundler' +require 'puppet_litmus/rake_tasks' if Gem.loaded_specs.key? 'puppet_litmus' require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet-lint/tasks/puppet-lint' +require 'puppet-syntax/tasks/puppet-syntax' +require 'github_changelog_generator/task' if Gem.loaded_specs.key? 'github_changelog_generator' +require 'puppet-strings/tasks' if Gem.loaded_specs.key? 'puppet-strings' -Rake::Task[:lint].clear -PuppetLint::RakeTask.new :lint do |config| - config.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp", "vendor/**/*.pp"] - config.disable_checks = ['140chars'] - config.fail_on_warnings = true +def changelog_user + return unless Rake.application.top_level_tasks.include? "changelog" + returnVal = nil || JSON.load(File.read('metadata.json'))['author'] + raise "unable to find the changelog_user in .sync.yml, or the author in metadata.json" if returnVal.nil? + puts "GitHubChangelogGenerator user:#{returnVal}" + returnVal end -PuppetSyntax.exclude_paths = ["spec/fixtures/**/*.pp", "vendor/**/*"] +def changelog_project + return unless Rake.application.top_level_tasks.include? "changelog" + + returnVal = nil + returnVal ||= begin + metadata_source = JSON.load(File.read('metadata.json'))['source'] + metadata_source_match = metadata_source && metadata_source.match(%r{.*\/([^\/]*?)(?:\.git)?\Z}) + + metadata_source_match && metadata_source_match[1] + end + + raise "unable to find the changelog_project in .sync.yml or calculate it from the source in metadata.json" if returnVal.nil? + + puts "GitHubChangelogGenerator project:#{returnVal}" + returnVal +end -# Publishing tasks -unless RUBY_VERSION =~ /^1\./ - require 'puppet_blacksmith' - require 'puppet_blacksmith/rake_tasks' +def changelog_future_release + return unless Rake.application.top_level_tasks.include? "changelog" + returnVal = "v%s" % JSON.load(File.read('metadata.json'))['version'] + raise "unable to find the future_release (version) in metadata.json" if returnVal.nil? + puts "GitHubChangelogGenerator future_release:#{returnVal}" + returnVal end + +PuppetLint.configuration.send('disable_relative') + + +if Gem.loaded_specs.key? 'github_changelog_generator' + GitHubChangelogGenerator::RakeTask.new :changelog do |config| + raise "Set CHANGELOG_GITHUB_TOKEN environment variable eg 'export CHANGELOG_GITHUB_TOKEN=valid_token_here'" if Rake.application.top_level_tasks.include? "changelog" and ENV['CHANGELOG_GITHUB_TOKEN'].nil? + config.user = "#{changelog_user}" + config.project = "#{changelog_project}" + config.future_release = "#{changelog_future_release}" + config.exclude_labels = ['maintenance'] + config.header = "# Change log\n\nAll notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org)." + config.add_pr_wo_labels = true + config.issues = false + config.merge_prefix = "### UNCATEGORIZED PRS; LABEL THEM ON GITHUB" + config.configure_sections = { + "Changed" => { + "prefix" => "### Changed", + "labels" => ["backwards-incompatible"], + }, + "Added" => { + "prefix" => "### Added", + "labels" => ["enhancement", "feature"], + }, + "Fixed" => { + "prefix" => "### Fixed", + "labels" => ["bug", "documentation", "bugfix"], + }, + } + end +else + desc 'Generate a Changelog from GitHub' + task :changelog do + raise < 1.15' + condition: "Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0')" +EOM + end +end + diff --git a/metadata.json b/metadata.json index 6a70ca8..c118f6a 100644 --- a/metadata.json +++ b/metadata.json @@ -17,12 +17,6 @@ "version_requirement": ">=2.2.1 < 5.0.0" } ], - "requirements": [ - { - "name": "puppet", - "version_requirement": ">= 6.0.0 < 9.0.0" - } - ], "operatingsystem_support": [ { "operatingsystem": "Debian", @@ -53,5 +47,14 @@ "9" ] } - ] + ], + "requirements": [ + { + "name": "puppet", + "version_requirement": ">= 6.0.0 < 9.0.0" + } + ], + "pdk-version": "3.0.0", + "template-url": "pdk-default#3.0.0", + "template-ref": "tags/3.0.0-0-g056e50d" } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 94d30d5..6820ceb 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,42 +1,74 @@ +# frozen_string_literal: true + +RSpec.configure do |c| + c.mock_with :rspec +end + require 'puppetlabs_spec_helper/module_spec_helper' require 'rspec-puppet-facts' + +require 'spec_helper_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_local.rb')) + include RspecPuppetFacts +default_facts = { + puppetversion: Puppet.version, + facterversion: Facter.version, +} -RSpec.configure do |c| - c.include PuppetlabsSpec::Files +default_fact_files = [ + File.expand_path(File.join(File.dirname(__FILE__), 'default_facts.yml')), + File.expand_path(File.join(File.dirname(__FILE__), 'default_module_facts.yml')), +] - c.before :each do - # Store any environment variables away to be restored later - @old_env = {} - ENV.each_key {|k| @old_env[k] = ENV[k]} +default_fact_files.each do |f| + next unless File.exist?(f) && File.readable?(f) && File.size?(f) - c.strict_variables = Gem::Version.new(Puppet.version) >= Gem::Version.new('3.5') - Puppet.features.stubs(:root?).returns(true) + begin + default_facts.merge!(YAML.safe_load(File.read(f), permitted_classes: [], permitted_symbols: [], aliases: true)) + rescue StandardError => e + RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" end +end - c.after :each do - PuppetlabsSpec::Files.cleanup +# read default_facts and merge them over what is provided by facterdb +default_facts.each do |fact, value| + add_custom_fact fact, value +end + +RSpec.configure do |c| + c.default_facts = default_facts + c.before :each do + # set to strictest setting for testing + # by default Puppet runs at warning level + Puppet.settings[:strict] = :warning + Puppet.settings[:strict_variables] = true + end + c.filter_run_excluding(bolt: true) unless ENV['GEM_BOLT'] + c.after(:suite) do + RSpec::Puppet::Coverage.report!(0) + end + + # Filter backtrace noise + backtrace_exclusion_patterns = [ + %r{spec_helper}, + %r{gems}, + ] + + if c.respond_to?(:backtrace_exclusion_patterns) + c.backtrace_exclusion_patterns = backtrace_exclusion_patterns + elsif c.respond_to?(:backtrace_clean_patterns) + c.backtrace_clean_patterns = backtrace_exclusion_patterns end end -require 'pathname' -dir = Pathname.new(__FILE__).parent -Puppet[:modulepath] = File.join(dir, 'fixtures', 'modules') - -# There's no real need to make this version dependent, but it helps find -# regressions in Puppet -# -# 1. Workaround for issue #16277 where default settings aren't initialised from -# a spec and so the libdir is never initialised (3.0.x) -# 2. Workaround for 2.7.20 that now only loads types for the current node -# environment (#13858) so Puppet[:modulepath] seems to get ignored -# 3. Workaround for 3.5 where context hasn't been configured yet, -# ticket https://tickets.puppetlabs.com/browse/MODULES-823 -# -ver = Gem::Version.new(Puppet.version.split('-').first) -if Gem::Requirement.new("~> 2.7.20") =~ ver || Gem::Requirement.new("~> 3.0.0") =~ ver || Gem::Requirement.new("~> 3.5") =~ ver || Gem::Requirement.new("~> 4.0") - puts "augeasproviders: setting Puppet[:libdir] to work around broken type autoloading" - # libdir is only a single dir, so it can only workaround loading of one external module - Puppet[:libdir] = "#{Puppet[:modulepath]}/augeasproviders_core/lib" +# Ensures that a module is defined +# @param module_name Name of the module +def ensure_module_defined(module_name) + module_name.split('::').reduce(Object) do |last_module, next_module| + last_module.const_set(next_module, Module.new) unless last_module.const_defined?(next_module, false) + last_module.const_get(next_module, false) + end end + +# 'spec_overrides' from sync.yml will appear below this line