name: build-test

on:
  pull_request:
    types: [opened, reopened, synchronize, ready_for_review]
    branches: [main]
  push:
    branches: [main]

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

jobs:
  # Detect changes to optimize test execution
  changes:
    runs-on: ubuntu-latest
    outputs:
      go-files: ${{ steps.filter.outputs.go-files }}
      preflight: ${{ steps.filter.outputs.preflight }}
      support-bundle: ${{ steps.filter.outputs.support-bundle }}
      examples: ${{ steps.filter.outputs.examples }}
    steps:
      - uses: actions/checkout@v6
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            go-files:
              - '**/*.go'
              - 'go.{mod,sum}'
              - 'Makefile'
            preflight:
              - 'cmd/preflight/**'
              - 'pkg/preflight/**'
            support-bundle:
              - 'cmd/troubleshoot/**'
              - 'pkg/supportbundle/**'

  # Lint
  lint:
    if: needs.changes.outputs.go-files == 'true'
    needs: changes
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-go@v6
        with:
          go-version-file: 'go.mod'

      - name: Check go mod tidy
        run: |
          go mod tidy
          git diff --exit-code go.mod go.sum || {
            echo "::error::Please run 'go mod tidy' and commit changes"
            exit 1
          }

      - name: Format and vet
        run: |
          make fmt
          git diff --exit-code || {
            echo "::error::Please run 'make fmt' and commit changes"
            exit 1
          }
          make vet

  # Unit and integration tests
  test:
    if: needs.changes.outputs.go-files == 'true'
    needs: [changes, lint]
    runs-on: ubuntu-latest
    timeout-minutes: 20
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-go@v6
        with:
          go-version-file: 'go.mod'

      - name: Setup K3s
        uses: replicatedhq/action-k3s@main
        with:
          version: v1.31.2-k3s1

      - name: Run tests
        run: make test-integration

  # Build binaries
  build:
    if: needs.changes.outputs.go-files == 'true'
    needs: [changes, lint]
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-go@v6
        with:
          go-version-file: 'go.mod'
      - run: make build
      - uses: actions/upload-artifact@v5
        with:
          name: binaries
          path: bin/
          retention-days: 1

  # E2E tests
  e2e:
    if: needs.changes.outputs.go-files == 'true' || github.event_name == 'push'
    needs: [changes, build]
    runs-on: ubuntu-latest
    timeout-minutes: 15
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: preflight
            target: preflight-e2e-test
            needs-k3s: true
          - name: support-bundle-shell
            target: support-bundle-e2e-test
            needs-k3s: true
          - name: support-bundle-go
            target: support-bundle-e2e-go-test
            needs-k3s: false
    steps:
      - uses: actions/checkout@v6

      - name: Setup K3s
        if: matrix.needs-k3s
        uses: replicatedhq/action-k3s@main
        with:
          version: v1.31.2-k3s1

      - uses: actions/download-artifact@v6
        with:
          name: binaries
          path: bin/

      - run: chmod +x bin/*
      - run: make ${{ matrix.target }}

  # Success summary
  success:
    if: always()
    needs: [lint, test, build, e2e]
    runs-on: ubuntu-latest
    steps:
      - name: Check results
        run: |
          # Check if any required jobs failed
          if [[ "${{ needs.lint.result }}" == "failure" ]] || \
             [[ "${{ needs.test.result }}" == "failure" ]] || \
             [[ "${{ needs.build.result }}" == "failure" ]] || \
             [[ "${{ needs.e2e.result }}" == "failure" ]]; then
            echo "::error::Some jobs failed or were cancelled"
            exit 1
          fi
          
          # Check if any required jobs were cancelled  
          if [[ "${{ needs.lint.result }}" == "cancelled" ]] || \
             [[ "${{ needs.test.result }}" == "cancelled" ]] || \
             [[ "${{ needs.build.result }}" == "cancelled" ]] || \
             [[ "${{ needs.e2e.result }}" == "cancelled" ]]; then
            echo "::error::Some jobs failed or were cancelled"
            exit 1
          fi
          
          echo "✅ All tests passed!"
