Often, I find myself needing to read JSON configs in a Makefile into variables that are used across targets, resulting in multiple jq
calls, one for each variable. Recently, I discovered a more efficient method by packing them into a single jq
call. This call queries all the variables, converts the results into tab-separated values, and then uses the word
function to split them into variables. Additionally, I added a check to ensure that the variable is present in the config file.
CONFIG_FILE = config.json
# load config file
CONFIG_VALUES := $(shell jq -rc '[\
.projectName // false \
, .glbProjectName // false \
, .$(ENV).domain.name // .default.domain.name // false \
, .$(ENV).region // .default.region // false \
, .$(ENV).domain.hostedZoneId // .default.domain.hostedZoneId // false \
, .$(ENV).logsRetentionInDays // .default.logsRetentionInDays // false \
, .$(ENV).errorResponseFileKey // .default.errorResponseFileKey // "404.html" \
] | @tsv' $(CONFIG_FILE))
# extract vars from config file
read_config_var = $(word $(1), $(CONFIG_VALUES))
PROJECT_NAME := $(call read_config_var,1)
GLB_PROJECT_NAME := $(call read_config_var,2)
DOMAIN := $(call read_config_var,3)
INFRA_REGION := $(call read_config_var,4)
HOSTED_ZONE_ID := $(call read_config_var,5)
LOGS_RETENTION_IN_DAYS := $(call read_config_var,6)
ERROR_RESPONSE_FILE := $(call read_config_var,7)
# validate that required config vars are set
assert_set = $(if $(filter $(1),false),$(error $(1) is not set),)
$(call assert_set,$(PROJECT_NAME))
$(call assert_set,$(GLB_PROJECT_NAME))
$(call assert_set,$(DOMAIN))
$(call assert_set,$(INFRA_REGION))
$(call assert_set,$(HOSTED_ZONE_ID))
$(call assert_set,$(LOGS_RETENTION_IN_DAYS))
$(call assert_set,$(ERROR_RESPONSE_FILE))