github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/Makefile (about)

     1  BIN := syft
     2  TEMP_DIR := ./.tmp
     3  
     4  # Command templates #################################
     5  LINT_CMD := $(TEMP_DIR)/golangci-lint run --tests=false
     6  GOIMPORTS_CMD := $(TEMP_DIR)/gosimports -local github.com/anchore
     7  RELEASE_CMD := $(TEMP_DIR)/goreleaser release --clean
     8  SNAPSHOT_CMD := $(RELEASE_CMD) --skip-publish --skip-sign --snapshot
     9  CHRONICLE_CMD = $(TEMP_DIR)/chronicle
    10  GLOW_CMD = $(TEMP_DIR)/glow
    11  
    12  # Tool versions #################################
    13  GOLANGCILINT_VERSION := v1.54.2
    14  GOSIMPORTS_VERSION := v0.3.8
    15  BOUNCER_VERSION := v0.4.0
    16  CHRONICLE_VERSION := v0.7.0
    17  GORELEASER_VERSION := v1.20.0
    18  YAJSV_VERSION := v1.4.1
    19  COSIGN_VERSION := v2.2.0
    20  QUILL_VERSION := v0.4.1
    21  GLOW_VERSION := v1.5.1
    22  
    23  # Formatting variables #################################
    24  BOLD := $(shell tput -T linux bold)
    25  PURPLE := $(shell tput -T linux setaf 5)
    26  GREEN := $(shell tput -T linux setaf 2)
    27  CYAN := $(shell tput -T linux setaf 6)
    28  RED := $(shell tput -T linux setaf 1)
    29  RESET := $(shell tput -T linux sgr0)
    30  TITLE := $(BOLD)$(PURPLE)
    31  SUCCESS := $(BOLD)$(GREEN)
    32  
    33  # Test variables #################################
    34  COMPARE_DIR := ./test/compare
    35  COMPARE_TEST_IMAGE := centos:8.2.2004
    36  COVERAGE_THRESHOLD := 62  # the quality gate lower threshold for unit test total % coverage (by function statements)
    37  
    38  ## Build variables #################################
    39  VERSION := $(shell git describe --dirty --always --tags)
    40  DIST_DIR := ./dist
    41  SNAPSHOT_DIR := ./snapshot
    42  CHANGELOG := CHANGELOG.md
    43  OS := $(shell uname | tr '[:upper:]' '[:lower:]')
    44  SNAPSHOT_BIN := $(realpath $(shell pwd)/$(SNAPSHOT_DIR)/$(OS)-build_$(OS)_amd64_v1/$(BIN))
    45  
    46  ifndef VERSION
    47  	$(error VERSION is not set)
    48  endif
    49  
    50  define title
    51      @printf '$(TITLE)$(1)$(RESET)\n'
    52  endef
    53  
    54  define safe_rm_rf
    55  	bash -c 'test -z "$(1)" && false || rm -rf $(1)'
    56  endef
    57  
    58  define safe_rm_rf_children
    59  	bash -c 'test -z "$(1)" && false || rm -rf $(1)/*'
    60  endef
    61  
    62  .DEFAULT_GOAL:=help
    63  
    64  
    65  .PHONY: all
    66  all: static-analysis test ## Run all linux-based checks (linting, license check, unit, integration, and linux compare tests)
    67  	@printf '$(SUCCESS)All checks pass!$(RESET)\n'
    68  
    69  .PHONY: static-analysis
    70  static-analysis: check-go-mod-tidy lint check-licenses check-json-schema-drift  ## Run all static analysis checks
    71  
    72  .PHONY: test
    73  test: unit integration validate-cyclonedx-schema benchmark cli ## Run all tests (currently unit, integration, linux compare, and cli tests)
    74  
    75  
    76  ## Bootstrapping targets #################################
    77  
    78  .PHONY: bootstrap
    79  bootstrap: $(TEMP_DIR) bootstrap-go bootstrap-tools ## Download and install all tooling dependencies (+ prep tooling in the ./tmp dir)
    80  	$(call title,Bootstrapping dependencies)
    81  
    82  .PHONY: bootstrap-tools
    83  bootstrap-tools: $(TEMP_DIR)
    84  	curl -sSfL https://raw.githubusercontent.com/anchore/quill/main/install.sh | sh -s -- -b $(TEMP_DIR)/ $(QUILL_VERSION)
    85  	GO111MODULE=off GOBIN=$(realpath $(TEMP_DIR)) go get -u golang.org/x/perf/cmd/benchstat
    86  	curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(TEMP_DIR)/ $(GOLANGCILINT_VERSION)
    87  	curl -sSfL https://raw.githubusercontent.com/wagoodman/go-bouncer/master/bouncer.sh | sh -s -- -b $(TEMP_DIR)/ $(BOUNCER_VERSION)
    88  	curl -sSfL https://raw.githubusercontent.com/anchore/chronicle/main/install.sh | sh -s -- -b $(TEMP_DIR)/ $(CHRONICLE_VERSION)
    89  	.github/scripts/goreleaser-install.sh -d -b $(TEMP_DIR)/ $(GORELEASER_VERSION)
    90  	# the only difference between goimports and gosimports is that gosimports removes extra whitespace between import blocks (see https://github.com/golang/go/issues/20818)
    91  	GOBIN="$(realpath $(TEMP_DIR))" go install github.com/rinchsan/gosimports/cmd/gosimports@$(GOSIMPORTS_VERSION)
    92  	GOBIN="$(realpath $(TEMP_DIR))" go install github.com/neilpa/yajsv@$(YAJSV_VERSION)
    93  	GOBIN="$(realpath $(TEMP_DIR))" go install github.com/sigstore/cosign/v2/cmd/cosign@$(COSIGN_VERSION)
    94  	GOBIN="$(realpath $(TEMP_DIR))" go install github.com/charmbracelet/glow@$(GLOW_VERSION)
    95  
    96  .PHONY: bootstrap-go
    97  bootstrap-go:
    98  	go mod download
    99  
   100  $(TEMP_DIR):
   101  	mkdir -p $(TEMP_DIR)
   102  
   103  
   104  ## Static analysis targets #################################
   105  
   106  .PHONY: lint
   107  lint:  ## Run gofmt + golangci lint checks
   108  	$(call title,Running linters)
   109  	# ensure there are no go fmt differences
   110  	@printf "files with gofmt issues: [$(shell gofmt -l -s .)]\n"
   111  	@test -z "$(shell gofmt -l -s .)"
   112  
   113  	# run all golangci-lint rules
   114  	$(LINT_CMD)
   115  	@[ -z "$(shell $(GOIMPORTS_CMD) -d .)" ] || (echo "goimports needs to be fixed" && false)
   116  
   117  	# go tooling does not play well with certain filename characters, ensure the common cases don't result in future "go get" failures
   118  	$(eval MALFORMED_FILENAMES := $(shell find . | grep -e ':'))
   119  	@bash -c "[[ '$(MALFORMED_FILENAMES)' == '' ]] || (printf '\nfound unsupported filename characters:\n$(MALFORMED_FILENAMES)\n\n' && false)"
   120  
   121  .PHONY: format
   122  format:  ## Auto-format all source code
   123  	$(call title,Running formatters)
   124  	gofmt -w -s .
   125  	$(GOIMPORTS_CMD) -w .
   126  	go mod tidy
   127  
   128  .PHONY: lint-fix
   129  lint-fix: format  ## Auto-format all source code + run golangci lint fixers
   130  	$(call title,Running lint fixers)
   131  	$(LINT_CMD) --fix
   132  
   133  .PHONY: check-licenses
   134  check-licenses:  ## Ensure transitive dependencies are compliant with the current license policy
   135  	$(call title,Checking for license compliance)
   136  	$(TEMP_DIR)/bouncer check ./...
   137  
   138  check-go-mod-tidy:
   139  	@ .github/scripts/go-mod-tidy-check.sh && echo "go.mod and go.sum are tidy!"
   140  
   141  check-json-schema-drift:
   142  	$(call title,Ensure there is no drift between the JSON schema and the code)
   143  	@.github/scripts/json-schema-drift-check.sh
   144  
   145  ## Testing targets #################################
   146  
   147  .PHONY: unit
   148  unit: $(TEMP_DIR) fixtures  ## Run unit tests (with coverage)
   149  	$(call title,Running unit tests)
   150  	go test -race -coverprofile $(TEMP_DIR)/unit-coverage-details.txt $(shell go list ./... | grep -v anchore/syft/test)
   151  	@.github/scripts/coverage.py $(COVERAGE_THRESHOLD) $(TEMP_DIR)/unit-coverage-details.txt
   152  
   153  .PHONY: integration
   154  integration:  ## Run integration tests
   155  	$(call title,Running integration tests)
   156  	go test -v ./test/integration
   157  	go run -race cmd/syft/main.go alpine:latest
   158  
   159  .PHONY: validate-cyclonedx-schema
   160  validate-cyclonedx-schema:
   161  	cd schema/cyclonedx && make
   162  
   163  .PHONY: cli
   164  cli: $(SNAPSHOT_DIR)  ## Run CLI tests
   165  	chmod 755 "$(SNAPSHOT_BIN)"
   166  	$(SNAPSHOT_BIN) version
   167  	SYFT_BINARY_LOCATION='$(SNAPSHOT_BIN)' \
   168  		go test -count=1 -timeout=15m -v ./test/cli
   169  
   170  
   171  ## Benchmark test targets #################################
   172  
   173  .PHONY: benchmark
   174  benchmark: $(TEMP_DIR)  ## Run benchmark tests and compare against the baseline (if available)
   175  	$(call title,Running benchmark tests)
   176  	go test -p 1 -run=^Benchmark -bench=. -count=7 -benchmem ./... | tee $(TEMP_DIR)/benchmark-$(VERSION).txt
   177  	(test -s $(TEMP_DIR)/benchmark-main.txt && \
   178  		$(TEMP_DIR)/benchstat $(TEMP_DIR)/benchmark-main.txt $(TEMP_DIR)/benchmark-$(VERSION).txt || \
   179  		$(TEMP_DIR)/benchstat $(TEMP_DIR)/benchmark-$(VERSION).txt) \
   180  			| tee $(TEMP_DIR)/benchstat.txt
   181  
   182  .PHONY: show-benchstat
   183  show-benchstat:
   184  	@cat $(TEMP_DIR)/benchstat.txt
   185  
   186  
   187  ## Test-fixture-related targets #################################
   188  
   189  # note: this is used by CI to determine if various test fixture cache should be restored or recreated
   190  fingerprints:
   191  	$(call title,Creating all test cache input fingerprints)
   192  
   193  	# for IMAGE integration test fixtures
   194  	cd test/integration/test-fixtures && \
   195  		make cache.fingerprint
   196  
   197  	# for BINARY test fixtures
   198  	cd syft/pkg/cataloger/binary/test-fixtures && \
   199  		make cache.fingerprint
   200  
   201  	# for JAVA BUILD test fixtures
   202  	cd syft/pkg/cataloger/java/test-fixtures/java-builds && \
   203  		make cache.fingerprint
   204  
   205  	# for GO BINARY test fixtures
   206  	cd syft/pkg/cataloger/golang/test-fixtures/archs && \
   207  		make binaries.fingerprint
   208  
   209  	# for RPM test fixtures
   210  	cd syft/pkg/cataloger/rpm/test-fixtures && \
   211  		make rpms.fingerprint
   212  
   213  	# for Kernel test fixtures
   214  	cd syft/pkg/cataloger/kernel/test-fixtures && \
   215  		make cache.fingerprint
   216  
   217  	# for INSTALL integration test fixtures
   218  	cd test/install && \
   219  		make cache.fingerprint
   220  
   221  	# for CLI test fixtures
   222  	cd test/cli/test-fixtures && \
   223  		make cache.fingerprint
   224  
   225  .PHONY: fixtures
   226  fixtures:
   227  	$(call title,Generating test fixtures)
   228  	cd syft/pkg/cataloger/java/test-fixtures/java-builds && make
   229  	cd syft/pkg/cataloger/rpm/test-fixtures && make
   230  	cd syft/pkg/cataloger/binary/test-fixtures && make
   231  
   232  .PHONY: show-test-image-cache
   233  show-test-image-cache:  ## Show all docker and image tar cache
   234  	$(call title,Docker daemon cache)
   235  	@docker images --format '{{.ID}} {{.Repository}}:{{.Tag}}' | grep stereoscope-fixture- | sort
   236  
   237  	$(call title,Tar cache)
   238  	@find . -type f -wholename "**/test-fixtures/cache/stereoscope-fixture-*.tar" | sort
   239  
   240  .PHONY: show-test-snapshots
   241  show-test-snapshots:  ## Show all test snapshots
   242  	$(call title,Test snapshots)
   243  	@find . -type f -wholename "**/test-fixtures/snapshot/*" | sort
   244  
   245  
   246  ## install.sh testing targets #################################
   247  
   248  install-test: $(SNAPSHOT_DIR)
   249  	cd test/install && \
   250  		make
   251  
   252  install-test-cache-save: $(SNAPSHOT_DIR)
   253  	cd test/install && \
   254  		make save
   255  
   256  install-test-cache-load: $(SNAPSHOT_DIR)
   257  	cd test/install && \
   258  		make load
   259  
   260  install-test-ci-mac: $(SNAPSHOT_DIR)
   261  	cd test/install && \
   262  		make ci-test-mac
   263  
   264  .PHONY: generate-compare-file
   265  generate-compare-file:
   266  	$(call title,Generating compare test file)
   267  	go run ./cmd/syft $(COMPARE_TEST_IMAGE) -o json > $(COMPARE_DIR)/test-fixtures/acceptance-centos-8.2.2004.json
   268  
   269  # note: we cannot clean the snapshot directory since the pipeline builds the snapshot separately
   270  .PHONY: compare-mac
   271  compare-mac: $(TEMP_DIR) $(SNAPSHOT_DIR)  ## Run compare tests on build snapshot binaries and packages (Mac)
   272  	$(call title,Running compare test: Run on Mac)
   273  	$(COMPARE_DIR)/mac.sh \
   274  			$(SNAPSHOT_DIR) \
   275  			$(COMPARE_DIR) \
   276  			$(COMPARE_TEST_IMAGE) \
   277  			$(TEMP_DIR)
   278  
   279  # note: we cannot clean the snapshot directory since the pipeline builds the snapshot separately
   280  .PHONY: compare-linux
   281  compare-linux: compare-test-deb-package-install compare-test-rpm-package-install  ## Run compare tests on build snapshot binaries and packages (Linux)
   282  
   283  .PHONY: compare-test-deb-package-install
   284  compare-test-deb-package-install: $(TEMP_DIR) $(SNAPSHOT_DIR)
   285  	$(call title,Running compare test: DEB install)
   286  	$(COMPARE_DIR)/deb.sh \
   287  			$(SNAPSHOT_DIR) \
   288  			$(COMPARE_DIR) \
   289  			$(COMPARE_TEST_IMAGE) \
   290  			$(TEMP_DIR)
   291  
   292  .PHONY: compare-test-rpm-package-install
   293  compare-test-rpm-package-install: $(TEMP_DIR) $(SNAPSHOT_DIR)
   294  	$(call title,Running compare test: RPM install)
   295  	$(COMPARE_DIR)/rpm.sh \
   296  			$(SNAPSHOT_DIR) \
   297  			$(COMPARE_DIR) \
   298  			$(COMPARE_TEST_IMAGE) \
   299  			$(TEMP_DIR)
   300  
   301  
   302  ## Code and data generation targets #################################
   303  
   304  .PHONY: generate-json-schema
   305  generate-json-schema:  ## Generate a new json schema
   306  	cd syft/internal && go generate . && cd jsonschema && go run .
   307  
   308  .PHONY: generate-license-list
   309  generate-license-list:  ## Generate an updated spdx license list
   310  	go generate ./internal/spdxlicense/...
   311  	gofmt -s -w ./internal/spdxlicense
   312  
   313  .PHONY: generate-cpe-dictionary-index
   314  generate-cpe-dictionary-index:  ## Build the CPE index based off of the latest available CPE dictionary
   315  	$(call title,Building CPE index)
   316  	go generate ./syft/pkg/cataloger/common/cpe/dictionary
   317  
   318  
   319  ## Build-related targets #################################
   320  
   321  .PHONY: build
   322  build:
   323  	CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o $@ ./cmd/syft
   324  
   325  $(SNAPSHOT_DIR):  ## Build snapshot release binaries and packages
   326  	$(call title,Building snapshot artifacts)
   327  
   328  	# create a config with the dist dir overridden
   329  	echo "dist: $(SNAPSHOT_DIR)" > $(TEMP_DIR)/goreleaser.yaml
   330  	cat .goreleaser.yaml >> $(TEMP_DIR)/goreleaser.yaml
   331  
   332  	# build release snapshots
   333  	$(SNAPSHOT_CMD) --config $(TEMP_DIR)/goreleaser.yaml
   334  
   335  .PHONY: changelog
   336  changelog: clean-changelog  ## Generate and show the changelog for the current unreleased version
   337  	$(CHRONICLE_CMD) -vvv -n --version-file VERSION > $(CHANGELOG)
   338  	@$(GLOW_CMD) $(CHANGELOG)
   339  
   340  $(CHANGELOG):
   341  	$(CHRONICLE_CMD) -vvv > $(CHANGELOG)
   342  
   343  .PHONY: release
   344  release:
   345  	@.github/scripts/trigger-release.sh
   346  
   347  .PHONY: ci-release
   348  ci-release: ci-check clean-dist $(CHANGELOG)
   349  	$(call title,Publishing release artifacts)
   350  
   351  	# create a config with the dist dir overridden
   352  	echo "dist: $(DIST_DIR)" > $(TEMP_DIR)/goreleaser.yaml
   353  	cat .goreleaser.yaml >> $(TEMP_DIR)/goreleaser.yaml
   354  
   355  	bash -c "\
   356  		$(RELEASE_CMD) \
   357  			--config $(TEMP_DIR)/goreleaser.yaml \
   358  			--release-notes <(cat $(CHANGELOG)) \
   359  				 || (cat /tmp/quill-*.log && false)"
   360  
   361  	# upload the version file that supports the application version update check (excluding pre-releases)
   362  	.github/scripts/update-version-file.sh "$(DIST_DIR)" "$(VERSION)"
   363  
   364  .PHONY: ci-check
   365  ci-check:
   366  	@.github/scripts/ci-check.sh
   367  
   368  ## Cleanup targets #################################
   369  
   370  .PHONY: clean
   371  clean: clean-dist clean-snapshot clean-test-image-cache  ## Remove previous builds, result reports, and test cache
   372  	$(call safe_rm_rf_children,$(TEMP_DIR))
   373  
   374  .PHONY: clean-snapshot
   375  clean-snapshot:
   376  	$(call safe_rm_rf,$(SNAPSHOT_DIR))
   377  	rm -f $(TEMP_DIR)/goreleaser.yaml
   378  
   379  .PHONY: clean-dist
   380  clean-dist: clean-changelog
   381  	$(call safe_rm_rf,$(DIST_DIR))
   382  	rm -f $(TEMP_DIR)/goreleaser.yaml
   383  
   384  .PHONY: clean-changelog
   385  clean-changelog:
   386  	rm -f $(CHANGELOG) VERSION
   387  
   388  clean-test-image-cache: clean-test-image-tar-cache clean-test-image-docker-cache ## Clean test image cache
   389  
   390  .PHONY: clear-test-image-tar-cache
   391  clean-test-image-tar-cache:  ## Delete all test cache (built docker image tars)
   392  	find . -type f -wholename "**/test-fixtures/cache/stereoscope-fixture-*.tar" -delete
   393  
   394  .PHONY: clear-test-image-docker-cache
   395  clean-test-image-docker-cache:	## Purge all test docker images
   396  	docker images --format '{{.ID}} {{.Repository}}' | grep stereoscope-fixture- | awk '{print $$1}' | uniq | xargs -r docker rmi --force
   397  
   398  ## Halp! #################################
   399  
   400  .PHONY: help
   401  help:  ## Display this help
   402  	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "$(BOLD)$(CYAN)%-25s$(RESET)%s\n", $$1, $$2}'