Contributing guide

Thank you for considering to contribute to Rex! Volunteers like you make this free and open source project possible.

We consider it important to ensure everyone involved can make an efficient use of the time and effort they choose to invest. This guide aims to streamline communication around contributions by documenting the most frequently discussed aspects.

While most sections focus on the code contributions we typically receive, we encourage and welcome other types of contributions too. For example:

Project guidelines

We took many decisions around Rex since the first commit in 2010. We found some of the ideas coming up more often than others, and decided to share them here (in no particular order).

Getting help and support

If you need help with questions like “How do I…?” and “Why does it…?”, please start a discussion via one of our support channels.

We list options there for both community and commercial support.

Discussions, issues, and pull requests

In short, we follow these steps in that order: discuss first, track next, implement last.

  1. Discuss: first we discuss the relevant details of any change proposal idea, and decide on next steps.
  2. Track: when we decide to work on a change proposal, we open an issue to track progress, and design or refine potential solutions.
  3. Implement: we open pull requests as a last step to propose and review a specific implementation of the given idea.

Please use the templates we provide to streamline our collaboration in typical situations.

Making exceptions

We may choose and accept skipping one or more of the steps in exceptional cases, as long as the reasoning makes sense and gets well documented. When we find ourselves repeating the same exception, we will document it here as a standard case instead.

When you feel our workflow, guidelines, or templates does not fit your situation, please consider that a strong indicator to contact us early, and we’ll help figuring out the best course of action.

Rex core vs extending Rex

Strictly speaking, we consider the following the core competency of Rex: execute commands and manage files, by defining tasks and orchestrating their execution.

Rex gained lots of other capabilities over time, and historically many of them landed in core as well. This includes the capability to extend Rex without changing the core (or only minimally), for example when adding support to:

We strongly encourage to add such new capabilities via their own extension modules outside the core. In case of questions or concerns, see also the “Common scenarios” section, or contact us.

Supported operating systems

We expect Rex to run on operating systems wherever Perl can run. This includes Linux, BSDs, Mac OS X, Windows, Solaris, and possibly others.

We also expect Rex to manage endpoints running different operating systems. This primarily means Unix-like systems for now.

We welcome patches and guides about how to support Rex both to run on and manage even more operating systems.

In general, we aim to support Rex to run on and manage actively maintained platforms only. See also the “Deprecation policy” section for more details.

Supported Perl versions

Rex aims to run even on older Perl versions up to 10 years old. Currently this means 5.14.4.

On top of the supported minimum version of Perl, we aim to support the latest versions of all minor stable Perl 5 releases since then. That makes the full list the following:

Backwards compatibility

We aim to remain backwards compatible within major versions of Rex, as implied by following Dotted Semantic Versioning.

To introduce new features while staying backwards compatible, Rex also uses feature flags. This makes it possible to selectively opt-in to or opt-out from new features, depending on the needs of the given use case.

Feature flags named after the minor releases of Rex (for example 1.4) enable the collection of preferred settings for the given Rex version.

In general, we strive to add new feature flags in pairs for opting in and out.

Deprecation policy

We may drop features and code paths by following a planned deprecation procedure. Adequate warnings and an ample transition period should precede any such change.

If a supported operating system gets deprecated, we may try to keep it supported while it doesn't cause any problems. As soon as a retired operating system starts causing bugs, or gets in the way of progress, we consider it a candidate to drop from support.

In other words, while we may choose to stay lazy to keep the support around, we also don’t plan to put active effort into maintaining compatibility with something which got abandoned by its own creators.

In case you depend on a deprecated feature, or must use or manage a retired operating system, please consider contributing your solutions, or asking for community or commercial support for your use case.

Code layout

We use the latest version of Perl::Tidy to format the Rex codebase according to the rules described in .perltidyrc. We expect all contributions to follow the same formatting rules, and we also actively test for it.

To avoid unnecessary “tidy only” commits in contributions, we recommend to integrate a formatting step directly into your workflow. For example via a git pre-commit hook, a shortcut in the editor, or as an automatic action upon saving.

Importantly, we emphasize the importance of a consistent layout throughout the codebase over any specific formatting rule. Since we include .perltidyrc in the repo, consider it as subject of contributions too.

Code quality

We use Test::Perl::Critic::Progressive to make sure every change follows the code quality rules in .perlcriticrc, and no contribution introduces any violations accidentally.

The dist.ini file contains the list of perlcritic policy modules we use.

Since we include both .perlcriticrc and dist.ini in the repo, consider it as subject of contributions too. In fact, we welcome improving both our policies and the codebase in this regard.

Tests should pass

Rex has two major test suites:

In general, we expect contributions to include their own tests for the proposed changes, while ensuring that previous tests still pass.

To make it easier to follow the guidelines of this document, we strive to have corresponding tests for them as well.

Have fun

We find it highly important to have fun while using Rex and contributing to it. If you have a different experience, then please let us know, as that probably indicates a bug somewhere.

Development tools

We use Git for version control of the source code, and host Rex code in a GitHub repository.

We recommend to use a separate Perl environment for development, like the ones you managed by Perlbrew or similar tools.

The code and examples use cpanm to install modules from CPAN.

We also use Dist::Zilla as an authoring tool.

Perltidy takes care of maintaining a consistent source code formatting.

Perlcritic makes sure the codebase follows best practices and adheres to our minimum quality requirements.

Dependencies

After cloning the source code, run the following commands to install dependencies:

dzil authordeps | cpanm
dzil listdeps | cpanm

While some optional dependencies may not support your platform, use this command to install these as well:

dzil listdeps --suggests | cpanm

Install the remaining dependencies specific to the operating system, and Rex itself with:

dzil install

To only install the dependencies specific to the operating system, run one of these commands:

When considering new dependencies, we prefer:

We welcome and encourage contributions aimed at reducing the amount of Rex dependencies, for example by:

Testing

Run the test suite included with the source code of Rex with prove:

prove --lib --recurse t/

Extended, author, and release tests may need further dependencies. Install these with:

dzil listdeps --author --missing | cpanm

Then run those tests with:

dzil test --all

As an important step before modifying the codebase, please run the progressive perlcritic tests on the default branch:

rm -f xt/author/.perlcritic-history
AUTHOR_TESTING=1 prove --lib xt/author/critic-progressive.t

The first run should succeed, and records the current state. This serves as baseline to compare later runs against. Please see the Test::Perl::Critic::Progressive NOTES for more details.

Git workflow

We prefer receiving contributions by forking the repository on GitHub, and then sending pull requests against the default branch of the repository. If you have to use a different way, please contact us first to discuss alternative options.

Please read and follow the “Discussions, issues, and pull requests” section before investing effort in a pull request.

We recommend to use feature branches when working on contributions. This helps keeping the commits related to the change together, while separating them from the main line of development.

We consider a single commit ideal when it:

We expect commit messages to follow the guidelines collected in the How to Write a Git Commit Message article, and we also test for most of those expectations.

We generally recommend to:

Common scenarios

Add support to manage new operating systems

Allowing Rex to manage a new operating system requires the following steps:

  1. Teach rex about how to detect the given operating system

    • add a way to Rex::Hardware::Host::get_operating_system() to detect the given operating system
    • add a new is_myos() function to Rex::Commands::Gather
  2. Let Rex choose the proper package and service management modules for the given operating system

    • add support in Rex::Service and Rex::Pkg
  3. Add new service and package management modules specific to the given operating system

    • add Rex::Service::MyOS
    • add Rex::Pkg::MyOS

While the first two steps must currently go into Rex core, please consider publishing the Rex::Service::MyOS and Rex::Pkg::MyOS modules as a separate distribution.

Add support for new virtualization methods

Follow these steps to add support for a new virtualization method called MyVirt:

Please consider publishing the Rex::Virtualization::MyVirt module as a separate distribution.

Contribute to this guide

If you think some of the information in this document got outdated, lacks clarity, or has bugs, please propose changes to it too.

Useful resources