libchai 0.4.0

汉字编码优化算法
Documentation
name: Commit CI

on:
  push:
    branches:
      - "*"
    paths-ignore:
      - "**.md"

jobs:
  static:
    runs-on: ubuntu-latest
    steps:
      # 拉取代码
      - name: Checkout
        uses: actions/checkout@v4
      # 获取静态资源
      - name: Fetch Static Resources
        run: |
          chmod +x fetch.sh
          ./fetch.sh
      # 拉取前端代码
      - name: Checkout Website
        uses: actions/checkout@v4
        with:
          repository: hanzi-chai/hanzi-chai.github.io
          path: hanzi-chai
      # 安装 Bun
      - name: Install Bun
        uses: oven-sh/setup-bun@v2
      # 编译前端
      - name: Build Website
        run: |
          cd hanzi-chai
          bun install
          bun run fetch
          bun run build:CLIENT
          cd ..
          cp -r hanzi-chai/dist/client client
      # 上传
      - name: Upload
        uses: actions/upload-artifact@v4
        with:
          name: static
          path: |
            assets
            examples
            client
            README.md
            LICENSE

      - name: 安装 Rust 工具链
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Rust cache
        uses: Swatinem/rust-cache@v2
      - name: Build documentation
        run: cargo doc --no-deps
      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./target/doc

  build-linux:
    runs-on: ubuntu-latest
    steps:
      - name: 拉取代码
        uses: actions/checkout@v4
      - name: 安装 Rust 工具链
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          target: "x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl"
      - name: Rust cache
        uses: Swatinem/rust-cache@v2
      - name: 构建 chai
        run: |
          cargo build --target x86_64-unknown-linux-gnu --bins --release
          cargo build --target x86_64-unknown-linux-musl --bins --release
      - name: Upload gnu
        uses: actions/upload-artifact@v4
        with:
          name: linux-gnu
          path: |
            target/x86_64-unknown-linux-gnu/release/chai
      - name: Upload musl
        uses: actions/upload-artifact@v4
        with:
          name: linux-musl
          path: |
            target/x86_64-unknown-linux-musl/release/chai

  build-windows:
    runs-on: windows-latest
    steps:
      - name: 拉取代码
        uses: actions/checkout@v4
      - name: 安装 Rust 工具链
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          target: "x86_64-pc-windows-msvc"
      - name: Rust cache
        uses: Swatinem/rust-cache@v2
      - name: Build
        run: cargo build --bins --release
      - name: Upload
        uses: actions/upload-artifact@v4
        with:
          name: windows
          path: |
            target/release/chai.exe

  build-macos:
    runs-on: macos-latest
    steps:
      - name: 拉取代码
        uses: actions/checkout@v4
      - name: Install Zig
        uses: goto-bus-stop/setup-zig@v2
        with:
          version: 0.13.0
      - name: 安装 Rust 工具链
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          target: "x86_64-apple-darwin, aarch64-apple-darwin"
      - name: Rust cache
        uses: Swatinem/rust-cache@v2
      - name: Install cargo-zigbuild
        run: cargo install cargo-zigbuild
      - name: Build
        run: cargo zigbuild --target universal2-apple-darwin --bins --release
      - name: Upload
        uses: actions/upload-artifact@v4
        with:
          name: macos
          path: |
            target/universal2-apple-darwin/release/chai

  bench:
    name: Benchmark
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: 安装 Rust 工具链
        uses: actions-rust-lang/setup-rust-toolchain@v1

      - name: Rust cache
        uses: Swatinem/rust-cache@v2

      - name: Fetch Static Resources (non-Windows)
        if: ${{ matrix.os != 'windows-latest' }}
        run: |
          chmod +x fetch.sh
          ./fetch.sh

      - name: Fetch Static Resources (Windows)
        if: ${{ matrix.os == 'windows-latest' }}
        shell: pwsh
        run: |
          .\fetch.ps1

      - name: Run cargo bench and save output
        # Use bash on all runners so we can tee output consistently
        shell: bash
        run: |
          set -euo pipefail
          echo "Running cargo bench on $(uname -s)"
          # Run benches and capture both stdout and exit code
          cargo bench --all-targets 2>&1 | tee bench-output.txt || true
          # Record the cargo exit status (first command in the pipe)
          echo "CARGO_EXIT=${PIPESTATUS[0]}" >> bench-output.txt

      - name: Write short summary to job summary
        if: always()
        shell: bash
        run: |
          echo "## cargo bench — ${{ matrix.os }}" >> "$GITHUB_STEP_SUMMARY"
          echo '```' >> "$GITHUB_STEP_SUMMARY"
          # include the first 200 lines of output for quick glance
          head -n 200 bench-output.txt >> "$GITHUB_STEP_SUMMARY" || true
          echo '```' >> "$GITHUB_STEP_SUMMARY"

      - name: Upload benchmark output artifact
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: bench-${{ matrix.os }}
          path: bench-output.txt

      - name: Comment PR with brief bench summary (only on PR events)
        if: ${{ github.event_name == 'pull_request' }}
        uses: actions/github-script@v6
        with:
          script: |
            const fs = require('fs')
            const out = fs.existsSync('bench-output.txt') ? fs.readFileSync('bench-output.txt','utf8').split('\n').slice(0,120).join('\n') : 'no output'
            const body = `Benchmark results for ${process.env.RUNNER_OS} (short):\n\n` + '```\n' + out + '\n```\n\nFull output is attached as an artifact.'
            github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body,
            })