docs: package versioned delivery artifacts

This commit is contained in:
youfak 2026-08-07 17:39:23 +08:00
parent a384fce1b0
commit bb4b205aa0
6 changed files with 190 additions and 3 deletions

View File

@ -116,7 +116,7 @@ flowchart LR
## 当前完成度
截至 **2026-08-07**,实施计划中可直接勾选的检查项为 **69 / 7592.0%**。详情见
截至 **2026-08-07**,实施计划中可直接勾选的检查项为 **70 / 7593.3%**。详情见
[实施计划](docs/development/implementation-plan.md)和
[交付完成度审计](docs/requirements/completion-audit.md)。
@ -159,8 +159,13 @@ Secret 分离管理。
```powershell
go run ./deploy/tools/configcheck deploy/config/local.yaml
./scripts/verify.ps1
./scripts/package-docs.ps1
```
`package-docs.ps1` 默认生成被忽略的 `dist/proxy-pool-docs-v1.0.zip`;包内包含 README、
`docs/`、图表、OpenAPI 和 Proto 契约,并以 `manifest.json` 记录 Git revision、文件大小和
SHA-256。可使用 `-Version vMAJOR.MINOR[.PATCH]``-OutputPath OUTPUT.zip` 生成指定交付物。
Redis、PostgreSQL 和 Controller fixture 脚本会使用 Docker 启动隔离依赖:
```powershell

View File

@ -384,7 +384,11 @@ CI 另有独立 Deployment job在占位凭据下渲染 Compose并使用 `k
reference, API guide, deployment guide, security model, testing guide, and roadmap.
- [x] Provide at least 20 validated configuration examples.
- [x] Provide at least 30 Mermaid architecture, flow, sequence, state, and failure diagrams.
- [ ] Generate `proxy-pool-docs-v1.0.zip` from versioned documentation assets.
- [x] Generate `proxy-pool-docs-v1.0.zip` from versioned documentation assets.
`scripts/package-docs.ps1` 会将 README、`docs/`、图表、OpenAPI 与 Proto 契约复制至临时目录,
生成包含 Git revision、文件大小和 SHA-256 的 `manifest.json`,再以临时 ZIP 原子替换目标。
默认输出为被 Git 忽略的 `dist/proxy-pool-docs-v1.0.zip`Go 回归测试实际执行脚本并校验归档内容。
## Task 15: Completion Audit

81
docs/package_test.go Normal file
View File

@ -0,0 +1,81 @@
package docs_test
import (
"archive/zip"
"encoding/json"
"os"
"os/exec"
"path/filepath"
"testing"
)
type docsPackageManifest struct {
Version string `json:"version"`
Revision string `json:"revision"`
Files []struct {
Path string `json:"path"`
SHA256 string `json:"sha256"`
} `json:"files"`
}
func TestPackageDocsCreatesTraceableArchive(t *testing.T) {
pwsh, err := exec.LookPath("pwsh")
if err != nil {
t.Skip("pwsh is required to exercise the documentation packaging script")
}
repositoryRoot := repositoryRoot(t)
outputPath := filepath.Join(t.TempDir(), "proxy-pool-docs-v1.0.zip")
if err := os.WriteFile(outputPath, []byte("incomplete"), 0o600); err != nil {
t.Fatalf("seed old documentation archive: %v", err)
}
command := exec.Command(pwsh, "-NoProfile", "-NonInteractive", "-File", filepath.Join(repositoryRoot, "scripts", "package-docs.ps1"), "-OutputPath", outputPath)
command.Dir = repositoryRoot
if output, err := command.CombinedOutput(); err != nil {
t.Fatalf("package docs: %v\n%s", err, output)
}
archive, err := zip.OpenReader(outputPath)
if err != nil {
t.Fatalf("open documentation archive: %v", err)
}
defer archive.Close()
entries := make(map[string]*zip.File, len(archive.File))
for _, entry := range archive.File {
entries[entry.Name] = entry
}
for _, required := range []string{
"README.md",
"docs/design/architecture.md",
"docs/operations/runbook.md",
"diagrams/README.md",
"api/openapi/proxy-pool.yaml",
"api/proto/controlplane/v1/controlplane.proto",
"manifest.json",
} {
if _, exists := entries[required]; !exists {
t.Errorf("documentation archive does not contain %s", required)
}
}
manifestEntry, exists := entries["manifest.json"]
if !exists {
return
}
reader, err := manifestEntry.Open()
if err != nil {
t.Fatalf("open manifest: %v", err)
}
defer reader.Close()
var manifest docsPackageManifest
if err := json.NewDecoder(reader).Decode(&manifest); err != nil {
t.Fatalf("decode manifest: %v", err)
}
if manifest.Version != "v1.0" || manifest.Revision == "" || len(manifest.Files) < 20 {
t.Fatalf("manifest = %+v", manifest)
}
for _, file := range manifest.Files {
if file.Path == "" || file.SHA256 == "" {
t.Fatalf("invalid manifest file = %+v", file)
}
}
}

View File

@ -11,6 +11,8 @@
- 产品设计、总体架构、项目结构、四项 ADR。
- 开发、配置、Distribution/Admin API、控制面协议、安全、测试、运维文档。
- 20 个配置场景和 35 张 Mermaid 架构/流程/状态/故障图。
- `scripts/package-docs.ps1` 可生成版本化 ZIP包含 README、文档、图表、OpenAPI、Proto
契约,以及带 Git revision 和 SHA-256 的文件清单。
### 机器契约

94
scripts/package-docs.ps1 Normal file
View File

@ -0,0 +1,94 @@
param(
[string]$Version = "v1.0",
[string]$OutputPath = ""
)
$ErrorActionPreference = "Stop"
if ([string]::IsNullOrWhiteSpace($Version) -or $Version -notmatch '^v[0-9]+(?:\.[0-9]+){1,2}$') {
throw "Version must use vMAJOR.MINOR or vMAJOR.MINOR.PATCH format"
}
$repositoryRoot = Split-Path -Parent $PSScriptRoot
if ([string]::IsNullOrWhiteSpace($OutputPath)) {
$OutputPath = Join-Path $repositoryRoot "dist/proxy-pool-docs-$Version.zip"
}
elseif (-not [System.IO.Path]::IsPathRooted($OutputPath)) {
$OutputPath = Join-Path $repositoryRoot $OutputPath
}
$OutputPath = [System.IO.Path]::GetFullPath($OutputPath)
if ([System.IO.Path]::GetExtension($OutputPath) -ne ".zip") {
throw "OutputPath must end in .zip"
}
$revision = (& git -C $repositoryRoot rev-parse --verify HEAD 2>$null).Trim()
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($revision)) {
throw "could not resolve the current Git revision"
}
$sources = @(
"README.md",
"docs",
"diagrams",
"api/openapi",
"api/proto"
)
$stagingRoot = Join-Path ([System.IO.Path]::GetTempPath()) ("proxy-pool-docs-" + [Guid]::NewGuid().ToString("N"))
$temporaryArchive = ""
try {
New-Item -ItemType Directory -Force -Path $stagingRoot | Out-Null
foreach ($relative in $sources) {
$source = Join-Path $repositoryRoot $relative
if (-not (Test-Path -LiteralPath $source)) {
throw "documentation source is missing: $relative"
}
$destination = Join-Path $stagingRoot $relative
$destinationParent = Split-Path -Parent $destination
New-Item -ItemType Directory -Force -Path $destinationParent | Out-Null
Copy-Item -LiteralPath $source -Destination $destination -Recurse -Force
}
$files = @(Get-ChildItem -LiteralPath $stagingRoot -File -Recurse | Sort-Object FullName)
if ($files.Count -eq 0) {
throw "documentation package has no files"
}
$manifestFiles = @(
foreach ($file in $files) {
[ordered]@{
path = [System.IO.Path]::GetRelativePath($stagingRoot, $file.FullName).Replace("\", "/")
sha256 = (Get-FileHash -LiteralPath $file.FullName -Algorithm SHA256).Hash.ToLowerInvariant()
bytes = $file.Length
}
}
)
[ordered]@{
package = "proxy-pool-docs"
version = $Version
revision = $revision
generatedAtUtc = [DateTime]::UtcNow.ToString("O")
files = $manifestFiles
} | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $stagingRoot "manifest.json") -Encoding utf8
$outputDirectory = Split-Path -Parent $OutputPath
New-Item -ItemType Directory -Force -Path $outputDirectory | Out-Null
$temporaryArchive = Join-Path $outputDirectory ("." + [System.IO.Path]::GetFileName($OutputPath) + "." + [Guid]::NewGuid().ToString("N") + ".tmp")
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::CreateFromDirectory(
$stagingRoot,
$temporaryArchive,
[System.IO.Compression.CompressionLevel]::Optimal,
$false
)
[System.IO.File]::Move($temporaryArchive, $OutputPath, $true)
$temporaryArchive = ""
Write-Host "documentation package: $OutputPath ($($manifestFiles.Count) files, $revision)"
}
finally {
if (-not [string]::IsNullOrWhiteSpace($temporaryArchive) -and (Test-Path -LiteralPath $temporaryArchive)) {
Remove-Item -LiteralPath $temporaryArchive -Force
}
if (Test-Path -LiteralPath $stagingRoot) {
Remove-Item -LiteralPath $stagingRoot -Recurse -Force
}
}

View File

@ -23,7 +23,8 @@
Fetch 分类、严格配置、不可变快照和本地调度参考实现
7. [已完成] 执行单元测试、静态检查、构建和静态部署/契约验证;本机因
`CGO_ENABLED=0` 且无 C 编译器未运行 race保留给 Linux CI
8. [已完成] 按需求矩阵逐项审计并生成版本化文档包
8. [已完成] 按需求矩阵逐项审计;`scripts/package-docs.ps1` 可生成带 revision 与 SHA-256
清单的版本化文档包
9. [已完成] 将 Proxy 明细、独占提取、短期幂等和 Worker 所有权统一到
TTL 活动池契约PostgreSQL 退出代理数据路径
10. [已完成] 实现生产 Redis Activity Adapter、原子 Lua、公用行为契约和