build: verify protobuf descriptors locally

This commit is contained in:
youfak 2026-07-29 22:00:27 +08:00
parent b86a729792
commit dacf48ea29
6 changed files with 68 additions and 2 deletions

View File

@ -6,6 +6,8 @@
- PostgreSQL 与 Redis 仅用于适配器集成测试,领域单测不依赖外部服务。
- 运行 `go test -race` 需要 CGO 和 C 编译器。
- Docker Compose 用于本地完整拓扑Docker 不应成为普通单测前置条件。
- Protobuf descriptor 验证需要 `protoc`;非标准安装可通过 `PROTOC_INCLUDE`
指定 Google well-known types 的 include 目录。
## 2. 开发循环
@ -59,6 +61,7 @@ go build ./...
```powershell
./scripts/verify.ps1
./scripts/verify-proto.ps1
```
审查还要确认:无 Secret 日志、无 Proxy IP 高基数标签、无默认 direct、无

View File

@ -226,7 +226,9 @@ Adapter 已通过真实 Redis 8.2 运行同一套公用契约;原子 Lua 覆
当前进度2026-07-29Distribution/Admin OpenAPI 已由 Go 测试在双平台 CI
校验本地 `$ref` 闭合、operationId 唯一、响应存在及 security scheme 引用;
完整 OAS 工具验证与 Protobuf descriptor CI 编译仍待完成。
`scripts/verify-proto.ps1` 已可复现编译包含 imports/source info 的 descriptor
并在本地存在 `protoc` 时进入完整验证;完整 OAS 工具验证与 CI 强制安装/执行
`protoc` 仍待完成。
## Task 13: Deployment and Observability

View File

@ -58,7 +58,7 @@
go test ./... PASS
go vet ./... PASS
go build ./... PASS
protoc descriptor compilation PASS
protoc descriptor compilation PASS (local script; CI enforcement pending)
docker compose config PASS
kubectl kustomize PASS
configuration examples 21/21 PASS

View File

@ -2,6 +2,9 @@
## 2026-07-29
- 新增公用 `verify-proto.ps1`:自动发现 Google well-known types include固定
编译控制面 Proto 的 imports/source-info descriptor并拒绝空输出本机生成
30,972 字节 descriptor。`verify.ps1` 在存在 protoc 时执行CI 强制安装待补。
- 新增 Distribution/Admin OpenAPI 公用 CI 结构门禁,递归验证本地 `$ref`
operationId 唯一性、HTTP operation 响应和 security scheme 引用;完整 OAS
工具验证与 Protobuf descriptor CI 编译仍保持未完成。

51
scripts/verify-proto.ps1 Normal file
View File

@ -0,0 +1,51 @@
param(
[string]$Protoc = "protoc",
[string]$IncludePath = $env:PROTOC_INCLUDE,
[string]$OutputPath = ""
)
$ErrorActionPreference = "Stop"
$repositoryRoot = Split-Path -Parent $PSScriptRoot
$protoRoot = Join-Path $repositoryRoot "api/proto"
$source = Join-Path $protoRoot "controlplane/v1/controlplane.proto"
$protocCommand = Get-Command $Protoc -ErrorAction Stop
if ([string]::IsNullOrWhiteSpace($IncludePath)) {
$installationRoot = Split-Path (Split-Path $protocCommand.Source -Parent) -Parent
$candidates = @(
(Join-Path $installationRoot "include"),
"/usr/include",
"/usr/local/include"
)
$IncludePath = $candidates |
Where-Object { Test-Path (Join-Path $_ "google/protobuf/timestamp.proto") } |
Select-Object -First 1
}
if ([string]::IsNullOrWhiteSpace($IncludePath) -or
-not (Test-Path (Join-Path $IncludePath "google/protobuf/timestamp.proto"))) {
throw "protoc well-known type include directory was not found; set PROTOC_INCLUDE"
}
if ([string]::IsNullOrWhiteSpace($OutputPath)) {
$outputDirectory = Join-Path $repositoryRoot ".tmp-proto"
New-Item -ItemType Directory -Force -Path $outputDirectory | Out-Null
$OutputPath = Join-Path $outputDirectory "controlplane.pb"
}
& $protocCommand.Source `
"--proto_path=$protoRoot" `
"--proto_path=$IncludePath" `
"--include_imports" `
"--include_source_info" `
"--descriptor_set_out=$OutputPath" `
$source
if ($LASTEXITCODE -ne 0) {
throw "protoc descriptor compilation failed with exit code $LASTEXITCODE"
}
$descriptor = Get-Item -LiteralPath $OutputPath
if ($descriptor.Length -le 0) {
throw "protoc produced an empty descriptor set"
}
Write-Host "descriptor: $($descriptor.FullName) ($($descriptor.Length) bytes)"

View File

@ -22,6 +22,13 @@ if ($unformatted) {
Invoke-Step "go vet" { go vet ./... }
Invoke-Step "unit tests" { go test -timeout 60s ./... }
if (Get-Command protoc -ErrorAction SilentlyContinue) {
Invoke-Step "protobuf descriptor" { & (Join-Path $PSScriptRoot "verify-proto.ps1") }
}
else {
Write-Host "==> protobuf descriptor skipped: protoc is not installed"
}
if ((go env CGO_ENABLED) -eq "1") {
Invoke-Step "race tests" { go test -race -timeout 60s ./internal/... }
} else {