The PDK Templates is the default templates repository for use with the Puppet Development Kit, within which we have defined all the templates for the creation and configuration of a module. Look into these directories to find the templates:
moduleroot
templates get deployed onnew module
,convert
andupdate
; use them to enforce a common boilerplate for central files.moduleroot_init
templates get only deployed when the target module does not yet exist; use them to provide skeletons for files the developer needs to modify heavily.object_templates
templates are used by the variousnew ...
commands for classes, defined types, etc.
PDK builds the configuration of the module by reading a set of default configuration from config_defaults.yml
and merging it with the contents of .sync.yml
from module's root directory, if exists. Top-level keys of the resulting hash correspond to target files or represent a global configuration. Global configuration will be merged with the configuration hash for a particular target file. This allows a module developer to override/amend the configuration by putting new values into .sync.yml
. A knockout prefix may be applied to elements within .sync.yml
to remove elements from the default set. Target files are created by rendering a corresponding template which is referring its configuration via the @configs
hash. The data for a target file may include delete: true
or unmanaged: true
in order to have the particular file removed from the module or left unmanaged, respectively.
Templates like this one can be used in conjunction with the PDK. As default the PDK itself uses the templates within this repository to render files for use within a module. Templates can be passed to the PDK as a flag for several of the commands.
pdk convert --template-url https://github.com/puppetlabs/pdk-templates
Please note that the template only needs to be passed in once if you wish to change it, every command run on the PDK will use the last specified template. For more on basic usage and more detailed description of the PDK in action please refer to the PDK documentation.
The following is a description and explanation of each of the keys within config_defaults. This will help clarify the default settings we choose to apply to pdk modules.
A .gitattributes file in your repo allows you to ensure consistent git settings.
Key | Description |
---|---|
include | Defines which extensions are handled by git automatic conversions (see the gitattributes documentation). The default configuration helps to keep line endings consistent between windows and linux users. |
A .gitignore file in your repo allows you to specify intentionally untracked files to ignore.
Key | Description |
---|---|
required | The default list of files or paths for git to ignore or untrack that are commonly specified in a module project. |
paths | Defines any additional files or paths for git to ignore or untrack. (see the gitignore documentation). |
These workflows are depending on puppet-internal resources and are currently not suited for public consumption. Feel free to take them as inspiration how to run some tests on Github Actions. Please let us know at [email protected] what you come up with!
The auto release workflows prepares a module release PR. By default the workflow can be triggered manually when a release preparation PR needs to be created, however it allows setting a cron based trigger that can run automatically. To set up the automated release cron you can add a configuration to your .sync.yml file that matches the following example:
release_schedule:
cron: '0 3 * * 6'
In this example the automated release prep workflow is triggered every Saturday at 3 am.
A .pdkignore file in your repo allows you to specify files to ignore when building a module package with
pdk build
.
Key | Description |
---|---|
required | The default list of files or paths for PDK to ignore when building a module package. |
paths | Defines additional files or paths for PDK to ignore when building a module package. |
YARD is a documentation generation tool for the Ruby programming language. It enables the user to generate consistent, usable documentation that can be exported to a number of formats very easily, and also supports extending for custom Ruby constructs such as custom class level definitions.
Key | Description |
---|---|
markup | Specifies the markup formatting of your documentation. Default is markdown . |
optional | Define any additional arguments you want to pass through to the yardoc command. |
Rake is a Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax within the Rakefile, present in the root directory of the code repository. Within modules context Rake tasks are used quite frequently, from ensuring the integrity of a module, running validation and tests, to tasks for releasing modules.
Key | Description |
---|---|
requires | A list of hashes with the library to 'require' , and an optional 'conditional' . |
changelog_user | Sets the github user for the change_log_generator rake task. Optional, if not set it will read the author from the metadata.json file. |
changelog_project | Sets the github project name for the change_log_generator rake task. Optional, if not set it will parse the source from the metadata.json file |
changelog_since_tag | Sets the github since_tag for the change_log_generator rake task. Required for the changelog rake task. |
changelog_max_issues | Sets the github max_issues for the change_log_generator rake task. Optional to limit max issues. |
changelog_version_tag_pattern | Template how the version tag is to be generated. Defaults to 'v%s' which eventually align with tag_pattern property of puppet-blacksmith, thus changelog is referring to the correct version tags and compare URLs. |
github_site | Override built-in default for public GitHub. Useful for GitHub Enterprise and other. (Example: github_site = https://git.domain.tld ) |
github_endpoint | Override built-in default for public GitHub. Useful for GitHub Enterprise and other. (Example: github_endpoint = https://git.domain.tld/api/v4 ) |
default_disabled_lint_checks | Defines any checks that are to be disabled by default when running lint checks. As default we disable the --relative lint check, which compares the module layout relative to the module root. Does affect .puppet-lint.rc. |
extra_disabled_lint_checks | Defines any checks that are to be disabled as extras when running lint checks. No defaults are defined for this configuration. Does affect .puppet-lint.rc. |
extras | An array of extra lines to add into your Rakefile. As an alternative you can add a directory named rakelib to your module and files in that directory that end in .rake would be loaded by the Rakefile. Example, to add syntax check exclusion paths for plan directories:
|
linter_options | An array of options to be passed into linter config. Does affect .puppet-lint.rc. |
linter_fail_on_warnings | A boolean indicating if the linter should exit non-zero on warnings as well as failures. Does affect .puppet-lint.rc. |
linter_exclusions | An array of paths that the linter should exclude from running against. |
RuboCop is a Ruby static code analyzer. We use Rubocop to enforce a level of quality and consistency within Ruby code. Rubocop can be configured within .rubocop.yml which is located in the root directory of the code repository. Rubocop works by defining a sanitized list of cops that'll cleanup a code base without much effort, all of which support autocorrect and that are fairly uncontroversial across wide segments of the Community.
Key | Description |
---|---|
include_todos | Allows you to use rubocop's "TODOs" to temporarily skip checks by setting this to true . See rubocop's --auto-gen-config option for details. Defaults to false . |
selected_profile | Allows you to define which profile is used by default, which is set to strict , which is fully defined within the profiles section. |
default_configs | Allows you to define the default configuration of which cops will run. Includes the full name of the cop followed by a description of it and an enforced style. Can also make use of the key excludes to exclude any files from that specific cop. |
cleanup_cops | Defines a set of cleanup cops to then be included within a rubocop profile. Cops are defined by their full name, and further configuration can be done by specifying secondary keys. By default we specify a large amount of cleanup cops using their default configuration. |
profiles | Defines the profiles that can be enabled and used within rubocop through the selected_profile option. By default we have set up three profiles: cleanups_only, strict, hardcore and off. |
A Gemfile is a file we create which is used for describing gem dependencies for Ruby programs. All modules should have an associated Gemfile for installing the relevant gems. As development and testing is somewhat consistant between modules we have used the template to define a set of gems relevant to these processes.
Key | Description |
---|---|
required | Allows you to specify gems that are required within the Gemfile. Gems can be defined here within groups, for example we use the :development gem group to add in several gems that are relevant to the development of any module and the :system_tests gem group for gems relevant only to acceptance testing. |
optional | Allows you to specify additional gems that are required within the Gemfile. This key can be used to further configure the Gemfile through assignment of a value in the .sync.yml file. |
Within each Gem group defined using the options above one or more gem item definitions may be listed in an array. Each item in that array must be a gem item hash.
Gem Item Hash Keys | Description |
---|---|
gem | Required option specifying the gem name. |
version | Required option to specify version or range of versions required using RubyGem version syntax. |
platforms | Defines an array of platforms for which the Gem should be included. See the Gemfile platform guide for a list of valid platforms. |
git | If required, specify a specific Git repository in which this Gem is located. See the Bundler docs for details. |
branch | Optionally specify a branch to use if using the git option. Defaults to main . |
ref | Optionally specify an arbitrary valid Git reference to use for the module version. |
source | Specify an alternate Rubygems repository to load the gem from. |
from_env | Specifies an environment variable containing either a Rubygem version specification indicating the version to use OR a URL indicating the location from which to load the gem. |
condition | An optional string containing a Ruby-code conditional controlling if this gem will be processed in the Gemfile. |
The spec/default_facts.yml file contains a list of facts to be used by default when running rspec tests
Key | Description |
---|---|
ip | Overrides the [networking][ip] fact's value in the base template. Defaults to "172.16.254.254". |
ip6 | Overrides the [networking][ip6] fact's value in the base template. Defaults to "FE80:0000:0000:0000:AAAA:AAAA:AAAA". |
mac | Overrides the [networking][mac] fact's value in the base template. Defaults to "AA:AA:AA:AA:AA:AA". |
is_pe | Overrides the is_pe fact's value in the base template. Defaults to false. |
extra_facts | List of extra facts to be added to the default_facts.yml file. They are in the form: "name of fact : value of fact " |
---
networking:
ip: "172.16.254.254"
ip6: "FE80:0000:0000:0000:AAAA:AAAA:AAAA"
mac: "AA:AA:AA:AA:AA:AA"
is_pe: false
The spec/spec_helper.rb file contains setup for rspec tests
Key | Description |
---|---|
default_facter_version | Sets the default_facter_version rspec-puppet-facts parameter. |
facter_implementation | Sets the facter_implementation rspec-puppet parameter. Current available options are rspec and facter , with facter being the default. The rspec implementation offers a significant performance improvement and results in faster unit tests. |
hiera_config | Sets the hiera_config rspec-puppet parameter. |
hiera_config_ruby | Sets the hiera_config rspec-puppet parameter. A ruby expression returning the path to your hiera.yaml file. hiera_config takes precedence if both values hiera_config and hiera_config_ruby are specified. |
mock_with | Defaults to ':rspec' . If you need the previous default of "some mocha and some rspec-mocks", set mock_with: ~ (tilde symbol, the YAML null value). |
spec_overrides | An array of extra lines to add into your spec_helper.rb . Can be used as an alternative to spec_helper_local |
strict_level | Defines the Puppet Strict configuration parameter. Defaults to :warning . Other values are: :error and :off . :error provides strictest level checking and is encouraged. |
strict_variables | Defines the Puppet Strict Variables configuration parameter. Defaults to true however due to puppetlabs_spec_helper forced override (https://github.com/puppetlabs/puppetlabs_spec_helper/blob/070ecb79a63cb8fa10f46532c413c055e2697682/lib/puppetlabs_spec_helper/module_spec_helper.rb#L71). Set to false to align with true default or with STRICT_VARIABLES=no environment setting. |
coverage_report | Enable rspec-puppet coverage reports. Defaults to false |
minimum_code_coverage_percentage | The desired code coverage percentage required for tests to pass. Defaults to 0 |
While we provide a basic template it is likely that it will not match what you need exactly, as such we allow it to be altered or added to through the use of the
.sync.yml
file.
Values can be added to the data passed to the templates by adding them to your local .sync.yml
file, thus allowing you to make changes such as testing against additional operating systems or adding new rubocop rules.
To add a value to an array simply place it into the .sync.yml
file as shown below, here I am adding an additional unit test run against Puppet 4:
.travis.yml:
includes:
- env: PUPPET_GEM_VERSION="~> 4.0" CHECK=parallel_spec
rvm: 2.1.9
Values can be removed from the data passed to the templates using the knockout prefix ---
in .sync.yml
.
To remove a value from an array, prefix the value ---
. For example, to remove
2.5.1
from the ruby_versions
array in .travis.yml
:
.travis.yml:
ruby_versions:
- '---2.5.1'
To remove a key from a hash, set the value to ---
. For example, to remove the
ip
fact from spec/default_facts.yml
:
spec/default_facts.yml:
networking:
ip: '---'
To add a custom internal puppet-lint
plugin served from an internal Rubygems source, add
an entry similar to the following in .sync.yml
file and run pdk update
.
Gemfile:
optional:
':development':
- gem: 'puppet-lint-my_awesome_custom_module'
version: '>= 2.0'
source: 'https://myrubygems.example.com/'
Please note that the early version of this template contained only a 'moduleroot' directory, and did not have a 'moduleroot_init'. The PDK 'pdk new module' command will still work with templates that only have 'moduleroot', however the 'pdk convert' command will fail if the template does not have a 'moduleroot_init' directory present. To remedy this please use the up to date version of the template.
As explained in Use GitHub actions at your own risk, when running github actions from outside the organisation, there is a risk that symbolic references get taken over by malicious actors. Similar things happened before in other ecosystems and other packaging registries. The blog post goes on to suggest pinning to specific SHAs and provides some tooling to do so. The downsides for us are that the tooling doesn't work well with our ERB templating, and the additional cost of updating the SHAs across all modules. Instead we fork at-risk actions into the puppetlabs namespace and use them from there. This allows us to consume updates at our pace and deploy changes across all modules without delay, while avoiding actions that surreptitiously change while we're not looking.
Since this still has some overhead, we exclude some "big-name" action maintainers:
- Anything maintained by Github, e.g. https://github.com/actions
- Anything maintained as part of a bigger OSS project we're using, like https://github.com/ruby/setup-ruby
- Anything maintained by a Puppet employee
To keep efforts low when updating actions, we list all forked actions here.
To keep confusion to a minimum, the version we use is always on a pdk-templates-v1
branch.
This way we can update (git fetch
/git push
) forked repositories with no prejudice, test out the changes, and only then update the pdk-templates-v1
branch.
That said, the branches used in pdk-templates should only contain upstream code and changes already in an upstream PR to minimize the diff we're carrying.
If we later need to support multiple versions of an action as we roll out changes, we can increment the -v1
part in the branch name to manage multiple versions.
- kvrhdn/gha-buildevents ➡️ puppetlabs/kvrhdn-gha-buildevents
- Gamesight/slack-workflow-status ➡️ puppetlabs/Gamesight-slack-workflow-status
The repos have restricted access only to @modules team members.