| # Set SHELL to 'strict mode' without using .SHELLFLAGS for max compatibility. |
| # See https://fieldnotes.tech/how-to-shell-for-compatible-makefiles/ |
| SHELL := /usr/bin/env bash -euo pipefail -c |
| |
| # CONFIG is the name of the make target someone |
| # would invoke to update the main config file (config.yml). |
| CONFIG ?= ci-config |
| # VERIFY is the name of the make target someone |
| # would invoke to verify the config file. |
| VERIFY ?= ci-verify |
| |
| CIRCLECI := circleci --skip-update-check |
| ifeq ($(DEBUG_CIRCLECI_CLI),YES) |
| CIRCLECI += --debug |
| endif |
| |
| # For config processing, always refer to circleci.com not self-hosted circleci, |
| # because self-hosted does not currently support the necessary API. |
| CIRCLECI_CLI_HOST := https://circleci.com |
| export CIRCLECI_CLI_HOST |
| |
| # Set up some documentation/help message variables. |
| # We do not attempt to install the CircleCI CLI from this Makefile. |
| CCI_INSTALL_LINK := https://circleci.com/docs/2.0/local-cli/\#installation |
| CCI_INSTALL_MSG := Please install CircleCI CLI. See $(CCI_INSTALL_LINK) |
| CCI_VERSION := $(shell $(CIRCLECI) version 2> /dev/null) |
| ifeq ($(CCI_VERSION),) |
| # Attempting to use the CLI fails with installation instructions. |
| CIRCLECI := echo '$(CCI_INSTALL_MSG)'; exit 1; \# |
| endif |
| |
| SOURCE_DIR := config |
| SOURCE_YML := $(shell [ ! -d $(SOURCE_DIR) ] || find $(SOURCE_DIR) -name '*.yml') |
| CONFIG_SOURCE := Makefile $(SOURCE_YML) | $(SOURCE_DIR) |
| OUT := config.yml |
| TMP := .tmp/config-processed |
| CONFIG_PACKED := .tmp/config-packed |
| |
| default: help |
| |
| help: |
| @echo "Usage:" |
| @echo " make $(CONFIG): recompile config.yml from $(SOURCE_DIR)/" |
| @echo " make $(VERIFY): verify that config.yml is a true mapping from $(SOURCE_DIR)/" |
| @echo |
| @echo "Diagnostics:" |
| @[ -z "$(CCI_VERSION)" ] || echo " circleci-cli version $(CCI_VERSION)" |
| @[ -n "$(CCI_VERSION)" ] || echo " $(CCI_INSTALL_MSG)" |
| |
| $(SOURCE_DIR): |
| @echo No source directory $(SOURCE_DIR) found.; exit 1 |
| |
| # Make sure our .tmp dir exists. |
| $(shell [ -d .tmp ] || mkdir .tmp) |
| |
| .PHONY: $(CONFIG) |
| $(CONFIG): $(OUT) |
| |
| .PHONY: $(VERIFY) |
| $(VERIFY): config-up-to-date |
| @$(CIRCLECI) config validate $(OUT) |
| |
| define GENERATED_FILE_HEADER |
| ### *** |
| ### WARNING: DO NOT manually EDIT or MERGE this file, it is generated by 'make $(CONFIG)'. |
| ### INSTEAD: Edit or merge the source in $(SOURCE_DIR)/ then run 'make $(CONFIG)'. |
| ### *** |
| endef |
| export GENERATED_FILE_HEADER |
| |
| # GEN_CONFIG writes the config to a temporary file. If the whole process succeeds, |
| # it them moves that file to $@. This makes it an atomic operation, so if it fails |
| # make doesn't consider a half-baked file up to date. |
| define GEN_CONFIG |
| @$(CIRCLECI) config pack $(SOURCE_DIR) > $(CONFIG_PACKED) |
| @echo "$$GENERATED_FILE_HEADER" > $@.tmp || { rm -f $@; exit 1; } |
| @$(CIRCLECI) config process $(CONFIG_PACKED) >> $@.tmp || { rm -f $@.tmp; exit 1; } |
| @mv -f $@.tmp $@ |
| endef |
| |
| $(OUT): $(CONFIG_SOURCE) |
| $(GEN_CONFIG) |
| @echo "$@ updated" |
| |
| $(TMP): $(CONFIG_SOURCE) |
| $(GEN_CONFIG) |
| |
| .PHONY: config-up-to-date |
| config-up-to-date: $(TMP) # Note this must not depend on $(OUT)! |
| @if diff -w $(OUT) $<; then \ |
| echo "Generated $(OUT) is up to date!"; \ |
| else \ |
| echo "Generated $(OUT) is out of date, run make $(CONFIG) to update."; \ |
| exit 1; \ |
| fi |