Files
STM32F4-Base/scripts/ci_find_python.ps1
wandering1 842d711ed6 refactor(编号): 测试验证层级去号——CI job / 门禁输出 / 命令行旗标换语义名 + ASCII 段名
用户裁定「我不想看到编号」。测试验证层级这一族的整族清退分三道并行:本笔是**代码与 CI 道**
(CI 步骤与门禁输出面),代码注释面另走、文档面由文档道走。

口径(旧 → 语义名 → ASCII 段名,段名只进日志/旗标/job id/文件名):
  L0 静态门禁 static | L0a 钩子解释器预检 preflight | L0b 提交信息门禁 commitmsg
  L0c 体积门禁 size | L0.5 主机侧纯逻辑单测 host-unit | L0.5c 覆盖率 coverage

- scripts/ci_local.py 43 站点:段标题与 [SUMMARY] 标签改 ASCII 段名(static: /
  host-unit:),函数 run_l0/run_l05 → run_static_gates/run_host_unit_tests,
  收尾「已跑:」列表用段名。旗标改 --static-only / --host-unit-only,**旧旗标
  --l0-only / --l05-only 保留为 argparse 别名**(肌肉记忆与既有脚本片段不断档,
  实测 --help 两名列出)。
- .gitea/workflows/ci.yml 42 站点:job id l0-gates → static-gates、
  l05-host-unit-tests → host-unit-tests;步骤名与 step-summary 标题改语义名;
  日志名 l0-pre-commit.log → static-pre-commit.log、l05-<模块>.log →
  host-unit-<模块>.log;::error::/::notice:: 文案同步。yaml.safe_load 核过
  两个 job id 与步骤名。
  host-unit-tests;步骤名与 step-summary 标题改语义名;日志名 l0-pre-commit.log →
  static-pre-commit.log、l05-<模块>.log → host-unit-<模块>.log;::error::/::notice::
  文案同步。yaml.safe_load 核过两个 job id 与步骤名。
- 门禁脚本 18 站点:check_registration(登记簿理由串 7)、check_test_coverage 5、
  README 8、check_generated_fresh 2、ram_baseline 2、check_size_gate 1、
  ci_find_python.ps1 2、ci_runner_bootstrap.ps1 2、.pre-commit-config.yaml 2、
  requirements.txt 1(保持纯 ASCII)。
- skills 7 站点:task-worktree(含 [SUMMARY] 样例两行)、mem-budget、ui-verify、
  task_worktree.py 的实跑标签。
- AGENTS.md 3 站点:CI 段「只跑静态门禁 + 主机侧纯逻辑单测」、自查命令段、
  「2026-10-11 静态门禁全灭」事件名。
- 归档:编号治理历史.md 新增 §10 换算表 + **撞族警示**(同形 L0/L1/L2/L3 还属 UI 设计
  令牌层 / UI 菜单层级 / 采集链 / 链路时延段 / CubeMX 三层 / 硬件位号与 FTP 应答字面量
  等六个族,其中 6 处在字符串字面量里,改了就是改行为——故全程只按行内置换、先判族)。
- docs/产品需求 §7.4 测试分层表:去号 + 顺带修掉上一批**错族替换疤**(该表 L1/L2 行曾被
  采集链层名「语义取数与有效性 / 全周傅氏相量」「保护判据」顶替,现按内容改写为板端测试
  套件 / 主机侧回归两行)。同文档 §1.5 G5 判据行同步。

门禁:ci_local --help 两面旗标并列;py_compile 7 个 .py 全过;yaml 解析通过;
check_ids_new --worktree rc=0;git diff --check 干净;17 个改动文件 FFFD=0、无 CR、
BOM 与原文件一致(含 requirements.txt 纯 ASCII)。本族无机器识别面(单字母+数字是
新增行门禁的自述盲区),口径来自自建逐行扫描器,复扫本族形态归零。
- 交接说明:文档道 teammate 在改 CI 指南时中断,剩余 9 处双写疤与 29 处 CI 标识
  (job id / 日志名 / 汇总行字面量)由 Lead 接手改完,逐处仍走断言式行内置换。
2026-10-28 17:46:52 +08:00

180 lines
7.3 KiB
PowerShell

<#
.SYNOPSIS
Pick a Python interpreter that actually works, for the CI jobs (and for
local use). Prints diagnostics with Write-Host and emits ONLY the chosen
interpreter path on the success stream, so a caller can capture it:
$py = & './scripts/ci_find_python.ps1' -NeedPreCommit -WriteEnv
.DESCRIPTION
Why this file exists (2026-10-11 CI incident):
The DTU_* env-var refactor moved the interpreter probe inline into
.gitea/workflows/ci.yml and narrowed it to two candidates
(PATH python + repo .venv). On the Windows runner BOTH are dead ends:
* PATH python for the SYSTEM account is C:\msys64\ucrt64\bin\python.exe,
which has no pre-commit module;
* the repo .venv is gitignored, so it does not exist in a fresh runner
workspace at all.
The interpreter that does work (a machine-wide install such as
C:\ProgramData\anaconda3\python.exe) was no longer probed, and no
machine-level DTU_PRECOMMIT_PYTHON had ever been set -> every static-gate job died
in "environment check" before running a single hook.
So discovery lives here now: one implementation, shared by both CI jobs and
runnable offline, and it keeps the well-known machine-wide install
locations as fallbacks.
Probe order (see the DTU_* local-tool-path plan under docs/ -- this file is
kept pure ASCII on purpose: PS 5.1 decodes BOM-less files as CP936):
1. DTU_PRECOMMIT_PYTHON -- explicit override. If it is set but the file
is missing, or it cannot satisfy the requirement, this script FAILS
with the variable name and does NOT silently fall back.
2. python on PATH
3. <repo>\.venv\Scripts\python.exe
4. well-known machine-wide installs (Program Files / ProgramData /
%LOCALAPPDATA%\Programs\Python), newest version first
.PARAMETER NeedPreCommit
Require the interpreter to expose the pre-commit module (static gates need it).
Probed with `-s` (no user site-packages) on purpose: the runner service
runs as SYSTEM, which cannot see a USER-scope site install at all, so only
an interpreter that works without user-site is accepted.
.PARAMETER WriteEnv
Append PYTHON=<path> to $env:GITHUB_ENV so later steps can use $env:PYTHON.
Written as ASCII: Out-File's PS 5.1 default is UTF-16LE, which appends
foreign-encoded lines to a file other steps also append to.
.OUTPUTS
The chosen python.exe path (single line, success stream).
.NOTES
Keep this file pure ASCII -- Windows PowerShell 5.1 decodes BOM-less files
as CP936, and non-ASCII bytes break string quoting (same trap as ci.yml).
Exit codes: 0 = found, 2 = no usable interpreter / bad DTU_* override.
#>
param(
[switch]$NeedPreCommit,
[switch]$WriteEnv
)
# Native probes write to stderr; the runner injects $ErrorActionPreference
# ='Stop', which would turn that into a terminating NativeCommandError and
# abort the probe loop before the next candidate is tried.
$ErrorActionPreference = 'Continue'
function Test-Interpreter {
param([string]$Exe, [bool]$RequirePreCommit)
if ([string]::IsNullOrWhiteSpace($Exe)) { return $false }
if (-not (Test-Path -LiteralPath $Exe -PathType Leaf)) { return $false }
$saved = $ErrorActionPreference
$ErrorActionPreference = 'Continue'
try {
if ($RequirePreCommit) {
& $Exe -s -m pre_commit --version 2>&1 | Out-Null
}
else {
& $Exe --version 2>&1 | Out-Null
}
return ($LASTEXITCODE -eq 0)
}
catch {
return $false
}
finally {
$ErrorActionPreference = $saved
}
}
$repoRoot = Split-Path -Parent $PSScriptRoot
$require = [bool]$NeedPreCommit
$what = if ($require) { 'pre-commit' } else { 'a runnable interpreter' }
# --- 1. explicit override: honour it or fail loudly -------------------------
$explicit = $env:DTU_PRECOMMIT_PYTHON
if (-not [string]::IsNullOrWhiteSpace($explicit)) {
$explicit = $explicit.Trim()
if (-not (Test-Path -LiteralPath $explicit -PathType Leaf)) {
Write-Host "::error::DTU_PRECOMMIT_PYTHON is set but does not exist: $explicit"
Write-Host '::error::fix the variable (full path to a python.exe) or unset it to use auto-discovery'
exit 2
}
if (-not (Test-Interpreter -Exe $explicit -RequirePreCommit $require)) {
Write-Host "::error::DTU_PRECOMMIT_PYTHON does not provide $what (probed without user-site, i.e. SYSTEM-visible): $explicit"
Write-Host '::error::fix the variable, or unset it to use auto-discovery'
exit 2
}
Write-Host "using python (DTU_PRECOMMIT_PYTHON): $explicit"
if ($WriteEnv -and $env:GITHUB_ENV) {
"PYTHON=$explicit" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding ascii
}
Write-Output $explicit
exit 0
}
# --- 2..4 auto-discovery ----------------------------------------------------
$programFiles = $env:ProgramFiles
$programFilesX86 = ${env:ProgramFiles(x86)}
if ([string]::IsNullOrWhiteSpace($programFiles)) { $programFiles = 'C:\Program Files' }
if ([string]::IsNullOrWhiteSpace($programFilesX86)) { $programFilesX86 = 'C:\Program Files (x86)' }
$candidates = @()
$onPath = Get-Command python -ErrorAction SilentlyContinue
if ($onPath) { $candidates += $onPath.Source }
$candidates += (Join-Path $repoRoot '.venv\Scripts\python.exe')
# Newest first: a fresh install is the usual intent.
foreach ($ver in @('Python313', 'Python312', 'Python311', 'Python310')) {
$candidates += (Join-Path $programFiles "$ver\python.exe")
$candidates += (Join-Path $programFilesX86 "$ver\python.exe")
if ($env:LOCALAPPDATA) {
$candidates += (Join-Path $env:LOCALAPPDATA "Programs\Python\$ver\python.exe")
}
}
# Machine-wide distributions (these are what the runner actually had).
if ($env:ProgramData) {
foreach ($dist in @('anaconda3', 'miniconda3')) {
$candidates += (Join-Path $env:ProgramData "$dist\python.exe")
}
}
$candidates += 'C:\ProgramData\anaconda3\python.exe'
$candidates += 'C:\ProgramData\miniconda3\python.exe'
$tried = New-Object System.Collections.Generic.List[string]
$chosen = $null
foreach ($c in $candidates) {
if ([string]::IsNullOrWhiteSpace($c)) { continue }
if ($tried.Contains($c)) { continue }
$tried.Add($c) | Out-Null
if (Test-Interpreter -Exe $c -RequirePreCommit $require) { $chosen = $c; break }
}
if (-not $chosen) {
Write-Host "::error::no Python providing $what found (tried `$DTU_PRECOMMIT_PYTHON`, PATH python, repo .venv, and the well-known machine-wide installs)"
foreach ($t in $tried) { Write-Host " tried: $t" }
Write-Host '::error::note: the runner service runs as SYSTEM, so a USER-scope `pip install --user pre-commit` is invisible to it'
Write-Host '::error::fix: set a MACHINE-level DTU_PRECOMMIT_PYTHON (see scripts/ci_runner_bootstrap.ps1 -SetEnv), or install pre-commit into a machine-wide interpreter'
exit 2
}
Write-Host "using python (auto-discovered): $chosen"
# Out-Host, NOT the pipeline: a native command's stdout joins the success
# stream, which would pollute the single-line path the caller captures.
& $chosen --version 2>&1 | Out-Host
if ($require) { & $chosen -s -m pre_commit --version 2>&1 | Out-Host }
if ($WriteEnv -and $env:GITHUB_ENV) {
"PYTHON=$chosen" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding ascii
}
Write-Output $chosen
exit 0