mirror of
https://github.com/anchore/grype
synced 2024-11-10 14:44:12 +00:00
d5ced7fb81
Fix the race conditions from setting stage.Current from multiple go routines by upgrading to a newer version of go-progress that includes an atomic version of stager and using that. Enable race detection on unit tests, and on a single invocation of the main command under the integration target. Signed-off-by: Will Murphy <will.murphy@anchore.com>
357 lines
12 KiB
Makefile
357 lines
12 KiB
Makefile
BIN := grype
|
|
TEMP_DIR := ./.tmp
|
|
|
|
# Command templates #################################
|
|
LINT_CMD := $(TEMP_DIR)/golangci-lint run --tests=false
|
|
GOIMPORTS_CMD := $(TEMP_DIR)/gosimports -local github.com/anchore
|
|
RELEASE_CMD := $(TEMP_DIR)/goreleaser release --clean
|
|
SNAPSHOT_CMD := $(RELEASE_CMD) --skip-publish --skip-sign --snapshot
|
|
CHRONICLE_CMD = $(TEMP_DIR)/chronicle
|
|
GLOW_CMD = $(TEMP_DIR)/glow
|
|
|
|
# Tool versions #################################
|
|
GOLANGCILINT_VERSION := v1.54.2
|
|
GOSIMPORTS_VERSION := v0.3.8
|
|
BOUNCER_VERSION := v0.4.0
|
|
CHRONICLE_VERSION := v0.7.0
|
|
GORELEASER_VERSION := v1.20.0
|
|
YAJSV_VERSION := v1.4.1
|
|
QUILL_VERSION := v0.4.1
|
|
GLOW_VERSION := v1.5.1
|
|
SKOPEO_VERSION := v1.12.0
|
|
|
|
# Formatting variables ############################
|
|
BOLD := $(shell tput -T linux bold)
|
|
PURPLE := $(shell tput -T linux setaf 5)
|
|
GREEN := $(shell tput -T linux setaf 2)
|
|
CYAN := $(shell tput -T linux setaf 6)
|
|
RED := $(shell tput -T linux setaf 1)
|
|
RESET := $(shell tput -T linux sgr0)
|
|
TITLE := $(BOLD)$(PURPLE)
|
|
SUCCESS := $(BOLD)$(GREEN)
|
|
|
|
# Test variables #################################
|
|
# the quality gate lower threshold for unit test total % coverage (by function statements)
|
|
COVERAGE_THRESHOLD := 47
|
|
RESULTS_DIR := $(TEMP_DIR)/results
|
|
COVER_REPORT := $(RESULTS_DIR)/cover.report
|
|
COVER_TOTAL := $(RESULTS_DIR)/cover.total
|
|
LICENSES_REPORT := $(RESULTS_DIR)/licenses.json
|
|
|
|
## Build variables #################################
|
|
VERSION := $(shell git describe --dirty --always --tags)
|
|
DIST_DIR := ./dist
|
|
SNAPSHOT_DIR := ./snapshot
|
|
CHANGELOG := CHANGELOG.md
|
|
OS := $(shell uname | tr '[:upper:]' '[:lower:]')
|
|
SNAPSHOT_BIN := $(realpath $(shell pwd)/$(SNAPSHOT_DIR)/$(OS)-build_$(OS)_amd64_v1/$(BIN))
|
|
|
|
ifndef TEMP_DIR
|
|
$(error TEMP_DIR is not set)
|
|
endif
|
|
|
|
ifndef RESULTS_DIR
|
|
$(error RESULTS_DIR is not set)
|
|
endif
|
|
|
|
ifndef DIST_DIR
|
|
$(error DIST_DIR is not set)
|
|
endif
|
|
|
|
ifndef SNAPSHOT_DIR
|
|
$(error SNAPSHOT_DIR is not set)
|
|
endif
|
|
|
|
ifndef VERSION
|
|
$(error VERSION is not set)
|
|
endif
|
|
|
|
define title
|
|
@printf '$(TITLE)$(1)$(RESET)\n'
|
|
endef
|
|
|
|
define safe_rm_rf
|
|
bash -c 'test -z "$(1)" && false || rm -rf $(1)'
|
|
endef
|
|
|
|
define safe_rm_rf_children
|
|
bash -c 'test -z "$(1)" && false || rm -rf $(1)/*'
|
|
endef
|
|
|
|
.DEFAULT_GOAL:=help
|
|
|
|
.PHONY: all
|
|
all: static-analysis test ## Run all checks (linting, license check, unit, integration, and linux acceptance tests tests)
|
|
@printf '$(SUCCESS)All checks pass!$(RESET)\n'
|
|
|
|
.PHONY: static-analysis
|
|
static-analysis: check-go-mod-tidy lint check-licenses validate-grype-db-schema
|
|
|
|
.PHONY: test
|
|
test: unit integration validate-cyclonedx-schema validate-grype-db-schema cli ## Run all tests (unit, integration, linux acceptance, and CLI tests)
|
|
|
|
.PHONY: validate-cyclonedx-schema
|
|
validate-cyclonedx-schema:
|
|
cd schema/cyclonedx && make
|
|
|
|
.PHONY: validate-grype-db-schema
|
|
validate-grype-db-schema:
|
|
# ensure the codebase is only referencing a single grype-db schema version, multiple is not allowed
|
|
python test/validate-grype-db-schema.py
|
|
|
|
|
|
## Bootstrapping targets #################################
|
|
|
|
.PHONY: bootstrap
|
|
bootstrap: $(TEMP_DIR) bootstrap-go bootstrap-tools ## Download and install all tooling dependencies (+ prep tooling in the ./tmp dir)
|
|
$(call title,Bootstrapping dependencies)
|
|
|
|
.PHONY: bootstrap-tools
|
|
bootstrap-tools: $(TEMP_DIR)
|
|
curl -sSfL https://raw.githubusercontent.com/anchore/quill/main/install.sh | sh -s -- -b $(TEMP_DIR)/ $(QUILL_VERSION)
|
|
GO111MODULE=off GOBIN=$(realpath $(TEMP_DIR)) go get -u golang.org/x/perf/cmd/benchstat
|
|
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(TEMP_DIR)/ $(GOLANGCILINT_VERSION)
|
|
curl -sSfL https://raw.githubusercontent.com/wagoodman/go-bouncer/master/bouncer.sh | sh -s -- -b $(TEMP_DIR)/ $(BOUNCER_VERSION)
|
|
curl -sSfL https://raw.githubusercontent.com/anchore/chronicle/main/install.sh | sh -s -- -b $(TEMP_DIR)/ $(CHRONICLE_VERSION)
|
|
.github/scripts/goreleaser-install.sh -d -b $(TEMP_DIR)/ $(GORELEASER_VERSION)
|
|
# the only difference between goimports and gosimports is that gosimports removes extra whitespace between import blocks (see https://github.com/golang/go/issues/20818)
|
|
GOBIN="$(realpath $(TEMP_DIR))" go install github.com/rinchsan/gosimports/cmd/gosimports@$(GOSIMPORTS_VERSION)
|
|
GOBIN="$(realpath $(TEMP_DIR))" go install github.com/neilpa/yajsv@$(YAJSV_VERSION)
|
|
GOBIN="$(realpath $(TEMP_DIR))" go install github.com/charmbracelet/glow@$(GLOW_VERSION)
|
|
GOBIN="$(realpath $(TEMP_DIR))" CGO_ENABLED=0 GO_DYN_FLAGS="" go install -tags "containers_image_openpgp" github.com/containers/skopeo/cmd/skopeo@$(SKOPEO_VERSION)
|
|
|
|
.PHONY: bootstrap-go
|
|
bootstrap-go:
|
|
go mod download
|
|
|
|
$(TEMP_DIR):
|
|
mkdir -p $(TEMP_DIR)
|
|
|
|
|
|
## Static analysis targets #################################
|
|
|
|
.PHONY: lint
|
|
lint: ## Run gofmt + golangci lint checks
|
|
$(call title,Running linters)
|
|
# ensure there are no go fmt differences
|
|
@printf "files with gofmt issues: [$(shell gofmt -l -s .)]\n"
|
|
@test -z "$(shell gofmt -l -s .)"
|
|
|
|
# run all golangci-lint rules
|
|
$(LINT_CMD)
|
|
@[ -z "$(shell $(GOIMPORTS_CMD) -d .)" ] || (echo "goimports needs to be fixed" && false)
|
|
|
|
# go tooling does not play well with certain filename characters, ensure the common cases don't result in future "go get" failures
|
|
$(eval MALFORMED_FILENAMES := $(shell find . | grep -e ':' | grep -v -e "test/quality/.yardstick" -e "test/quality/vulnerability-match-labels"))
|
|
@bash -c "[[ '$(MALFORMED_FILENAMES)' == '' ]] || (printf '\nfound unsupported filename characters:\n$(MALFORMED_FILENAMES)\n\n' && false)"
|
|
|
|
.PHONY: format
|
|
format: ## Auto-format all source code
|
|
$(call title,Running formatters)
|
|
gofmt -w -s .
|
|
$(GOIMPORTS_CMD) -w .
|
|
go mod tidy
|
|
|
|
.PHONY: lint-fix
|
|
lint-fix: format ## Auto-format all source code + run golangci lint fixers
|
|
$(call title,Running lint fixers)
|
|
$(LINT_CMD) --fix
|
|
|
|
.PHONY: check-licenses
|
|
check-licenses: ## Ensure transitive dependencies are compliant with the current license policy
|
|
$(call title,Checking for license compliance)
|
|
$(TEMP_DIR)/bouncer check ./...
|
|
|
|
check-go-mod-tidy:
|
|
@ .github/scripts/go-mod-tidy-check.sh && echo "go.mod and go.sum are tidy!"
|
|
|
|
## Testing targets #################################
|
|
|
|
.PHONY: unit
|
|
unit: $(TEMP_DIR) ## Run unit tests (with coverage)
|
|
$(call title,Running unit tests)
|
|
go test -race -coverprofile $(TEMP_DIR)/unit-coverage-details.txt $(shell go list ./... | grep -v anchore/grype/test)
|
|
@.github/scripts/coverage.py $(COVERAGE_THRESHOLD) $(TEMP_DIR)/unit-coverage-details.txt
|
|
|
|
.PHONY: integration
|
|
integration: ## Run integration tests
|
|
$(call title,Running integration tests)
|
|
go test -v ./test/integration
|
|
go run cmd/grype/main.go alpine:latest
|
|
|
|
.PHONY: quality
|
|
quality: ## Run quality tests
|
|
$(call title,Running quality tests)
|
|
cd test/quality && make
|
|
|
|
.PHONY: cli
|
|
cli: $(SNAPSHOT_DIR) ## Run CLI tests
|
|
chmod 755 "$(SNAPSHOT_BIN)"
|
|
$(SNAPSHOT_BIN) version
|
|
SYFT_BINARY_LOCATION='$(SNAPSHOT_BIN)' \
|
|
go test -count=1 -timeout=15m -v ./test/cli
|
|
|
|
## Test-fixture-related targets #################################
|
|
|
|
# note: this is used by CI to determine if various test fixture cache should be restored or recreated
|
|
# TODO (cphillips) check for all fixtures and individual makefile
|
|
fingerprints:
|
|
$(call title,Creating all test cache input fingerprints)
|
|
|
|
# for IMAGE integration test fixtures
|
|
cd test/integration/test-fixtures && \
|
|
make cache.fingerprint
|
|
|
|
# for INSTALL integration test fixtures
|
|
cd test/install && \
|
|
make cache.fingerprint
|
|
|
|
# for CLI test fixtures
|
|
cd test/cli/test-fixtures && \
|
|
make cache.fingerprint
|
|
|
|
.PHONY: show-test-image-cache
|
|
show-test-image-cache: ## Show all docker and image tar cache
|
|
$(call title,Docker daemon cache)
|
|
@docker images --format '{{.ID}} {{.Repository}}:{{.Tag}}' | grep stereoscope-fixture- | sort
|
|
|
|
$(call title,Tar cache)
|
|
@find . -type f -wholename "**/test-fixtures/cache/stereoscope-fixture-*.tar" | sort
|
|
|
|
.PHONY: show-test-snapshots
|
|
show-test-snapshots: ## Show all test snapshots
|
|
$(call title,Test snapshots)
|
|
@find . -type f -wholename "**/test-fixtures/snapshot/*" | sort
|
|
|
|
## install.sh testing targets #################################
|
|
|
|
install-test: $(SNAPSHOT_DIR)
|
|
cd test/install && \
|
|
make
|
|
|
|
install-test-cache-save: $(SNAPSHOT_DIR)
|
|
cd test/install && \
|
|
make save
|
|
|
|
install-test-cache-load: $(SNAPSHOT_DIR)
|
|
cd test/install && \
|
|
make load
|
|
|
|
install-test-ci-mac: $(SNAPSHOT_DIR)
|
|
cd test/install && \
|
|
make ci-test-mac
|
|
|
|
.PHONY: compare-test-deb-package-install
|
|
compare-test-deb-package-install: $(TEMP_DIR) $(SNAPSHOT_DIR)
|
|
$(call title,Running compare test: DEB install)
|
|
$(COMPARE_DIR)/deb.sh \
|
|
$(SNAPSHOT_DIR) \
|
|
$(COMPARE_DIR) \
|
|
$(COMPARE_TEST_IMAGE) \
|
|
$(TEMP_DIR)
|
|
|
|
.PHONY: compare-test-rpm-package-install
|
|
compare-test-rpm-package-install: $(TEMP_DIR) $(SNAPSHOT_DIR)
|
|
$(call title,Running compare test: RPM install)
|
|
$(COMPARE_DIR)/rpm.sh \
|
|
$(SNAPSHOT_DIR) \
|
|
$(COMPARE_DIR) \
|
|
$(COMPARE_TEST_IMAGE) \
|
|
$(TEMP_DIR)
|
|
|
|
## Code generation targets #################################
|
|
## TODO (cphillips) what does grype have here?
|
|
|
|
## Build-related targets #################################
|
|
|
|
.PHONY: build
|
|
build: $(SNAPSHOT_DIR)
|
|
|
|
$(SNAPSHOT_DIR): ## Build snapshot release binaries and packages
|
|
$(call title,Building snapshot artifacts)
|
|
|
|
# create a config with the dist dir overridden
|
|
echo "dist: $(SNAPSHOT_DIR)" > $(TEMP_DIR)/goreleaser.yaml
|
|
cat .goreleaser.yaml >> $(TEMP_DIR)/goreleaser.yaml
|
|
|
|
# build release snapshots
|
|
$(SNAPSHOT_CMD) --config $(TEMP_DIR)/goreleaser.yaml
|
|
|
|
.PHONY: changelog
|
|
changelog: clean-changelog ## Generate and show the changelog for the current unreleased version
|
|
$(CHRONICLE_CMD) -vv -n --version-file VERSION > $(CHANGELOG)
|
|
@$(GLOW_CMD) $(CHANGELOG)
|
|
|
|
$(CHANGELOG):
|
|
$(CHRONICLE_CMD) -vvv > $(CHANGELOG)
|
|
|
|
.PHONY: release
|
|
release:
|
|
@.github/scripts/trigger-release.sh
|
|
|
|
.PHONY: ci-release
|
|
ci-release: ci-check clean-dist $(CHANGELOG)
|
|
$(call title,Publishing release artifacts)
|
|
|
|
# create a config with the dist dir overridden
|
|
echo "dist: $(DIST_DIR)" > $(TEMP_DIR)/goreleaser.yaml
|
|
cat .goreleaser.yaml >> $(TEMP_DIR)/goreleaser.yaml
|
|
|
|
bash -c "\
|
|
$(RELEASE_CMD) \
|
|
--config $(TEMP_DIR)/goreleaser.yaml \
|
|
--release-notes <(cat $(CHANGELOG)) \
|
|
|| (cat /tmp/quill-*.log && false)"
|
|
|
|
# upload the version file that supports the application version update check (excluding pre-releases)
|
|
.github/scripts/update-version-file.sh "$(DIST_DIR)" "$(VERSION)"
|
|
|
|
.PHONY: ci-check
|
|
ci-check:
|
|
@.github/scripts/ci-check.sh
|
|
|
|
## Cleanup targets #################################
|
|
|
|
.PHONY: clean
|
|
clean: clean-dist clean-snapshot ## Remove previous builds, result reports, and test cache
|
|
$(call safe_rm_rf_children,$(TEMP_DIR))
|
|
|
|
.PHONY: clean-snapshot
|
|
clean-snapshot:
|
|
$(call safe_rm_rf,$(SNAPSHOT_DIR))
|
|
rm -f $(TEMP_DIR)/goreleaser.yaml
|
|
|
|
.PHONY: clean-dist
|
|
clean-dist: clean-changelog
|
|
$(call safe_rm_rf,$(DIST_DIR))
|
|
rm -f $(TEMP_DIR)/goreleaser.yaml
|
|
|
|
.PHONY: clean-changelog
|
|
clean-changelog:
|
|
rm -f $(CHANGELOG) VERSION
|
|
|
|
clean-test-image-cache: clean-test-image-tar-cache clean-test-image-docker-cache ## Clean test image cache
|
|
|
|
## Halp! #################################
|
|
|
|
.PHONY: help
|
|
help: ## Display this help
|
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "$(BOLD)$(CYAN)%-25s$(RESET)%s\n", $$1, $$2}'
|
|
|
|
|
|
.PHONY: validate-grype-test-config
|
|
validate-grype-test-config:
|
|
# ensure the update URL is not overridden (not pointing to staging)
|
|
@bash -c '\
|
|
grep -q "update-url" test/grype-test-config.yaml; \
|
|
if [ $$? -eq 0 ]; then \
|
|
echo "Found \"update-url\" in CLI testing config. Cannot release if previous CLI testing did not use production (default) values"; \
|
|
fi'
|
|
|
|
.PHONY: validate-syft-release-version
|
|
validate-syft-release-version:
|
|
@./.github/scripts/syft-released-version-check.sh
|
|
|
|
.PHONY: clean-test-cache
|
|
clean-test-cache: ## Delete all test cache (built docker image tars)
|
|
find . -type f -wholename "**/test-fixtures/cache/*.tar" -delete
|