name: "Release"
on:
  workflow_dispatch:
    inputs:
      version:
        description: tag the latest commit on main with the given version (prefixed with v)
        required: true

permissions:
  contents: read

jobs:
  quality-gate:
    environment: release
    runs-on: ubuntu-20.04
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7

      - name: Check if running on main
        if: github.ref != 'refs/heads/main'
        # we are using the following flag when running `cosign blob-verify` for checksum signature verification:
        #   --certificate-identity-regexp "https://github.com/anchore/.github/workflows/release.yaml@refs/heads/main"
        # if we are not on the main branch, the signature will not be verifiable since the suffix requires the main branch
        # at the time of when the OIDC token was issued on the Github Actions runner.
        run: echo "This can only be run on the main branch otherwise releases produced will not be verifiable with cosign" && exit 1

      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7

      - name: Check if pinned syft is a release version
        run: .github/scripts/check-syft-version-is-release.sh

      - name: Check if tag already exists
        # note: this will fail if the tag already exists
        run: |
          [[ "${{ github.event.inputs.version }}" == v* ]] || (echo "version '${{ github.event.inputs.version }}' does not have a 'v' prefix" && exit 1)
          git tag ${{ github.event.inputs.version }}

      - name: Check static analysis results
        uses: fountainhead/action-wait-for-check@5a908a24814494009c4bb27c242ea38c93c593be # v1.2.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@5a908a24814494009c4bb27c242ea38c93c593be # v1.2.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@5a908a24814494009c4bb27c242ea38c93c593be # v1.2.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@5a908a24814494009c4bb27c242ea38c93c593be # v1.2.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@5a908a24814494009c4bb27c242ea38c93c593be # v1.2.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@5a908a24814494009c4bb27c242ea38c93c593be # v1.2.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

  # only release core assets within the "release" job. Any other assets not already under the purview of the
  # goreleaser configuration should be added as separate jobs to allow for debugging separately from the release workflow
  # as well as not accidentally be re-run as a step multiple times (as could be done within the release workflow) as
  # not all actions are guaranteed to be idempotent.
  release:
    needs: [quality-gate]
    runs-on: ubuntu-20.04
    permissions:
      contents: write
      packages: write
      id-token: write
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
        with:
          fetch-depth: 0

      - name: Bootstrap environment
        uses: ./.github/actions/bootstrap
        with:
          # use the same cache we used for building snapshots
          build-cache-key-prefix: "snapshot"

      - name: Login to Docker Hub
        uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446  #v3.2.0
        with:
          username: ${{ secrets.ANCHOREOSSWRITE_DH_USERNAME }}
          password: ${{ secrets.ANCHOREOSSWRITE_DH_PAT }}

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

      - name: Tag release
        run: |
          git config user.name "anchoreci"
          git config user.email "anchoreci@users.noreply.github.com"
          git tag -a ${{ github.event.inputs.version }} -m "Release ${{ github.event.inputs.version }}"
          git push origin --tags
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Build & publish release artifacts
        run: make ci-release
        env:
          # for mac signing and notarization...
          QUILL_SIGN_P12: ${{ secrets.ANCHORE_APPLE_DEVELOPER_ID_CERT_CHAIN }}
          QUILL_SIGN_PASSWORD: ${{ secrets.ANCHORE_APPLE_DEVELOPER_ID_CERT_PASS }}
          QUILL_NOTARY_ISSUER: ${{ secrets.APPLE_NOTARY_ISSUER }}
          QUILL_NOTARY_KEY_ID: ${{ secrets.APPLE_NOTARY_KEY_ID }}
          QUILL_NOTARY_KEY: ${{ secrets.APPLE_NOTARY_KEY }}
          # for creating the release (requires write access to packages and content)
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          # for updating brew formula in anchore/homebrew-syft
          GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }}

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

      - uses: 8398a7/action-slack@28ba43ae48961b90635b50953d216767a6bea486 # v3.16.2
        continue-on-error: true
        with:
          status: ${{ job.status }}
          fields: repo,workflow,action,eventName
          text: "A new Grype release has been published: https://github.com/anchore/grype/releases/tag/${{ github.event.inputs.version }}"
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
        if: ${{ success() }}

  release-version-file:
    needs: [release]
    uses: ./.github/workflows/release-version-file.yaml
    with:
      version: ${{ github.event.inputs.version }}
    secrets: inherit
