/yet-another-puppet-git-hook

Provide linting and syntax checks for working with puppet code

Primary LanguageShellGNU General Public License v3.0GPL-3.0

yet-another-puppet-git-hook

1. Overview

This repo provides a pre-commit hook, which checks the linting and syntax of .pp, .epp, .yaml files and of the Puppetfile.

2. Installation

2.1. Dependencies

The hook requires the following software:

Please check, that your PATH is valid (all commands are executable), e.g. add things like export PATH="${PATH}:$(find ~/.gem/ruby/ -maxdepth 2 -type d -name bin)" to your .bashrc

2.2. Manually configure pre-commit hook

  • clone this repo
  • navigate to your puppet repo
  • cd .git/hooks/
  • ln -s <path-to-this-repo>/pre-commit
  • chmod +x pre-commit

2.3. Automatically configure pre-commit hook

Either include this profile (tested on Ubuntu 18.04) in your role or safe the included /usr/share/git-core/templates/hooks/post-checkout directly. This script will install the pre-commit hook, when a repo is cloned. Afterwards, it will do a git pull on the yet-another-puppet-git-hook repo (pre-commit hook) by every branch checkout.

# installs and configures https://github.com/chrisongthb/yet-another-puppet-git-hook

class profile::git_pre_commit_hook {

  $gem_proxy = lookup('profile::git_pre_commit_hook::gem_install_proxy', Optional[Stdlib::HTTPUrl], first, Undef)

  # provide required packages
  ensure_packages( 'yamllint', {'ensure' => 'present'})
  if $gem_proxy {
    ensure_packages(
      [
        'r10k',
        'puppet-lint',
        'puppet-lint-legacy_facts-check',
        'puppet-lint-strict_indent-check',
      ], {
        ensure   => 'installed',
        provider => 'gem',
        install_options => { '--http-proxy' => $gem_proxy }
      }
    )
  }
  else {
    ensure_packages(
      [
        'r10k',
        'puppet-lint',
        'puppet-lint-legacy_facts-check',
        'puppet-lint-strict_indent-check',
      ], {
        ensure   => 'installed',
        provider => 'gem'
      }
    )
  }

  # Rollout post-checkout in git-init(1) template,
  # which manages pre-commit hook in local git repos
  # lint:ignore:single_quote_string_with_variables
  file { '/usr/share/git-core/templates/hooks/post-checkout':
    ensure  => 'file',
    owner   => 'root',
    group   => 'root',
    mode    => '0755',
    content => '#!/bin/bash
# This file is managed by Puppet

# Do nothing, if we do not checkout a branch:
#   $3 is a flag indicating whether the checkout was a branch checkout
#   the post-checkout hook is also run after git clone and the flag is always "1"
#   see docs for more information
#   https://git-scm.com/docs/githooks#_post_checkout
#
# These are all parameters given to post-checkout:
# 0000000000000000000000000000000000000000 702529a575af026b10a82c5a855df7c455056d09 1
# We could also use the null-ref as test, but we want the hooks to be up to date.
# Hence, we do an update on every branch switch.
#
if [ "$3" == "1" ]; then
  # just to be sure we are in repo root
  cd $(git rev-parse --show-toplevel)
  repo_uri=$(git config --get remote.origin.url)

  echo "Configuring pre-commit hook..."
  if [ -d ~/.yet-another-puppet-git-hook/.git/ ]; then
    cd ~/.yet-another-puppet-git-hook
    GIT_DIR=~/.yet-another-puppet-git-hook/.git/ git fetch --all --quiet
    GIT_DIR=~/.yet-another-puppet-git-hook/.git/ git reset --hard --quiet origin/main --
    cd $OLDPWD
  else
    rm -rf ~/.yet-another-puppet-git-hook/
    git clone https://github.com/chrisongthb/yet-another-puppet-git-hook.git ~/.yet-another-puppet-git-hook/
  fi
  ln -s --force ~/.yet-another-puppet-git-hook/pre-commit .git/hooks/
  chmod +x .git/hooks/pre-commit
fi
',
  }
  # lint:endignore
}

3. Usage

Just follow your current workflow. The pre-commit hook will only check those files, that are staged for this commit (not the whole repo). I recommend using dot files in the puppet repo root (e.g. .puppet-lint.rc, .yamllint), instead of changing the check invocation.

4. Extending pre-commit

Try using the function _puppet_git_hooks_check in pre-commit. In case the check invocation is complex, just define your own function in a new file beneath modules/ and call the function in pre-commit. You may want to use the _puppet_git_hooks_say method for colored output, see also modules/libs.sh. All files matching *.sh in modules/ gonna be sourced.

5. References

I used ideas from https://github.com/gini/puppet-git-hooks and https://github.com/drwahl/puppet-git-hooks

6. Limitations

  • Does not check erb templates
  • Does not support whitespaces in filenames
  • This is tested on Ubuntu 16.04 and 18.04

7. Support

Please create bug reports and feature requests in GitHub issues.