diff --git a/.github/scripts/verify-signature.sh b/.github/scripts/verify-signature.sh new file mode 100755 index 00000000..c022afc5 --- /dev/null +++ b/.github/scripts/verify-signature.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -ue + +DISTDIR=$1 + +export FINGERPRINT=$(gpg --verify ${DISTDIR}/*checksums.txt.sig ${DISTDIR}/*checksums.txt 2>&1 | grep 'using RSA key' | awk '{ print $NF }') + +if [[ "${FINGERPRINT}" == "${SIGNING_FINGERPRINT}" ]]; then + echo 'verified signature' +else + echo "signed with unknown fingerprint: ${FINGERPRINT}" + echo " expected fingerprint: ${SIGNING_FINGERPRINT}" + exit 1 +fi diff --git a/.github/workflows/acceptance-test.yaml b/.github/workflows/acceptance-test.yaml new file mode 100644 index 00000000..00b89940 --- /dev/null +++ b/.github/workflows/acceptance-test.yaml @@ -0,0 +1,71 @@ +name: 'Acceptance' +on: + push: + # ... only act on pushes to master + branches: + - master + # ... do not act on release tags + tags-ignore: + - v* +env: + GO_VERSION: "1.14.x" +jobs: + # Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline + Build-Snapshot-Artifacts: + runs-on: ubuntu-latest + steps: + + # TODO: remove me after release + - name: Configure git for private modules + env: + TOKEN: ${{ secrets.ANCHORE_GIT_READ_TOKEN }} + run: git config --global url."https://anchore:${TOKEN}@github.com".insteadOf "https://github.com" + + - uses: actions/setup-go@v2 + with: + go-version: ${{ env.GO_VERSION }} + + - uses: actions/checkout@v2 + + - name: Restore bootstrap cache + id: cache + uses: actions/cache@v2 + with: + path: | + ~/go/pkg/mod + ${{ github.workspace }}/.tmp + key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}-${{ hashFiles('Makefile') }} + restore-keys: | + ${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}- + ${{ runner.os }}-go-${{ env.GO_VERSION }}- + + - name: Bootstrap dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: make ci-bootstrap + + - name: Import GPG key + id: import_gpg + uses: crazy-max/ghaction-import-gpg@v2 + env: + GPG_PRIVATE_KEY: ${{ secrets.SIGNING_GPG_PRIVATE_KEY }} + PASSPHRASE: ${{ secrets.SIGNING_GPG_PASSPHRASE }} + + - name: GPG signing info + run: | + echo "fingerprint: ${{ steps.import_gpg.outputs.fingerprint }}" + echo "keyid: ${{ steps.import_gpg.outputs.keyid }}" + echo "name: ${{ steps.import_gpg.outputs.name }}" + echo "email: ${{ steps.import_gpg.outputs.email }}" + + - name: Build snapshot artifacts + run: make snapshot + env: + GPG_PRIVATE_KEY: ${{ secrets.SIGNING_GPG_PRIVATE_KEY }} + PASSPHRASE: ${{ secrets.SIGNING_GPG_PASSPHRASE }} + + - uses: actions/upload-artifact@v2 + with: + name: artifacts + path: snapshot/**/* + +# TODO: currently we only do a snapshot build, later we will add explicit acceptance tests per-platform \ No newline at end of file diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 95ba8f3e..b9d33d32 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -23,6 +23,15 @@ jobs: git fetch origin master git merge-base --is-ancestor ${GITHUB_REF##*/} origin/master && echo "${GITHUB_REF##*/} is a commit on master!" + - name: Build snapshot artifacts + uses: fountainhead/action-wait-for-check@v1 + id: snapshot + with: + token: ${{ secrets.GITHUB_TOKEN }} + # This check name is defined as the circle-ci workflow name (in .circleci/config.yaml) + checkName: "Build-Snapshot-Artifacts" + ref: ${{ github.event.pull_request.head.sha || github.sha }} + - name: Check static anaylysis, unit, and integration test results uses: fountainhead/action-wait-for-check@v1 id: sa-unit-int @@ -33,9 +42,10 @@ jobs: ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Quality gate - if: steps.sa-unit-int.outputs.conclusion != 'success' + if: steps.sa-unit-int.outputs.conclusion != 'success' || steps.snapshot.outputs.conclusion != 'success' run: | - echo "Static/Unit/Integration Status: ${{ steps.sa-unit-int.outputs.conclusion }}" + echo "Static/Unit/Integration Status : ${{ steps.sa-unit-int.outputs.conclusion }}" + echo "Build Snapshot Artifacts Status: ${{ steps.snapshot.outputs.conclusion }}" false release: @@ -70,12 +80,29 @@ jobs: if: steps.cache.outputs.cache-hit != 'true' run: make ci-bootstrap + - name: Import GPG key + id: import_gpg + uses: crazy-max/ghaction-import-gpg@v2 + env: + GPG_PRIVATE_KEY: ${{ secrets.SIGNING_GPG_PRIVATE_KEY }} + PASSPHRASE: ${{ secrets.SIGNING_GPG_PASSPHRASE }} + + - name: GPG signing info + run: | + echo "fingerprint: ${{ steps.import_gpg.outputs.fingerprint }}" + echo "keyid: ${{ steps.import_gpg.outputs.keyid }}" + echo "name: ${{ steps.import_gpg.outputs.name }}" + echo "email: ${{ steps.import_gpg.outputs.email }}" + - name: Build snapshot artifacts run: make release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GPG_PRIVATE_KEY: ${{ secrets.SIGNING_GPG_PRIVATE_KEY }} + PASSPHRASE: ${{ secrets.SIGNING_GPG_PASSPHRASE }} + SIGNING_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} - uses: actions/upload-artifact@v2 with: name: artifacts - path: dist \ No newline at end of file + path: dist/**/* \ No newline at end of file diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 5f4661d4..7c7d92aa 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,3 +1,13 @@ +release: + # If set to auto, will mark the release as not ready for production + # in case there is an indicator for this in the tag e.g. v1.0.0-rc1 + # If set to true, will mark the release as not ready for production. + prerelease: auto + +signs: + - artifacts: checksum + args: ["--output", "${signature}", "--detach-sign", "${artifact}"] + builds: - binary: grype env: @@ -29,12 +39,13 @@ nfpms: - rpm - deb -brews: - - tap: - owner: anchore - name: homebrew-grype - homepage: *website - description: *description +# TODO: add back in when open sourced +#brews: +# - tap: +# owner: anchore +# name: homebrew-grype +# homepage: *website +# description: *description archives: - format: tar.gz diff --git a/Makefile b/Makefile index 64c416d4..894c0388 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ endef .PHONY: all bootstrap lint lint-fix unit coverage integration check-pipeline clear-cache help test -all: clean lint check-licenses test ## Run all checks (linting, license check, unit, and integration tests) +all: clean lint check-licenses test ## Run all checks (linting, license check, unit, integration, and linux acceptance tests tests) @printf '$(SUCCESS)All checks pass!$(RESET)\n' .PHONY: compare @@ -56,7 +56,7 @@ compare: @cd test/inline-compare && make .PHONY: test -test: unit integration ## Run all tests (currently unit & integration tests ) +test: unit integration acceptance-linux ## Run all tests (unit, integration, and linux acceptance tests ) help: @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "$(BOLD)$(CYAN)%-25s$(RESET)%s\n", $$1, $$2}' @@ -141,6 +141,9 @@ $(SNAPSHOTDIR): ## Build snapshot release binaries and packages BUILD_GIT_TREE_STATE=$(GITTREESTATE) \ $(TEMPDIR)/goreleaser release --skip-publish --rm-dist --snapshot --config $(TEMPDIR)/goreleaser.yaml +.PHONY: acceptance-linux +acceptance-linux: $(SNAPSHOTDIR) ## Run acceptance tests on build snapshot binaries and packages (Linux) + # TODO: this is not releasing yet .PHONY: release release: clean-dist ## Build and publish final binaries and packages @@ -151,18 +154,21 @@ release: clean-dist ## Build and publish final binaries and packages # release BUILD_GIT_TREE_STATE=$(GITTREESTATE) \ - $(TEMPDIR)/goreleaser --skip-publish --rm-dist --config $(TEMPDIR)/goreleaser.yaml + $(TEMPDIR)/goreleaser --rm-dist --config $(TEMPDIR)/goreleaser.yaml + + # verify checksum signatures + .github/scripts/verify-signature.sh "$(DISTDIR)" # create a version file for version-update checks echo "$(VERSION)" > $(DISTDIR)/VERSION # TODO: add upload to bucket .PHONY: clean -clean: clean-dist clean-shapshot ## Remove previous builds and result reports +clean: clean-dist clean-snapshot ## Remove previous builds and result reports rm -rf $(RESULTSDIR)/* -.PHONY: clean-shapshot -clean-shapshot: +.PHONY: clean-snapshot +clean-snapshot: rm -rf $(SNAPSHOTDIR) $(TEMPDIR)/goreleaser.yaml .PHONY: clean-dist