drission 0.3.2

Rust 反检测浏览器自动化 + 内置验证码识别:ddddocr 离线 OCR 与图片滑块缺口距离(极验/顶象),默认 Google Chrome/CDP、可选 Camoufox/Firefox、自动过 Cloudflare 盾、高并发爬虫与 XHR 监听拦截,DrissionPage 风格 API。Anti-detect browser automation in Rust with built-in ddddocr captcha OCR + slider-gap solving, Chrome/CDP by default, optional Camoufox, Cloudflare bypass — a Rust DrissionPage.
Documentation
name: CI

on:
  push:
    branches: [main, master]
  pull_request:

permissions:
  contents: read

env:
  CARGO_TERM_COLOR: always

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

jobs:
  fmt:
    name: rustfmt
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt
      - run: cargo fmt --all --check

  clippy:
    name: clippy (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy
      - uses: Swatinem/rust-cache@v2
      # ── 按后端分开 clippy ──────────────────────────────────────────────────
      # 两后端的统一名(Browser/Tab/…)是 **cdp 优先**:同时开 cdp+camoufox 时 canonical=cdp,
      # 此时 camoufox 示例(用 canonical 名)会被按 cdp 类型编译而失败 —— 故 **示例必须按后端分开编**。
      # 默认后端(cdp):lib + cdp 示例。
      - run: cargo clippy --all-targets -- -D warnings
      # Camoufox 后端(关掉 cdp,canonical=camoufox):lib + camoufox/slider 示例。
      - run: cargo clippy --all-targets --no-default-features --features camoufox,slider -- -D warnings
      # 零后端(仅后端无关模块):lib 必须干净。
      - run: cargo clippy --lib --no-default-features -- -D warnings

  test:
    name: test (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      # 单测 + 离线集成测试(tests/);不跑需要浏览器/网络的 example。
      # `--lib --tests`(不带 --all-targets)不编译示例,故两后端可同时开。
      - run: cargo test --features camoufox,cdp,slider --lib --tests
      # 零后端:后端无关模块的单测必须独立通过(防只在某后端下才编译的回归)。
      - run: cargo test --no-default-features --lib

  ocr:
    name: build+test (ocr feature)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy
      - uses: Swatinem/rust-cache@v2
      # OCR 引入 tract/image 重依赖,单独一档(仅 ubuntu)。只跑不需要下载模型的纯单测。
      - run: cargo test --features ocr --lib
      # OCR 示例按后端分开 clippy(det/yidun 走 cdp;ocr_captcha/apizero/hotswap 走 camoufox)。
      - run: cargo clippy --all-targets --features cdp,ocr -- -D warnings
      - run: cargo clippy --all-targets --no-default-features --features camoufox,slider,ocr -- -D warnings

  signer:
    name: build+test (signer feature)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy
      - uses: Swatinem/rust-cache@v2
      # 纯算签名运行器(内嵌 QuickJS / rquickjs)。后端无关,单独一档。
      - run: cargo clippy --all-targets --no-default-features --features signer -- -D warnings
      - run: cargo test --no-default-features --features signer --lib

  impersonate-linux:
    name: build+test (impersonate feature, linux)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      # impersonate = wreq + BoringSSL(boring-sys2);build.rs 跑 cmake 编 BoringSSL + bindgen 解析头文件,
      # 需 cmake / C++ 编译器 / libclang。ubuntu-latest 多已自带,这里显式装齐兜底。
      - name: Install BoringSSL build deps (cmake / clang / libclang)
        run: sudo apt-get update && sudo apt-get install -y cmake clang libclang-dev
      # impersonate 隐含 camoufox(SessionPage 在 camoufox 门下),故用 --no-default-features 让统一接口
      # canonical=camoufox,session_tls 示例(required-features=impersonate)才能正确编译。
      # 全量目标编译 = Linux 上 impersonate(含 BoringSSL / JA3 指纹)能否落地的硬证据(能编过即可用)。
      - name: build all targets (impersonate)
        run: cargo build --all-targets --no-default-features --features impersonate
      - name: lib unit tests (impersonate)
        run: cargo test --no-default-features --features impersonate --lib

  cross-windows-gnu:
    name: cross-check (x86_64-pc-windows-gnu)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: x86_64-pc-windows-gnu
      - uses: Swatinem/rust-cache@v2
      # reqwest 默认 rustls 后端会引入 aws-lc-sys(C 代码),交叉编译到 windows-gnu 需 mingw-w64 的
      # x86_64-w64-mingw32-gcc;nasm 供其 x86_64 汇编(同 scripts/win-cross-build.sh 的依赖约定)。
      - name: Install mingw-w64 + nasm (C deps cross-compile to windows-gnu)
        run: sudo apt-get update && sudo apt-get install -y gcc-mingw-w64 nasm
      # 两后端 lib 一起交叉编译(验证 Windows 注册表 / 命名管道分支类型正确)。
      - name: cross-check lib
        run: cargo check --lib --target x86_64-pc-windows-gnu --features camoufox,cdp,slider
        env:
          # aws-lc-sys 的 cmake/cc 交叉构建显式指向 mingw 工具链。
          CC_x86_64_pc_windows_gnu: x86_64-w64-mingw32-gcc
          CXX_x86_64_pc_windows_gnu: x86_64-w64-mingw32-g++
          AR_x86_64_pc_windows_gnu: x86_64-w64-mingw32-ar
          CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER: x86_64-w64-mingw32-gcc

  docs:
    name: docs.rs build
    runs-on: ubuntu-latest
    env:
      # 与 docs.rs 一致:nightly + --cfg docsrs,启用 doc_cfg(已合并 doc_auto_cfg)的 feature 徽标。
      RUSTDOCFLAGS: --cfg docsrs
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@nightly
      - uses: Swatinem/rust-cache@v2
      # 注意:仓库根 rust-toolchain.toml 钉了 stable,会覆盖上面装的 nightly;而 feature(doc_cfg)
      # 只能在 nightly 用(stable 报 E0554)。故用 `cargo +nightly` 显式覆盖 toolchain 文件走 nightly。
      - run: cargo +nightly doc --no-deps --all-features

  # musl 静态构建:产出**完全静态、不依赖 glibc** 的 Linux 二进制,一份跑遍所有发行版
  # (CentOS7 / Alibaba Cloud Linux / Ubuntu / Alpine …),覆盖国内绝大多数服务器。
  # x86_64 + aarch64 两个架构(后者覆盖鲲鹏/倚天/飞腾/信创 ARM 服务器)。
  # 用 cross(Docker 内置 musl 交叉 C 工具链)+ Cross.toml(装 cmake/clang 供 aws-lc-sys)。
  musl-static:
    name: musl static (${{ matrix.target }})
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        target:
          - x86_64-unknown-linux-musl
          - aarch64-unknown-linux-musl
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      - uses: Swatinem/rust-cache@v2
        with:
          key: musl-${{ matrix.target }}
      - uses: taiki-e/install-action@v2
        with:
          tool: cross
      # 编默认后端(cdp)lib + cdp_demo 示例:cdp_demo 产物用于验证「完全静态链接」——最硬的 C 依赖
      # aws-lc-sys(reqwest rustls)也被静态编入即证 musl 链路通。**不带 ocr**:tract-onnx 的 x86_64
      # SIMD 内核极多、冷缓存全量编译要 20+ 分钟,拖慢每次 push;ocr 是纯 Rust、在 gnu 已验证,且
      # aarch64 musl 实测带 ocr 也能编过(见 docs 里程碑 71)。需要 ocr 的 musl 包用 scripts/linux-musl-build.sh。
      - name: build musl static (lib + cdp_demo)
        run: cross build --release --target ${{ matrix.target }} --lib --example cdp_demo
      - name: verify fully static (no glibc / no dynamic deps)
        run: |
          BIN="target/${{ matrix.target }}/release/examples/cdp_demo"
          file "$BIN"
          if file "$BIN" | grep -q "statically linked"; then
            echo "OK: 完全静态链接 → 跨所有 Linux 发行版通用"
          else
            echo "ERROR: 不是静态二进制(仍依赖动态库)"; exit 1
          fi
      - name: upload static binary
        uses: actions/upload-artifact@v4
        with:
          name: drission-cdp_demo-${{ matrix.target }}
          path: target/${{ matrix.target }}/release/examples/cdp_demo
          if-no-files-found: error