Files
dstalk/.github/workflows/ci.yml
XiuChengWu df3bf298ee
Some checks failed
CI / Determine matrix (push) Has been cancelled
CI / ${{ matrix.os }} / ${{ matrix.build_type }} (push) Has been cancelled
CI / Sanitizer (ASan+UBSan) / ubuntu-24.04 (push) Has been cancelled
CI / Coverage (gcovr) / ubuntu-24.04 (push) Has been cancelled
W22: coverage metric + network tests + Tool stream feedback + stdin pipe + session path + dependency check (W22.1-W22.6)
- W22.1: gcovr 覆盖率度量 + CI coverage job(40% 阈值 warning)
- W22.2: network_plugin 单元测试(parse_headers_json/extract_host_port/SSE/异常保护)
- W22.3: Tool Calling 流式反馈(chat_stream + "[工具调用]/[工具结果]" 状态行)
- W22.4: --prompt stdin pipe(--prompt - 从 stdin 读取)
- W22.5: session 路径健壮化(static 缓存 + mkdir + fallback)
- W22.6: 插件依赖拓扑静态校验(validate_dependencies 循环/缺失检测)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 21:21:24 +08:00

331 lines
14 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: CI
on:
push:
branches: [master]
pull_request:
branches: [master]
env:
CMAKE_BUILD_PARALLEL_LEVEL: 0
CCACHE_DIR: ${{ github.workspace }}/.ccache
CCACHE_MAXSIZE: 256M
jobs:
# ── 动态矩阵 ──────────────────────────────────────────────
# PR 仅跑 Ubuntu 节省 minutespush master 跑全矩阵 Ubuntu + Windows
matrix:
name: Determine matrix
runs-on: ubuntu-24.04
outputs:
os: ${{ steps.set-matrix.outputs.os }}
steps:
- id: set-matrix
shell: bash
run: |
if [ "${{ github.event_name }}" = "push" ] && [ "${{ github.ref }}" = "refs/heads/master" ]; then
echo "os=[\"ubuntu-24.04\",\"windows-2025\"]" >> "$GITHUB_OUTPUT"
else
echo "os=[\"ubuntu-24.04\"]" >> "$GITHUB_OUTPUT"
fi
# ── 构建 & 测试 ───────────────────────────────────────────
build:
name: ${{ matrix.os }} / ${{ matrix.build_type }}
needs: matrix
strategy:
fail-fast: false
matrix:
os: ${{ fromJSON(needs.matrix.outputs.os) }}
build_type: [Release]
runs-on: ${{ matrix.os }}
steps:
# ── 1. 源码检出 ──────────────────────────────────────
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
# ── 2. 平台编译工具链 ─────────────────────────────────
# Ubuntu: clang-18 + Ninja + ccache
- name: Install toolchain (Ubuntu)
if: runner.os == 'Linux'
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq clang-18 ninja-build ccache
echo "CC=clang-18" >> $GITHUB_ENV
echo "CXX=clang++-18" >> $GITHUB_ENV
# Windows: LLVM (clang-cl) + Ninja + ccache
- name: Install toolchain (Windows)
if: runner.os == 'Windows'
shell: bash
run: |
choco install -y llvm ninja ccache --no-progress 2>/dev/null || true
# Add clang-cl to PATH (both possible locations)
# Prefer choco-installed LLVM; fall back to VS-bundled clang-cl
if [ -d "/c/Program Files/LLVM/bin" ]; then
echo "/c/Program Files/LLVM/bin" >> $GITHUB_PATH
elif [ -d "/c/Program Files/Microsoft Visual Studio/2026/Enterprise/VC/Tools/Llvm/x64/bin" ]; then
echo "/c/Program Files/Microsoft Visual Studio/2026/Enterprise/VC/Tools/Llvm/x64/bin" >> $GITHUB_PATH
elif [ -d "/c/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/x64/bin" ]; then
echo "/c/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/x64/bin" >> $GITHUB_PATH
fi
echo "CC=clang-cl" >> $GITHUB_ENV
echo "CXX=clang-cl" >> $GITHUB_ENV
# ── 3. ccache 缓存恢复 ────────────────────────────────
- name: Cache ccache
uses: actions/cache@v4
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ runner.os }}-ccache-${{ matrix.build_type }}-${{ github.run_id }}
restore-keys: |
${{ runner.os }}-ccache-${{ matrix.build_type }}-
${{ runner.os }}-ccache-
# ── 4. Python + Conan ─────────────────────────────────
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Conan
run: pip install conan
# ── 5. Conan 依赖缓存 ─────────────────────────────────
- name: Cache Conan
uses: actions/cache@v4
with:
path: |
~/.conan2
~/.conan2/p
key: ${{ runner.os }}-conan-${{ matrix.build_type }}-${{ hashFiles('deps/conanfile.txt') }}
restore-keys: |
${{ runner.os }}-conan-${{ matrix.build_type }}-
${{ runner.os }}-conan-
# ── 6. Conan 依赖安装 ─────────────────────────────────
- name: Install Conan dependencies
shell: bash
run: |
conan profile detect --force
conan install deps --build=missing -s build_type=${{ matrix.build_type }}
# ── 7. CMake 配置 ─────────────────────────────────────
- name: Configure CMake
shell: bash
run: |
cmake --preset ci-release \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
# ── 8. 构建(含计时) ─────────────────────────────────
- name: Build
id: build
shell: bash
run: |
echo "::group::Build (${{ matrix.os }})"
START_NS=$(date +%s%N 2>/dev/null || echo 0)
START_S=$(date +%s)
cmake --build --preset ci-release --config ${{ matrix.build_type }}
END_S=$(date +%s)
END_NS=$(date +%s%N 2>/dev/null || echo 0)
DURATION=$((END_S - START_S))
echo "::endgroup::"
echo "duration=${DURATION}" >> $GITHUB_OUTPUT
echo "Build wall time: ${DURATION}s"
# ── 9. ccache 统计 ────────────────────────────────────
- name: ccache stats
if: always()
shell: bash
run: |
ccache -s || echo "ccache stats unavailable"
ccache -z || true
# ── 10. 测试 ──────────────────────────────────────────
- name: Test
shell: bash
run: ctest --preset ci-release -C ${{ matrix.build_type }} --output-on-failure
# ── 11. 构建时间摘要 ──────────────────────────────────
- name: Build time summary
if: always()
shell: bash
run: |
DURATION="${{ steps.build.outputs.duration }}"
echo "| Platform | Compiler | Build Time |" >> $GITHUB_STEP_SUMMARY
echo "|----------|----------|-----------|" >> $GITHUB_STEP_SUMMARY
echo "| ${{ matrix.os }} | ${{ (runner.os == 'Linux' && 'clang-18') || 'clang-cl' }} | ${DURATION}s |" >> $GITHUB_STEP_SUMMARY
echo "CI build: ${{ matrix.os }} / ${{ (runner.os == 'Linux' && 'clang-18') || 'clang-cl' }} wall time ${DURATION}s"
# ── Sanitizer (PR-only, Linux clang-18, no ccache) ───────
sanitize:
name: Sanitizer (ASan+UBSan) / ubuntu-24.04
if: github.event_name == 'pull_request'
runs-on: ubuntu-24.04
steps:
# ── 1. 源码检出 ──────────────────────────────────────
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
# ── 2. 工具链 (clang-18) ─────────────────────────────
- name: Install toolchain (Ubuntu)
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq clang-18 ninja-build
echo "CC=clang-18" >> $GITHUB_ENV
echo "CXX=clang++-18" >> $GITHUB_ENV
# ── 3. Python + Conan ─────────────────────────────────
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Conan
run: pip install conan
# ── 4. Conan 依赖缓存 ─────────────────────────────────
- name: Cache Conan
uses: actions/cache@v4
with:
path: |
~/.conan2
~/.conan2/p
key: ${{ runner.os }}-conan-Release-${{ hashFiles('deps/conanfile.txt') }}
restore-keys: |
${{ runner.os }}-conan-Release-
${{ runner.os }}-conan-
# ── 5. Conan 依赖安装 ─────────────────────────────────
- name: Install Conan dependencies
shell: bash
run: |
conan profile detect --force
conan install deps --build=missing -s build_type=Release
# ── 6. CMake 配置 ─────────────────────────────────────
- name: Configure CMake (Sanitizer)
shell: bash
run: cmake --preset ci-sanitize
# ── 7. 构建 ───────────────────────────────────────────
- name: Build (Sanitizer)
shell: bash
run: cmake --build --preset ci-sanitize
# ── 8. 测试 ──────────────────────────────────────────
- name: Test (Sanitizer)
shell: bash
run: ctest --preset ci-sanitize --output-on-failure
# ── Coverage (PR + push master, Linux clang-18, gcovr) ──
coverage:
name: Coverage (gcovr) / ubuntu-24.04
runs-on: ubuntu-24.04
steps:
# ── 1. 源码检出 ──────────────────────────────────────
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
# ── 2. 工具链 (clang-18) ─────────────────────────────
- name: Install toolchain (Ubuntu)
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq clang-18 ninja-build
echo "CC=clang-18" >> $GITHUB_ENV
echo "CXX=clang++-18" >> $GITHUB_ENV
# ── 3. Python + Conan ─────────────────────────────────
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Conan + gcovr
run: pip install conan gcovr
# ── 4. Conan 依赖缓存 ─────────────────────────────────
- name: Cache Conan
uses: actions/cache@v4
with:
path: |
~/.conan2
~/.conan2/p
key: ${{ runner.os }}-conan-Release-${{ hashFiles('deps/conanfile.txt') }}
restore-keys: |
${{ runner.os }}-conan-Release-
${{ runner.os }}-conan-
# ── 5. Conan 依赖安装 ─────────────────────────────────
- name: Install Conan dependencies
shell: bash
run: |
conan profile detect --force
conan install deps --build=missing -s build_type=Release
# ── 6. CMake 配置 ─────────────────────────────────────
- name: Configure CMake (Coverage)
shell: bash
run: cmake --preset ci-coverage
# ── 7. 构建 ───────────────────────────────────────────
- name: Build (Coverage)
shell: bash
run: cmake --build --preset ci-coverage
# ── 8. 测试 ──────────────────────────────────────────
- name: Test (Coverage)
shell: bash
run: ctest --preset ci-coverage --output-on-failure
# ── 9. 覆盖率报告 ────────────────────────────────────
- name: Coverage report
id: coverage
shell: bash
run: |
gcovr -r . --object-directory=build/ci-coverage \
--gcov-executable "llvm-cov-18 gcov" \
--print-summary > coverage_summary.txt 2>&1 || true
cat coverage_summary.txt
# Extract line coverage percentage
LINE_COV=$(grep -oP 'lines:\s*\K[\d.]+' coverage_summary.txt || echo "0")
echo "line_rate=${LINE_COV}" >> $GITHUB_OUTPUT
# Also generate HTML report
mkdir -p build/ci-coverage/coverage
gcovr -r . --object-directory=build/ci-coverage \
--gcov-executable "llvm-cov-18 gcov" \
--html --html-details \
-o build/ci-coverage/coverage/index.html || true
echo "HTML report: build/ci-coverage/coverage/index.html"
# ── 10. 覆盖率摘要 + 阈值门禁 ─────────────────────────
- name: Coverage summary
if: always()
shell: bash
run: |
LINE_COV="${{ steps.coverage.outputs.line_rate }}"
THRESHOLD=40
echo "## Coverage Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Metric | Value | Threshold | Status |" >> $GITHUB_STEP_SUMMARY
echo "|--------|-------|-----------|--------|" >> $GITHUB_STEP_SUMMARY
if [ -z "$LINE_COV" ] || [ "$LINE_COV" = "0" ]; then
echo "| Line Coverage | N/A | ${THRESHOLD}% | :grey_question: (no data) |" >> $GITHUB_STEP_SUMMARY
elif awk "BEGIN {exit !($LINE_COV < $THRESHOLD)}"; then
echo "| Line Coverage | ${LINE_COV}% | ${THRESHOLD}% | :warning: BELOW THRESHOLD |" >> $GITHUB_STEP_SUMMARY
echo "::warning title=Coverage below threshold::Line coverage ${LINE_COV}% is below ${THRESHOLD}% threshold"
else
echo "| Line Coverage | ${LINE_COV}% | ${THRESHOLD}% | :white_check_mark: OK |" >> $GITHUB_STEP_SUMMARY
echo "Line coverage ${LINE_COV}% >= ${THRESHOLD}% threshold - OK"
fi