Skip to content

Cookiecutter powered Mac Maker OSX machine profile generator.

License

Notifications You must be signed in to change notification settings

osx-provisioner/profile-generator

Repository files navigation

Mac Maker Profile Generator

(Powered by CICD-Tools.)

Mac Maker is a single binary executable for configuring new Mac's with the software/tools you use every day.

  • This repository allows you to generate an example Mac Maker Profile which you can quickly customize for personal use.
  • It's intended as a starting point to put your system under idempotent, declarative version control.

The configuration files themselves comprise a customized Ansible playbook, allowing you to leverage Ansible's robust tool chain with minimal fuss.

Main Branch (Follows the latest production tag)

profile-generator-template-test

Dev Branch

profile-generator-template-test

About

This cookiecutter template generates a development environment for Mac Maker Profile 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.

Requirements

An OSX machine is of course the best platform to development your profile on, although you could probably use a Linux or BSD machine in a pinch.

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 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/osx-provisioner/profile-generator

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 the Python virtualenv)

You can now start customizing your Mac Maker Profile.

Managing Dependencies For Your Project

Python Dependencies

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

You SHOULD have everything you need to build out your profile, however if you find your need to customize the Python environment you can make use of Poetry:

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.

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

If you do modify your pyproject.toml, and you opted to render your Profile with TOML linting, you may need to make use tomll.

The template 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 the Profile Generator

A fundamental pillar of the Profile Generator 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.

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 all shell scripts.
format-toml Optionally runs tomll to format your TOML configuration file.
lint-ansible Runs ansible-lint to check your project for best Ansible practices and behaviour.
lint-github-workflow Optionally runs actionlint on all GitHub workflows.
lint-github-workflow-header Optionally runs a shell script to parse the headers on GitHub workflows.
lint-shell Runs shellcheck to lint all shell scripts.
lint-markdown Runs markdown-lint on your Markdown files.
spelling-commit-message Runs vale on your 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 Profile Generator 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 repository is scanned for any checked in secrets.
  3. The documentation is checked for any invalid HTML links.
  4. Ansible Lint is run to validate the role.
  5. The Pre-Commit hooks themselves are tested to ensure they are still working. (i.e. Do bad commits still fail correctly?)
  6. The commit messages are linted.
  7. The CI then executes the configured Pre-Commit hooks for the repository against all files, ensuring the integrity of the code base.
  8. If you have pushed a tag conforming to Semantic Versioning, the workflow creates a release for you with an automated changelog.

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 main branch: git checkout main
  • Add the new remote origin: git remote add origin git@github.com:\<your_github_handle\>/\<your_project_slug\>.git
  • Push to the new remote origin: git push -u origin main

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.

4. Creating a Release

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.

Restricted Paths

Certain versions of the Ansible tool chain may use these folders, which you would be best to avoid when building out your profile:

  • .ansible/
  • .cache/
  • profile/.ansible/
  • profile/.cache/

Mac Maker itself also writes some data overtop of the role (ephemerally at run time) in order to process it, this means there are a few paths that you should shy away from using:

  • spec.json *
  • profile/.mac_maker/
  • profile/collections/ *
  • profile/env/ *
  • profile/inventory/ *
  • profile/roles/ *

* (these paths are marked for deprecation, soon freeing them up for use)

License

GNU GPL