Skip to content
This repository has been archived by the owner on Nov 7, 2023. It is now read-only.

Ansible role development environment, powered by cookiecutter.

License

Notifications You must be signed in to change notification settings

niall-byrne/ansible-workbench

Repository files navigation

Ansible Workbench

Ansible role development environment powered by Molecule.


November 2023: Project has been Deprecated

Ansible has slowly been phasing out the use of legacy roles in favour of the new collections format.

At this time, I've made the decision to put this project on hiatus, but if there is sufficient interest I'll refactor it into a solution for collections.


Master Branch (Follows the latest production tag)

ansible-workbench-self-test

Dev Branch

ansible-workbench-self-test

About

This cookiecutter template generates a development environment for Ansible Roles with comprehensive CI/CD for GitHub Actions.

Poetry powers a Python virtual environment loaded with Molecule and Ansible-Lint allowing you to develop and test roles with a focus on quality.

CICD-Tools provides managed CI/CD components giving you a functional pipeline from day one, and maintains the pipeline components for you.

Windows Users:

  • If you are working locally with Windows, you'll need a Posix or Linux virtual environment of some kind to use this template.
  • Neither Ansible, nor Ansible-Lint support this platform.

OSX, Linux, BSD Users:

Requirements

Mandatory

  • You'll need Python 3.9 or later to use this template. (Ansible now requires this.)

Recommended

  • A container runtime environment such as Docker or Colima is recommended, to make use of the configured pre-commit hooks.
  • You'll have to disable the pre-commit hooks if you choose not to follow this path.

Optional

  • An account on Ansible Galaxy is needed if you intend to publish your role.
  • An account on GitHub is needed to make use of the CI/CD.
  • A configured Slack Webhook is also handy for keeping tabs on the CI/CD.

Quick Start Guide

Open your shell, and run the following commands:

  • pip install cookiecutter poetry
  • cookiecutter https://github.com/niall-byrne/ansible-workbench.git

When prompted:

  • Give your project a name, and populate the other required template inputs.
  • See the section on TOML Linting for details on this optional tooling.
  • If you plan on using GitHub Actions with your project, consider using the Workflow Linting.

Once the templating is finished:

  • cd <your new project directory>
  • poetry shell (to interact with Ansible and Molecule inside a virtualenv)

You can then interact with the example role and Molecule scenarios:

  • molecule lint
  • molecule test -s docker1

More importantly: you can now build off this existing scaffolding to develop your own high quality Ansible role.

Managing Dependencies For Your Project

1. Ansible Galaxy Dependencies

Modify the templated requirements.yml file to add or remove the external roles or collections your role requires.

2. Python Dependencies

The pyproject.toml file is there to store your project's Python dependencies in accordance with PEP 518.

Poetry is leveraged to manage the Python dependencies:

i. Default Installed Python Packages

Package Description
ansible Simple, agentless IT automation.
ansible-lint Checks playbooks for best practices and behaviours.
commitizen Standardizes commit messages.
poetry Python package manager.
pre-commit A framework for managing pre-commit hooks.
molecule Ansible test framework.

ii. Maintaining your 'pyproject.toml' File (only needed if you add Python packages)

The template also presents the option to render a pre-commit hook and a CI step to lint the pyproject.toml file:

  • This is accomplished via the golang binary tomll.
  • This is the most robust TOML formatter I'm aware of right now.
  • Use of the pre-commit hooks "as-rendered" requires you have a container runtime such as Docker installed on your system.

If you prefer to install a binary on your system:

  • You can download the latest binary here.
  • Alternatively, your OS's package manager may support this tool.
  • You can also compile the tool yourself fairly easily from source.
    • If you have go installed: $ go install github.com/pelletier/go-toml/v2/cmd/tomll@latest

Working With Ansible Workbench

A fundamental pillar of Ansible Workbench is the use of Conventional Commits.

1. Why Conventional Commits?

  • Following this standard has numerous advantages, but among the largest is its tight integration with Semantic Versioning.
  • The CI/CD in particular, changelog generation and release automation is made possible through adherence to this format.
  • Being able to read commits from different people that conform to a standard also makes interactive rebasing relatively painless.

2. Making A Conventional Commit With commitizen

  • This tool leverages commitizen to enforce Conventional Commits as well as Semantic Versioning.
  • Stage any changes as your normally would: git add tasks/new_task_file.yml
  • Launch commitizen: poetry run cz c (See the next section to shorten that command.)
  • Alternatively, you might instead opt to manually make your commits: git commit -m "feat(NEW_TASK): added my new task file"

3. Optimizing Your Workflow

It's a bit more practical to work inside the Poetry virtual environment itself:

  • Start the virtual environment: poetry shell
  • Stage your changes: git add new_task_file.yml
  • Make your commit: cz c

It's recommended to install a container runtime such as Docker or Colima on your system:

4. Linting Your Commits

5. Legacy Commit Problems

  • If you have legacy (non-conventional) commits in your git history, you can still use the CI/CD.
  • See the section on configuring the 'push' workflow:
    • Setting ci_commitzen_rev_range to: "<my first conventional commit hash>..HEAD" will stop failing the CI on older commits
  • With this workaround in place you may still have CI failures when rebasing legacy commits that you don't fix-up.

Writing Molecule Tests with Ansible Workbench

There are 3 example Molecule scenarios created during templating:

Scenario Name Description
default Intended as a configuration reference and for use in linting and caching dependencies.
docker1 An example using Molecule's docker driver.
hostmachine1 An example using Molecule's delegated driver.

1. The Recommended Molecule Scenario Workflow

i. Try To Avoid Modifying the Default Scenario

It's recommended to avoid modifying the default scenario, to make the most of the rendered CI/CD.

  • Molecule actually supports different requirements.yml files for each scenario you create, however to optimize dependency caching the CI will try to cache the dependencies using this default scenario.
  • We recommend keeping one set of requirements in the requirements.yml file to speed up CI execution.

ii. Build Your Own Test Scenarios with Molecule

To add tests to your role, create new scenarios with Molecule:

  • poetry run molecule init scenario my_scenario

iii. Add Your New Scenarios to CI/CD

If you are using the rendered GitHub CI/CD, you can tweak which scenarios are executed by the CI via the workflow configuration. Name your workflow with reference to the regex specified in the ci_molecule_excluded_scenarios_regex key.

You could of course also modify the workflow itself for more fine-tuned control.

2. The Recommended Ansible Galaxy Settings

Connections to the Ansible Galaxy API can sometimes time out, unfortunately.

i. Cache Your Dependencies

In your Molecule Scenario file set the dependency option force: false as shown here.

In concert with this setting, it's also strongly recommended to avoid modifying the default Molecule scenario:

  • This will also help you get the most speed out of the default CI/CD configuration.
  • All of this assumes that your role always uses the same set of dependencies. Multiple sets of requirements for different scenarios is supported by Molecule, but will impact CI execution speed due to inefficient caching.

ii. Set a Generous Timeout Value

In your Molecule Scenario file set the dependency option timeout: 120 as shown here.

Pre-Commit Git Hooks

The python library pre-commit is installed during templating with a few useful initial hooks.

What are these hooks for?

These hooks are your quality controls, there to help you avoid senseless time-wasting mistakes.

These hooks are deeply integrated with CICD-Tools and are executed TWICE for all commits:

  1. Whenever you make a commit locally to your project.
  2. Whenever you push a commit to GitHub. (The CI/CD will ALSO execute the check.)

Containerization and Pre-Commit

These hooks all rely on 3rd party software to perform different types of static analysis on your code:

  • Some of this software can be managed by pre-commit itself (Especially if it's Python based.)
  • Other steps require the use of binaries that you may not be familiar with. (See the complete list in the next section.)

To simplify the process of seamlessly installing these 3rd party tools we leverage containers:

  • CICD-Tools provides several vetted binaries via its own container.
  • There are additional binary tools configured to run in 3rd party containers following this same paradigm.

For this reason we strongly recommend installing a container runtime such as Docker or Colima on your development machine.

If you do NOT wish to use a container runtime, please see the section on removing pre-commit hooks.

Default Pre-Commit Hooks

Hook Name Description
check-jsonschema Runs check-jsonschema to confirm the CI/CD configuration files are correct.
commitizen Runs commitizen on your commit message to validate it.
format-shell Runs shfmt to format your shell scripts.
format-toml Runs tomll to format your TOML configuration files.
lint-ansible Runs ansible-lint to check for Ansible best practices and behaviours.
lint-github-workflow Optionally runs actionlint on all GitHub workflows.
lint-github-workflow-header Optionally runs a shell script to lint GitHub workflow headers.
lint-markdown Runs markdown-lint on your Markdown files.
lint-shell Runs shellcheck to lint all shell scripts.
spelling-commit-message Runs vale on your git commit messages to check for spelling errors.
spelling-markdown Runs vale on your Markdown files to check for spelling errors.
yamllint Runs yamllint on all YAML files.

Pre-Commit Hook Definitions

Deactivating Pre-Commit Hooks

If you wish to remove or deactivate a particular hook remove its reference from these TWO places in your project:

  1. Find and remove the hook's definition in the .pre-commit-config.yaml file.
  2. Find and remove the hook's integration in the CI/CD workflow definition file.

Configuring The Pre-Commit Hooks

Hook Name Exe Source Configuration File(s)
check-jsonschema pre-commit .pre-commit-config.yaml
commitizen poetry/pre-commit pyproject.toml
format-shell CICD-Tools .pre-commit-config.yaml
format-toml CICD-Tools None
lint-ansible poetry .ansible-lint
lint-github-workflow CICD-Tools actionlint.yaml
lint-github-workflow-header shell lint-github-workflow-header.sh
lint-markdown 3rd party .markdownlint.yml
lint-shell CICD-Tools .pre-commit-config.yaml
spelling-commit-message CICD-Tools .vale.ini, vocab lists
spelling-markdown CICD-Tools .vale.ini, vocab lists
yamllint pre-commit .yamllint.yml

Using Ansible Workbench with GitHub

This project has deep integration with CICD-Tools which provides managed, reusable CI/CD components. This allows you to focus on your project, while befitting from the extensive quality control tools this integration provides.

At this time CICD-Tools has chosen to focus exclusively on GitHub Actions Perhaps eventually other CI platforms will be supported, but for now to get the most out of this project it's recommended to use the GitHub platform.

1. An Overview of the CI/CD

i. Push Workflow Sequence

Whenever you push to GitHub, the Push Workflow is triggered.

  1. The configuration in workflow-push.json is read by the workflow.
    • Customize this file to modify workflow parameters without having to modify the workflow itself.
  2. The active Molecule Scenarios are identified
  3. The repository is scanned for any checked in secrets.
  4. The documentation is checked for any invalid HTML links.
  5. Ansible Lint is run to validate the role.
  6. The Molecule Scenarios are tested.
  7. The Pre-Commit hooks themselves are tested to ensure they are still working. (i.e. Do bad commits still fail correctly?)
  8. The commit messages are linted.
  9. The CI then executes the configured Pre-Commit hooks for the repository against all files, ensuring the integrity of the code base.
  10. If you have pushed a tag conforming to Semantic Versioning, the workflow creates a release for you with an automated changelog.

ii. Release Workflow Sequence

If you have created something you want to share with the Ansible community, there is an included automated release process which enables you to publish your role to both on GitHub and Ansible Galaxy:

  1. The Push Workflow will respond to a pushed Semantic Versioned tag by creating a draft GitHub release with an automatically generated changelog.
  2. Edit this release on GitHub to your liking and then "publish" it.
  3. If you have created the required GitHub Secrets and configured your role's metadata correctly, your role will now automatically be published to Ansible Galaxy.

For more details please read section on creating a release.

2. Setting Up Your Project on GitHub

i. Creating Your Repository on GitHub

The values you've entered into the cookiecutter template determine what your repository should be named, and who it should be owned by.

  • Create a repository in GitHub using the github_handle you specified, and the project_slug name that was created during templating from the project name you input.
  • If you want to change the project_name or github_handle value because of this, you should run cookiecutter again.
  • If you don't remember the project_slug value, the file .cookiecutter/cookiecutter.json will be templated in your role's repository with all the values you entered during templating.

ii. Connecting Your New Repository

Connect your new remote repository and push:

  • Checkout the master branch: git checkout master
  • Add the new remote origin: git remote add origin [email protected]:\<your_github_handle\>/\<your_project_slug\>.git
  • Push to the new remote origin: git push -u origin master

3. Configuring Your Workflow

i. Basic Configuration

To make working with the CI/CD easy to get started with, there is configuration that is templated with sensible defaults. This gives you a low complexity option for modifying several common workflow settings.

The configuration files will be created in the .github/config folder:

There are also JSON schemas available here to help you understand all settings, and ensure your configuration stays consistent.

ii. GitHub Secrets

You'll need to create some secrets to enable the full functionality of your CI/CD.

To make the most out of your CI/CD, create the following secrets:

  • SLACK_WEBHOOK: This optional secret value should contain a Slack Webhook you've configured to get status updates on how your commit is proceeding through the CI/CD.
    • The verbosity of this integration can be controlled by setting the ci_verbose_notifications setting in this rendered configuration file.
    • See this documentation on how to create a Slack Webhook for your team.
    • If you do not wish to use CI/CD notifications, simply leave this secret unset.
  • GALAXY_API_KEY: This optional secret value can be created from the API key found on your Ansible Galaxy account page, and enables automated publishing to Galaxy.
    • If you do not wish to publish your role, simply leave this secret unset.

4. Creating a Release

If you have created something you want to share with the Ansible community, there is an included automated release process which enables you to publish your role to both on GitHub and Ansible Galaxy.

i. Prerequisites

Release generation depends in part on your use of Conventional Commits to format each individual commit to your code base.

ii. Tagging Your Releases

Tag your release with Semantic Versioning. (Avoid prefixing a 'v' or 'version' to your tag.)

  • It's recommended to use commitizen to manage the process of updating versions, and ensuring tags are in the correct format.
    • To "bump" your release: poetry run cz bump
  • If you are managing this process manually, take care to ensure the version field is updated inside your pyproject.toml file.

iii. Publishing Your Release to GitHub

  • Push your new semantic conforming tag to GitHub, and ensure the CI passes: git push --tags
  • The CI will create a draft release for you with a changelog on GitHub.
    • The changelog is generated in accordance with this configuration file.
    • Customize this file according to it's JSON Schema
  • Review it and if all is well, edit and then publish the release on GitHub.

iv. Publishing Your Release to Ansible Galaxy

  • If you have configured a secret for Ansible Galaxy more automation will now begin after you've published your GitHub release.
  • The release workflow will be triggered, and will publish your release automatically to Ansible Galaxy.

License

MPL-2