name: "Release"
on:
  push:
    # take no actions on push to any branch...
    branches-ignore:
      - "**"
    # ... only act on release tags
    tags:
      - "v*"

env:
  GO_VERSION: "1.18.x"
  GO_STABLE_VERSION: true

jobs:
  quality-gate:
    environment: release
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      # we don't want to release commits that have been pushed and tagged, but not necessarily merged onto main
      - name: Ensure tagged commit is on main
        run: |
          echo "Tag: ${GITHUB_REF##*/}"
          git fetch origin main
          git merge-base --is-ancestor ${GITHUB_REF##*/} origin/main && echo "${GITHUB_REF##*/} is a commit on main!"

      - name: Check static analysis results
        uses: fountainhead/action-wait-for-check@v1.0.0
        id: static-analysis
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          # This check name is defined as the github action job name (in .github/workflows/testing.yaml)
          checkName: "Static analysis"
          ref: ${{ github.event.pull_request.head.sha || github.sha }}

      - name: Check unit test results
        uses: fountainhead/action-wait-for-check@v1.0.0
        id: unit
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          # This check name is defined as the github action job name (in .github/workflows/testing.yaml)
          checkName: "Unit tests"
          ref: ${{ github.event.pull_request.head.sha || github.sha }}

      - name: Check integration test results
        uses: fountainhead/action-wait-for-check@v1.0.0
        id: integration
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          # This check name is defined as the github action job name (in .github/workflows/testing.yaml)
          checkName: "Integration tests"
          ref: ${{ github.event.pull_request.head.sha || github.sha }}

      - name: Check acceptance test results (linux)
        uses: fountainhead/action-wait-for-check@v1.0.0
        id: acceptance-linux
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          # This check name is defined as the github action job name (in .github/workflows/testing.yaml)
          checkName: "Acceptance tests (Linux)"
          ref: ${{ github.event.pull_request.head.sha || github.sha }}

      - name: Check acceptance test results (mac)
        uses: fountainhead/action-wait-for-check@v1.0.0
        id: acceptance-mac
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          # This check name is defined as the github action job name (in .github/workflows/testing.yaml)
          checkName: "Acceptance tests (Mac)"
          ref: ${{ github.event.pull_request.head.sha || github.sha }}

      - name: Check cli test results (linux)
        uses: fountainhead/action-wait-for-check@v1.0.0
        id: cli-linux
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          # This check name is defined as the github action job name (in .github/workflows/testing.yaml)
          checkName: "CLI tests (Linux)"
          ref: ${{ github.event.pull_request.head.sha || github.sha }}

      - name: Quality gate
        if: steps.static-analysis.outputs.conclusion != 'success' || steps.unit.outputs.conclusion != 'success' || steps.integration.outputs.conclusion != 'success' || steps.cli-linux.outputs.conclusion != 'success' || steps.acceptance-linux.outputs.conclusion != 'success' || steps.acceptance-mac.outputs.conclusion != 'success'
        run: |
          echo "Static Analysis Status: ${{ steps.static-analysis.conclusion }}"
          echo "Unit Test Status: ${{ steps.unit.outputs.conclusion }}"
          echo "Integration Test Status: ${{ steps.integration.outputs.conclusion }}"
          echo "Acceptance Test (Linux) Status: ${{ steps.acceptance-linux.outputs.conclusion }}"
          echo "Acceptance Test (Mac) Status: ${{ steps.acceptance-mac.outputs.conclusion }}"
          echo "CLI Test (Linux) Status: ${{ steps.cli-linux.outputs.conclusion }}"
          false

  release:
    needs: [quality-gate]
    # due to our code signing process, it's vital that we run our release steps on macOS
    runs-on: macos-latest
    steps:
      - uses: actions/setup-go@v2
        with:
          go-version: ${{ env.GO_VERSION }}
          stable: ${{ env.GO_STABLE_VERSION }}

      - uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - 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: Build & publish release artifacts
        run: make release
        env:
          GITHUB_TOKEN: ${{ secrets.ANCHORE_GIT_READ_TOKEN }}
          AWS_ACCESS_KEY_ID: ${{ secrets.TOOLBOX_AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.TOOLBOX_AWS_SECRET_ACCESS_KEY }}
          # used during macOS code signing
          APPLE_DEVELOPER_ID_CERT: ${{ secrets.APPLE_DEVELOPER_ID_CERT }}
          APPLE_DEVELOPER_ID_CERT_PASS: ${{ secrets.APPLE_DEVELOPER_ID_CERT_PASS }}
          # used during macOS notarization
          AC_USERNAME: ${{ secrets.ENG_CI_APPLE_ID }}
          AC_PASSWORD: ${{ secrets.ENG_CI_APPLE_ID_PASS }}

      - uses: anchore/sbom-action@v0
        continue-on-error: true
        with:
          artifact-name: sbom.spdx.json

      - uses: 8398a7/action-slack@v3
        continue-on-error: true
        with:
          status: ${{ job.status }}
          fields: repo,workflow,action,eventName
          text: "A new Grype release is ready to be manually published: https://github.com/anchore/grype/releases"
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
        if: ${{ success() }}

      - uses: actions/upload-artifact@v2
        with:
          name: artifacts
          path: dist/**/*

  release-docker-assets:
    needs: [release]
    # code signing requires we run on mac-os runners. docker does not come installed on the mac-os runner
    # a previous release process installed and configured docker on the mac-os runner which lead to blocked releases
    # the anchore tools team opted to break this step out to a separate process to remove this work constraint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-go@v2
        with:
          go-version: ${{ env.GO_VERSION }}

      - name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.TOOLBOX_DOCKER_USER }}
          password: ${{ secrets.TOOLBOX_DOCKER_PASS }}

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v2
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - 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: Build & Publish docker images
        run: make release-docker-assets
