diff --git a/.github/actions/bootstrap/action.yaml b/.github/actions/bootstrap/action.yaml
new file mode 100644
index 00000000..5544402d
--- /dev/null
+++ b/.github/actions/bootstrap/action.yaml
@@ -0,0 +1,81 @@
+name: "Bootstrap"
+description: "Bootstrap all tools and dependencies"
+inputs:
+ go-version:
+ description: "Go version to install"
+ required: true
+ default: "1.19.x"
+ use-go-cache:
+ description: "Restore go cache"
+ required: true
+ default: "true"
+ cache-key-prefix:
+ description: "Prefix all cache keys with this value"
+ required: true
+ default: "831180ac25"
+ build-cache-key-prefix:
+ description: "Prefix build cache key with this value"
+ required: true
+ default: "f8b6d31dea"
+ bootstrap-apt-packages:
+ description: "Space delimited list of tools to install via apt"
+ default: ""
+
+runs:
+ using: "composite"
+ steps:
+ - uses: actions/setup-go@v3
+ with:
+ go-version: ${{ inputs.go-version }}
+
+ - name: Restore tool cache
+ id: tool-cache
+ uses: actions/cache@v3
+ with:
+ path: ${{ github.workspace }}/.tmp
+ key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('Makefile') }}
+
+ # note: we need to keep restoring the go mod cache before bootstrapping tools since `go install` is used in
+ # some installations of project tools.
+ - name: Restore go module cache
+ id: go-mod-cache
+ if: inputs.use-go-cache == 'true'
+ uses: actions/cache@v3
+ with:
+ path: |
+ ~/go/pkg/mod
+ key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-${{ hashFiles('**/go.sum') }}
+ restore-keys: |
+ ${{ inputs.cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-
+
+ - name: (cache-miss) Bootstrap project tools
+ shell: bash
+ if: steps.tool-cache.outputs.cache-hit != 'true'
+ run: make bootstrap-tools
+
+ - name: Restore go build cache
+ id: go-cache
+ if: inputs.use-go-cache == 'true'
+ uses: actions/cache@v3
+ with:
+ path: |
+ ~/.cache/go-build
+ key: ${{ inputs.cache-key-prefix }}-${{ inputs.build-cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-${{ hashFiles('**/go.sum') }}
+ restore-keys: |
+ ${{ inputs.cache-key-prefix }}-${{ inputs.build-cache-key-prefix }}-${{ runner.os }}-go-${{ inputs.go-version }}-
+
+ - name: (cache-miss) Bootstrap go dependencies
+ shell: bash
+ if: steps.go-mod-cache.outputs.cache-hit != 'true' && inputs.use-go-cache == 'true'
+ run: make bootstrap-go
+
+ - name: Bootstrap CI dependencies
+ shell: bash
+ run: make ci-bootstrap
+
+ - name: Install apt packages
+ if: inputs.bootstrap-apt-packages != ''
+ shell: bash
+ run: |
+ DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y ${{ inputs.bootstrap-apt-packages }}
+
diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh
new file mode 100755
index 00000000..18f13cb4
--- /dev/null
+++ b/.github/scripts/build.sh
@@ -0,0 +1,80 @@
+#!/usr/bin/env bash
+set -uo pipefail
+
+# Based on https://gist.github.com/eduncan911/68775dba9d3c028181e4 and https://gist.github.com/makeworld-the-better-one/e1bb127979ae4195f43aaa3ad46b1097
+# but improved to use the `go` command so it never goes out of date.
+
+type setopt >/dev/null 2>&1
+
+contains() {
+ # Source: https://stackoverflow.com/a/8063398/7361270
+ [[ $1 =~ (^|[[:space:]])$2($|[[:space:]]) ]]
+}
+
+mkdir -p snapshot
+rm -f snapshot/*
+
+OUTPUT=snapshot/stereoscope-example
+FAILURES=""
+
+# You can set your own flags on the command line
+FLAGS=${FLAGS:-"-ldflags=\"-s -w\""}
+
+# A list of OSes and architectures to not build for, space-separated
+# It can be set from the command line when the script is called.
+NOT_ALLOWED_OS=${NOT_ALLOWED_OS:-"js android ios solaris illumos aix dragonfly plan9"}
+NOT_ALLOWED_ARCH=${NOT_ALLOWED_ARCH:-"riscv64 mips mips64 mips64le ppc64 ppc64le s390x wasm"}
+
+
+# Get all targets
+while IFS= read -r target; do
+ GOOS=${target%/*}
+ GOARCH=${target#*/}
+ BIN_FILENAME="${OUTPUT}-${GOOS}-${GOARCH}"
+
+ if contains "$NOT_ALLOWED_OS" "$GOOS" ; then
+ continue
+ fi
+
+ if contains "$NOT_ALLOWED_ARCH" "$GOARCH" ; then
+ continue
+ fi
+
+ # Check for arm and set arm version
+ if [[ $GOARCH == "arm" ]]; then
+ # Set what arm versions each platform supports
+ if [[ $GOOS == "darwin" ]]; then
+ arms="7"
+ elif [[ $GOOS == "windows" ]]; then
+ # This is a guess, it's not clear what Windows supports from the docs
+ # But I was able to build all these on my machine
+ arms="5 6 7"
+ elif [[ $GOOS == *"bsd" ]]; then
+ arms="6 7"
+ else
+ # Linux goes here
+ arms="5 6 7"
+ fi
+
+ # Now do the arm build
+ for GOARM in $arms; do
+ BIN_FILENAME="${OUTPUT}-${GOOS}-${GOARCH}${GOARM}"
+ if [[ "${GOOS}" == "windows" ]]; then BIN_FILENAME="${BIN_FILENAME}.exe"; fi
+ CMD="GOARM=${GOARM} GOOS=${GOOS} GOARCH=${GOARCH} go build $FLAGS -o ${BIN_FILENAME} $@"
+ echo "${CMD}"
+ eval "${CMD}" || FAILURES="${FAILURES} ${GOOS}/${GOARCH}${GOARM}"
+ done
+ else
+ # Build non-arm here
+ if [[ "${GOOS}" == "windows" ]]; then BIN_FILENAME="${BIN_FILENAME}.exe"; fi
+ CMD="GOOS=${GOOS} GOARCH=${GOARCH} go build $FLAGS -o ${BIN_FILENAME} $@"
+ echo "${CMD}"
+ eval "${CMD}" || FAILURES="${FAILURES} ${GOOS}/${GOARCH}"
+ fi
+done <<< "$(go tool dist list)"
+
+if [[ "${FAILURES}" != "" ]]; then
+ echo ""
+ echo "build failed for: ${FAILURES}"
+ exit 1
+fi
\ No newline at end of file
diff --git a/.github/scripts/coverage.py b/.github/scripts/coverage.py
new file mode 100755
index 00000000..db14135c
--- /dev/null
+++ b/.github/scripts/coverage.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+import subprocess
+import sys
+import shlex
+
+
+class bcolors:
+ HEADER = '\033[95m'
+ OKBLUE = '\033[94m'
+ OKCYAN = '\033[96m'
+ OKGREEN = '\033[92m'
+ WARNING = '\033[93m'
+ FAIL = '\033[91m'
+ ENDC = '\033[0m'
+ BOLD = '\033[1m'
+ UNDERLINE = '\033[4m'
+
+
+if len(sys.argv) < 3:
+ print("Usage: coverage.py [threshold] [go-coverage-report]")
+ sys.exit(1)
+
+
+threshold = float(sys.argv[1])
+report = sys.argv[2]
+
+
+args = shlex.split(f"go tool cover -func {report}")
+p = subprocess.run(args, capture_output=True, text=True)
+
+percent_coverage = float(p.stdout.splitlines()[-1].split()[-1].replace("%", ""))
+print(f"{bcolors.BOLD}Coverage: {percent_coverage}%{bcolors.ENDC}")
+
+if percent_coverage < threshold:
+ print(f"{bcolors.BOLD}{bcolors.FAIL}Coverage below threshold of {threshold}%{bcolors.ENDC}")
+ sys.exit(1)
diff --git a/.github/scripts/go-mod-tidy-check.sh b/.github/scripts/go-mod-tidy-check.sh
new file mode 100755
index 00000000..28f22fcd
--- /dev/null
+++ b/.github/scripts/go-mod-tidy-check.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+set -eu
+
+ORIGINAL_STATE_DIR=$(mktemp -d "TEMP-original-state-XXXXXXXXX")
+TIDY_STATE_DIR=$(mktemp -d "TEMP-tidy-state-XXXXXXXXX")
+
+trap "cp -p ${ORIGINAL_STATE_DIR}/* ./ && git update-index -q --refresh && rm -fR ${ORIGINAL_STATE_DIR} ${TIDY_STATE_DIR}" EXIT
+
+# capturing original state of files...
+cp go.mod go.sum "${ORIGINAL_STATE_DIR}"
+
+# capturing state of go.mod and go.sum after running go mod tidy...
+go mod tidy
+cp go.mod go.sum "${TIDY_STATE_DIR}"
+
+set +e
+
+# detect difference between the git HEAD state and the go mod tidy state
+DIFF_MOD=$(diff -u "${ORIGINAL_STATE_DIR}/go.mod" "${TIDY_STATE_DIR}/go.mod")
+DIFF_SUM=$(diff -u "${ORIGINAL_STATE_DIR}/go.sum" "${TIDY_STATE_DIR}/go.sum")
+
+if [[ -n "${DIFF_MOD}" || -n "${DIFF_SUM}" ]]; then
+ echo "go.mod diff:"
+ echo "${DIFF_MOD}"
+ echo "go.sum diff:"
+ echo "${DIFF_SUM}"
+ echo ""
+ printf "FAILED! go.mod and/or go.sum are NOT tidy; please run 'go mod tidy'.\n\n"
+ exit 1
+fi
diff --git a/.github/workflows/benchmark-testing.yaml b/.github/workflows/benchmark-testing.yaml
new file mode 100644
index 00000000..4cd87594
--- /dev/null
+++ b/.github/workflows/benchmark-testing.yaml
@@ -0,0 +1,58 @@
+name: "Benchmark testing"
+
+on:
+ workflow_dispatch:
+ pull_request:
+
+jobs:
+
+ Benchmark-Test:
+ name: "Benchmark tests"
+ runs-on: ubuntu-20.04
+ # note: we want benchmarks to run on pull_request events in order to publish results to a sticky comment, and
+ # we also want to run on push such that merges to main are recorded to the cache. For this reason we don't filter
+ # the job by event.
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Bootstrap environment
+ uses: ./.github/actions/bootstrap
+
+ - name: Restore base benchmark result
+ uses: actions/cache@v3
+ with:
+ path: test/results/benchmark-main.txt
+ # use base sha for PR or new commit hash for main push in benchmark result key
+ key: ${{ runner.os }}-bench-${{ (github.event.pull_request.base.sha != github.event.after) && github.event.pull_request.base.sha || github.event.after }}
+
+ - name: Run benchmark tests
+ id: benchmark
+ run: |
+ REF_NAME=${GITHUB_REF##*/} make benchmark
+ OUTPUT=$(make show-benchstat)
+ OUTPUT="${OUTPUT//'%'/'%25'}" # URL encode all '%' characters
+ OUTPUT="${OUTPUT//$'\n'/'%0A'}" # URL encode all '\n' characters
+ OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters
+ echo "::set-output name=result::$OUTPUT"
+
+ - uses: actions/upload-artifact@v3
+ with:
+ name: benchmark-test-results
+ path: test/results/**/*
+
+ - name: Update PR benchmark results comment
+ uses: marocchino/sticky-pull-request-comment@v2
+ continue-on-error: true
+ with:
+ header: benchmark
+ message: |
+ ### Benchmark Test Results
+
+
+ Benchmark results from the latest changes vs base branch
+
+ ```
+ ${{ steps.benchmark.outputs.result }}
+ ```
+
+
diff --git a/.github/workflows/validations.yaml b/.github/workflows/validations.yaml
index 4ed98466..f0314a6b 100644
--- a/.github/workflows/validations.yaml
+++ b/.github/workflows/validations.yaml
@@ -16,79 +16,28 @@ on:
- main
pull_request:
-env:
- GO_VERSION: "1.19.x"
-
jobs:
Static-Analysis:
name: "Static analysis"
runs-on: ubuntu-20.04
steps:
- - uses: actions/setup-go@v2
- with:
- go-version: ${{ env.GO_VERSION }}
-
- - uses: actions/checkout@v2
-
- - name: Restore tool cache
- id: tool-cache
- uses: actions/cache@v2.1.3
- with:
- path: ${{ github.workspace }}/.tmp
- key: ${{ runner.os }}-tool-${{ hashFiles('Makefile') }}
+ - uses: actions/checkout@v3
- - name: Restore go cache
- id: go-cache
- uses: actions/cache@v2.1.3
- with:
- path: ~/go/pkg/mod
- key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}
- restore-keys: |
- ${{ runner.os }}-go-${{ env.GO_VERSION }}-
-
- - name: (cache-miss) Bootstrap all project dependencies
- if: steps.tool-cache.outputs.cache-hit != 'true' || steps.go-cache.outputs.cache-hit != 'true'
- run: make bootstrap
+ - name: Bootstrap environment
+ uses: ./.github/actions/bootstrap
- - name: Bootstrap CI environment dependencies
- run: make ci-bootstrap
-
- - name: Run static analysis
- run: make static-analysis
+ - name: Run static analysis
+ run: make static-analysis
Unit-Test:
name: "Unit tests"
runs-on: ubuntu-20.04
steps:
- - uses: actions/setup-go@v2
- with:
- go-version: ${{ env.GO_VERSION }}
-
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- - name: Restore tool cache
- id: tool-cache
- uses: actions/cache@v2.1.3
- with:
- path: ${{ github.workspace }}/.tmp
- key: ${{ runner.os }}-tool-${{ hashFiles('Makefile') }}
-
- - name: Restore go cache
- id: go-cache
- uses: actions/cache@v2.1.3
- with:
- path: ~/go/pkg/mod
- key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}
- restore-keys: |
- ${{ runner.os }}-go-${{ env.GO_VERSION }}-
-
- - name: (cache-miss) Bootstrap all project dependencies
- if: steps.tool-cache.outputs.cache-hit != 'true' || steps.go-cache.outputs.cache-hit != 'true'
- run: make bootstrap
-
- - name: Bootstrap CI environment dependencies
- run: make ci-bootstrap
+ - name: Bootstrap environment
+ uses: ./.github/actions/bootstrap
- name: Run unit tests
run: make unit
@@ -102,11 +51,10 @@ jobs:
name: "Integration tests"
runs-on: ubuntu-20.04
steps:
- - uses: actions/setup-go@v2
- with:
- go-version: ${{ env.GO_VERSION }}
+ - uses: actions/checkout@v3
- - uses: actions/checkout@v2
+ - name: Bootstrap environment
+ uses: ./.github/actions/bootstrap
- name: Enable systemd for podman socket activation
run: |
@@ -128,29 +76,6 @@ jobs:
with:
limit-access-to-actor: true
- - name: Restore tool cache
- id: tool-cache
- uses: actions/cache@v2.1.3
- with:
- path: ${{ github.workspace }}/.tmp
- key: ${{ runner.os }}-tool-${{ hashFiles('Makefile') }}
-
- - name: Restore go cache
- id: go-cache
- uses: actions/cache@v2.1.3
- with:
- path: ~/go/pkg/mod
- key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}
- restore-keys: |
- ${{ runner.os }}-go-${{ env.GO_VERSION }}-
-
- - name: (cache-miss) Bootstrap all project dependencies
- if: steps.tool-cache.outputs.cache-hit != 'true' || steps.go-cache.outputs.cache-hit != 'true'
- run: make bootstrap
-
- - name: Bootstrap CI environment dependencies
- run: make ci-bootstrap
-
- name: Build key for test-fixture cache
run: make integration-fingerprint
@@ -177,77 +102,15 @@ jobs:
- name: Run integration tests
run: make integration
- Benchmark-Test:
- name: "Benchmark tests"
+ Build-Snapshot-Artifacts:
+ name: "Build snapshot artifacts"
runs-on: ubuntu-20.04
- # note: we want benchmarks to run on pull_request events in order to publish results to a sticky comment, and
- # we also want to run on push such that merges to main are recorded to the cache. For this reason we don't filter
- # the job by event.
steps:
- - uses: actions/setup-go@v2
- with:
- go-version: ${{ env.GO_VERSION }}
-
- - uses: actions/checkout@v2
-
- - name: Restore tool cache
- id: tool-cache
- uses: actions/cache@v2.1.3
- with:
- path: ${{ github.workspace }}/.tmp
- key: ${{ runner.os }}-tool-${{ hashFiles('Makefile') }}
-
- - name: Restore go cache
- id: go-cache
- uses: actions/cache@v2.1.3
- with:
- path: ~/go/pkg/mod
- key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}
- restore-keys: |
- ${{ runner.os }}-go-${{ env.GO_VERSION }}-
-
- - name: (cache-miss) Bootstrap all project dependencies
- if: steps.tool-cache.outputs.cache-hit != 'true' || steps.go-cache.outputs.cache-hit != 'true'
- run: make bootstrap
-
- - name: Bootstrap CI environment dependencies
- run: make ci-bootstrap
-
- - name: Restore base benchmark result
- uses: actions/cache@v2
- with:
- path: test/results/benchmark-main.txt
- # use base sha for PR or new commit hash for main push in benchmark result key
- key: ${{ runner.os }}-bench-${{ (github.event.pull_request.base.sha != github.event.after) && github.event.pull_request.base.sha || github.event.after }}
-
- - name: Run benchmark tests
- id: benchmark
- run: |
- REF_NAME=${GITHUB_REF##*/} make benchmark
- OUTPUT=$(make show-benchstat)
- OUTPUT="${OUTPUT//'%'/'%25'}" # URL encode all '%' characters
- OUTPUT="${OUTPUT//$'\n'/'%0A'}" # URL encode all '\n' characters
- OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters
- echo "::set-output name=result::$OUTPUT"
-
- - uses: actions/upload-artifact@v2
- with:
- name: benchmark-test-results
- path: test/results/**/*
-
- - name: Update PR benchmark results comment
- uses: marocchino/sticky-pull-request-comment@v2
- continue-on-error: true
- with:
- header: benchmark
- message: |
- ### Benchmark Test Results
+ - uses: actions/checkout@v3
-
- Benchmark results from the latest changes vs base branch
+ - name: Bootstrap environment
+ uses: ./.github/actions/bootstrap
- ```
- ${{ steps.benchmark.outputs.result }}
- ```
+ - name: Build snapshot artifacts
+ run: make snapshot
-
diff --git a/.gitignore b/.gitignore
index 930ca30b..26630caf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@
coverage.txt
**/test-fixtures/cache/
**/*.fingerprint
+snapshot/
# Binaries for programs and plugins
*.exe
diff --git a/Makefile b/Makefile
index 181594bb..74de855c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,15 @@
-TEMPDIR = ./.tmp
-RESULTSDIR = test/results
-COVER_REPORT = $(RESULTSDIR)/unit-coverage-details.txt
-COVER_TOTAL = $(RESULTSDIR)/unit-coverage-summary.txt
-LINTCMD = $(TEMPDIR)/golangci-lint run --tests=false --config .golangci.yaml
+TEMP_DIR = ./.tmp
+
+# Command templates #################################
+LINT_CMD = $(TEMP_DIR)/golangci-lint run --tests=false --config .golangci.yaml
+
+# Tool versions #################################
+GOLANGCILINT_VERSION := v1.51.0
+GOSIMPORTS_VERSION := v0.3.5
+BOUNCER_VERSION := v0.4.0
+CHRONICLE_VERSION := v0.5.1
+
+# Formatting variables #################################
BOLD := $(shell tput -T linux bold)
PURPLE := $(shell tput -T linux setaf 5)
GREEN := $(shell tput -T linux setaf 2)
@@ -11,15 +18,16 @@ RED := $(shell tput -T linux setaf 1)
RESET := $(shell tput -T linux sgr0)
TITLE := $(BOLD)$(PURPLE)
SUCCESS := $(BOLD)$(GREEN)
-# the quality gate lower threshold for unit test total % coverage (by function statements)
-COVERAGE_THRESHOLD := 48
+
+# Test variables #################################
+COVERAGE_THRESHOLD := 55 # the quality gate lower threshold for unit test total % coverage (by function statements)
ifeq "$(strip $(VERSION))" ""
override VERSION = $(shell git describe --always --tags --dirty)
endif
-ifndef TEMPDIR
- $(error TEMPDIR is not set)
+ifndef TEMP_DIR
+ $(error TEMP_DIR is not set)
endif
ifndef REF_NAME
@@ -31,37 +39,43 @@ define title
endef
.PHONY: all
-all: static-analysis test ## Run all checks (linting, all tests, and dependencies license checks)
+all: static-analysis test ## Run all linux-based checks (linting, license check, unit, integration, and linux compare tests)
@printf '$(SUCCESS)All checks pass!$(RESET)\n'
+.PHONY: static-analysis
+static-analysis: check-go-mod-tidy lint check-licenses ## Run all static analysis checks
+
.PHONY: test
-test: unit integration benchmark ## Run all levels of test
+test: unit integration benchmark ## Run all tests (currently unit and integrations)
-.PHONY: help
-help:
- @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "$(BOLD)$(CYAN)%-25s$(RESET)%s\n", $$1, $$2}'
+
+## Bootstrapping targets #################################
.PHONY: ci-bootstrap
ci-bootstrap: bootstrap
- sudo apt install -y bc
curl -sLO https://github.com/sylabs/singularity/releases/download/v3.10.0/singularity-ce_3.10.0-focal_amd64.deb && sudo apt-get install -y -f ./singularity-ce_3.10.0-focal_amd64.deb
-$(RESULTSDIR):
- mkdir -p $(RESULTSDIR)
-
-.PHONY: boostrap
-bootstrap: $(RESULTSDIR) ## Download and install all project dependencies (+ prep tooling in the ./tmp dir)
- $(call title,Downloading dependencies)
- @pwd
- # prep temp dirs
- mkdir -p $(TEMPDIR)
- mkdir -p $(RESULTSDIR)
- # install go dependencies
+.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)
+ 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)
+ # 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)
+
+.PHONY: bootstrap-go
+bootstrap-go:
go mod download
- # install utilities
- [ -f "$(TEMPDIR)/benchstat" ] || GO111MODULE=off GOBIN=$(shell realpath $(TEMPDIR)) go get -u golang.org/x/perf/cmd/benchstat
- [ -f "$(TEMPDIR)/golangci" ] || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(TEMPDIR)/ v1.51.0
- [ -f "$(TEMPDIR)/bouncer" ] || curl -sSfL https://raw.githubusercontent.com/wagoodman/go-bouncer/master/bouncer.sh | sh -s -- -b $(TEMPDIR)/ v0.4.0
+
+$(TEMP_DIR):
+ mkdir -p $(TEMP_DIR)
+
+## Static analysis targets #################################
.PHONY: static-analysis
static-analysis: check-licenses lint
@@ -71,40 +85,55 @@ lint: ## Run gofmt + golangci lint checks
$(call title,Running linters)
@printf "files with gofmt issues: [$(shell gofmt -l -s .)]\n"
@test -z "$(shell gofmt -l -s .)"
- $(LINTCMD)
+ $(LINT_CMD)
.PHONY: lint-fix
lint-fix: ## Auto-format all source code + run golangci lint fixers
$(call title,Running lint fixers)
gofmt -w -s .
- $(LINTCMD) --fix
+ $(LINT_CMD) --fix
go mod tidy
.PHONY: check-licenses
check-licenses:
$(call title,Validating licenses for go dependencies)
- $(TEMPDIR)/bouncer check
+ $(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: $(RESULTSDIR) ## Run unit tests (with coverage)
+unit: $(TEMP_DIR) ## Run unit tests (with coverage)
$(call title,Running unit tests)
- go test --race -coverprofile $(COVER_REPORT) $(shell go list ./... | grep -v anchore/stereoscope/test/integration)
- @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
+ go test -coverprofile $(TEMP_DIR)/unit-coverage-details.txt $(shell go list ./... | grep -v anchore/stereoscope/test)
+ @.github/scripts/coverage.py $(COVERAGE_THRESHOLD) $(TEMP_DIR)/unit-coverage-details.txt
+
+
+.PHONY: integration
+integration: integration-tools ## Run integration tests
+ $(call title,Running integration tests)
+ go test -v ./test/integration
+
+## Benchmark test targets #################################
+
.PHONY: benchmark
-benchmark: $(RESULTSDIR) ## Run benchmark tests and compare against the baseline (if available)
+benchmark: $(TEMP_DIR) ## Run benchmark tests and compare against the baseline (if available)
$(call title,Running benchmark tests)
- go test -cpu 2 -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
+ go test -cpu 2 -p 1 -run=^Benchmark -bench=. -count=5 -benchmem ./... | tee $(TEMP_DIR)/benchmark-$(REF_NAME).txt
+ (test -s $(TEMP_DIR)/benchmark-main.txt && \
+ $(TEMP_DIR)/benchstat $(TEMP_DIR)/benchmark-main.txt $(TEMP_DIR)/benchmark-$(REF_NAME).txt || \
+ $(TEMP_DIR)/benchstat $(TEMP_DIR)/benchmark-$(REF_NAME).txt) \
+ | tee $(TEMP_DIR)/benchstat.txt
+
.PHONY: show-benchstat
show-benchstat:
- @cat $(RESULTSDIR)/benchstat.txt
+ @cat $(TEMP_DIR)/benchstat.txt
+
+## Test-fixture-related targets #################################
# note: this is used by CI to determine if the integration test fixture cache (docker image tars) should be busted
.PHONY: integration-fingerprint
@@ -127,11 +156,22 @@ integration-tools-load:
integration-tools-save:
@cd test/integration/tools && make save-cache
-.PHONY: integration
-integration: integration-tools ## Run integration tests
- $(call title,Running integration tests)
- go test -v ./test/integration
+## Build-related targets #################################
+
+.PHONY: snapshot
+snapshot: ## Build the binary
+ $(call title,Build compatability test)
+ @.github/scripts/build.sh
+
+## Cleanup targets #################################
.PHONY: clear-test-cache
clear-test-cache: ## Delete all test cache (built docker image tars)
find . -type f -wholename "**/test-fixtures/cache/*.tar" -delete
+
+
+## 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}'
diff --git a/pkg/file/metadata.go b/pkg/file/metadata.go
index 5ba884af..4dab4021 100644
--- a/pkg/file/metadata.go
+++ b/pkg/file/metadata.go
@@ -2,12 +2,13 @@ package file
import (
"archive/tar"
- "github.com/anchore/stereoscope/internal/log"
"io"
"os"
"path"
"path/filepath"
+ "github.com/anchore/stereoscope/internal/log"
+
"github.com/sylabs/squashfs"
)
diff --git a/pkg/file/type.go b/pkg/file/type.go
index 0d587a1b..2555fd46 100644
--- a/pkg/file/type.go
+++ b/pkg/file/type.go
@@ -37,7 +37,7 @@ func AllTypes() []Type {
func TypeFromTarType(ty byte) Type {
switch ty {
- case tar.TypeReg, tar.TypeRegA:
+ case tar.TypeReg, tar.TypeRegA: // nolint: staticcheck
return TypeReg
case tar.TypeLink:
return TypeHardLink