Last active
April 4, 2019 22:17
-
-
Save robbat2/28386d30a8d6810d5bbe3621c48110b4 to your computer and use it in GitHub Desktop.
Makefile for git precommit
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)))) | |
# Autogenerated files | |
AUTOGEN = hieradata/puppet/automated.yaml | |
PUPPET_VERSION := $(shell puppet --version) | |
PUPPET_PARSER_VALIDATE_PARSER_OPT = $(shell puppet parser validate --help) | |
LINT.PP_DISABLE_CHECKS := \ | |
--no-80chars-check \ | |
--no-documentation-check \ | |
--no-arrow_alignment-check \ | |
--no-140chars-check | |
LINT.PP_MAKE_OUTPUT_FORMAT = --log-format '%{path}:%{line}:%{KIND} %{message}' | |
ifdef LINT_LAZY | |
LINT.PP_DISABLE_CHECKS += \ | |
--no-2sp_soft_tabs-check \ | |
--no-arrow_alignment-check \ | |
--no-double_quoted_strings-check \ | |
--no-ensure_first_param-check \ | |
--no-hard_tabs-check \ | |
--no-only_variable_string-check \ | |
--no-selector_inside_resource-check \ | |
endif | |
LINT.PP = puppet-lint --fail-on-warnings \ | |
$(LINT.PP_DISABLE_CHECKS) $(LINT.PP_MAKE_OUTPUT_FORMAT) | |
LINTFIX.PP = $(LINT.PP) --fix | |
VALIDATE.PP_OPTS = --color false --render-as s | |
# Puppet 2.x did not have it, and newer versions of Puppet 4 do not have it. | |
ifneq (,$(findstring --parser.,$(PUPPET_PARSER_VALIDATE_PARSER_OPT))) | |
VALIDATE.PP_OPTS += --parser future | |
endif | |
VALIDATE.PP = puppet parser validate $(VALIDATE.PP_OPTS) | |
CORRECT_VIM_FOOTER_SRCFILE = $(ROOT_DIR)/STYLE-GUIDE.md | |
ifneq (,$(wildcard $(CORRECT_VIM_FOOTER_SRCFILE))) | |
CORRECT_VIM_FOOTER_CMD := grep '^..vim:' $(CORRECT_VIM_FOOTER_SRCFILE) | |
CORRECT_VIM_FOOTER := $(shell $(CORRECT_VIM_FOOTER_CMD) ) | |
endif | |
# quiet | |
Q := 0 | |
Q_CMD := $(if $(filter 1,$(Q)),true,) | |
ECHO := $(Q_CMD) echo | |
MAKEOPT_Q := $(if $(filter 1,$(Q)),--no-print-directory,--print-directory) | |
# 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 eyaml | |
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)) \ | |
$(filter %.eyaml,$(D)) \ | |
$(filter %.tmp-yaml,$(D)) \ | |
$(filter %.tmp-eyaml,$(D)) | |
# targets for each validated file | |
D_ERB_TARGETS := $(patsubst %,%.validate,$(D_ERB)) | |
D_JSON_TARGETS := $(patsubst %,%.validate,$(D_JSON)) | |
D_PP_LINT_TARGETS := $(patsubst %,%.lint,$(D_PP)) | |
D_PP_LINTFIX_TARGETS := $(patsubst %,%.lint-fix,$(D_PP)) | |
D_PP_VALIDATE_TARGETS := $(patsubst %,%.validate,$(D_PP)) | |
D_RB_TARGETS := $(patsubst %,%.validate,$(D_RB)) | |
D_YAML_TARGETS := $(patsubst %,%.validate,$(D_YAML)) | |
# 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 | |
# helper | |
check: validate | |
# autogenerated files | |
autogen: $(AUTOGEN) | |
# Lint and validate targets are summary ones | |
lint-fix: lint-fix.pp | |
lint: lint.pp | |
validate: $(VALIDATE_TARGETS) | |
# Normally we run both | |
lint.pp: validate.pp lint.pp.only | |
lint-fix.pp: lint-fix.pp.only | |
# But you can skip the validate if you really want | |
%.pp.lint: %.pp | |
$(V_CMD)$(ECHO) "(LINT.PP) $<" ; \ | |
$(LINT.PP) $< | |
%.pp.lint-fix: %.pp | |
$(V_CMD)$(ECHO) "(LINTFIX.PP) $<" ; \ | |
$(LINTFIX.PP) $< | |
lint.pp.only: $(D_PP_LINT_TARGETS) | |
lint-fix.pp.only: $(D_PP_LINTFIX_TARGETS) | |
validate.pp: validate.pp.all | |
validate.pp.all: $(D_PP) | |
ifneq ($(strip $(D_PP)),) | |
$(V_CMD)$(ECHO) "(VALIDATE.PP) $^" | |
$(V_CMD)$(VALIDATE.PP) $^ | |
endif | |
%.pp.validate: %.pp | |
$(V_CMD)$(ECHO) "(VALIDATE.PP) $<" ; \ | |
$(VALIDATE.PP) $< | |
validate.pp.iterate: $(D_PP_VALIDATE_TARGETS) | |
%.rb.validate: %.rb | |
$(V_CMD)$(ECHO) "(VALIDATE.RB) $<" ; \ | |
ruby -c $< >/dev/null | |
validate.rb: $(D_RB_TARGETS) | |
%.erb.validate: %.erb | |
$(V_CMD)$(ECHO) "(VALIDATE.ERB) $<" ; \ | |
erb -P -x -T - $< | ruby -c >/dev/null | |
validate.erb: $(D_ERB_TARGETS) | |
%.tmp-yaml.validate: %.tmp-yaml | |
$(V_CMD)$(ECHO) "(VALIDATE.TMP-YAML) $<" ; \ | |
ruby -e "require 'yaml'; YAML.load_file('$<')" | |
%.yaml.validate: %.yaml | |
$(V_CMD)$(ECHO) "(VALIDATE.YAML) $<" ; \ | |
ruby -e "require 'yaml'; YAML.load_file('$<')" | |
%.tmp-eyaml.validate: %.tmp-eyaml | |
$(V_CMD)$(ECHO) "(VALIDATE.TMP-YAML) $<" ; \ | |
ruby -e "require 'yaml'; YAML.load_file('$<')" | |
%.eyaml.validate: %.eyaml | |
$(V_CMD)$(ECHO) "(VALIDATE.YAML) $<" ; \ | |
ruby -e "require 'yaml'; YAML.load_file('$<')" | |
validate.yaml: $(D_YAML_TARGETS) | |
%.json.validate: %.json | |
$(V_CMD)$(ECHO) "(VALIDATE.JSON) $<" ; \ | |
ruby -e "require 'json'; JSON.parse((File.new '$<').read)" | |
validate.json: $(D_JSON_TARGETS) | |
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 | |
CORRECT_VIM_FOOTER_PP = check-footer.pp | |
$(CORRECT_VIM_FOOTER_PP): $(D_PP) | |
ifneq (,$(CORRECT_VIM_FOOTER)) | |
ifneq ($(strip $(D_PP)),) | |
ifeq ($(filter $(CORRECT_VIM_FOOTER_PP).all,$(CHECKS)),$(CORRECT_VIM_FOOTER_PP).all) | |
ifeq ($(filter $(CORRECT_VIM_FOOTER_PP),$(CHECKS)),$(CORRECT_VIM_FOOTER_PP)) | |
$(V_CMD)$(ECHO) "(CHECK-VIM-FOOTER.PP) $^" | |
$(V_CMD)fgrep -x -L '$(CORRECT_VIM_FOOTER)' $^ | |
endif | |
endif | |
endif | |
endif | |
$(CORRECT_VIM_FOOTER_PP).all: $(CORRECT_VIM_FOOTER_PP) | |
#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) | |
.PRECIOUS: %.tmp-yaml | |
%.tmp-yaml: %.yaml.erb %.yaml.erb.validate | |
$(V_CMD)$(ECHO) "(YAML.ERB) $^" | |
$(V_CMD)erb "$(<)" >"$(@)" || rm -f "$(@).tmp" | |
%.yaml: %.tmp-yaml %.tmp-yaml.validate | |
$(V_CMD)$(ECHO) "(TMP.YAML) $^" | |
$(V_CMD)mv -f "$(<)" "$(@)" | |
.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