name: CI

on:
  push:
    branches:
      - main
    tags:
      - '**'
  pull_request: {}

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - name: set up uv
      uses: astral-sh/setup-uv@v6
      with:
        python-version: '3.12'

    - name: Install dependencies
      # Installing pip is required for the pre-commit action:
      run: |
        uv sync --group linting --all-extras
        uv pip install pip

    - uses: pre-commit/action@v3.0.1
      with:
        extra_args: --all-files

  test:
    name: test py${{ matrix.python }} on ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python: ['3.10', '3.11', '3.12', '3.13', '3.14']

    env:
      PYTHON: ${{ matrix.python }}
      OS: ${{ matrix.os }}
      UV_PYTHON_PREFERENCE: only-managed

    runs-on: ${{ matrix.os }}

    steps:
    - uses: actions/checkout@v4

    - name: set up uv
      uses: astral-sh/setup-uv@v6
      with:
        python-version: ${{ matrix.python }}

    - name: Install dependencies
      run: |
        uv sync --group testing --all-extras

    - run: mkdir coverage

    - name: test
      run: make test
      env:
        COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python }}
        CONTEXT: ${{ runner.os }}-py${{ matrix.python }}

    - name: uninstall deps
      run: uv pip uninstall PyYAML

    - name: test without deps
      run: make test
      env:
        COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python }}-without-deps
        CONTEXT: ${{ runner.os }}-py${{ matrix.python }}-without-deps

    - name: store coverage files
      uses: actions/upload-artifact@v4
      with:
        name: coverage-${{ matrix.python }}-${{ runner.os }}
        path: coverage
        include-hidden-files: true

  coverage:
    runs-on: ubuntu-latest
    needs: [test]
    steps:
      - uses: actions/checkout@v4
        with:
          # needed for diff-cover
          fetch-depth: 0

      - name: get coverage files
        uses: actions/download-artifact@v4
        with:
          merge-multiple: true
          path: coverage

      - uses: astral-sh/setup-uv@v5
        with:
          enable-cache: true

      - run: uv sync --group testing --all-extras

      - run: uv run coverage combine coverage

      - run: uv run coverage html --show-contexts --title "Pydantic Settings coverage for ${{ github.sha }}"

      - name: Store coverage html
        uses: actions/upload-artifact@v4
        with:
          name: coverage-html
          path: htmlcov
          include-hidden-files: true

      - run: uv run coverage xml

      - run: uv run diff-cover coverage.xml --html-report index.html

      - name: Store diff coverage html
        uses: actions/upload-artifact@v4
        with:
          name: diff-coverage-html
          path: index.html

      - run: uv run coverage report --fail-under 98

  check:  # This job does nothing and is only used for the branch protection
    if: always()
    needs: [lint, test, coverage]
    runs-on: ubuntu-latest

    outputs:
      result: ${{ steps.all-green.outputs.result }}

    steps:
      - name: Decide whether the needed jobs succeeded or failed
        uses: re-actors/alls-green@release/v1
        id: all-green
        with:
          jobs: ${{ toJSON(needs) }}

  release:
    needs: [check]
    if: needs.check.outputs.result == 'success' && startsWith(github.ref, 'refs/tags/')
    runs-on: ubuntu-latest
    environment: release

    permissions:
      id-token: write

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install 'build' library
        run: pip install -U build

      - name: Check version
        id: check-tag
        uses: samuelcolvin/check-python-version@v4.1
        with:
          version_file_path: pydantic_settings/version.py

      - name: Build library
        run: python -m build

      - name: Upload package to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
