name: CI

on:
  push:
    branches:
      - main
    tags:
      - 'core-v*'
      - 'backend-v*'
      - 'sdk-v*'
  pull_request:
    branches:
      - main
    types:
      - opened
      - synchronize
      - ready_for_review

permissions:
  id-token: write  # Required for PyPI trusted publishing
  contents: read

jobs:
  lint:
    if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
    runs-on: ubuntu-latest

    strategy:
      fail-fast: false

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

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

      - name: Install dependencies
        run: uv sync --all-groups

      - name: Check style against standards
        run: uv run make lint

  coverage:
    if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
    runs-on: ubuntu-latest

    strategy:
      fail-fast: false

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

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

      - name: Install dependencies
        run: uv sync --all-groups

      - name: Run unit tests with coverage
        run: |
          uv run coverage run -m pytest
          uv run coverage html --show-contexts --title "Coverage for ${{ github.sha }}"
          uv run coverage xml
          uv run diff-cover coverage.xml --html-report index.html

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

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

      - name: Check coverage
        run: |
          uv run coverage report --fail-under 95
          uv run diff-cover coverage.xml --fail-under 100

  postgres-persistence:
    if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
    runs-on: ubuntu-latest

    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: postgres
        ports:
          - 5432:5432
        options: >-
          --health-cmd "pg_isready -U postgres"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

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

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

      - name: Install dependencies
        run: uv sync --all-groups

      - name: Run Postgres persistence checks
        env:
          ORCHEO_POSTGRES_DSN: postgresql://postgres:postgres@localhost:5432/postgres
          ORCHEO_CHECKPOINT_BACKEND: postgres
        run: |
          uv run pytest tests/integration/test_postgres_persistence.py -q

  build-and-release:
    needs: [lint, coverage, postgres-persistence]
    if: "startsWith(github.ref, 'refs/tags/')"
    runs-on: ubuntu-latest

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

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

      - name: Determine package context
        id: package
        run: |
          tag="${GITHUB_REF_NAME}"
          if [[ "$tag" == core-v* ]]; then
            echo "package=orcheo" >> "$GITHUB_OUTPUT"
          elif [[ "$tag" == backend-v* ]]; then
            echo "package=orcheo-backend" >> "$GITHUB_OUTPUT"
          elif [[ "$tag" == sdk-v* ]]; then
            echo "package=orcheo-sdk" >> "$GITHUB_OUTPUT"
          else
            echo "Unsupported tag prefix: $tag" >&2
            exit 1
          fi
          echo "dist_dir=dist/${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"

      - name: Install dependencies
        run: uv sync --all-groups

      - name: Build ${{ steps.package.outputs.package }}
        run: |
          uv build --package "${{ steps.package.outputs.package }}" --out-dir "${{ steps.package.outputs.dist_dir }}"

      - name: Publish ${{ steps.package.outputs.package }} to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          packages-dir: ${{ steps.package.outputs.dist_dir }}

  canvas:
    if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: apps/canvas
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
      - name: Install dependencies
        run: |
          rm -rf node_modules package-lock.json
          npm install
      - name: Lint
        run: npm run lint
      - name: Test
        run: npm run test -- --run
