name: CI

on:
  push:
    branches:
      - main
      - develop
      - "copilot/**"
      - "feature/**"
      - "fix/**"
  pull_request:
    branches:
      - main
      - develop

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

env:
  PYTHON_VERSION: "3.13"
  POETRY_VERSION: "2.3.4"
  PIP_AUDIT_POLICY: "fail-on-any"

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 20
    permissions:
      contents: read

    steps:
    - name: Checkout repository
      uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4

    - name: Set up Python ${{ env.PYTHON_VERSION }}
      uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v5
      with:
        python-version: ${{ env.PYTHON_VERSION }}

    - name: Install Poetry
      uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1
      with:
        version: ${{ env.POETRY_VERSION }}
        virtualenvs-create: true
        virtualenvs-in-project: true

    - name: Cache Poetry dependencies
      uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v4
      with:
        path: .venv
        key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
        restore-keys: |
          ${{ runner.os }}-poetry-

    - name: Sync dependencies
      run: poetry sync --no-interaction --all-extras

    - name: Adjust pip-audit policy for Dependabot PRs
      if: github.event_name == 'pull_request'
      run: |
        if [ "${{ github.event.pull_request.user.login }}" = "dependabot[bot]" ]; then
          echo "PIP_AUDIT_POLICY=report-only" >> "$GITHUB_ENV"
          echo "Using report-only pip-audit policy for Dependabot PR."
        fi

    - name: Dependency audit with pip-audit
      run: |
        echo "pip-audit policy: $PIP_AUDIT_POLICY"
        case "$PIP_AUDIT_POLICY" in
          fail-on-any)
            poetry run pip-audit --strict
            ;;
          report-only)
            poetry run pip-audit
            ;;
          *)
            echo "Unsupported PIP_AUDIT_POLICY: $PIP_AUDIT_POLICY"
            exit 2
            ;;
        esac

    - name: Lint with ruff
      run: poetry run ruff check .

    - name: Type-check with mypy
      run: poetry run mypy souschef

    - name: Run tests with coverage
      run: poetry run pytest --cov=souschef --cov-report=xml --cov-report=term-missing

    - name: Upload Python coverage
      uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v4
      with:
        name: python-coverage
        path: coverage.xml
        retention-days: 1

  test-terraform-provider:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    needs: test
    permissions:
      contents: read

    steps:
    - name: Checkout repository
      uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4

    - name: Set up Go
      uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v5
      with:
        go-version-file: 'go.work'
        cache-dependency-path: terraform-provider/go.sum

    - name: Set up Python ${{ env.PYTHON_VERSION }}
      uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v5
      with:
        python-version: ${{ env.PYTHON_VERSION }}

    - name: Install Poetry
      uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1
      with:
        version: ${{ env.POETRY_VERSION }}
        virtualenvs-create: true
        virtualenvs-in-project: true

    - name: Sync Python dependencies
      run: poetry sync --no-interaction --all-extras

    - name: Set souschef path for Terraform tests
      run: |
        SOUSCHEF_PATH=$(realpath $(poetry run which souschef))
        echo "TF_VAR_souschef_path=$SOUSCHEF_PATH" >> $GITHUB_ENV
        echo "Souschef CLI path: $SOUSCHEF_PATH"

    # Run unit tests first (no TF_ACC) so failures surface quickly.
    # Run ./... to include the main package (main.go) in coverage, not just
    # internal/provider.
    # Acceptance tests (TF_ACC=1) also execute resource.Test cases
    # that require a live Terraform binary and the souschef CLI.
    - name: Run Go unit tests with coverage
      working-directory: terraform-provider
      run: go test ./... -v -timeout 5m -coverprofile=coverage.out -covermode=atomic

    - name: Install Terraform CLI for acceptance tests
      uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # v4
      with:
        terraform_wrapper: false

    - name: Run Terraform provider acceptance tests
      env:
        TF_ACC: "1"
      working-directory: terraform-provider
      run: go test ./internal/provider -v -timeout 15m

    - name: Upload Go coverage
      uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v4
      if: always()
      with:
        name: go-coverage
        path: terraform-provider/coverage.out
        retention-days: 1

  test-cli:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    needs: test
    permissions:
      contents: read

    steps:
    - name: Checkout repository
      uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4

    - name: Set up Python ${{ env.PYTHON_VERSION }}
      uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v5
      with:
        python-version: ${{ env.PYTHON_VERSION }}

    - name: Install Poetry
      uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1
      with:
        version: ${{ env.POETRY_VERSION }}
        virtualenvs-create: true
        virtualenvs-in-project: true

    - name: Cache Poetry dependencies
      uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v4
      with:
        path: .venv
        key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
        restore-keys: |
          ${{ runner.os }}-poetry-

    - name: Sync dependencies
      run: poetry sync --no-interaction --all-extras

    - name: Test CLI functionality
      run: |
        poetry run souschef --help
        poetry run souschef ls tests/integration/fixtures/sample_cookbook
        poetry run souschef structure tests/integration/fixtures/sample_cookbook
        poetry run souschef metadata tests/integration/fixtures/sample_cookbook/metadata.rb
        if [ -f tests/integration/fixtures/sample_cookbook/recipes/default.rb ]; then
          poetry run souschef recipe tests/integration/fixtures/sample_cookbook/recipes/default.rb
        fi
        TEMPLATE_FILE=$(find tests/integration/fixtures/sample_cookbook/templates/default -name '*.erb' -type f | head -n 1)
        if [ -n "$TEMPLATE_FILE" ]; then
          poetry run souschef template "$TEMPLATE_FILE"
        fi
