2021-03-11 17:41:10 +00:00
BIN = syft
TEMPDIR = ./.tmp
2021-03-18 13:01:07 +00:00
RESULTSDIR = test/results
COVER_REPORT = $( RESULTSDIR) /unit-coverage-details.txt
COVER_TOTAL = $( RESULTSDIR) /unit-coverage-summary.txt
2021-04-21 12:59:48 +00:00
LINTCMD = $( TEMPDIR) /golangci-lint run --tests= false --timeout= 2m --config .golangci.yaml
2021-03-11 17:41:10 +00:00
ACC_TEST_IMAGE = centos:8.2.2004
ACC_DIR = ./test/acceptance
2020-07-06 10:58:34 +00:00
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)
2020-05-12 14:45:18 +00:00
TITLE := $( BOLD) $( PURPLE)
SUCCESS := $( BOLD) $( GREEN)
2020-07-06 10:58:34 +00:00
# the quality gate lower threshold for unit test total % coverage (by function statements)
2021-03-23 14:28:57 +00:00
COVERAGE_THRESHOLD := 70
2020-12-22 21:22:42 +00:00
# CI cache busting values; change these if you want CI to not use previous stored cache
2021-03-23 17:04:13 +00:00
INTEGRATION_CACHE_BUSTER = "88738d2f"
2021-03-18 13:01:07 +00:00
CLI_CACHE_BUSTER = "789bacdf"
2021-03-23 10:58:30 +00:00
BOOTSTRAP_CACHE = "c7afb99ad"
2020-05-12 14:45:18 +00:00
2020-07-23 14:52:44 +00:00
## Build variables
2021-03-11 17:41:10 +00:00
DISTDIR = ./dist
SNAPSHOTDIR = ./snapshot
GITTREESTATE = $( if $( shell git status --porcelain) ,dirty,clean)
2021-03-20 11:33:13 +00:00
OS := $( shell uname)
i f e q ( $( OS ) , D a r w i n )
SNAPSHOT_CMD = $( shell realpath $( shell pwd ) /$( SNAPSHOTDIR) /$( BIN) -macos_darwin_amd64/$( BIN) )
e l s e
SNAPSHOT_CMD = $( shell realpath $( shell pwd ) /$( SNAPSHOTDIR) /$( BIN) _linux_amd64/$( BIN) )
e n d i f
2020-07-23 14:52:44 +00:00
2021-03-11 17:41:10 +00:00
i f e q "$(strip $(VERSION))" ""
override VERSION = $( shell git describe --always --tags --dirty)
e n d i f
2021-03-10 18:25:31 +00:00
2020-09-25 21:57:51 +00:00
# used to generate the changelog from the second to last tag to the current tag (used in the release pipeline when the release tag is in place)
2021-03-11 17:41:10 +00:00
LAST_TAG := $( shell git describe --abbrev= 0 --tags $( shell git rev-list --tags --max-count= 1) )
SECOND_TO_LAST_TAG := $( shell git describe --abbrev= 0 --tags $( shell git rev-list --tags --skip= 1 --max-count= 1) )
2020-09-25 21:57:51 +00:00
2020-07-23 14:52:44 +00:00
## Variable assertions
2020-05-21 13:37:20 +00:00
i f n d e f T E M P D I R
2020-07-23 14:52:44 +00:00
$( error TEMPDIR is not set )
e n d i f
i f n d e f R E S U L T S D I R
$( error RESULTSDIR is not set )
e n d i f
i f n d e f A C C _ D I R
$( error ACC_DIR is not set )
e n d i f
i f n d e f D I S T D I R
$( error DISTDIR is not set )
e n d i f
2021-03-11 17:41:10 +00:00
i f n d e f S N A P S H O T D I R
$( error SNAPSHOTDIR is not set )
e n d i f
2021-03-18 13:01:07 +00:00
i f n d e f R E F _ N A M E
REF_NAME = $( VERSION)
e n d i f
2020-07-06 10:58:34 +00:00
d e f i n e t i t l e
@printf '$(TITLE)$(1)$(RESET)\n'
e n d e f
2020-05-12 14:45:18 +00:00
2020-07-23 14:52:44 +00:00
## Tasks
2020-07-06 10:58:34 +00:00
2020-07-23 14:52:44 +00:00
.PHONY : all
2020-07-25 20:40:37 +00:00
all : clean static -analysis test ## Run all linux-based checks (linting, license check, unit, integration, and linux acceptance tests)
2020-05-12 14:45:18 +00:00
@printf '$(SUCCESS)All checks pass!$(RESET)\n'
2020-07-23 14:52:44 +00:00
.PHONY : test
2021-03-23 17:00:25 +00:00
test : unit validate -cyclonedx -schema integration benchmark acceptance -linux cli ## Run all tests (currently unit, integration, linux acceptance, and cli tests)
2020-07-06 10:58:34 +00:00
2020-07-23 14:52:44 +00:00
.PHONY : help
2020-07-06 10:58:34 +00:00
help :
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $( MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "$(BOLD)$(CYAN)%-25s$(RESET)%s\n", $$1, $$2}'
2021-03-11 17:41:10 +00:00
.PHONY : ci -bootstrap
ci-bootstrap :
DEBIAN_FRONTEND = noninteractive sudo apt update && sudo -E apt install -y bc jq libxml2-utils
2021-03-18 13:01:07 +00:00
.PHONY :
ci-bootstrap-mac :
github_changelog_generator --version || sudo gem install github_changelog_generator
$(RESULTSDIR) :
2020-07-06 10:58:34 +00:00
mkdir -p $( RESULTSDIR)
2021-03-18 13:01:07 +00:00
$(TEMPDIR) :
mkdir -p $( TEMPDIR)
.PHONY : bootstrap -tools
bootstrap-tools : $( TEMPDIR )
2021-03-23 10:58:30 +00:00
GO111MODULE = off GOBIN = $( shell realpath $( TEMPDIR) ) go get -u golang.org/x/perf/cmd/benchstat
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $( TEMPDIR) / v1.26.0
curl -sSfL https://raw.githubusercontent.com/wagoodman/go-bouncer/master/bouncer.sh | sh -s -- -b $( TEMPDIR) / v0.2.0
curl -sfL https://install.goreleaser.com/github.com/goreleaser/goreleaser.sh | sh -s -- -b $( TEMPDIR) / v0.160.0
2020-07-23 14:52:44 +00:00
2021-03-18 13:01:07 +00:00
.PHONY : bootstrap -go
bootstrap-go :
go mod download
2021-04-21 12:45:51 +00:00
go mod tidy # note: it is important that the go.sum is kept in a consistent state at all times (especially during release)
2021-03-18 13:01:07 +00:00
.PHONY : bootstrap
bootstrap : $( RESULTSDIR ) bootstrap -go bootstrap -tools ## Download and install all go dependencies (+ prep tooling in the ./tmp dir)
$( call title,Bootstrapping dependencies)
2020-07-25 20:40:37 +00:00
.PHONY : static -analysis
static-analysis : lint check -licenses
2020-07-23 14:52:44 +00:00
.PHONY : lint
2020-07-06 10:58:34 +00:00
lint : ## Run gofmt + golangci lint checks
$( call title,Running linters)
2020-07-23 17:08:31 +00:00
# ensure there are no go fmt differences
2020-07-06 10:58:34 +00:00
@printf " files with gofmt issues: [ $( shell gofmt -l -s .) ]\n "
@test -z " $( shell gofmt -l -s .) "
2020-07-23 17:08:31 +00:00
# run all golangci-lint rules
2020-05-12 14:45:18 +00:00
$( LINTCMD)
2020-07-23 17:08:31 +00:00
# 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 ':' ) )
@bash -c " [[ ' $( MALFORMED_FILENAMES) ' == '' ]] || (printf '\nfound unsupported filename characters:\n $( MALFORMED_FILENAMES) \n\n' && false) "
2020-07-23 14:52:44 +00:00
.PHONY : lint -fix
2020-07-06 10:58:34 +00:00
lint-fix : ## Auto-format all source code + run golangci lint fixers
$( call title,Running lint fixers)
2020-05-21 13:37:20 +00:00
gofmt -w -s .
2020-05-12 14:45:18 +00:00
$( LINTCMD) --fix
2020-07-23 14:52:44 +00:00
.PHONY : check -licenses
check-licenses :
$( TEMPDIR) /bouncer check
2020-08-27 23:12:45 +00:00
.PHONY : validate -cyclonedx -schema
validate-cyclonedx-schema :
cd schema/cyclonedx && make
2020-07-23 14:52:44 +00:00
.PHONY : unit
2021-03-18 13:01:07 +00:00
unit : $( RESULTSDIR ) fixtures ## Run unit tests (with coverage)
2020-07-06 10:58:34 +00:00
$( call title,Running unit tests)
2021-03-23 18:31:59 +00:00
go test -coverprofile $( COVER_REPORT) $( shell go list ./... | grep -v anchore/syft/test)
2020-07-06 10:58:34 +00:00
@go tool cover -func $( COVER_REPORT) | grep total | awk '{print substr($$3, 1, length($$3)-1)}' > $( COVER_TOTAL)
@echo " Coverage: $$ (cat $( COVER_TOTAL) ) "
@if [ $$ ( echo " $$ (cat $( COVER_TOTAL) ) >= $( COVERAGE_THRESHOLD) " | bc -l) -ne 1 ] ; then echo " $( RED) $( BOLD) Failed coverage quality gate (> $( COVERAGE_THRESHOLD) %) $( RESET) " && false; fi
2020-05-12 14:45:18 +00:00
2021-03-18 13:01:07 +00:00
.PHONY : benchmark
benchmark : $( RESULTSDIR ) ## Run benchmark tests and compare against the baseline (if available)
$( call title,Running benchmark tests)
go test -p 1 -run= ^Benchmark -bench= . -count= 5 -benchmem ./... | tee $( RESULTSDIR) /benchmark-$( REF_NAME) .txt
( test -s $( RESULTSDIR) /benchmark-main.txt && \
$( TEMPDIR) /benchstat $( RESULTSDIR) /benchmark-main.txt $( RESULTSDIR) /benchmark-$( REF_NAME) .txt || \
$( TEMPDIR) /benchstat $( RESULTSDIR) /benchmark-$( REF_NAME) .txt) \
| tee $( RESULTSDIR) /benchstat.txt
.PHONY : show -benchstat
show-benchstat :
@cat $( RESULTSDIR) /benchstat.txt
2020-07-23 14:52:44 +00:00
.PHONY : integration
2020-07-06 10:58:34 +00:00
integration : ## Run integration tests
$( call title,Running integration tests)
2021-03-11 17:41:10 +00:00
2020-10-14 20:04:52 +00:00
go test -v ./test/integration
2020-08-10 14:33:44 +00:00
# note: this is used by CI to determine if the integration test fixture cache (docker image tars) should be busted
integration-fingerprint :
2020-12-22 21:22:42 +00:00
find test/integration/test-fixtures/image-* -type f -exec md5sum { } + | awk '{print $1}' | sort | md5sum | tee test/integration/test-fixtures/cache.fingerprint && echo " $( INTEGRATION_CACHE_BUSTER) " >> test/integration/test-fixtures/cache.fingerprint
2020-07-07 22:04:27 +00:00
2020-07-23 14:52:44 +00:00
.PHONY : java -packages -fingerprint
2020-07-13 16:11:11 +00:00
java-packages-fingerprint :
2021-03-18 13:01:07 +00:00
@cd syft/pkg/cataloger/java/test-fixtures/java-builds && \
2020-07-13 16:11:11 +00:00
make packages.fingerprint
2020-07-25 14:06:52 +00:00
.PHONY : fixtures
fixtures :
$( call title,Generating test fixtures)
2021-03-18 13:01:07 +00:00
cd syft/pkg/cataloger/java/test-fixtures/java-builds && make
2020-07-25 14:06:52 +00:00
2020-08-04 20:05:53 +00:00
.PHONY : generate -json -schema
2020-11-20 12:14:36 +00:00
generate-json-schema : ## Generate a new json schema
2020-12-18 19:08:19 +00:00
cd schema/json && go run generate.go
2020-08-04 20:05:53 +00:00
2021-03-11 17:41:10 +00:00
.PHONY : build
build : $( SNAPSHOTDIR ) ## Build release snapshot binaries and packages
2020-07-23 14:52:44 +00:00
2021-03-11 17:41:10 +00:00
$(SNAPSHOTDIR) : ## Build snapshot release binaries and packages
$( call title,Building snapshot artifacts)
# create a config with the dist dir overridden
echo " dist: $( SNAPSHOTDIR) " > $( TEMPDIR) /goreleaser.yaml
cat .goreleaser.yaml >> $( TEMPDIR) /goreleaser.yaml
2020-07-23 14:52:44 +00:00
2021-03-11 17:41:10 +00:00
# build release snapshots
BUILD_GIT_TREE_STATE = $( GITTREESTATE) \
2021-03-19 12:19:39 +00:00
$( TEMPDIR) /goreleaser release --skip-publish --skip-sign --rm-dist --snapshot --config $( TEMPDIR) /goreleaser.yaml
2020-07-23 14:52:44 +00:00
2021-03-11 17:41:10 +00:00
# note: we cannot clean the snapshot directory since the pipeline builds the snapshot separately
2020-07-23 14:52:44 +00:00
.PHONY : acceptance -mac
2021-03-18 13:01:07 +00:00
acceptance-mac : $( RESULTSDIR ) $( SNAPSHOTDIR ) ## Run acceptance tests on build snapshot binaries and packages (Mac)
2020-07-23 14:52:44 +00:00
$( call title,Running acceptance test: Run on Mac)
$( ACC_DIR) /mac.sh \
$( SNAPSHOTDIR) \
2020-07-24 21:41:22 +00:00
$( ACC_DIR) \
$( ACC_TEST_IMAGE) \
$( RESULTSDIR)
2020-07-23 14:52:44 +00:00
2021-03-11 17:41:10 +00:00
# note: we cannot clean the snapshot directory since the pipeline builds the snapshot separately
2020-07-23 14:52:44 +00:00
.PHONY : acceptance -linux
2021-03-11 17:41:10 +00:00
acceptance-linux : acceptance -test -deb -package -install acceptance -test -rpm -package -install ## Run acceptance tests on build snapshot binaries and packages (Linux)
2020-07-23 14:52:44 +00:00
.PHONY : acceptance -test -deb -package -install
2021-03-18 13:01:07 +00:00
acceptance-test-deb-package-install : $( RESULTSDIR ) $( SNAPSHOTDIR )
2020-07-23 14:52:44 +00:00
$( call title,Running acceptance test: DEB install)
$( ACC_DIR) /deb.sh \
$( SNAPSHOTDIR) \
2020-07-24 21:41:22 +00:00
$( ACC_DIR) \
$( ACC_TEST_IMAGE) \
$( RESULTSDIR)
2020-07-23 14:52:44 +00:00
.PHONY : acceptance -test -rpm -package -install
2021-03-18 13:01:07 +00:00
acceptance-test-rpm-package-install : $( RESULTSDIR ) $( SNAPSHOTDIR )
2020-07-23 14:52:44 +00:00
$( call title,Running acceptance test: RPM install)
$( ACC_DIR) /rpm.sh \
$( SNAPSHOTDIR) \
2020-07-24 21:41:22 +00:00
$( ACC_DIR) \
$( ACC_TEST_IMAGE) \
$( RESULTSDIR)
2020-07-23 14:52:44 +00:00
2021-03-18 13:01:07 +00:00
# note: this is used by CI to determine if the integration test fixture cache (docker image tars) should be busted
cli-fingerprint :
find test/cli/test-fixtures/image-* -type f -exec md5sum { } + | awk '{print $1}' | sort | md5sum | tee test/cli/test-fixtures/cache.fingerprint && echo " $( CLI_CACHE_BUSTER) " >> test/cli/test-fixtures/cache.fingerprint
2021-03-20 11:33:13 +00:00
.PHONY : cli
cli : $( SNAPSHOTDIR ) ## Run CLI tests
chmod 755 " $( SNAPSHOT_CMD) "
$( SNAPSHOT_CMD) version
SYFT_BINARY_LOCATION = '$(SNAPSHOT_CMD)' \
2021-03-18 13:01:07 +00:00
go test -count= 1 -v ./test/cli
2020-09-25 20:58:56 +00:00
.PHONY : changlog -release
changelog-release :
2021-03-11 17:41:10 +00:00
@echo " Last tag: $( SECOND_TO_LAST_TAG) "
2021-03-11 19:23:31 +00:00
@docker run --rm \
-v " $( shell pwd ) " :/usr/local/src/your-app \
ferrarimarco/github-changelog-generator \
2020-08-27 12:10:56 +00:00
--user anchore \
--project $( BIN) \
-t ${ GITHUB_TOKEN } \
2020-09-25 22:28:48 +00:00
--exclude-labels 'duplicate,question,invalid,wontfix,size:small,size:medium,size:large,size:x-large' \
2020-08-27 12:10:56 +00:00
--no-pr-wo-labels \
--no-issues-wo-labels \
2020-09-25 22:28:48 +00:00
--since-tag $( SECOND_TO_LAST_TAG)
2020-08-27 12:10:56 +00:00
2021-03-11 17:41:10 +00:00
@printf '\n$(BOLD)$(CYAN)Release $(VERSION) Changelog$(RESET)\n\n'
@cat CHANGELOG.md
2020-09-26 03:13:21 +00:00
2020-09-25 20:58:56 +00:00
.PHONY : changelog -unreleased
changelog-unreleased : ## show the current changelog that will be produced on the next release (note: requires GITHUB_TOKEN set)
2021-03-11 17:41:10 +00:00
@docker run -it --rm \
2020-11-04 20:47:55 +00:00
-v " $( shell pwd ) " :/usr/local/src/your-app \
ferrarimarco/github-changelog-generator \
2020-09-25 20:58:56 +00:00
--user anchore \
--project $( BIN) \
-t ${ GITHUB_TOKEN } \
2020-09-25 22:28:48 +00:00
--exclude-labels 'duplicate,question,invalid,wontfix,size:small,size:medium,size:large,size:x-large' \
--since-tag $( LAST_TAG)
2021-03-11 17:41:10 +00:00
@printf '\n$(BOLD)$(CYAN)Unreleased Changes (closed PRs and issues will not be in the final changelog)$(RESET)\n'
2020-09-25 22:28:48 +00:00
2021-03-11 17:41:10 +00:00
@docker run -it --rm \
2020-09-25 20:58:56 +00:00
-v $( shell pwd ) /CHANGELOG.md:/CHANGELOG.md \
rawkode/mdv \
2020-09-26 03:13:21 +00:00
-t 748.5989 \
2020-09-25 20:58:56 +00:00
/CHANGELOG.md
2021-03-11 17:41:10 +00:00
.PHONY : release
2021-03-11 19:23:31 +00:00
release : clean -dist changelog -release ## Build and publish final binaries and packages. Intended to be run only on macOS.
2021-03-11 17:41:10 +00:00
$( call title,Publishing release artifacts)
# Prepare for macOS-specific signing process
.github/scripts/mac-prepare-for-signing.sh
2021-03-25 20:50:09 +00:00
# login to docker
# note: the previous step creates a new keychain, so it is important to reauth into docker.io
@echo $$ { DOCKER_PASSWORD} | docker login docker.io -u $$ { DOCKER_USERNAME} --password-stdin
2021-03-11 17:41:10 +00:00
# create a config with the dist dir overridden
echo " dist: $( DISTDIR) " > $( TEMPDIR) /goreleaser.yaml
cat .goreleaser.yaml >> $( TEMPDIR) /goreleaser.yaml
# release (note the version transformation from v0.7.0 --> 0.7.0)
bash -c " \
BUILD_GIT_TREE_STATE = $( GITTREESTATE) \
VERSION = $( VERSION:v%= %) \
$( TEMPDIR) /goreleaser \
--rm-dist \
--config $( TEMPDIR) /goreleaser.yaml \
--release-notes <( cat CHANGELOG.md) "
# verify checksum signatures
.github/scripts/verify-signature.sh " $( DISTDIR) "
2020-07-25 11:47:14 +00:00
2020-07-29 18:54:47 +00:00
# upload the version file that supports the application version update check (excluding pre-releases)
2021-03-11 17:41:10 +00:00
.github/scripts/update-version-file.sh " $( DISTDIR) " " $( VERSION) "
2020-07-23 14:52:44 +00:00
2021-03-11 19:23:31 +00:00
2020-07-23 14:52:44 +00:00
.PHONY : clean
2021-03-23 18:31:59 +00:00
clean : clean -dist clean -snapshot clean -test -image -cache ## Remove previous builds, result reports, and test cache
2020-07-23 14:52:44 +00:00
rm -rf $( RESULTSDIR) /*
2021-03-10 18:25:31 +00:00
.PHONY : clean -snapshot
clean-snapshot :
rm -rf $( SNAPSHOTDIR) $( TEMPDIR) /goreleaser.yaml
2021-03-11 17:41:10 +00:00
.PHONY : clean -dist
clean-dist :
rm -rf $( DISTDIR) $( TEMPDIR) /goreleaser.yaml
2021-03-23 18:31:59 +00:00
clean-test-image-cache : clean -test -image -tar -cache clean -test -image -docker -cache
.PHONY : clear -test -image -tar -cache
clean-test-image-tar-cache : ## Delete all test cache (built docker image tars)
find . -type f -wholename "**/test-fixtures/cache/stereoscope-fixture-*.tar" -delete
.PHONY : clear -test -image -docker -cache
clean-test-image-docker-cache : ## Purge all test docker images
docker images --format '{{.ID}} {{.Repository}}' | grep stereoscope-fixture- | awk '{print $$1}' | uniq | xargs docker rmi --force
.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