Skip to content

Instantly share code, notes, and snippets.

@robbat2
Created March 6, 2015 22:50
Show Gist options
  • Save robbat2/7c947562b52a09642ac6 to your computer and use it in GitHub Desktop.
Save robbat2/7c947562b52a09642ac6 to your computer and use it in GitHub Desktop.
Makefile for puppet lint & validation (and other filetypes too)
# Puppet validation & lint Makefile
# Copyright 2014-2015 Robin Johnson <robbat2@gentoo.org>
#
# Targets:
# all: does validate, lint, check-footer
# validate: runs validations on many filetypes
# lint: runs puppet-lint only
# check: alias for validate
# validate.${FILETYPE}: validate a specific filetype, eg validate.pp
#
# Validated file extensions:
# pp erb json rb yaml sudo
#
# Parameters:
# D="..." list of files to check
# Q=0 Normal output
# Q=1 Be extra quiet
# V=1 Be more verbose (shows each command)
# INCLUDE_SUBMODULE=1 Also check submodules
#
# This Makefile does try to go parallel wherever possible, running with a
# reasonable -j level is recommended.
#
# This makefile does NOT check submodule content by default.
#
# If you want to use this in a Git pre-commit hook, I suggest you do:
#------ CUT HERE AND REMOVE FIRST COLUMN: START --------
##!/bin/bash
#syntax_errors=0
#against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 # Empty tree
#git rev-parse --quiet --verify HEAD >/dev/null && against=HEAD
#CHANGES="$(git diff-index --diff-filter=AM --name-only --cached $against | tr '\n' ' ')"
#if [ -n "${CHANGES}" ]; then
# make -j -l4 --silent validate D="${CHANGES}"
# if [ "$?" -ne 0 ]
# then
# syntax_errors=$(($syntax_errors + 1))
# fi
#fi
#
## Whitespace check
#git diff-index --check --cached $against -- || syntax_errors=$(($syntax_errors + 1))
#
## Any other checks you want
#
#[ $syntax_errors -ne 0 ] && exit 1
# exit 0
#------ CUT HERE AND REMOVE FIRST COLUMN: END --------
ROOT_MAKEFILE = $(abspath $(lastword $(MAKEFILE_LIST)))
ROOT_DIR = $(dir $(ROOT_MAKEFILE))
CURRENT_DIR = $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
PUPPET_LINT_VERSION_STRING := $(shell puppet-lint --version 2>&1)
PUPPET_LINT_VERSION := $(word 2,$(PUPPET_LINT_VERSION_STRING))
LINT.PP_DISABLE_CHECKS := --no-80chars-check --no-documentation-check --no-arrow_alignment-check
# puppet lint >=1.1 changes linenumber to line
# this will need improvement in future
ifneq (,$(findstring 1.1,$(PUPPET_LINT_VERSION)))
LINT.PP_MAKE_OUTPUT_FORMAT = --log-format '%{path}:%{line}:%{KIND} %{message}'
else
LINT.PP_MAKE_OUTPUT_FORMAT = --log-format '%{path}:%{linenumber}:%{KIND} %{message}'
endif
LINT.PP = puppet-lint $(LINT.PP_DISABLE_CHECKS) $(LINT.PP_MAKE_OUTPUT_FORMAT)
VALIDATE.PP_OPTS = --parser future --color false --render-as s
VALIDATE.PP = puppet parser validate $(VALIDATE.PP_OPTS)
CORRECT_VIM_FOOTER_CMD := cat $(ROOT_DIR)/vim-modeline.txt
CORRECT_VIM_FOOTER := $(shell $(CORRECT_VIM_FOOTER_CMD) )
# quiet
Q := 0
Q_CMD := $(if $(filter 1,$(Q)),true,)
ECHO := $(Q_CMD) echo
# verbose
V := 0
V_CMD := $(if $(filter 0,$(V)),@,)
# Optionally validate all submodules
INCLUDE_SUBMODULE := 0
SUBMODULE_LIST = $(shell find -mindepth 2 -name .git -printf '%h\n' )
SUBMODULE_LIST_SUFFIX = $(addsuffix /%,$(SUBMODULE_LIST))
SUBMODULE_TRUE :=
SUBMODULE_FALSE := $(SUBMODULE_LIST_SUFFIX)
SUBMODULE_PATTERNS := $(if $(filter 1,$(INCLUDE_SUBMODULE)),$(SUBMODULE_TRUE),$(SUBMODULE_FALSE))
VALIDATE_EXT_AUTO := erb json pp rb yaml
VALIDATE_EXT_MANUAL := sudo
VALIDATE_EXT := $(VALIDATE_EXT_AUTO) $(VALIDATE_EXT_MANUAL)
VALIDATE_TARGETS := $(foreach v,$(VALIDATE_EXT),validate.$(v))
# VALIDATE_EXT_AUTO
FIND_ARGS := $(foreach v,$(VALIDATE_EXT_AUTO),-name '*.$(v)' -o) -false
D_ := $(shell find . $(FIND_ARGS))
D := $(filter-out $(SUBMODULE_PATTERNS),$(D_))
D_ERB := $(filter %.erb,$(D))
D_JSON := $(filter %.json,$(D))
D_PP := $(filter %.pp,$(D))
D_RB := $(filter %.rb,$(D))
D_YAML := $(filter %.yaml,$(D))
# VALIDATE_EXT_MANUAL
ifeq ($(strip $(D)),)
D_SUDO_SRC := .
else
D_SUDO_SRC := $(D)
endif
D_SUDO_ := $(shell find $(D_SUDO_SRC) -path '*sudoers.d*' -exec find \{} -type f ! -name '*.erb' \;)
D_SUDO := $(filter-out $(SUBMODULE_PATTERNS),$(D_SUDO_))
# TODO: ability to disable checks: WIP TODO
ALL_CHECKS := $(VALIDATE_TARGETS) lint.pp.only lint.pp check-footer.pp check-footer.pp.all validate.pp.iterate validate.pp.all
EXCLUDE_CHECKS :=
CHECKS := $(filter-out $(EXCLUDE_CHECKS),$(ALL_CHECKS))
# default target:
all: validate lint check-footer.pp
# Lint and validate targets are summary ones
lint: lint.pp
validate: $(VALIDATE_TARGETS)
# Normally we run both
lint.pp: validate.pp lint.pp.only
# But you can skip the validate if you really want
lint.pp.only: $(D_PP)
ifneq ($(strip $(D_PP)),)
$(V_CMD)for i in $(^); do \
$(ECHO) "(LINT.PP) $$i" ; \
$(LINT.PP) $$i ; \
done
endif
validate.pp: validate.pp.all
validate.pp.all: $(D_PP)
ifneq ($(strip $(D_PP)),)
$(V_CMD)$(ECHO) "(VALIDATE.PP) $^"
$(V_CMD)$(VALIDATE.PP) $^
endif
validate.pp.iterate: $(D_PP)
ifneq ($(strip $(D_PP)),)
$(V_CMD)for i in $(^); do \
$(ECHO) "(VALIDATE.PP) $$i" ; \
$(VALIDATE.PP) $$i ; \
done
endif
validate.rb: $(D_RB)
ifneq ($(strip $(D_RB)),)
$(V_CMD)for i in $(^); do \
$(ECHO) "(VALIDATE.RB) $$i" ; \
ruby -c $$i >/dev/null ; \
done ;
endif
validate.erb: $(D_ERB)
ifneq ($(strip $(D_ERB)),)
$(V_CMD)for i in $(^); do \
$(ECHO) "(VALIDATE.ERB) $$i" ; \
erb -P -x -T - $$i | ruby -c >/dev/null ; \
done ;
endif
validate.yaml: $(D_YAML)
ifneq ($(strip $(D_YAML)),)
$(V_CMD)for i in $(^); do \
$(ECHO) "(VALIDATE.YAML) $$i" ; \
ruby -e "require 'yaml'; YAML.load_file('$$i')" ; \
done
endif
validate.json: $(D_JSON)
ifneq ($(strip $(D_JSON)),)
$(V_CMD)for i in $(^); do \
$(ECHO) "(VALIDATE.JSON) $$i" ; \
ruby -e "require 'json'; JSON.parse((File.new '$$i').read)" ; \
done
endif
validate.sudo: $(D_SUDO)
ifneq ($(strip $(D_SUDO)),)
$(V_CMD)for i in $(^); do \
$(ECHO) "(VALIDATE.SUDO) $$i" ; \
/usr/sbin/visudo -c -f $$i >/dev/null ; \
done ;
endif
T = check-footer.pp
$(T): $(D_PP)
ifeq ($(filter $(T).all,$(CHECKS)),$(T).all)
ifeq ($(filter $(T),$(CHECKS)),$(T))
$(V_CMD)$(ECHO) "(CHECK-VIM-FOOTER.PP) $^"
$(V_CMD)fgrep -x -L '$(CORRECT_VIM_FOOTER)' $^
endif
endif
$(T).all: $(T)
#test:
# @echo INCLUDE_SUBMODULE=$(INCLUDE_SUBMODULE)
# @echo SUBMODULE_LIST=$(SUBMODULE_LIST)
# @echo SUBMODULE_LIST_SUFFIX=$(SUBMODULE_LIST_SUFFIX)
# @echo SUBMODULE_TRUE=$(SUBMODULE_TRUE)
# @echo SUBMODULE_FALSE=$(SUBMODULE_FALSE)
# @echo SUBMODULE_PATTERNS=$(SUBMODULE_PATTERNS)
# @echo D_=$(D_)
# @echo D=$(D)
check: validate
.PHONY: validate lint lint.pp lint.pp.only $(VALIDATE_TARGETS) validate.pp.all validate.pp.iterate check
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment