name: Execute Notebooks

on:
  pull_request:
    branches: [ main ]
    types: [opened, synchronize, reopened, labeled]
    paths:
      - "python/sglang/**"
      - "docs/**"
      - "!python/sglang/**/*.md"
      - "!docs/**/*.md"
  workflow_dispatch:


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

env:
  SGLANG_IS_IN_CI: true

jobs:
  call-gate:
    # Align with PR Test: fail fast if PR doesn't have run-ci label.
    # This makes /tag-and-rerun-ci work by rerunning this failed workflow.
    uses: ./.github/workflows/pr-gate.yml
    secrets: inherit

  run-all-notebooks:
    needs: [call-gate]
    runs-on: 1-gpu-h100
    if: github.event_name != 'pull_request' || needs.call-gate.result == 'success'
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Install dependencies
        run: |
          bash scripts/ci/cuda/ci_install_dependency.sh
          pip install -r docs/requirements.txt
          apt-get update && apt-get install -y pandoc parallel retry
          ln -sf "$(which python3)" /usr/bin/python

      - name: Setup Jupyter Kernel
        run: |
          python -m ipykernel install --user --name python3 --display-name "Python 3"

      - name: Execute notebooks
        timeout-minutes: 40
        run: |
          cd docs
          make clean
          make compile


  notebook-finish:
    needs: [
      call-gate,
      run-all-notebooks
    ]
    runs-on: ubuntu-latest
    if: always() && needs.run-all-notebooks.result != 'skipped'
    steps:
      - name: Check all dependent job statuses
        run: |
          results=(${{ join(needs.*.result, ' ') }})
          for result in "${results[@]}"; do
            if [ "$result" = "failure" ] || [ "$result" = "cancelled" ]; then
              echo "Job failed with result: $result"
              exit 1
            fi
          done
          echo "All jobs completed successfully"
          exit 0
