# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: tests
on:
  push:
    branches:
      - "main"
  pull_request:
  pull_request_target:
    types: [labeled]

# Declare default permissions as read only.
permissions: read-all

jobs:
  integration:
    # run job on proper workflow event triggers (skip job for pull_request event from forks and only run pull_request_target for "tests: run" label)
    if: "${{ (github.event.action != 'labeled' && github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name) || github.event.label.name == 'tests: run' }}"
    name: unit tests
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [macos-latest, windows-latest, ubuntu-latest]
      fail-fast: false
    permissions:
      contents: "read"
      issues: "write"
      pull-requests: "write"
    steps:
      - name: Remove PR label
        if: "${{ github.event.action == 'labeled' && github.event.label.name == 'tests: run' }}"
        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            try {
              await github.rest.issues.removeLabel({
                name: 'tests: run',
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: context.payload.pull_request.number
              });
            } catch (e) {
              console.log('Failed to remove label. Another job may have already removed it!');
            }

      - name: Setup Go
        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
        with:
          go-version: "1.24"

      - name: Checkout code
        uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          repository: ${{ github.event.pull_request.head.repo.full_name }}
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: Install dependencies
        run: go get .

      - name: Build
        run: go build -v ./...

      - name: Run tests with coverage
        if: ${{ runner.os == 'Linux' }}
        env:
          GOTOOLCHAIN: go1.25.0+auto
        run: |
          source_dir="./internal/sources/*"
          tool_dir="./internal/tools/*"
          prompt_dir="./internal/prompts/*"
          auth_dir="./internal/auth/*"
          int_test_dir="./tests/*"
          included_packages=$(go list ./... | grep -v -e "$source_dir" -e "$tool_dir"  -e "$prompt_dir" -e "$auth_dir" -e "$int_test_dir")
          go test -race -cover -coverprofile=coverage.out -v $included_packages
          go test -race -v ./internal/sources/... ./internal/tools/... ./internal/prompts/... ./internal/auth/...

      - name: Run tests without coverage
        if: ${{ runner.os != 'Linux' }}
        run: |
          go test -race -v ./internal/... ./cmd/...

      - name: Check coverage
        if: ${{ runner.os == 'Linux' }}
        run: |
          FILE_TO_EXCLUDE="github.com/googleapis/genai-toolbox/internal/server/config.go"
          ESCAPED_PATH=$(echo "$FILE_TO_EXCLUDE" | sed 's/\//\\\//g; s/\./\\\./g')
          sed -i "/^${ESCAPED_PATH}:/d" coverage.out
          total_coverage=$(go tool cover -func=coverage.out | grep "total:" | awk '{print $3}')
          echo "Total coverage: $total_coverage"
          coverage_numeric=$(echo "$total_coverage" | sed 's/%//')
          if (( $(echo "$coverage_numeric < 40" | bc -l) )); then
              echo "Coverage failure: total coverage($total_coverage) is below 40%."
              exit 1
          fi
