Repository navigation
build: Bump the minor-and-patch group with 8 updates #162
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 日常 push / PR 的构建与测试门禁;发布流水线见 release.yml。 | |
| name: ci | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| jobs: | |
| build-test: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # 现代 .NET 在 linux 跑(附带覆盖率收集);net48(验证 netstandard2.0 资产)需要 Windows 运行时 | |
| - os: ubuntu-latest | |
| frameworks: "net8.0 net10.0" | |
| - os: windows-latest | |
| frameworks: "net48" | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Set up .NET | |
| uses: actions/setup-dotnet@v6 | |
| with: | |
| dotnet-version: | | |
| 8.0.x | |
| 10.0.x | |
| - name: Build | |
| run: dotnet build StreamFrame.slnx -c Release | |
| - name: Test (${{ matrix.frameworks }}) | |
| shell: bash | |
| env: | |
| FRAMEWORKS: ${{ matrix.frameworks }} | |
| # 覆盖率只在 Ubuntu 收集(矩阵值不进 job 名,避免必需检查名随之变化) | |
| COLLECT_COVERAGE: ${{ matrix.os == 'ubuntu-latest' }} | |
| run: | | |
| for fw in $FRAMEWORKS; do | |
| if [ "$COLLECT_COVERAGE" = "true" ]; then | |
| dotnet test StreamFrame.slnx -c Release --no-build -f $fw \ | |
| --collect:"XPlat Code Coverage" --results-directory "coverage/$fw" | |
| else | |
| dotnet test StreamFrame.slnx -c Release --no-build -f $fw | |
| fi | |
| done | |
| # 覆盖率摘要写入 job Summary(自包含,不依赖外部服务);原始 cobertura XML 附为 artifact | |
| - name: Coverage summary | |
| if: matrix.os == 'ubuntu-latest' | |
| shell: bash | |
| run: | | |
| python3 - <<'PYEOF' | |
| import glob, os, xml.etree.ElementTree as ET | |
| def fmt(rate): | |
| return f"{rate * 100:.1f}%" | |
| lines = ["", "## 测试覆盖率(XPlat Code Coverage)", "", | |
| "| 目标 | Line | Branch | 覆盖行/总行 |", "|---|---|---|---|"] | |
| for tfm_dir in sorted(glob.glob("coverage/*")): | |
| tfm = os.path.basename(tfm_dir) | |
| reports = glob.glob(os.path.join(tfm_dir, "**", "coverage.cobertura.xml"), recursive=True) | |
| if not reports: | |
| continue | |
| # 同一 TFM 只应有一份(单一测试项目);防御性取第一份 | |
| root = ET.parse(reports[0]).getroot() | |
| line_rate = float(root.get("line-rate", "0")) | |
| branch_rate = float(root.get("branch-rate", "0")) | |
| all_lines = list(root.iter("line")) | |
| covered_lines = sum(1 for l in all_lines if int(l.get("hits", "0")) > 0) | |
| lines.append(f"| {tfm} | {fmt(line_rate)} | {fmt(branch_rate)} | {covered_lines}/{len(all_lines)} |") | |
| if tfm.endswith("net8.0"): | |
| detail = ["", f"<details><summary>按程序集({tfm})</summary>", "", | |
| "| 程序集 | Line | Branch |", "|---|---|---|"] | |
| for pkg in root.iter("package"): | |
| detail.append(f"| {pkg.get('name', '?')} | " | |
| f"{fmt(float(pkg.get('line-rate', '0')))} | " | |
| f"{fmt(float(pkg.get('branch-rate', '0')))} |") | |
| detail += ["", "</details>", ""] | |
| lines += detail | |
| summary = "\n".join(lines) + "\n" | |
| print(summary) | |
| with open(os.environ.get("GITHUB_STEP_SUMMARY", "/dev/stdout"), "a", encoding="utf-8") as f: | |
| f.write(summary) | |
| PYEOF | |
| - name: Upload coverage artifacts | |
| if: matrix.os == 'ubuntu-latest' | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: coverage-${{ github.run_number }} | |
| path: coverage/ | |
| retention-days: 14 | |
| # NativeAOT/裁剪兼容性门禁(非必需检查):发布引用库的冒烟工程(PublishAot 在工程内开启, | |
| # 涵盖裁剪分析)。IL2026/IL3050 等警告经 TreatWarningsAsErrors 变为错误,防止库悄悄 | |
| # 引入反射/动态代码。ubuntu runner 自带 AOT 原生工具链。 | |
| aot: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Set up .NET | |
| uses: actions/setup-dotnet@v6 | |
| with: | |
| dotnet-version: | | |
| 8.0.x | |
| 10.0.x | |
| - name: PublishAot(NativeAOT + 裁剪警告门禁) | |
| run: dotnet publish samples/StreamFrame.AotSmoke -c Release -r linux-x64 -o artifacts/aot | |
| - name: Run NativeAOT smoke(连接、会话发送、普通发送与内容校验) | |
| run: timeout 40s ./artifacts/aot/StreamFrame.AotSmoke | |
| - name: Verify NativeAOT failure exit codes | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| for fault in connect missing consumer content; do | |
| category="$fault" | |
| case "$fault" in | |
| connect) category=connection ;; | |
| missing) category=messages ;; | |
| esac | |
| status=0 | |
| timeout 40s ./artifacts/aot/StreamFrame.AotSmoke "--fault=$fault" > "$fault.log" 2>&1 || status=$? | |
| cat "$fault.log" | |
| # 只接受程序自身报告的指定故障:0、崩溃、启动失败或 timeout 的 124 均失败。 | |
| if [ "$status" -ne 1 ] || ! grep -Fq "AOT smoke FAILED [$category]:" "$fault.log"; then | |
| echo "::error::Fault $fault was not detected correctly (exit=$status)" | |
| exit 1 | |
| fi | |
| echo "Verified expected failure: $fault (exit=$status)" | tee -a "$GITHUB_STEP_SUMMARY" | |
| done |