name: CI

on:
  push:
    branches:
      - main
    tags:
      - "v*"
  pull_request: {}
  workflow_dispatch:

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

jobs:
  check-manifest:
    name: Check Manifest
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Check
        run: pipx run check-manifest

  test:
    name: ${{ matrix.platform }} (${{ matrix.python-version }}) ${{ matrix.resolution }}
    runs-on: ${{ matrix.platform }}
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
        platform: [ubuntu-latest, macos-latest, windows-latest]
        resolution: [highest]
        include:
          - python-version: "3.10"
            platform: "ubuntu-latest"
            resolution: "lowest-direct"

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

      - name: Install the latest version of uv
        uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b
        with:
          python-version: ${{ matrix.python-version }}
          activate-environment: true

      - name: Install dependencies
        run: |
          uv pip install -e .[testing,docs]
        env:
          UV_RESOLUTION: ${{ matrix.resolution }}

      - name: Test
        run: |
          coverage run --source=npe2 -m pytest --color yes

      - name: Test build docs
        run: pytest --color yes -m "github_main_only"

      - name: Upload coverage as artifact
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
        with:
          name: coverage reports ${{ matrix.platform }} py ${{ matrix.python-version }} ${{ matrix.resolution }}
          path: |
            ./.coverage.*
          include-hidden-files: true

  test_napari:
    name: napari tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          repository: napari/napari
          path: napari-from-github
          fetch-depth: 0

      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version: "3.10"
      - name: Install
        run: |
          python -m pip install --upgrade pip
          python -m pip install -e ./napari-from-github -c "./napari-from-github/resources/constraints/constraints_py3.10.txt"
          python -m pip install -e .[json]
          # bare minimum required to test napari/plugins
          python -m pip install pytest pytest-pretty scikit-image[data] zarr xarray hypothesis matplotlib

      - name: Run napari plugin headless tests
        run: pytest -W 'ignore::DeprecationWarning' src/napari/plugins src/napari/settings src/napari/layers src/napari/components
        working-directory: napari-from-github

  test_docs_render:
    name: docs render
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version: "3.14"
      - name: Build schema
        run: |
          python -m pip install --upgrade pip
          pip install -e .[docs] check-jsonschema
          python -m npe2.manifest.schema > _schema.json
          check-jsonschema --check-metaschema _schema.json
      - name: Test rendering docs
        run: python _docs/render.py
        env:
          NPE2_SCHEMA: "_schema.json"
      - name: Build jupyter book
        # generate toc, then build
        run: |
          cd docs
          jupyter-book toc from-project . -f jb-book > _toc.yml
          jupyter-book build .
      # Upload the book's HTML as an artifact
      - name: Upload artifact
        uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
        with:
          path: "docs/_build/html"

  upload_coverage:
    needs: test
    name: Upload coverage
    if: always()
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version: "3.14"
          cache-dependency-path: setup.cfg
          cache: 'pip'

      - name: Install Dependencies
        run: |
          pip install --upgrade pip
          pip install codecov

      - name: Download coverage data
        uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
        with:
          pattern: coverage reports*
          path: coverage
          merge-multiple: true

      - name: combine coverage data
        run: |
          python -Im coverage combine coverage
          python -Im coverage xml -o coverage.xml

          # Report and write to summary.
          python -Im coverage report --format=markdown --skip-empty --skip-covered >> $GITHUB_STEP_SUMMARY

      - name: Upload coverage data
        uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
        with:
          fail_ci_if_error: true
          token: ${{ secrets.CODECOV_TOKEN }}

  deploy:
    name: Deploy
    needs: test
    if: "success() && startsWith(github.ref, 'refs/tags/')"
    runs-on: ubuntu-latest
    permissions:
      contents: write
      id-token: write
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

      - name: Set up Python
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version: "3.x"

      - name: install
        run: |
          git tag
          pip install -U pip
          pip install -U twine build
          python -m build .
          twine check dist/*
          ls -lh dist

      - name: write schema
        run: |
          pip install -e . check-jsonschema
          python -m npe2.manifest.schema > schema.json
          check-jsonschema --check-metaschema schema.json

      - name: Build and publish
        run: twine upload dist/*
        env:
          TWINE_USERNAME: __token__
          TWINE_PASSWORD: ${{ secrets.TWINE_API_KEY }}

      - uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
        if: startsWith(github.ref, 'refs/tags/')
        with:
          generate_release_notes: true
          files: schema.json
