name: build-and-test
on:
  push:
    branches: [main]
    tags:
      - "v[0-9]+.[0-9]+.[0-9]+*"
  pull_request:

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

jobs:
  setup-environment:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
      - name: Setup Go
        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
        with:
          go-version: ~1.21.9
          cache: false
      - name: Cache Go
        id: go-cache
        uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
        with:
          path: |
            ~/go/bin
            ~/go/pkg/mod
          key: go-cache-${{ runner.os }}-${{ hashFiles('**/go.sum') }}
      - name: Install dependencies
        if: steps.go-cache.outputs.cache-hit != 'true'
        run: make gomoddownload

  lint:
    runs-on: ubuntu-latest
    needs: [setup-environment]
    steps:
      - name: Checkout Repo
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
      - name: Setup Go
        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
        with:
          go-version: ~1.21.9
          cache: false
      - name: Cache Go
        id: go-cache
        uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
        with:
          path: |
            ~/go/bin
            ~/go/pkg/mod
          key: go-cache-${{ runner.os }}-${{ hashFiles('**/go.sum') }}
      - name: golint
        run: make -j2 golint
      - name: goimpi
        run: make goimpi

  govulncheck:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - name: Checkout Repo
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
      - name: Setup Go
        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
        with:
          go-version: ~1.21.9
          cache: false
      - name: Cache Go
        id: go-cache
        uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
        with:
          path: |
            ~/go/bin
            ~/go/pkg/mod
          key: go-cache-${{ runner.os }}-${{ hashFiles('**/go.sum') }}
      - name: Install Tools
        if: steps.go-cache.outputs.cache-hit != 'true'
        run: make install-tools
      - name: Run `govulncheck`
        run: make govulncheck

  checks:
    runs-on: ubuntu-latest
    needs: [setup-environment]
    steps:
      - name: Checkout Repo
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
      - name: Setup Go
        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
        with:
          go-version: ~1.21.9
          cache: false
      - name: Cache Go
        id: go-cache
        uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
        with:
          path: |
            ~/go/bin
            ~/go/pkg/mod
          key: go-cache-${{ runner.os }}-${{ hashFiles('**/go.sum') }}
      - name: checklicense
        run: make checklicense
      - name: misspell
        run: make misspell
      - name: checkdoc
        run: make checkdoc
      - name: Check for go mod dependency changes
        run: |
          make gotidy
          git diff --exit-code || (echo 'go.mod/go.sum deps changes detected, please run "make gotidy" and commit the changes in this PR.' && exit 1)
      - name: go:porto
        run: |
          make goporto
          git diff --exit-code || (echo 'Porto links are out of date, please run "make goporto" and commit the changes in this PR.' && exit 1)
      - name: go:generate
        run: |
          make gogenerate
          git diff --exit-code || (echo 'Generated code is out of date, please run "make gogenerate" and commit the changes in this PR.' && exit 1)
      - name: Gen Pdata
        run: |
          make genpdata
          git diff --exit-code || (echo 'Generated code is out of date, please run "make genpdata" and commit the changes in this PR.' && exit 1)
      - name: Gen otelcorecol
        run: |
          make genotelcorecol
          git diff -s --exit-code || (echo 'Generated code is out of date, please run "make genotelcorecol" and commit the changes in this PR.' && exit 1)
      - name: Multimod verify
        run: make multimod-verify
      - name: crosslink
        run: |
          make crosslink
          git diff -s --exit-code || (echo 'Replace statements are out of date, please run "make crosslink" and commit the changes in this PR.' && exit 1)

  unittest-matrix:
    strategy:
      matrix:
        runner: [ubuntu-latest, actuated-arm64-4cpu-4gb]
        go-version: ["~1.22", "~1.21.9"] # 1.20 needs quotes otherwise it's interpreted as 1.2
    runs-on: ${{ matrix.runner }}
    needs: [setup-environment]
    steps:
      - name: Set up arkade
        uses: alexellis/setup-arkade@v3
      - name: Install vmmeter
        run: |
          sudo -E arkade oci install ghcr.io/openfaasltd/vmmeter:latest --path /usr/local/bin/
      - name: Run vmmeter
        uses: self-actuated/vmmeter-action@v1
      - name: Checkout Repo
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
      - name: Setup Go
        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
        with:
          go-version: ${{ matrix.go-version }}
          cache: false
      - name: Cache Go
        id: go-cache
        uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
        with:
          path: |
            ~/go/bin
            ~/go/pkg/mod
          key: go-cache-${{ runner.os }}-${{ matrix.runner }}-${{ hashFiles('**/go.sum') }}
      - name: Cache Build
        uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
        with:
          path: ~/.cache/go-build
          key: unittest-${{ runner.os }}-${{ matrix.runner }}-go-build-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }}
      - name: Run Unit Tests
        run: |
          make -j4 gotest
  unittest:
    if: always()
    runs-on: ubuntu-latest
    needs: [setup-environment, unittest-matrix]
    steps:
      - name: Print result
        run: echo ${{ needs.unittest-matrix.result }}
      - name: Interpret result
        run: |
          if [[ success == ${{ needs.unittest-matrix.result }} ]]
          then
            echo "All matrix jobs passed!"
          else
            echo "One or more matrix jobs failed."
            false
          fi

  test-coverage:
    runs-on: ubuntu-latest
    needs: [setup-environment]
    steps:
      - name: Checkout Repo
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
      - name: Setup Go
        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
        with:
          go-version: ~1.21.9
          cache: false
      - name: Cache Go
        id: go-cache
        uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
        with:
          path: |
            ~/go/bin
            ~/go/pkg/mod
          key: go-cache-${{ runner.os }}-${{ hashFiles('**/go.sum') }}
      - name: Cache Build
        uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
        with:
          path: ~/.cache/go-build
          key: coverage-${{ runner.os }}-go-build-${{ hashFiles('**/go.sum') }}
      - name: Run Unit Tests With Coverage
        run: make gotest-with-cover
      - name: Upload coverage report
        uses: Wandalen/wretry.action@7afe8a7967f5a1d3f9bc048911bbe75943ad27b5 # v3.2.0
        with:
          action: codecov/codecov-action@v4
          with: |
            file: ./coverage.txt
            fail_ci_if_error: true
            verbose: true
            token: ${{ secrets.CODECOV_TOKEN }}
          attempt_limit: 10
          attempt_delay: 15000

  cross-build-collector:
    needs: [setup-environment]
    runs-on: ubuntu-latest
    timeout-minutes: 10
    strategy:
      fail-fast: false
      matrix:
        include:
          # Go 1.15 dropped support for 32-bit binaries
          # on macOS: https://go.dev/doc/go1.15
          #- goos: darwin
          #  goarch: 386
          - goos: darwin
            goarch: amd64
          - goos: darwin
            goarch: arm64
          - goos: linux
            goarch: 386
          - goos: linux
            goarch: amd64
          - goos: linux
            goarch: arm64
          - goos: linux
            goarch: ppc64le
          - goos: linux
            goarch: arm
            goarm: 7
          - goos: linux
            goarch: s390x
          - goos: windows
            goarch: 386
          - goos: windows
            goarch: amd64

    steps:
      - name: Checkout Repo
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
      - name: Setup Go
        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
        with:
          go-version: ~1.21.9
          cache: false
      - name: Cache Go
        id: go-cache
        uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
        with:
          path: |
            ~/go/bin
            ~/go/pkg/mod
          key: go-cache-${{ runner.os }}-${{ hashFiles('**/go.sum') }}
      - name: Build
        env:
          GOOS: ${{matrix.goos}}
          GOARCH: ${{matrix.goarch}}
          GOARM: ${{matrix.goarm}}
        run: |
          make otelcorecol
