# ============================================================================
# ADK-FLUENT: Sync with upstream ADK
# ============================================================================
#
# Runs weekly and on-demand to detect upstream ADK changes.
# Pipeline: install latest ADK -> scan -> diff -> generate -> test -> auto-PR
#

name: Sync with ADK Upstream

on:
  schedule:
    - cron: "0 8 * * MON"       # Every Monday morning UTC
  workflow_dispatch:
    inputs:
      adk_version:
        description: "Specific ADK version (leave empty for latest)"
        required: false
        default: ""

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

permissions:
  contents: write
  pull-requests: write

env:
  UV_VERSION: "0.8.17"

jobs:
  # =========================================================================
  # Scan ADK and generate code
  # =========================================================================
  scan-and-generate:
    runs-on: ubuntu-latest
    outputs:
      adk_version: ${{ steps.scan.outputs.adk_version }}
      has_changes: ${{ steps.check_changes.outputs.has_changes }}
      is_breaking: ${{ steps.check_changes.outputs.is_breaking }}

    steps:
      - uses: actions/checkout@v4

      - uses: ./.github/actions/setup-env
        with:
          uv-version: ${{ env.UV_VERSION }}

      - name: Install target ADK version
        run: |
          if [ -n "${{ github.event.inputs.adk_version }}" ]; then
            uv pip install "google-adk==${{ github.event.inputs.adk_version }}"
          else
            uv pip install google-adk --upgrade
          fi

      - name: Scan ADK upstream
        id: scan
        run: |
          uv run python scripts/scanner.py -o manifest.json
          uv run python scripts/scanner.py --summary
          ADK_VERSION=$(uv run python -c "from importlib.metadata import version; print(version('google-adk'))")
          echo "adk_version=$ADK_VERSION" >> "$GITHUB_OUTPUT"

      - name: Diff against previous manifest
        id: check_changes
        run: |
          if [ -f manifest.previous.json ]; then
            DIFF=$(uv run python scripts/scanner.py --diff manifest.previous.json)
            echo "$DIFF" | uv run python -c "
          import sys, json
          d = json.load(sys.stdin)
          changes = bool(d.get('added_classes') or d.get('removed_classes') or d.get('field_changes'))
          breaking = d.get('breaking', False)
          print(f'has_changes={str(changes).lower()}')
          print(f'is_breaking={str(breaking).lower()}')
          " >> "$GITHUB_OUTPUT"

            echo "### ADK Diff Report" >> "$GITHUB_STEP_SUMMARY"
            echo '```json' >> "$GITHUB_STEP_SUMMARY"
            echo "$DIFF" >> "$GITHUB_STEP_SUMMARY"
            echo '```' >> "$GITHUB_STEP_SUMMARY"
          else
            echo "has_changes=true" >> "$GITHUB_OUTPUT"
            echo "is_breaking=false" >> "$GITHUB_OUTPUT"
            echo "No previous manifest found — generating from scratch." >> "$GITHUB_STEP_SUMMARY"
          fi

      - name: Generate code
        run: |
          uv run python scripts/generator.py \
            seeds/seed.toml \
            manifest.json \
            --output-dir src/adk_fluent \
            --test-dir tests/generated

      - name: Generate LLM context and editor rules
        run: uv run python scripts/llms_generator.py manifest.json seeds/seed.toml

      - name: Archive manifest
        run: cp manifest.json manifest.previous.json

      - uses: actions/upload-artifact@v4
        with:
          name: generated-code
          retention-days: 14
          path: |
            src/adk_fluent/
            tests/generated/
            manifest.json
            manifest.previous.json
            docs/llms.txt
            CLAUDE.md
            .cursor/
            .github/instructions/
            .windsurfrules
            .clinerules/

  # =========================================================================
  # Type-check generated stubs
  # =========================================================================
  type-check:
    needs: scan-and-generate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: ./.github/actions/setup-env
        with:
          uv-version: ${{ env.UV_VERSION }}

      - uses: actions/download-artifact@v4
        with:
          name: generated-code

      - name: Type-check
        run: uv run pyright src/adk_fluent/ --pythonversion 3.12

  # =========================================================================
  # N-5 compatibility tests against older ADK versions
  # =========================================================================
  test:
    needs: scan-and-generate
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        adk-version:
          - "latest"
          - "1.26.0"
          - "1.25.1"
          - "1.24.1"
          - "1.23.0"
          - "1.22.1"
    steps:
      - uses: actions/checkout@v4

      - uses: ./.github/actions/setup-env
        with:
          uv-version: ${{ env.UV_VERSION }}

      - uses: actions/download-artifact@v4
        with:
          name: generated-code

      - name: Pin ADK version (${{ matrix.adk-version }})
        if: matrix.adk-version != 'latest'
        run: uv pip install "google-adk==${{ matrix.adk-version }}"

      - name: Run tests
        run: uv run pytest tests/ -v --tb=short

  # =========================================================================
  # Create auto-PR if stubs changed
  # =========================================================================
  auto-pr:
    needs: [scan-and-generate, type-check, test]
    if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/download-artifact@v4
        with:
          name: generated-code

      - name: Create PR
        uses: peter-evans/create-pull-request@v6
        with:
          title: "chore: sync with google-adk ${{ needs.scan-and-generate.outputs.adk_version }}"
          branch: auto/sync-adk-${{ needs.scan-and-generate.outputs.adk_version }}
          commit-message: |
            chore: regenerate from google-adk ${{ needs.scan-and-generate.outputs.adk_version }}

            Auto-generated by scan-and-generate workflow.
            Breaking changes: ${{ needs.scan-and-generate.outputs.is_breaking }}
          body: |
            ## ADK Sync: ${{ needs.scan-and-generate.outputs.adk_version }}

            This PR was auto-generated by the weekly ADK sync workflow.

            - **ADK Version**: ${{ needs.scan-and-generate.outputs.adk_version }}
            - **Breaking Changes**: ${{ needs.scan-and-generate.outputs.is_breaking }}
            - **Compat Matrix**: Tested against N-5 ADK versions

            ### What changed
            See the diff report in the workflow summary.

            ### What to review
            - [ ] `.pyi` stubs match expected API surface
            - [ ] All tests pass across the N-5 ADK matrix
            - [ ] No unexpected field removals
          labels: |
            automated
            adk-sync
