diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 2d27b0df..51270a69 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -17,7 +17,9 @@ jobs: - name: Go unit tests run: make go-test - integration: + upload: needs: go-test - uses: ./.github/workflows/tests-integration.yaml + uses: ./.github/workflows/upload.yaml secrets: inherit + with: + region: us-west-2 diff --git a/.github/workflows/upload.yaml b/.github/workflows/upload.yaml new file mode 100644 index 00000000..470de77e --- /dev/null +++ b/.github/workflows/upload.yaml @@ -0,0 +1,66 @@ +name: Upload assets + +on: + # pull_request: + workflow_dispatch: + inputs: + region: + type: string + description: 'Restrict packaging for a single region' + required: true + workflow_call: + inputs: + region: + type: string + description: 'Restrict packaging for a single region' + required: true + +env: + SAM_CLI_TELEMETRY: 0 + +jobs: + permission_check: + runs-on: ubuntu-latest + outputs: + can-write: ${{ steps.check.outputs.can-write }} + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + steps: + - id: check + run: | + # If the AWS_ACCESS_KEY_ID secret is MIA we can't run tests + if [[ -z "$AWS_ACCESS_KEY_ID" ]]; then + echo "can-write=false" >> $GITHUB_OUTPUT + else + echo "can-write=true" >> $GITHUB_OUTPUT + fi + + upload: + needs: [permission_check] + if: needs.permission_check.outputs.can-write == 'true' + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Fetch tags for versioning + # TODO: skip if version is passed in + run: git fetch --prune --unshallow --tags + + - name: Setup AWS credentials + uses: aws-actions/configure-aws-credentials@v4.0.2 + with: + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + aws-region: us-west-2 + + - name: AWS Info + run: aws sts get-caller-identity + + - name: Build and upload SAM apps + run: | + make sam-upload${{ inputs.region && '-' }}${{ inputs.region }} + env: + MAKEFLAGS: "-j 8" + S3_BUCKET_PREFIX: "observeinc-" diff --git a/Makefile b/Makefile index 07f19a80..f6db8454 100644 --- a/Makefile +++ b/Makefile @@ -16,44 +16,114 @@ MAKEFLAGS += --no-builtin-rules MAKEFLAGS += --warn-undefined-variables .SUFFIXES: -VERSION ?= $(shell git describe --tags --always --dirty) - --include golang.mk - - - -APPS := $(shell find apps/* -type d -maxdepth 0 -exec basename {} \;) -AWS_REGION ?= us-west-2 -AWS_REGIONS := us-west-2 \ - us-west-1 \ - us-east-2 \ - us-east-1 \ - sa-east-1 \ - eu-west-3 \ - eu-west-2 \ - eu-west-1 \ - eu-north-1 \ - eu-central-1 \ - ca-central-1 \ - ap-southeast-2 \ - ap-southeast-1 \ - ap-south-1 \ - ap-northeast-3 \ - ap-northeast-2 \ - ap-northeast-1 \ - -# leave this undefined for the purposes of development -S3_BUCKET_PREFIX ?= -SAM_BUILD_DIR ?= .aws-sam/build -SAM_CONFIG_FILE ?= $(shell pwd)/samconfig.yaml -SAM_CONFIG_ENV ?= default -TF_TESTS ?= $(shell ls integration/tests | awk -F. '{print $$1}') -TF_TEST_DEBUG ?= 0 -TF_TEST_ARGS ?= +-include variables.mk + +LAMBDA_MAKEFILE = bin/$(OS)_$(ARCH)/Makefile + +$(LAMBDA_MAKEFILE): $(GO_BUILD_DIRS) + cp lambda.mk $@ .PHONY: clean clean: # @HELP removes built binaries and temporary files -clean: bin-clean +clean: go-clean sam-clean + +$(GO_BUILD_DIRS): + mkdir -p $@ + +# The following structure defeats Go's (intentional) behavior to always touch +# result files, even if they have not changed. This will still run `go` but +# will not trigger further work if nothing has actually changed. +GO_OUTBINS = $(foreach bin,$(GO_BINS),bin/$(OS)_$(ARCH)/$(bin)) + +go-build: # @HELP build Go binaries +go-build: $(GO_OUTBINS) + echo + +# Each outbin target is just a facade for the respective stampfile target. +# This `eval` establishes the dependencies for each. +$(foreach outbin,$(GO_OUTBINS),$(eval \ + $(outbin): .go/$(outbin).stamp \ +)) + +# This is the target definition for all outbins. +$(GO_OUTBINS): + true + +# Each stampfile target can reference an $(OUTBIN) variable. +$(foreach outbin,$(GO_OUTBINS),$(eval $(strip \ + .go/$(outbin).stamp: OUTBIN = $(outbin) \ +))) + +# This is the target definition for all stampfiles. +# This will build the binary under ./.go and update the real binary iff needed. +GO_STAMPS = $(foreach outbin,$(GO_OUTBINS),.go/$(outbin).stamp) +.PHONY: $(GO_STAMPS) +$(GO_STAMPS): go-build-bin + echo -ne "binary: $(OUTBIN) " + if ! cmp -s .go/$(OUTBIN) $(OUTBIN); then \ + mv .go/$(OUTBIN) $(OUTBIN); \ + date >$@; \ + echo; \ + else \ + echo "(cached)"; \ + fi + +# This runs the actual `go build` which updates all binaries. +go-build-bin: | $(GO_BUILD_DIRS) + $(call check_var,VERSION) + echo "# building $(VERISON) for $(OS)/$(ARCH)" + docker run \ + -i \ + --rm \ + -u $$(id -u):$$(id -g) \ + -v $$(pwd):/src \ + -w /src \ + -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin \ + -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin/$(OS)_$(ARCH) \ + -v $$(pwd)/.go/cache:/.cache \ + -v $$(pwd)/.go/pkg:/go/pkg \ + --env CGO_ENABLED=0 \ + --env GOARCH=$(ARCH) \ + --env GOFLAGS="$(GOFLAGS) -mod=$(GO_MOD)" \ + --env GOOS=$(OS) \ + $(GO_BUILD_IMAGE) \ + /bin/sh -c " \ + go install \ + -installsuffix \"static\" \ + -ldflags \"-X $$(go list -m)/pkg/version.Version=${VERSION}\" \ + ./... \ + " + +go-clean: # @HELP clean Go temp files +go-clean: + test -d .go && chmod -R u+w .go || true + rm -rf .go bin + +go-test: # @HELP run Go unit tests +go-test: | $(GO_BUILD_DIRS) + docker run \ + -i \ + --rm \ + -u $$(id -u):$$(id -g) \ + -v $$(pwd):/src \ + -w /src \ + -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin \ + -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin/$(OS)_$(ARCH) \ + -v $$(pwd)/.go/cache:/.cache \ + -v $$(pwd)/.go/pkg:/go/pkg \ + --env CGO_ENABLED=0 \ + --env GOFLAGS="$(GOFLAGS) -mod=$(GO_MOD)" \ + $(GO_BUILD_IMAGE) \ + /bin/sh -c " \ + go test -installsuffix "static" ./... \ + " + +go-lint: # @HELP lint Go workspace +go-lint: + docker run --rm -v "$$(pwd):/workspace:cached" -w "/workspace/." golangci/golangci-lint:latest golangci-lint run --timeout 3m && echo "lint passed" + +sam-clean: # @HELP remove SAM build directory +sam-clean: rm -rf $(SAM_BUILD_DIR) SAM_BUILD_TEMPLATES = $(foreach app,$(APPS), $(SAM_BUILD_DIR)/apps/$(app)/template.yaml) @@ -62,14 +132,14 @@ $(foreach template,$(SAM_BUILD_TEMPLATE),$(eval \ $(template): apps/$(call get_app, $(template))/template.yaml \ )) -$(SAM_BUILD_TEMPLATES): go-build bin/Makefile +$(SAM_BUILD_TEMPLATES): go-build $(LAMBDA_MAKEFILE) sam build \ - -p \ - -beta-features \ - --template-file $(patsubst $(SAM_BUILD_DIR)/%,%,$@) \ - --build-dir $(patsubst %template.yaml,%,$@) \ - --config-file $(SAM_CONFIG_FILE) \ - --config-env $(SAM_CONFIG_ENV) + -p \ + -beta-features \ + --template-file $(patsubst $(SAM_BUILD_DIR)/%,%,$@) \ + --build-dir $(patsubst %template.yaml,%,$@) \ + --config-file $(SAM_CONFIG_FILE) \ + --config-env $(SAM_CONFIG_ENV) SAM_PACKAGE_TARGETS = $(foreach app,$(APPS),sam-package-$(app)) @@ -79,6 +149,10 @@ $(foreach target,$(SAM_PACKAGE_TARGETS),$(eval \ $(target): $(SAM_BUILD_DIR)/regions/$(AWS_REGION)/$(lastword $(subst -, , $(target))).yaml \ )) +define check_var + @[[ -n "$($1)" ]] || (echo >&2 "The environment variable '$1' is not set." && exit 2) +endef + define get_region $(lastword $(subst /, ,$(basename $(dir $(1))))) endef @@ -100,26 +174,48 @@ $(SAM_PACKAGE_DIRS): $(SAM_PACKAGE_TEMPLATES): | $(SAM_PACKAGE_DIRS) ifeq ($(S3_BUCKET_PREFIX),) sam package \ - --template-file $(SAM_BUILD_DIR)/apps/$(call get_app, $@)/template.yaml \ - --output-template-file $@ \ - --region $(call get_region, $@) \ - --resolve-s3 \ - --s3-prefix aws-sam-apps/$(VERSION) \ - --no-progressbar \ - --config-file $(SAM_CONFIG_FILE) \ - --config-env $(SAM_CONFIG_ENV) + --template-file $(SAM_BUILD_DIR)/apps/$(call get_app, $@)/template.yaml \ + --output-template-file $@ \ + --region $(call get_region, $@) \ + --resolve-s3 \ + --s3-prefix aws-sam-apps/$(VERSION) \ + --no-progressbar \ + --config-file $(SAM_CONFIG_FILE) \ + --config-env $(SAM_CONFIG_ENV) else sam package \ - --template-file apps/$(call get_app, $@)/template.yaml \ - --output-template-file $@ \ - --region $(call get_region, $@) \ - --s3-bucket "$(S3_BUCKET_PREFIX)$(call get_region, $@)" \ - --s3-prefix aws-sam-apps/$(VERSION) \ - --no-progressbar \ - --config-file $(SAM_CONFIG_FILE) \ - --config-env $(SAM_CONFIG_ENV) + --template-file $(SAM_BUILD_DIR)/apps/$(call get_app, $@)/template.yaml \ + --output-template-file $@ \ + --region $(call get_region, $@) \ + --s3-bucket "$(S3_BUCKET_PREFIX)$(call get_region, $@)" \ + --s3-prefix aws-sam-apps/$(VERSION) \ + --no-progressbar \ + --config-file $(SAM_CONFIG_FILE) \ + --config-env $(SAM_CONFIG_ENV) endif +SAM_UPLOAD_REGION_TARGETS = $(foreach region,$(AWS_REGIONS),sam-upload-$(region)) + +$(foreach target,$(SAM_UPLOAD_REGION_TARGETS),$(eval \ + $(target): $(foreach app,$(APPS), $(SAM_BUILD_DIR)/regions/$(subst sam-upload-,,$(target))/$(app).yaml) \ +)) + +require_bucket_prefix: + $(call check_var,S3_BUCKET_PREFIX) + +.PHONY: $(SAM_UPLOAD_REGION_TARGETS) +$(SAM_UPLOAD_REGION_TARGETS): require_bucket_prefix + # ensure all previously uploaded assets are public + aws s3 cp \ + --acl public-read \ + --recursive \ + s3://$(S3_BUCKET_PREFIX)$(subst sam-upload-,,$@)/aws-sam-apps/$(VERSION)/ s3://$(S3_BUCKET_PREFIX)$(subst sam-upload-,,$@)/aws-sam-apps/$(VERSION)/ + # upload base manifests + aws s3 cp \ + --acl public-read \ + --recursive \ + $(SAM_BUILD_DIR)/regions/$(subst sam-upload-,,$@)/ s3://$(S3_BUCKET_PREFIX)$(subst sam-upload-,,$@)/aws-sam-apps/$(VERSION)/ + SAM_VALIDATE_TARGETS = $(foreach app,$(APPS),sam-validate-$(app)) .PHONY: $(SAM_VALIDATE_TARGETS) @@ -138,38 +234,48 @@ test-init: .PHONY: $(TEST_INTEGRATION_TARGETS) $(TEST_INTEGRATION_TARGETS): test-init if [ "$(TF_TEST_DEBUG)" = "1" ]; then \ - CHECK_DEBUG_FILE=debug.sh terraform -chdir=integration test -filter=tests/$(lastword $(subst -, ,$@)).tftest.hcl $(TF_TEST_ARGS); \ + CHECK_DEBUG_FILE=debug.sh terraform -chdir=integration test -filter=tests/$(lastword $(subst -, ,$@)).tftest.hcl $(TF_TEST_ARGS); \ else \ - terraform -chdir=integration test -filter=tests/$(lastword $(subst -, ,$@)).tftest.hcl $(TF_TEST_ARGS); \ + terraform -chdir=integration test -filter=tests/$(lastword $(subst -, ,$@)).tftest.hcl $(TF_TEST_ARGS); \ fi -.PHONY: release -release: $(SAM_PACKAGE_TEMPLATES) - .PHONY: sam-package -sam-package: # @HELP package all SAM templates. For specific app append name (e.g sam-package-forwarder) +sam-package: # @HELP package all SAM templates. sam-package: $(SAM_PACKAGE_TARGETS) +sam-package-%: # @HELP package specific SAM app (e.g sam-package-forwarder). + +.PHONY: sam-upload +sam-upload: # @HELP upload SAM assets to S3 to all regions. +sam-upload: $(SAM_UPLOAD_REGION_TARGETS) + +sam-upload-%: # @HELP upload all SAM apps to specific region (e.g sam-upload-us-west-2) + .PHONY: sam-validate -sam-validate: # @HELP validate all SAM templates. For specific app append name (e.g sam-validate-logwriter) +sam-validate: # @HELP validate all SAM templates. sam-validate: $(SAM_VALIDATE_TARGETS) +sam-validate-%: # @HELP validate specific SAM app (e.g. sam-validate-logwriter). + .PHONY: test-integration -test-integration: # @HELP run all integration tests. For specific test append name (e.g test-integration-stack) +test-integration: # @HELP run all integration tests test-integration: $(TEST_INTEGRATION_TARGETS) +test-integration-%: # @HELP run specific integration test (e.g. test-integration-stack). help: # @HELP displays this message help: echo "VARIABLES:" - echo " APPS = $(APPS)" - echo " AWS_REGION = $(AWS_REGION)" - echo " BINS = $(BINS)" - echo " TF_TESTS = $(TF_TESTS)" - echo " VERSION = $(VERSION)" + echo " APPS = $(APPS)" + echo " AWS_REGION = $(AWS_REGION)" + echo " GO_BINS = $(GO_BINS)" + echo " GO_BUILD_DIRS = $(GO_BUILD_DIRS)" + echo " TF_TESTS = $(TF_TESTS)" + echo " VERSION = $(VERSION)" echo echo "TARGETS:" - grep -E '^.*: *# *@HELP' $(MAKEFILE_LIST) \ + $(call check_var,VERSION) + grep -E '^.*: *# *@HELP' $(MAKEFILE_LIST) | cut -d':' -f2- \ | awk ' \ BEGIN {FS = ": *# *@HELP"}; \ { printf " %-30s %s\n", $$1, $$2 }; \ diff --git a/apps/forwarder/template.yaml b/apps/forwarder/template.yaml index cda06be3..61187173 100644 --- a/apps/forwarder/template.yaml +++ b/apps/forwarder/template.yaml @@ -388,7 +388,7 @@ Resources: - !Ref AWS::StackName - !Ref NameOverride Role: !GetAtt Role.Arn - CodeUri: ../../bin/ + CodeUri: ../../bin/linux_arm64 Handler: bootstrap Runtime: provided.al2 MemorySize: !If diff --git a/apps/logwriter/template.yaml b/apps/logwriter/template.yaml index cecf578b..9dc2e306 100644 --- a/apps/logwriter/template.yaml +++ b/apps/logwriter/template.yaml @@ -422,7 +422,7 @@ Resources: - !Ref AWS::StackName - !Ref NameOverride Role: !GetAtt SubscriberRole.Arn - CodeUri: ../../bin/ + CodeUri: ../../bin/linux_arm64 Handler: bootstrap Runtime: provided.al2 MemorySize: !If diff --git a/golang.mk b/golang.mk deleted file mode 100644 index 95f71cea..00000000 --- a/golang.mk +++ /dev/null @@ -1,112 +0,0 @@ -BINS := forwarder subscriber - -GO_BUILD_IMAGE ?= golang:1.22-alpine - -OS := $(if $(GOOS),$(GOOS),linux) -ARCH := $(if $(GOARCH),$(GOARCH),arm64) - -# Which Go modules mode to use ("mod" or "vendor") -MOD ?= vendor - -# Satisfy --warn-undefined-variables. -GOFLAGS ?= - -# The following structure defeats Go's (intentional) behavior to always touch -# result files, even if they have not changed. This will still run `go` but -# will not trigger further work if nothing has actually changed. -GO_OUTBINS = $(foreach bin,$(BINS),bin/$(OS)_$(ARCH)/$(bin)) - -go-build: $(GO_OUTBINS) - echo - -# Directories that we need created to build/test. -GO_BUILD_DIRS := bin/$(OS)_$(ARCH) \ - .go/bin/$(OS)_$(ARCH) \ - .go/cache \ - .go/pkg - -$(GO_BUILD_DIRS): - mkdir -p $@ - -# Each outbin target is just a facade for the respective stampfile target. -# This `eval` establishes the dependencies for each. -$(foreach outbin,$(GO_OUTBINS),$(eval \ - $(outbin): .go/$(outbin).stamp \ -)) - -# This is the target definition for all outbins. -$(GO_OUTBINS): - true - -# Each stampfile target can reference an $(OUTBIN) variable. -$(foreach outbin,$(GO_OUTBINS),$(eval $(strip \ - .go/$(outbin).stamp: OUTBIN = $(outbin) \ -))) - -# This is the target definition for all stampfiles. -# This will build the binary under ./.go and update the real binary iff needed. -STAMPS = $(foreach outbin,$(GO_OUTBINS),.go/$(outbin).stamp) -.PHONY: $(STAMPS) -$(STAMPS): go-build-bin - echo -ne "binary: $(OUTBIN) " - if ! cmp -s .go/$(OUTBIN) $(OUTBIN); then \ - mv .go/$(OUTBIN) $(OUTBIN); \ - date >$@; \ - echo; \ - else \ - echo "(cached)"; \ - fi - -# This runs the actual `go build` which updates all binaries. -go-build-bin: | $(GO_BUILD_DIRS) - echo "# building $(VERSION) for $(OS)/$(ARCH)" - docker run \ - -i \ - --rm \ - -u $$(id -u):$$(id -g) \ - -v $$(pwd):/src \ - -w /src \ - -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin/$(OS)_$(ARCH) \ - -v $$(pwd)/.go/cache:/.cache \ - -v $$(pwd)/.go/pkg:/go/pkg \ - --env GOARCH=$(ARCH) \ - --env GOOS=$(OS) \ - $(GO_BUILD_IMAGE) \ - /bin/sh -c " \ - go install \ - -installsuffix \"static\" \ - -ldflags \"-X $$(go list -m)/pkg/version.Version=${VERSION}\" \ - ./... \ - " - -bin/Makefile: $(GO_BUILD_DIRS) - cp lambda.mk $@ - -bin-clean: - test -d .go && chmod -R u+w .go || true - rm -rf .go bin - -go-test: | $(GO_BUILD_DIRS) - docker run \ - -i \ - --rm \ - -u $$(id -u):$$(id -g) \ - -v $$(pwd):/src \ - -w /src \ - -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin \ - -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin/$(OS)_$(ARCH) \ - -v $$(pwd)/.go/cache:/.cache \ - -v $$(pwd)/.go/pkg:/go/pkg \ - $(GO_BUILD_IMAGE) \ - /bin/sh -c " \ - ARCH=$(ARCH) \ - OS=$(OS) \ - VERSION=$(VERSION) \ - MOD=$(MOD) \ - GOFLAGS=$(GOFLAGS) \ - go test -installsuffix "static" ./... \ - " - -go-lint: # @HELP lint golang workspace -go-lint: - docker run --rm -v "$$(pwd):/workspace:cached" -w "/workspace/." golangci/golangci-lint:latest golangci-lint run --timeout 3m && echo "lint passed" diff --git a/lambda.mk b/lambda.mk index e844f176..8c57be83 100644 --- a/lambda.mk +++ b/lambda.mk @@ -1,5 +1,17 @@ +# This makefile is called by `sam package` when it is assembling template assets +# We do not compile the binaries in this Makefile. Instead, we rely on our +# Makefile to have already compiled everything prior to reaching this stage. +# +# This Makefile is copied into the Go build directory where it can be invoked by SAM. +# We do this because SAM will copy over the entire directory referenced in the +# CodeUri field. Relying on our root Makefile incurs a lot of delay due to the +# large number of files that would be copied over. +# +# SAM invokes this makefile with the target `build-`. We name our +# lambda function resources according to the binary name, but capitalize them +# for consistency with the remainder of the SAM template. We must therefore +# make the copy case insensitive. strip_and_lowercase = $(shell echo $(1) | sed 's/^build-//' | tr '[:upper:]' '[:lower:]') build-%: - cp linux_arm64/$(call strip_and_lowercase,$@) $(ARTIFACTS_DIR)/bootstrap - + cp $(call strip_and_lowercase,$@) $(ARTIFACTS_DIR)/bootstrap diff --git a/variables.mk b/variables.mk new file mode 100644 index 00000000..2f0aaf26 --- /dev/null +++ b/variables.mk @@ -0,0 +1,59 @@ +# Each directory under apps/* must contain a validate SAM template +APPS := $(shell find apps/* -type d -maxdepth 0 -exec basename {} \;) + +# This is our default region when not provided. +AWS_REGION ?= us-west-2 + +# List of regions supported by `make sam-upload-*`. +AWS_REGIONS := us-west-2 \ + us-west-1 \ + us-east-2 \ + us-east-1 \ + sa-east-1 \ + eu-west-3 \ + eu-west-2 \ + eu-west-1 \ + eu-north-1 \ + eu-central-1 \ + ca-central-1 \ + ap-southeast-2 \ + ap-southeast-1 \ + ap-south-1 \ + ap-northeast-3 \ + ap-northeast-2 \ + ap-northeast-1 \ + +# Assume lambda functions are linux/arm64 +# These variables must be defined before GO_BUILD_DIRS +OS := $(if $(GOOS),$(GOOS),linux) +ARCH := $(if $(GOARCH),$(GOARCH),arm64) + +# Names of binaries to compile as lambda functions +GO_BINS := forwarder subscriber +# Directories that we need created to build/test. +GO_BUILD_DIRS := bin/$(OS)_$(ARCH) \ + .go/bin/$(OS)_$(ARCH) \ + .go/cache \ + .go/pkg +# Build image to use for building lambda functions +GO_BUILD_IMAGE ?= golang:1.22-alpine +# Which Go modules mode to use ("mod" or "vendor") +GO_MOD ?= vendor +GOFLAGS ?= + +# Bucket prefix used when running `sam-upload-*`. This can be omitted for +# development purposes, in which case the `sam package` command will provision +# a bucket. +S3_BUCKET_PREFIX ?= +SAM_BUILD_DIR ?= .aws-sam/build +SAM_CONFIG_FILE ?= $(shell pwd)/samconfig.yaml +SAM_CONFIG_ENV ?= default + +# List of tftests supported by `make test-integration-*` +TF_TESTS ?= $(shell ls integration/tests | awk -F. '{print $$1}') +# Setting this flag to 1 will enable verbose logging and allow debugging of checks. +TF_TEST_DEBUG ?= 0 +TF_TEST_ARGS ?= + +# Version should only be overridden in CI. Cannot be empty. +VERSION ?= $(shell git describe --tags --always --dirty)