Files
STM32F4-Base/.gitea/workflows/ci.yml
T
wandering1 e90486524d CI:Gitea Actions 落地 L0+L0.5(补 T-6)
新增 .gitea/workflows/ci.yml:push/PR 触发两个 Windows job——
l0-gates 跑 pre-commit --all-files(无 Keil .map 时自适应跳过 mem-numbers),
l05-host-unit-tests 遍历 test/host/**/run_unit_test.py(缺 MSVC 则告警降级跳过)。
刻意不跑 @build(需 Keil 授权);L1/L2/L3 需真机+ST-LINK,不上 CI。

新增 scripts/ci_local.py:本地跑与 CI 等价的门禁(自动选用装了 pre-commit
的解释器;.map 自适应;退出码 0/1/2 与 CI 对齐),供提交前自查与 runner 就绪前过渡。

文档同步:测试开发标准流程 §9(CI 章节)/§1/§4.1、待处理内容 T-6 销项、
项目部署环境要求 §2.11(runner 前置)、pre-commit 使用说明 §1、scripts/README.md、AGENTS.md。

验证:scripts/ci_local.py rc=0(L0 14 钩子全过 + L0.5 39/39)。
2026-10-01 10:19:38 +08:00

187 lines
7.7 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.
# Gitea Actions CI —— STM32F4-Base 持续集成
#
# 覆盖范围(**只做不依赖硬件的层**,见 docs/测试说明/测试开发标准流程.md §1/§9):
# L0 静态门禁 = pre-commit 全部钩子(等价本地 `pre-commit run --all-files`)
# L0.5 主机侧纯逻辑单测 = test/host/**(MSVC 离线编译,零硬件)
#
# ⛔ L1 板端套件(test/board/,需真机 + ST-LINK)/ L2 @test 闭环 / L3 人工目检
# **不上 CI** —— 需要开发板与烧录器,只能在本地跑。
#
# 明确不做的两件事(都是刻意为之):
# 1. `@build`(Keil UV4)—— 需本机 Keil 授权,runner 上不具备;且 L0 的 cppcheck +
# 代码规范已覆盖"编译前的静态问题",真编译仍是开发者的本地红线(AGENTS.md)。
# 2. `mem-numbers` 钩子 —— 它的事实源是 `MDK-ARM/**/*.map`(Keil 构建产物、已 gitignore),
# 无 `@build` 即无 `.map`。故本 workflow 在**检测不到 .map 时自动跳过该钩子**
# (见下方 "决定跳过哪些钩子" 步骤),有 .map 的 runner(如自建带 Keil 的机器)则照常跑。
#
# 触发:push(除纯文档路径外)与 pull_request。
#
# ⚠️ 前置(部署到 Gitea 时需确认):
# - 该 Gitea 实例已启用 Actions:`[actions] ENABLED = true`(site admin 配置)
# - 已注册一个 **Windows** runner(labels 含 `windows`),且装有:
# Python 3.x、cppcheck、pre-commit、MSVC(VS2019/2022 的 C++ 工具链 + Windows SDK)
# - 缺 MSVC 时 L0.5 步骤会**降级为提示并跳过**(不硬失败),但会打印醒目 WARNING
#
# 本地等价命令(与 CI 同一套判定,见 scripts/ci_local.py):
# & '.venv\Scripts\python.exe' scripts/ci_local.py
name: CI
on:
push:
branches: ['**']
paths-ignore:
- 'docs/**'
- '**/*.md'
- '.workbuddy-ai/**'
pull_request:
paths-ignore:
- 'docs/**'
- '**/*.md'
- '.workbuddy-ai/**'
workflow_dispatch:
# 同一分支的旧运行自动取消,省 runner
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
# ------------------------------------------------------------------
# L0:静态门禁(pre-commit 钩子全集)
# ------------------------------------------------------------------
l0-gates:
name: L0 静态门禁 (pre-commit)
runs-on: windows
steps:
- uses: actions/checkout@v4
with:
# 钩子要对比基线与历史(doc-links 等读工作区即可,但 gitlint/cubemx 需完整历史)
fetch-depth: 0
- name: 环境自检(Python / cppcheck / pre-commit)
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$missing = @()
foreach ($item in @(
@{ name = 'Python'; cmd = 'python' },
@{ name = 'cppcheck'; cmd = 'cppcheck' }
)) {
if (-not (Get-Command $item.cmd -ErrorAction SilentlyContinue)) {
$missing += $item.name
}
}
if ($missing.Count -gt 0) {
Write-Host "::error::runner 缺少:$($missing -join ', ') —— 请安装后重跑"
exit 1
}
python --version
cppcheck --version
# pre-commit:优先用 `python -m pre_commit`(不依赖 PATH 里的 console script)
python -m pre_commit --version
if ($LASTEXITCODE -ne 0) {
Write-Host "::error::runner 缺少 pre-commit(pip install pre-commit / uv tool install pre-commit)"
exit 1
}
Write-Host "runner 环境自检通过"
- name: 安装 pre-commit 钩子到本仓库
shell: pwsh
run: python -m pre_commit install --install-hooks
- name: 决定跳过哪些钩子(Keil 依赖)
id: skip
shell: pwsh
run: |
# mem-numbers 的事实源是 Keil 构建产物 .map(已 gitignore)。
# 无 .map => 本 runner 不可能跑 L0 的该钩子 => 跳过(不是"通过",是"不适用")。
$map = Get-ChildItem -Path 'MDK-ARM' -Recurse -Filter '*.map' -ErrorAction SilentlyContinue
if ($map) {
Write-Host "找到 .map:$($map[0].FullName) —— mem-numbers 照常运行"
"value=" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
} else {
Write-Host "::notice::未找到 .map(未做 Keil 构建)—— 跳过 mem-numbers 钩子"
"value=mem-numbers" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
}
- name: 运行 L0 门禁(--all-files)
shell: pwsh
env:
SKIP: ${{ steps.skip.outputs.value }}
run: |
if ($env:SKIP) { Write-Host "SKIP=$env:SKIP" }
python -m pre_commit run --all-files --show-diff-on-failure
if ($LASTEXITCODE -ne 0) {
Write-Host "::error::L0 静态门禁未通过(详见上方输出)"
exit $LASTEXITCODE
}
# ------------------------------------------------------------------
# L0.5:主机侧纯逻辑单测(零硬件;缺 MSVC 则跳过)
# ------------------------------------------------------------------
l05-host-unit-tests:
name: L0.5 主机侧单测 (MSVC)
runs-on: windows
steps:
- uses: actions/checkout@v4
- name: 探测 MSVC(VS BuildTools / Community 等)
id: msvc
shell: pwsh
run: |
# 与 test/host/common/unit_test_harness.py 的 VS_ROOTS 保持一致
$roots = @(
'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools',
'C:\Program Files\Microsoft Visual Studio\2022\BuildTools',
'C:\Program Files\Microsoft Visual Studio\2022\Community',
'C:\Program Files\Microsoft Visual Studio\2022\Professional'
)
$found = $false
foreach ($r in $roots) {
if (Test-Path $r) {
$cl = Get-ChildItem -Path $r -Recurse -Filter 'cl.exe' -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -like '*Hostx64\x64*' } | Select-Object -First 1
if ($cl) { $found = $true; Write-Host "找到 cl.exe: $($cl.FullName)"; break }
}
}
if ($found) {
"value=yes" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
} else {
Write-Host "::warning::runner 未安装 MSVC(VS C++ 工具链)—— 跳过 L0.5 单测。请安装 VS BuildTools 后重跑。"
"value=no" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
}
- name: 运行主机侧单测
if: steps.msvc.outputs.value == 'yes'
shell: pwsh
run: |
# 遍历 test/host/*/run_unit_test.py(各模块自带运行器,统一走 common harness)
$runners = Get-ChildItem -Path 'test/host' -Recurse -Filter 'run_unit_test.py' |
Sort-Object FullName
if (-not $runners) {
Write-Host "::warning::未找到 test/host/**/run_unit_test.py —— 跳过"
exit 0
}
$fail = 0
foreach ($r in $runners) {
Write-Host "================================"
Write-Host "运行:$($r.FullName)"
Write-Host "================================"
python $r.FullName
if ($LASTEXITCODE -ne 0) {
Write-Host "::error::单测失败:$($r.FullName)(退出码 $LASTEXITCODE)"
$fail = 1
}
}
exit $fail
- name: L0.5 跳过说明
if: steps.msvc.outputs.value == 'no'
shell: pwsh
run: |
Write-Host "L0.5 未执行:runner 缺 MSVC。"
Write-Host "本地等价命令:& '.venv\Scripts\python.exe' scripts/ci_local.py"
exit 0