Created
March 6, 2015 22:50
-
-
Save robbat2/7c947562b52a09642ac6 to your computer and use it in GitHub Desktop.
Makefile for puppet lint & validation (and other filetypes too)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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