name: integration-tests

on:
  push:
    branches: ["main"]
    paths-ignore:
      - "**/*.md"
  pull_request:
    branches: ["main"]
    paths-ignore:
      - "**/*.md"

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.id || github.sha }}
  cancel-in-progress: true

permissions:
  contents: read

defaults:
  run:
    shell: bash

env:
  # Windows CI would fail without this.
  # Ref: https://gist.github.com/NodeJSmith/e7e37f2d3f162456869f015f842bcf15
  # TODO: can we fix windows encoding natively within reflex? Bug above can hit real users too (less common, but possible)
  # - Catch encoding errors when printing logs
  # - Best effort print lines that contain illegal chars (map to some default char, etc.)
  PYTHONIOENCODING: "utf8"
  REFLEX_TELEMETRY_ENABLED: false
  NODE_OPTIONS: "--max_old_space_size=8192"

jobs:
  example-counter-and-nba-proxy:
    env:
      OUTPUT_FILE: import_benchmark.json
    timeout-minutes: 30
    strategy:
      # Prioritize getting more information out of the workflow (even if something fails)
      fail-fast: false
      matrix:
        # Show OS combos first in GUI
        os: [ubuntu-latest, windows-latest]
        python-version: ["3.14"]

    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-tags: true
          fetch-depth: 0
          persist-credentials: false
      - uses: ./.github/actions/setup_build_env
        with:
          python-version: ${{ matrix.python-version }}
          run-uv-sync: true

      - name: Clone Reflex Examples Repo
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          repository: reflex-dev/reflex-examples
          path: reflex-examples
          persist-credentials: false
      - name: Install requirements for counter example
        working-directory: ./reflex-examples/counter
        run: |
          uv pip install -r requirements.txt
      - name: Check export --backend-only before init for counter example
        working-directory: ./reflex-examples/counter
        run: |
          uv run reflex export --backend-only
      - name: Check run --backend-only before init for counter example
        run: |
          uv run bash scripts/integration.sh ./reflex-examples/counter dev 8001 --backend-only --backend-port 8001
      - name: Init Website for counter example
        working-directory: ./reflex-examples/counter
        run: |
          uv run reflex init --loglevel debug
      - name: Check export for counter example
        working-directory: ./reflex-examples/counter
        run: |
          uv run reflex export
      - name: Run Website and Check for errors
        run: |
          # Check that npm is home
          npm -v
          uv run bash scripts/integration.sh ./reflex-examples/counter dev
      - name: Install requirements for nba proxy example
        working-directory: ./reflex-examples/nba-proxy
        run: |
          uv pip install -r requirements.txt
      - name: Check export --backend-only before init for nba-proxy example
        working-directory: ./reflex-examples/nba-proxy
        run: |
          uv run reflex export --backend-only
      - name: Init Website for nba-proxy example
        working-directory: ./reflex-examples/nba-proxy
        run: |
          uv run reflex init --loglevel debug
      - name: Run Website and Check for errors
        run: |
          # Check that npm is home
          npm -v
          uv run bash scripts/integration.sh ./reflex-examples/nba-proxy dev

  reflex-docs:
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.11", "3.12"]

    env:
      REFLEX_WEB_WINDOWS_OVERRIDE: "1"
      # reflex-enterprise restricts `reflex run --env prod` to paid tiers but
      # exempts reflex's own integration tests via the app harness flag.
      APP_HARNESS_FLAG: "true"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-tags: true
          fetch-depth: 0
          persist-credentials: false

      # Install sfw BEFORE any dependency installation so all packages are scanned.
      - name: Install Socket.dev Firewall (free)
        uses: SocketDev/action@ba6de6cc0565af1f42295590380973573297e31f # v1.3.2
        with:
          mode: firewall-free

      - name: Install Bun
        uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
      - name: Activate sfw shims for npm and bun
        run: |
          SHIM_DIR="$(cd scripts/sfw-shims && pwd)"
          echo "$SHIM_DIR" >> "$GITHUB_PATH"
          echo "REFLEX_USE_SYSTEM_BUN=1" >> "$GITHUB_ENV"

      # Inline setup_build_env steps so all installs go through sfw.
      - name: Install UV
        uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
        with:
          python-version: ${{ matrix.python-version }}
          enable-cache: true
          prune-cache: false
          activate-environment: true
          cache-dependency-glob: "uv.lock"
      - name: Setup Node
        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
        with:
          node-version: 22

      - name: Install reflex-docs dependencies
        working-directory: ./docs/app
        run: sfw uv sync --frozen

      - name: Init Website for reflex-docs
        working-directory: ./docs/app
        run: uv run --active --no-sync reflex init
      - name: Run Website and Check for errors
        run: |
          # Verify sfw wrappers are on PATH
          which npm && npm -v
          uv run --active --no-sync bash scripts/integration.sh ./docs/app prod

      - name: Validate /docs links against generated sitemap
        working-directory: ./docs/app
        run: uv run --active --no-sync pytest --runxfail tests/test_doc_links.py -v

      - name: Upload Socket.dev Firewall report
        if: always()
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: sfw-report-reflex-docs-py${{ matrix.python-version }}
          path: ${{ env.SFW_JSON_REPORT_PATH }}
          if-no-files-found: warn

  rx-shout-from-template:
    strategy:
      fail-fast: false
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-tags: true
          fetch-depth: 0
          persist-credentials: false
      - uses: ./.github/actions/setup_build_env
        with:
          python-version: "3.14"
          run-uv-sync: true

      - name: Create app directory
        run: mkdir rx-shout-from-template
      - name: Init rx-shout from template
        run: uv run reflex init --template https://github.com/masenf/rx_shout
        working-directory: ./rx-shout-from-template
      - name: Override reflex sources to local checkout
        # Force reflex install editable from this repo instead of PyPI.
        working-directory: ./rx-shout-from-template
        run: |
          cat >> pyproject.toml <<'EOF'

          [tool.uv.sources]
          reflex = { path = "..", editable = true }
          EOF
      - name: Install rx-shout dependencies
        # Re-locks because pyproject.toml changed; --prerelease=allow matches
        # the template's own lock options (rx_shout depends on reflex pre-releases).
        working-directory: ./rx-shout-from-template
        run: uv sync --prerelease=allow
      - name: Run App and Check for errors
        run: |
          # Check that npm is home
          npm -v
          uv run --project ./rx-shout-from-template --no-sync bash scripts/integration.sh ./rx-shout-from-template prod

  reflex-docs-macos:
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    strategy:
      fail-fast: false
      matrix:
        # Note: py311 version chosen due to available arm64 darwin builds.
        python-version: ["3.11", "3.12"]
    env:
      # reflex-enterprise restricts `reflex run --env prod` to paid tiers but
      # exempts reflex's own integration tests via the app harness flag.
      APP_HARNESS_FLAG: "true"
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-tags: true
          fetch-depth: 0
          persist-credentials: false
      - uses: ./.github/actions/setup_build_env
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install Requirements for reflex-docs
        working-directory: ./docs/app
        run: uv sync
      - name: Init Website for reflex-docs
        working-directory: ./docs/app
        run: uv run --active --no-sync reflex init
      - name: Run Website and Check for errors
        run: |
          # Check that npm is home
          npm -v
          uv run --active --no-sync bash scripts/integration.sh ./docs/app prod
