name: build-test-deploy

on:
  pull_request:
    types:
      - opened
      - reopened
      - synchronize
      - ready_for_review
    branches:
      - main
  push:
    branches:
      - "main"
    tags:
      - "v*.*.*"

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  fail_if_pull_request_is_draft:
    if: github.event.pull_request.draft == true
    runs-on: ubuntu-20.04
    steps:
      - name: Fails in order to indicate that pull request needs to be marked as ready to review and unit tests workflow needs to pass.
        run: exit 1

  test:
    runs-on: ubuntu-20.04
    steps:
      - uses: actions/setup-go@v5
        with:
          go-version: "1.22"

      - name: setup env
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
        shell: bash

      - uses: actions/checkout@v4

      - run: make test

  test-integration:
    runs-on: ubuntu-20.04
    steps:
      - uses: actions/setup-go@v5
        with:
          go-version: "1.22"

      - name: setup env
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
        shell: bash

      - uses: actions/checkout@v4
      - uses: replicatedhq/action-k3s@main
        id: k3s
        with:
          version: v1.24.1-k3s1

      - run: make test-integration

  ensure-schemas-are-generated:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-go@v5
        with:
          go-version: "1.22"
      - name: setup env
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
        shell: bash
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - run: make check-schemas

  compile-preflight:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-go@v5
        with:
          go-version: "1.22"
      - name: setup env
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
        shell: bash
      - uses: actions/checkout@v4
      - run: make generate preflight
      - uses: actions/upload-artifact@v4
        with:
          name: preflight
          path: bin/preflight

  validate-preflight:
    runs-on: ubuntu-latest
    needs: compile-preflight
    steps:
      - uses: replicatedhq/action-k3s@main
        id: k3s
        with:
          version: v1.23.6-k3s1
      - name: Download preflight binary
        uses: actions/download-artifact@v4
        with:
          name: preflight
          path: bin/
      - run: chmod +x bin/preflight
      - run: |
          set +e
          ./bin/preflight --interactive=false --format=json https://preflight.replicated.com > result.json
          EXIT_CODE=$?
          cat result.json

          EXIT_STATUS=0
          if [ $EXIT_CODE -ne 3 ]; then
            echo "Expected exit code of 3 (some checks failed), got $EXIT_CODE"
            EXIT_STATUS=1
          fi

          if grep -q "was not collected" result.json; then
            echo "Some files were not collected"
            EXIT_STATUS=1
          fi

          if (( `jq '.pass | length' result.json` < 1 )); then
            echo "No passing preflights found"
            EXIT_STATUS=1
          fi

          if (( `jq '.warn | length' result.json` < 1 )); then
            echo "No warnings found"
            EXIT_STATUS=1
          fi

          if (( `jq '.fail | length' result.json` < 1 )); then
            echo "No failed preflights found"
            EXIT_STATUS=1
          fi

          exit $EXIT_STATUS

  validate-preflight-e2e:
    runs-on: ubuntu-latest
    needs: compile-preflight
    steps:
      - uses: actions/checkout@v4
      - uses: replicatedhq/action-k3s@main
        id: k3s
        with:
          version: v1.23.6-k3s1
      - name: Download preflight binary
        uses: actions/download-artifact@v4
        with:
          name: preflight
          path: bin/
      - run: chmod +x bin/preflight
      - run: make preflight-e2e-test

  run-examples:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: make run-examples

  compile-supportbundle:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-go@v5
        with:
          go-version: "1.22"
      - name: setup env
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
        shell: bash
      - uses: actions/checkout@v4
      - run: make generate support-bundle
      - uses: actions/upload-artifact@v4
        with:
          name: support-bundle
          path: bin/support-bundle

  validate-supportbundle:
    runs-on: ubuntu-latest
    needs: compile-supportbundle
    steps:
      - uses: actions/checkout@v4
      - uses: replicatedhq/action-k3s@main
        id: k3s
        with:
          version: v1.23.6-k3s1
      - name: Download support-bundle binary
        uses: actions/download-artifact@v4
        with:
          name: support-bundle
          path: bin/
      - run: chmod +x bin/support-bundle
      - run: ./bin/support-bundle ./examples/support-bundle/sample-collectors.yaml
      - run: ./bin/support-bundle ./examples/support-bundle/sample-supportbundle.yaml
      - run: ./bin/support-bundle https://kots.io

  validate-supportbundle-e2e:
    runs-on: ubuntu-latest
    needs: compile-supportbundle
    steps:
      - uses: actions/checkout@v4
      - uses: replicatedhq/action-k3s@main
        id: k3s
        with:
          version: v1.23.6-k3s1
      - name: Download support bundle binary
        uses: actions/download-artifact@v4
        with:
          name: support-bundle
          path: bin/
      - run: chmod +x bin/support-bundle
      - run: make support-bundle-e2e-test

  validate-supportbundle-e2e-go-test:
    runs-on: ubuntu-latest
    needs: compile-supportbundle
    steps:
      - uses: actions/setup-go@v5
        with:
          go-version: "1.22"
      - name: setup env
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
        shell: bash
      - uses: actions/checkout@v4
      - name: Download support bundle binary
        uses: actions/download-artifact@v4
        with:
          name: support-bundle
          path: bin/
      - run: chmod +x bin/support-bundle
      - run: make support-bundle-e2e-go-test

  compile-collect:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-go@v5
        with:
          go-version: "1.22"
      - name: setup env
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
        shell: bash
      - uses: actions/checkout@v4
      - run: make generate collect
      - uses: actions/upload-artifact@v4
        with:
          name: collect
          path: bin/collect

  goreleaser-test:
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/v') != true
    strategy:
      matrix:
        goarch: [amd64, arm64]
        goos: [darwin, linux, windows]
        include:
          - goarch: arm
            goos: linux
          - goarch: riscv64
            goos: linux
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-go@v5
        with:
          go-version: "1.22"

      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@v6
        with:
          version: "v0.183.0"
          args: build --rm-dist --snapshot --config deploy/.goreleaser.yaml --single-target
        env:
          GOARCH: ${{ matrix.goarch }}
          GOOS: ${{ matrix.goos }}

  goreleaser:
    runs-on: ubuntu-latest
    needs:
      - validate-preflight
      - validate-preflight-e2e
      - validate-supportbundle
    if: startsWith(github.ref, 'refs/tags/v')
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: azure/docker-login@v2
        with:
          username: ${{ secrets.DOCKERHUB_USER }}
          password: ${{ secrets.DOCKERHUB_PASSWORD }}

      - uses: actions/setup-go@v5
        with:
          go-version: "1.22"

      - uses: sigstore/cosign-installer@v3
        with:
          # DO NOT USE v2 until we decide on whether to use Rekor or not
          cosign-release: "v1.13.1"  # Binary version to install

      - name: Get Cosign Key
        run: |
          echo $COSIGN_KEY | base64 -d > ./cosign.key
        env:
          COSIGN_KEY: ${{secrets.COSIGN_KEY}}

      - name: Generate SBOM
        run: |
          make sbom
        env:
          COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
          COSIGN_KEY: ${{ secrets.COSIGN_KEY }}

      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@v6
        with:
          version: "v1.x"  # Binary version to install
          args: release --rm-dist --config deploy/.goreleaser.yaml
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Update new preflight version in krew-index
        uses: rajatjindal/krew-release-bot@v0.0.46
        with:
          krew_template_file: deploy/krew/preflight.yaml
      - name: Update new support-bundle version in krew-index
        uses: rajatjindal/krew-release-bot@v0.0.46
        with:
          krew_template_file: deploy/krew/support-bundle.yaml


# summary jobs, these jobs will only run if all the other jobs have succeeded
  validate-pr-tests:
    runs-on: ubuntu-latest
    needs:
      - test
      - test-integration
      - run-examples
      - compile-collect
      - validate-preflight
      - validate-preflight-e2e
      - validate-supportbundle
      - validate-supportbundle-e2e
      - validate-supportbundle-e2e-go-test
      - ensure-schemas-are-generated
    steps:
      - run: echo "All PR tests passed"


  # this job will validate that the validation did not fail and that all pr-tests succeed
  # it is used for the github branch protection rule
  validate-success:
    runs-on: ubuntu-latest
    needs:
      - validate-pr-tests
    if: always()
    steps:
      # https://docs.github.com/en/actions/learn-github-actions/contexts#needs-context
      # if the validate-pr-tests job was not successful, this job will fail
      - name: fail if validate-pr-tests job was not successful
        if: needs.validate-pr-tests.result != 'success'
        run: exit 1
      # if the validate-pr-tests job was successful, this job will succeed
      - name: succeed if validate-pr-tests job succeeded
        if: needs.validate-pr-tests.result == 'success'
        run: echo "Validation succeeded"