Files
STM32F4-Base/.gitea/workflows/ci.yml
T
wandering1 e241fea801
CI / L0 静态门禁 (pre-commit) (push) Failing after 17s
CI / L0.5 主机侧单测 (MSVC) (push) Successful in 16s
CI:run 脚本改纯 ASCII(PS5.1 按 GBK 解码临时 ps1)
第二次 CI 运行(run#2)仍失败,但失败点前移:
  pwsh 问题已修(环境自检步骤确实由 Windows PowerShell 5.1 执行)
  新错误:TerminatorExpectedAtEndOfString @ 含中文那一行
根因:runner 把每个 run: 块写入临时 .ps1(无 BOM)交 PS5.1 执行,
      PS5.1 按 GBK/CP936 解码 → UTF-8 中文字节与相邻引号错位 →
      字符串缺少终止符(报错行号即含中文行,极易误判)。
与 AGENTS.md「字符串字面量必须纯 ASCII」同源。

处置:所有 run: 块内改为纯 ASCII(提示语改英文),中文仅保留在
YAML 的 name:/注释(Gitea 按 UTF-8 读、不喂 PowerShell,安全)。
workflow 头部补该坑说明。已用脚本核验 run: 块内零非 ASCII。
2026-10-02 01:17:24 +08:00

203 lines
8.8 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。
#
# 🔴 shell 用 `powershell` 而非 `pwsh`(2026-10-02 实测修正):
# `pwsh` = PowerShell 7,**不是 Windows 自带**;本机 runner 只有
# Windows PowerShell 5.1(`C:\Windows\System32\WindowsPowerShell\v1.0\`),
# 用 `shell: pwsh` 会直接报 `Cannot find: pwsh in PATH` → job 失败(跑不到任何业务逻辑)。
# `shell: powershell` 在任意 Windows 上都存在。
#
# 🔴🔴 `run:` 脚本内容必须【纯 ASCII】(2026-10-02 第二次实测修正):
# runner 把每个 `run:` 块写入临时 `.ps1`(`...\act\workflow\N.ps1`)再交给
# Windows PowerShell 5.1 执行,而该临时文件**无 BOM** → PS 5.1 按 **GBK/CP936** 解码。
# 脚本里的 UTF-8 中文字节会与相邻引号错位 → 报
# `TerminatorExpectedAtEndOfString` / `字符串缺少终止符: "` / `缺少右"}"`
# (报错行号正是含中文的那一行,极易误判为逻辑错误)。
# **故本文件所有 `run:` 块内零非 ASCII**(中文仅出现在 YAML 的 name:/注释里——
# 那些由 Gitea 按 UTF-8 读,不喂给 PowerShell,安全)。
# ⚠️ 与 AGENTS.md「字符串字面量必须纯 ASCII」同源;改脚本时务必守住。
#
# ⚠️ 前置(部署到 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: powershell
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: $($missing -join ', ') -- install then re-run"
exit 1
}
python --version
cppcheck --version
# pre-commit: use `python -m pre_commit` (does not rely on PATH console script)
python -m pre_commit --version
if ($LASTEXITCODE -ne 0) {
Write-Host "::error::runner missing pre-commit (pip install pre-commit)"
exit 1
}
Write-Host "runner environment check passed"
- name: 安装 pre-commit 钩子到本仓库
shell: powershell
run: python -m pre_commit install --install-hooks
- name: 决定跳过哪些钩子(Keil 依赖)
id: skip
shell: powershell
run: |
# mem-numbers fact source is the Keil build artifact .map (gitignored).
# No .map => this hook cannot run => skip (not "pass", but "not applicable").
$map = Get-ChildItem -Path 'MDK-ARM' -Recurse -Filter '*.map' -ErrorAction SilentlyContinue
if ($map) {
Write-Host "found .map: $($map[0].FullName) -- mem-numbers runs normally"
"value=" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
} else {
Write-Host "::notice::no .map found (no Keil build) -- skipping mem-numbers hook"
"value=mem-numbers" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
}
- name: 运行 L0 门禁(--all-files)
shell: powershell
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 static gates failed (see output above)"
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: powershell
run: |
# Keep in sync with VS_ROOTS in test/host/common/unit_test_harness.py
$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 "found cl.exe: $($cl.FullName)"; break }
}
}
if ($found) {
"value=yes" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
} else {
Write-Host "::warning::runner has no MSVC (VS C++ toolchain) -- skipping L0.5. Install VS BuildTools and re-run."
"value=no" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
}
- name: 运行主机侧单测
if: steps.msvc.outputs.value == 'yes'
shell: powershell
run: |
# Iterate test/host/*/run_unit_test.py (each module ships its own runner via common harness)
$runners = Get-ChildItem -Path 'test/host' -Recurse -Filter 'run_unit_test.py' |
Sort-Object FullName
if (-not $runners) {
Write-Host "::warning::no test/host/**/run_unit_test.py found -- skipping"
exit 0
}
$fail = 0
foreach ($r in $runners) {
Write-Host "================================"
Write-Host "run: $($r.FullName)"
Write-Host "================================"
python $r.FullName
if ($LASTEXITCODE -ne 0) {
Write-Host "::error::unit test failed: $($r.FullName) (exit $LASTEXITCODE)"
$fail = 1
}
}
exit $fail
- name: L0.5 跳过说明
if: steps.msvc.outputs.value == 'no'
shell: powershell
run: |
Write-Host "L0.5 skipped: runner has no MSVC."
Write-Host "Local equivalent: & '.venv\Scripts\python.exe' scripts/ci_local.py"
exit 0