name: Shared Checks

on:
  workflow_call:

permissions:
  contents: read

env:
  COLUMNS: 150

jobs:
  pre-commit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
        with:
          persist-credentials: false

      # setup-uv's manifest fetch is a single request with a hard 5s timeout
      # (astral-sh/setup-uv#869); retry once. Drop when upstream adds a retry.
      - name: Install uv
        id: setup-uv
        continue-on-error: true
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
        with:
          enable-cache: true
          version: 0.9.5

      - name: Install uv (retry)
        if: steps.setup-uv.outcome == 'failure'
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
        with:
          enable-cache: true
          version: 0.9.5

      - name: Install dependencies
        run: uv sync --frozen --all-extras --python 3.10

      - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
        with:
          extra_args: --all-files --verbose

      - name: Surface types match vendored schema
        run: |
          uv sync --group codegen --frozen
          uv run --frozen --group codegen python scripts/gen_surface_types.py --check

      # Resolves only mcp-types' declared dependencies into an empty environment,
      # so an import of the SDK or anything from its stack fails here.
      - name: mcp-types installs and imports standalone
        run: |
          uv run --isolated --no-project --with ./src/mcp-types python -c \
            "import mcp_types, mcp_types.jsonrpc, mcp_types.methods, mcp_types.version, mcp_types.v2025_11_25, mcp_types.v2026_07_28"

  test:
    name: test (${{ matrix.python-version }}, ${{ matrix.dep-resolution.name }}, ${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    timeout-minutes: 10
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
        dep-resolution:
          - name: lowest-direct
            install-flags: "--upgrade --resolution lowest-direct"
          - name: locked
            install-flags: "--frozen"
        os: [ubuntu-latest, windows-latest]

    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
        with:
          persist-credentials: false

      # setup-uv's manifest fetch is a single request with a hard 5s timeout
      # (astral-sh/setup-uv#869); retry once. Drop when upstream adds a retry.
      - name: Install uv
        id: setup-uv
        continue-on-error: true
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
        with:
          enable-cache: true
          version: 0.9.5

      - name: Install uv (retry)
        if: steps.setup-uv.outcome == 'failure'
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
        with:
          enable-cache: true
          version: 0.9.5

      - name: Install the project
        run: uv sync ${{ matrix.dep-resolution.install-flags }} --all-extras --python ${{ matrix.python-version }}

      - name: Run pytest with coverage
        shell: bash
        env:
          # tests/examples/test_stories_smoke.py is gated on this var; it spawns real
          # stdio + uvicorn subprocesses, so run it on exactly one matrix cell.
          MCP_EXAMPLES_SMOKE: ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12' && matrix.dep-resolution.name == 'locked' && '1' || '' }}
        run: |
          uv run --frozen --no-sync coverage erase
          uv run --frozen --no-sync coverage run -m pytest -n auto
          uv run --frozen --no-sync coverage combine
          uv run --frozen --no-sync coverage report

      - name: Check for unnecessary no cover pragmas
        if: runner.os != 'Windows'
        run: uv run --frozen --no-sync strict-no-cover

  readme-snippets:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
        with:
          persist-credentials: false

      # setup-uv's manifest fetch is a single request with a hard 5s timeout
      # (astral-sh/setup-uv#869); retry once. Drop when upstream adds a retry.
      - name: Install uv
        id: setup-uv
        continue-on-error: true
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
        with:
          enable-cache: true
          version: 0.9.5

      - name: Install uv (retry)
        if: steps.setup-uv.outcome == 'failure'
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
        with:
          enable-cache: true
          version: 0.9.5

      - name: Install dependencies
        run: uv sync --frozen --all-extras --python 3.10

      - name: Check README snippets are up to date
        run: uv run --frozen scripts/update_readme_snippets.py --check

  # `scripts/docs/build.sh` is the whole gauntlet: build_config.py fails on
  # nav entries without a page and pages without a nav entry, `zensical build
  # --strict` fails on broken .md links, `pymdownx.snippets: check_paths:
  # true` fails on a deleted `docs_src/` include, and the post-build steps
  # fail on unresolved cross-references, inventory download failures, and
  # broken non-markdown link targets.
  # Until this job existed the docs were only ever built post-merge by
  # `deploy-docs.yml`, so those failures went green on the PR and broke the next
  # deploy of main. This is the check path; `deploy-docs.yml` stays the deploy
  # path.
  docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
        with:
          persist-credentials: false

      # setup-uv's manifest fetch is a single request with a hard 5s timeout
      # (astral-sh/setup-uv#869); retry once. Drop when upstream adds a retry.
      - name: Install uv
        id: setup-uv
        continue-on-error: true
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
        with:
          enable-cache: true
          version: 0.9.5

      - name: Install uv (retry)
        if: steps.setup-uv.outcome == 'failure'
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
        with:
          enable-cache: true
          version: 0.9.5

      - name: Build the docs in strict mode
        run: bash scripts/docs/build.sh
