Add Phase 0 build verification gate (T-004)
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
name: Phase 0 build gate
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
verify:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Go 1.25
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.25.0"
|
||||
cache: false
|
||||
- name: Run Phase 0 verification
|
||||
run: bash scripts/verify_phase0.sh
|
||||
@@ -45,12 +45,12 @@ SoftBox 软件盒子是一个使用 Go + Gio 开发的 Windows 桌面客户端,
|
||||
|
||||
## 当前阶段
|
||||
|
||||
当前项目处于:**MVP 起步(Phase 0 工程骨架建设中)**。
|
||||
当前项目处于:**M1 已完成(Phase 0 工程骨架、双 Gio 窗口与双目标编译闸门已建立),准备进入 Phase 1 高风险原型**。
|
||||
|
||||
优先路径:
|
||||
|
||||
1. Phase 0:monorepo 骨架 + 双目标编译 + 空 Gio 窗口。
|
||||
2. Phase 1:三大高风险原型(清单验签、ZIP 安全解压、原子切换回滚)。
|
||||
1. 已完成 Phase 0:monorepo 骨架 + 双目标编译 + 空 Gio 窗口。
|
||||
2. 下一步 Phase 1:三大高风险原型(清单验签、ZIP 安全解压、原子切换回滚)。
|
||||
3. Phase 2-3:清单/列表 → 下载/安装。
|
||||
4. Phase 4-5:启动/更新/自更新 → 授权。
|
||||
5. Phase 6:Win7 加固与双通道发布。
|
||||
@@ -133,17 +133,17 @@ MVP 不做:
|
||||
|
||||
## 验证命令
|
||||
|
||||
统一启动与验证入口收敛到根目录 `./init.sh` / `./init.ps1`;脚本会同步工作区依赖并运行 core 基础验证。标准命令:
|
||||
统一启动与验证入口收敛到根目录 `./init.sh` / `./init.ps1`;脚本会同步工作区依赖并运行完整 Phase 0 闸门。也可直接运行 `bash scripts/verify_phase0.sh` / `./scripts/verify_phase0.ps1`。标准分项命令:
|
||||
|
||||
```bash
|
||||
# core 测试(Linux 无头可跑)
|
||||
cd core && go vet ./... && go test -count=1 ./...
|
||||
|
||||
# 现代版构建
|
||||
cd app-modern && GOTOOLCHAIN=go1.25.0 GOOS=windows GOARCH=amd64 go build ./cmd/softbox
|
||||
cd app-modern && GOTOOLCHAIN=go1.25.0 CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags="-H=windowsgui" ./cmd/softbox
|
||||
|
||||
# Win7 版构建(强制 Go 1.20)
|
||||
cd app-win7 && GOTOOLCHAIN=go1.20.14 GOOS=windows GOARCH=amd64 go build ./cmd/softbox
|
||||
cd app-win7 && GOTOOLCHAIN=go1.20.14 CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags="-H=windowsgui" ./cmd/softbox
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
| Windows API | golang.org/x/sys/windows + 动态加载(LoadLibrary) | 已定 | Win10 专属 API 动态加载并降级,不进导入表 |
|
||||
| EXE 签名 | Authenticode | 已定 | 主程序与 Updater 均签名;证书采购待确认 |
|
||||
| 测试 | go test(core 无头可测) + fake/stub 注入 | 已定 | domain/application 不依赖 Gio 与 Windows API |
|
||||
| CI | 待定(Gitea Actions 或本地脚本) | 待定 | 需同时编译 modern 与 win7 双目标 |
|
||||
| CI | Gitea Actions 模板 + 本地 Phase 0 脚本 | 部分已定 | `.gitea/workflows/phase0-build.yml` 复用本地入口;远端 runner 可用性待确认 |
|
||||
| 静态检查 | go vet(+ 待定 golangci-lint) | 部分已定 | vet 必跑;lint 工具后续确认 |
|
||||
|
||||
## 二、决策记录与演进
|
||||
@@ -37,13 +37,15 @@
|
||||
|
||||
> 工程骨架由 T-001 建立;根目录 `init.sh`/`init.ps1` 统一执行依赖同步与 core 基础验证,并打印双目标构建命令。
|
||||
|
||||
| 用途 | 命令(计划) |
|
||||
| 用途 | 命令 |
|
||||
| --- | --- |
|
||||
| Phase 0 完整闸门(Unix) | `bash scripts/verify_phase0.sh` |
|
||||
| Phase 0 完整闸门(Windows) | `./scripts/verify_phase0.ps1` |
|
||||
| 同步工作区依赖 | `go work sync` |
|
||||
| core 测试 | `cd core && go test -count=1 ./...` |
|
||||
| core 静态检查 | `cd core && go vet ./...` |
|
||||
| 现代版构建 | `cd app-modern && GOTOOLCHAIN=go1.25.0 GOOS=windows GOARCH=amd64 go build -o ../dist/SoftBox.exe ./cmd/softbox` |
|
||||
| Win7 版构建 | `cd app-win7 && GOTOOLCHAIN=go1.20.14 GOOS=windows GOARCH=amd64 go build -o ../dist/SoftBox-win7.exe ./cmd/softbox` |
|
||||
| 现代版构建 | `cd app-modern && GOTOOLCHAIN=go1.25.0 CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags="-H=windowsgui" -o ../dist/SoftBox.exe ./cmd/softbox` |
|
||||
| Win7 版构建 | `cd app-win7 && GOTOOLCHAIN=go1.20.14 CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags="-H=windowsgui" -o ../dist/SoftBox-win7.exe ./cmd/softbox` |
|
||||
| 本地运行(开发) | Windows 下直接 `go run ./cmd/softbox`(WSL 中构建 EXE 后到 Windows 侧运行) |
|
||||
|
||||
根 `go.work` 纳入三个模块并使用 modern 所需的 Go 1.25 workspace 版本;`app-win7/go.work` 是就近的 Go 1.20 workspace,只纳入 `app-win7` 与 `core`,确保 Go 1.20.14 不需要解析 modern 模块。
|
||||
|
||||
+12
-15
@@ -13,15 +13,15 @@
|
||||
## 当前快照
|
||||
|
||||
- 日期:2026-07-16
|
||||
- 阶段:MVP 起步(Phase 0 工程骨架建设中)
|
||||
- 阶段:M1 已完成(Phase 0 工程骨架、状态/事件模型、双 Gio 窗口、平台 stub 与双目标验证闸门全部落地)
|
||||
- 技术栈:根 Go workspace 纳入 core/app-modern/app-win7 三模块;`app-win7/go.work` 隔离 Go 1.20.14 构建;modern Gio v0.10.1 与 win7 Gio v0.6.0 已实际接入
|
||||
- 生产代码:core 已有状态模型与事件 runtime;modern/win7 均可打开最小 AppShell,并有平台接口、Windows 实现与非 Windows stub
|
||||
- 测试:core 覆盖状态/事件 runtime;两个 app 覆盖 AppShell 布局尺寸与平台 stub 契约
|
||||
- 测试:core 覆盖状态/事件 runtime;两个 app 覆盖 AppShell 布局尺寸与平台 stub 契约;Phase 0 脚本统一执行全部验证
|
||||
- 数据:无;Catalog 清单与测试样例待建
|
||||
- 标准启动路径:`./init.sh` / `./init.ps1`(同步依赖、验证 core、打印 modern/win7 双目标构建命令)
|
||||
- 标准验证路径:`go -C core vet ./...` + `go -C core test -count=1 ./...`;双目标构建命令见下文
|
||||
- 标准启动路径:`./init.sh` / `./init.ps1`(同步依赖、执行完整 Phase 0 闸门、打印双目标构建命令)
|
||||
- 标准验证路径:`bash scripts/verify_phase0.sh` / `./scripts/verify_phase0.ps1`
|
||||
- 版本管理:git 已初始化,main 分支,远端 origin 为 Gitea `opc/soft_quay`;harness 文档已提交
|
||||
- 当前 blocker:无;下一步按路线图落成并领取 T-004
|
||||
- 当前 blocker:无;下一步按路线图落成并领取 T-101
|
||||
|
||||
## 当前目录要点
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
| --- | --- | --- |
|
||||
| `docs/` | 已有 | harness coding 文档集(本次初始化完成) |
|
||||
| `docs/tasks/` | 已有 | 任务目录;T-001 已完成,T-002 待按路线图落成 |
|
||||
| `scripts/` | 已有 | harness 治理脚本 + `check_core_boundaries.py`;Phase 0 构建闸门待 T-004 |
|
||||
| `scripts/` | 已有 | harness 治理、core 边界、Go 版本检查与 Phase 0 双平台验证入口 |
|
||||
| `core/` | 已建 | Go 1.20 兼容共享模块;已有 domain 状态模型与 application 事件 runtime |
|
||||
| `app-modern/` | 已建 | Go 1.25.0 + Gio v0.10.1;可打开 Modern AppShell |
|
||||
| `app-win7/` | 已建 | Go 1.20 + Gio v0.6.0;可打开带 Legacy 标识的 AppShell |
|
||||
@@ -40,23 +40,20 @@
|
||||
|
||||
任务状态以 `docs/tasks/` 各任务文件 frontmatter 的 `status` 为准。本节只写项目级摘要:
|
||||
|
||||
- 已完成:`T-001 初始化 monorepo 骨架`、`T-002 建立 domain 状态模型与事件总线`、`T-003 Gio 空窗口 + 平台层 stub`。
|
||||
- 已完成:Phase 0 的 `T-001`、`T-002`、`T-003`、`T-004`。
|
||||
- 正在进行:无。
|
||||
- 下一个可领取任务:按路线图落成并领取 `T-004 CI 双目标编译闸门`。
|
||||
- 下一个可领取任务:按路线图落成并领取 `T-101 签名清单验签与缓存回退原型`。
|
||||
|
||||
## 当前可运行内容
|
||||
|
||||
```bash
|
||||
# 统一依赖同步 + core 验证:
|
||||
# 统一依赖同步 + 完整 Phase 0 验证:
|
||||
./init.sh
|
||||
# Windows PowerShell 使用 ./init.ps1
|
||||
|
||||
# 独立验证:
|
||||
go -C core vet ./...
|
||||
go -C core test -count=1 ./...
|
||||
python scripts/check_core_boundaries.py
|
||||
GOTOOLCHAIN=go1.25.0 GOOS=windows GOARCH=amd64 go -C app-modern build ./cmd/softbox
|
||||
GOTOOLCHAIN=go1.20.14 GOOS=windows GOARCH=amd64 go -C app-win7 build ./cmd/softbox
|
||||
# 直接运行验证闸门:
|
||||
bash scripts/verify_phase0.sh
|
||||
# Windows PowerShell 使用 ./scripts/verify_phase0.ps1
|
||||
```
|
||||
|
||||
## 开始编码前检查
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
id: T-004
|
||||
title: 建立 Phase 0 双目标编译与依赖版本闸门
|
||||
phase: 0
|
||||
deps: [T-001]
|
||||
status: DONE
|
||||
created: 2026-07-16
|
||||
issue: null
|
||||
context_ref: 6f920eb4578c17c0962b6e593177cd2a3ca57f1b
|
||||
claim_branch: null
|
||||
work_branch: agent/codex/T-004
|
||||
write_paths:
|
||||
- docs/tasks/T-004.md
|
||||
- scripts/check_go_versions.py
|
||||
- scripts/verify_phase0.ps1
|
||||
- scripts/verify_phase0.sh
|
||||
- .gitea/workflows/phase0-build.yml
|
||||
- init.ps1
|
||||
- init.sh
|
||||
- docs/00-ai-start-here.md
|
||||
- docs/03-tech-stack.md
|
||||
- docs/current-state.md
|
||||
---
|
||||
|
||||
## 问题 / 背景
|
||||
|
||||
Phase 0 已有可编译骨架、core 状态/事件模型和两个 Gio 窗口,但验证命令仍分散在文档与人工操作中。需要一个可重复执行的本地/CI 闸门,防止 modern、Win7 或 core 兼容性在后续任务中悄然破坏。
|
||||
|
||||
## 方案
|
||||
|
||||
1. 新增 Windows PowerShell 与 Unix shell 两个等价入口,统一运行治理检查、core 边界检查、Go 1.20 core vet/test、modern UI/platform 测试与构建、win7 UI/platform 测试与构建。
|
||||
2. 新增 Python 标准库依赖版本检查:校验 go/workspace 指令与 Gio 锁定版本,并用 Go 1.20.14 的 `go list -m -json all` 拒绝 core/win7 依赖声明 Go 1.21+。
|
||||
3. Windows 构建统一使用 `CGO_ENABLED=0`、`-trimpath` 与 Windows GUI subsystem linker flag。
|
||||
4. 根 init 脚本的 VERIFY 命令改为调用 Phase 0 闸门。
|
||||
5. 新增 Gitea Actions workflow 模板,在 push/PR 使用同一 Unix 验证入口;runner 未启用时以本地同命令为验收证据。
|
||||
|
||||
## 验收要点
|
||||
|
||||
- `scripts/verify_phase0.ps1` 在当前 Windows 环境全绿。
|
||||
- Git Bash `scripts/verify_phase0.sh` 在当前环境全绿。
|
||||
- 闸门包含 core vet/test、core 边界、modern 构建、win7 Go 1.20.14 构建、UI/platform 测试和治理检查。
|
||||
- 版本检查能拒绝 core/win7 的 Go 1.21+ 模块,并验证 Gio v0.10.1/v0.6.0 锁定。
|
||||
- `.gitea/workflows/phase0-build.yml` 只读权限、关闭 checkout 凭据持久化,调用同一本地入口。
|
||||
- `./init.ps1` 与 Git Bash `./init.sh` 通过新的完整 VERIFY 路径。
|
||||
|
||||
## 边界(不改什么)
|
||||
|
||||
- 不启用或配置远端 runner,不宣称远端 CI 已运行。
|
||||
- 不升级 Go、Gio 或其他依赖版本。
|
||||
- 不实现 Phase 1 业务功能。
|
||||
- 不写入密钥、token 或真实发布配置。
|
||||
|
||||
## 协作约束
|
||||
|
||||
未启用 Gitea;本任务在 `agent/codex/T-004` 分支串行执行。CI 与本地必须复用同一脚本,不得维护两套不同验证逻辑。
|
||||
|
||||
## 执行记录
|
||||
|
||||
- 2026-07-16:新增 `scripts/verify_phase0.ps1` 与 `scripts/verify_phase0.sh`,统一运行治理、core 边界、Go 1.20 core vet/test、modern/win7 adapter 测试与双目标 GUI 构建。
|
||||
- 2026-07-16:新增 `scripts/check_go_versions.py`,校验 root/core/modern/win7 的 go 指令与 Gio 锁定版本,并强制使用 Go 1.20.14 扫描 core/win7 完整模块图。
|
||||
- 2026-07-16:版本检查确认 13 个模块记录均声明 Go 1.20 或更低;内置 self-check 明确接受 1.20、拒绝 1.21。
|
||||
- 2026-07-16:Windows 构建统一使用 `CGO_ENABLED=0`、`-trimpath`、`-H=windowsgui`;根 init 脚本 VERIFY 已切换到完整 Phase 0 闸门。
|
||||
- 2026-07-16:新增 `.gitea/workflows/phase0-build.yml`,使用只读权限、禁用 checkout 凭据持久化并复用 Unix 本地入口。远端 runner 未启用/未验证,不宣称远端 CI 已跑绿。
|
||||
- 验证通过:`./scripts/verify_phase0.ps1`。
|
||||
- 验证通过:Git Bash `bash scripts/verify_phase0.sh`。
|
||||
- 验证通过:`./init.ps1` 与 Git Bash `./init.sh`,均执行完整 Phase 0 闸门。
|
||||
- 验证结果:core Go 1.20.14 vet/test、modern Go 1.25.0 Windows amd64 GUI 构建、win7 Go 1.20.14 Windows amd64 GUI 构建、两个 adapter 测试、治理与边界检查全部通过。
|
||||
@@ -7,11 +7,14 @@
|
||||
# 三个命令是仓库统一入口;换工具链时同步更新文档与这里。
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$Utf8 = [System.Text.UTF8Encoding]::new($false)
|
||||
[Console]::OutputEncoding = $Utf8
|
||||
$OutputEncoding = $Utf8
|
||||
Set-Location -Path $PSScriptRoot
|
||||
|
||||
$InstallCmd = "go work sync"
|
||||
$VerifyCmd = 'go -C core vet ./...; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }; go -C core test -count=1 ./...'
|
||||
$StartCmd = '$env:GOTOOLCHAIN="go1.25.0"; $env:GOOS="windows"; $env:GOARCH="amd64"; go build -C app-modern -o ../dist/SoftBox.exe ./cmd/softbox; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }; $env:GOTOOLCHAIN="go1.20.14"; go build -C app-win7 -o ../dist/SoftBox-win7.exe ./cmd/softbox'
|
||||
$VerifyCmd = "./scripts/verify_phase0.ps1"
|
||||
$StartCmd = '$env:CGO_ENABLED="0"; $env:GOOS="windows"; $env:GOARCH="amd64"; $env:GOTOOLCHAIN="go1.25.0"; go build -C app-modern -trimpath "-ldflags=-H=windowsgui" -o ../dist/SoftBox.exe ./cmd/softbox; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }; $env:GOTOOLCHAIN="go1.20.14"; go build -C app-win7 -trimpath "-ldflags=-H=windowsgui" -o ../dist/SoftBox-win7.exe ./cmd/softbox'
|
||||
|
||||
Write-Host "==> 当前目录: $($PWD.Path)"
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
INSTALL_CMD="go work sync"
|
||||
VERIFY_CMD="go -C core vet ./... && go -C core test -count=1 ./..."
|
||||
START_CMD="GOTOOLCHAIN=go1.25.0 GOOS=windows GOARCH=amd64 go -C app-modern build -o ../dist/SoftBox.exe ./cmd/softbox && GOTOOLCHAIN=go1.20.14 GOOS=windows GOARCH=amd64 go -C app-win7 build -o ../dist/SoftBox-win7.exe ./cmd/softbox"
|
||||
VERIFY_CMD="bash scripts/verify_phase0.sh"
|
||||
START_CMD="GOTOOLCHAIN=go1.25.0 CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go -C app-modern build -trimpath -ldflags=-H=windowsgui -o ../dist/SoftBox.exe ./cmd/softbox && GOTOOLCHAIN=go1.20.14 CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go -C app-win7 build -trimpath -ldflags=-H=windowsgui -o ../dist/SoftBox-win7.exe ./cmd/softbox"
|
||||
|
||||
echo "==> 当前目录: $PWD"
|
||||
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate toolchain pins and Go 1.20 compatibility of core/win7 modules."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
MAX_LEGACY_GO_VERSION = (1, 20)
|
||||
|
||||
|
||||
def version_tuple(value):
|
||||
match = re.fullmatch(r"(\d+)\.(\d+)(?:\.(\d+))?", value)
|
||||
if not match:
|
||||
raise ValueError("invalid Go version {!r}".format(value))
|
||||
return tuple(int(part or 0) for part in match.groups())
|
||||
|
||||
|
||||
def decode_json_stream(text):
|
||||
decoder = json.JSONDecoder()
|
||||
index = 0
|
||||
while index < len(text):
|
||||
while index < len(text) and text[index].isspace():
|
||||
index += 1
|
||||
if index >= len(text):
|
||||
return
|
||||
value, index = decoder.raw_decode(text, index)
|
||||
yield value
|
||||
|
||||
|
||||
def read_text(path):
|
||||
return path.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def go_directive(path):
|
||||
match = re.search(r"(?m)^go\s+(\d+\.\d+(?:\.\d+)?)\s*$", read_text(path))
|
||||
if not match:
|
||||
raise ValueError("{} has no go directive".format(path))
|
||||
return match.group(1)
|
||||
|
||||
|
||||
def required_version(path, module_path):
|
||||
pattern = r"(?m)^\s*{}\s+(v[^\s]+)".format(re.escape(module_path))
|
||||
match = re.search(pattern, read_text(path))
|
||||
if not match:
|
||||
raise ValueError(
|
||||
"{} does not require {}".format(path, module_path)
|
||||
)
|
||||
return match.group(1)
|
||||
|
||||
|
||||
def run_go(repo_root, cwd, arguments, go_work):
|
||||
environment = os.environ.copy()
|
||||
environment["GOWORK"] = str(go_work) if go_work else "off"
|
||||
result = subprocess.run(
|
||||
["go"] + arguments,
|
||||
cwd=str(cwd),
|
||||
env=environment,
|
||||
check=False,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
universal_newlines=True,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print(result.stderr, file=sys.stderr, end="")
|
||||
raise SystemExit(result.returncode)
|
||||
return result.stdout
|
||||
|
||||
|
||||
def validate_pins(repo_root):
|
||||
expected_go_directives = {
|
||||
repo_root / "go.work": "1.25.0",
|
||||
repo_root / "core" / "go.mod": "1.20",
|
||||
repo_root / "app-modern" / "go.mod": "1.25.0",
|
||||
repo_root / "app-win7" / "go.mod": "1.20",
|
||||
repo_root / "app-win7" / "go.work": "1.20",
|
||||
}
|
||||
violations = []
|
||||
|
||||
for path, expected in expected_go_directives.items():
|
||||
actual = go_directive(path)
|
||||
if actual != expected:
|
||||
violations.append(
|
||||
"{} go directive is {}, want {}".format(
|
||||
path.relative_to(repo_root), actual, expected
|
||||
)
|
||||
)
|
||||
|
||||
gio_pins = {
|
||||
repo_root / "app-modern" / "go.mod": "v0.10.1",
|
||||
repo_root / "app-win7" / "go.mod": "v0.6.0",
|
||||
}
|
||||
for path, expected in gio_pins.items():
|
||||
actual = required_version(path, "gioui.org")
|
||||
if actual != expected:
|
||||
violations.append(
|
||||
"{} pins gioui.org {}, want {}".format(
|
||||
path.relative_to(repo_root), actual, expected
|
||||
)
|
||||
)
|
||||
|
||||
return violations
|
||||
|
||||
|
||||
def validate_go20_toolchain(repo_root):
|
||||
output = run_go(repo_root, repo_root, ["version"], None).strip()
|
||||
if "go1.20.14" not in output:
|
||||
return ["compatibility scan uses {!r}, want go1.20.14".format(output)]
|
||||
return []
|
||||
|
||||
|
||||
def validate_module_versions(repo_root):
|
||||
module_sets = (
|
||||
("core", repo_root / "core", None),
|
||||
(
|
||||
"win7",
|
||||
repo_root / "app-win7",
|
||||
repo_root / "app-win7" / "go.work",
|
||||
),
|
||||
)
|
||||
violations = []
|
||||
checked = 0
|
||||
|
||||
for label, cwd, go_work in module_sets:
|
||||
output = run_go(
|
||||
repo_root,
|
||||
cwd,
|
||||
["list", "-m", "-json", "all"],
|
||||
go_work,
|
||||
)
|
||||
for module in decode_json_stream(output):
|
||||
checked += 1
|
||||
go_version = module.get("GoVersion")
|
||||
if not go_version:
|
||||
continue
|
||||
if version_tuple(go_version)[:2] > MAX_LEGACY_GO_VERSION:
|
||||
violations.append(
|
||||
"{} module {} declares go {}, exceeds 1.20".format(
|
||||
label, module["Path"], go_version
|
||||
)
|
||||
)
|
||||
|
||||
return violations, checked
|
||||
|
||||
|
||||
def self_check():
|
||||
if version_tuple("1.20")[:2] > MAX_LEGACY_GO_VERSION:
|
||||
raise AssertionError("Go 1.20 should be accepted")
|
||||
if version_tuple("1.20.14")[:2] > MAX_LEGACY_GO_VERSION:
|
||||
raise AssertionError("Go 1.20.14 should be accepted")
|
||||
if not version_tuple("1.21")[:2] > MAX_LEGACY_GO_VERSION:
|
||||
raise AssertionError("Go 1.21 should be rejected")
|
||||
|
||||
|
||||
def main():
|
||||
self_check()
|
||||
repo_root = pathlib.Path(__file__).resolve().parents[1]
|
||||
violations = validate_pins(repo_root)
|
||||
violations.extend(validate_go20_toolchain(repo_root))
|
||||
module_violations, checked = validate_module_versions(repo_root)
|
||||
violations.extend(module_violations)
|
||||
|
||||
if violations:
|
||||
for violation in violations:
|
||||
print("ERROR: " + violation, file=sys.stderr)
|
||||
raise SystemExit(1)
|
||||
|
||||
print(
|
||||
"Go version check passed: pins valid; {} module records are Go 1.20-compatible.".format(
|
||||
checked
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env pwsh
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$Utf8 = [System.Text.UTF8Encoding]::new($false)
|
||||
[Console]::OutputEncoding = $Utf8
|
||||
$OutputEncoding = $Utf8
|
||||
$Root = Split-Path -Parent $PSScriptRoot
|
||||
Set-Location -Path $Root
|
||||
|
||||
function Assert-NativeSuccess {
|
||||
param([string]$Step)
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "$Step failed with exit code $LASTEXITCODE"
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-Step {
|
||||
param(
|
||||
[string]$Name,
|
||||
[scriptblock]$Command
|
||||
)
|
||||
Write-Host "==> $Name"
|
||||
& $Command
|
||||
Assert-NativeSuccess -Step $Name
|
||||
}
|
||||
|
||||
$GoPath = (& go env GOPATH).Trim()
|
||||
Assert-NativeSuccess -Step "Locate GOPATH"
|
||||
$GoBin = Join-Path $GoPath "bin"
|
||||
if (Test-Path (Join-Path $GoBin "go1.20.14.exe")) {
|
||||
$env:PATH = "$GoBin;$env:PATH"
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory -Force -Path (Join-Path $Root "dist") | Out-Null
|
||||
|
||||
Invoke-Step "Sync root workspace" {
|
||||
$env:GOTOOLCHAIN = "go1.25.0"
|
||||
Remove-Item Env:GOWORK -ErrorAction SilentlyContinue
|
||||
go work sync
|
||||
}
|
||||
|
||||
Invoke-Step "Validate harness governance" {
|
||||
python scripts/validate_agent_context.py
|
||||
Assert-NativeSuccess -Step "Validate agent context"
|
||||
python -m unittest discover -s tests -p "test_*.py"
|
||||
Assert-NativeSuccess -Step "Run governance tests"
|
||||
python scripts/validate_harness_governance.py
|
||||
}
|
||||
|
||||
Invoke-Step "Validate core architecture boundary" {
|
||||
python scripts/check_core_boundaries.py --self-test
|
||||
Assert-NativeSuccess -Step "Self-test core boundary matcher"
|
||||
python scripts/check_core_boundaries.py
|
||||
}
|
||||
|
||||
Invoke-Step "Validate Go and dependency pins" {
|
||||
$env:GOTOOLCHAIN = "go1.20.14"
|
||||
python scripts/check_go_versions.py
|
||||
}
|
||||
|
||||
Invoke-Step "Vet and test core with Go 1.20.14" {
|
||||
$env:GOTOOLCHAIN = "go1.20.14"
|
||||
$env:GOWORK = "off"
|
||||
go -C core vet ./...
|
||||
Assert-NativeSuccess -Step "Vet core"
|
||||
go -C core test -count=1 ./...
|
||||
}
|
||||
|
||||
Invoke-Step "Test and build modern target with Go 1.25.0" {
|
||||
$env:GOTOOLCHAIN = "go1.25.0"
|
||||
$env:GOWORK = (Resolve-Path "go.work").Path
|
||||
Remove-Item Env:GOOS -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:GOARCH -ErrorAction SilentlyContinue
|
||||
$env:CGO_ENABLED = "0"
|
||||
go -C app-modern test -count=1 ./ui/gio ./platform/windows
|
||||
Assert-NativeSuccess -Step "Test modern adapters"
|
||||
$env:GOOS = "windows"
|
||||
$env:GOARCH = "amd64"
|
||||
go -C app-modern build -trimpath "-ldflags=-H=windowsgui" -o ../dist/SoftBox.exe ./cmd/softbox
|
||||
}
|
||||
|
||||
Invoke-Step "Test and build Win7 target with Go 1.20.14" {
|
||||
$env:GOTOOLCHAIN = "go1.20.14"
|
||||
$env:GOWORK = (Resolve-Path "app-win7/go.work").Path
|
||||
Remove-Item Env:GOOS -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:GOARCH -ErrorAction SilentlyContinue
|
||||
$env:CGO_ENABLED = "0"
|
||||
go -C app-win7 test -count=1 ./ui/gio ./platform/windows
|
||||
Assert-NativeSuccess -Step "Test Win7 adapters"
|
||||
$env:GOOS = "windows"
|
||||
$env:GOARCH = "amd64"
|
||||
go -C app-win7 build -trimpath "-ldflags=-H=windowsgui" -o ../dist/SoftBox-win7.exe ./cmd/softbox
|
||||
}
|
||||
|
||||
Write-Host "Phase 0 verification passed."
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
if python3 --version >/dev/null 2>&1; then
|
||||
PYTHON=python3
|
||||
elif python --version >/dev/null 2>&1; then
|
||||
PYTHON=python
|
||||
else
|
||||
echo "ERROR: Python 3 is required." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
GO_PATH="$(go env GOPATH)"
|
||||
if command -v cygpath >/dev/null 2>&1; then
|
||||
GO_PATH="$(cygpath -u "$GO_PATH")"
|
||||
fi
|
||||
GO_BIN="$GO_PATH/bin"
|
||||
if [ -x "$GO_BIN/go1.20.14" ] || [ -x "$GO_BIN/go1.20.14.exe" ]; then
|
||||
export PATH="$GO_BIN:$PATH"
|
||||
fi
|
||||
|
||||
mkdir -p dist
|
||||
|
||||
echo "==> Sync root workspace"
|
||||
GOTOOLCHAIN=go1.25.0 go work sync
|
||||
|
||||
echo "==> Validate harness governance"
|
||||
"$PYTHON" scripts/validate_agent_context.py
|
||||
"$PYTHON" -m unittest discover -s tests -p "test_*.py"
|
||||
"$PYTHON" scripts/validate_harness_governance.py
|
||||
|
||||
echo "==> Validate core architecture boundary"
|
||||
"$PYTHON" scripts/check_core_boundaries.py --self-test
|
||||
"$PYTHON" scripts/check_core_boundaries.py
|
||||
|
||||
echo "==> Validate Go and dependency pins"
|
||||
GOTOOLCHAIN=go1.20.14 "$PYTHON" scripts/check_go_versions.py
|
||||
|
||||
echo "==> Vet and test core with Go 1.20.14"
|
||||
GOTOOLCHAIN=go1.20.14 GOWORK=off go -C core vet ./...
|
||||
GOTOOLCHAIN=go1.20.14 GOWORK=off go -C core test -count=1 ./...
|
||||
|
||||
echo "==> Test and build modern target with Go 1.25.0"
|
||||
GOTOOLCHAIN=go1.25.0 GOWORK="$ROOT_DIR/go.work" CGO_ENABLED=0 \
|
||||
go -C app-modern test -count=1 ./ui/gio ./platform/windows
|
||||
GOTOOLCHAIN=go1.25.0 GOWORK="$ROOT_DIR/go.work" CGO_ENABLED=0 \
|
||||
GOOS=windows GOARCH=amd64 \
|
||||
go -C app-modern build -trimpath -ldflags="-H=windowsgui" \
|
||||
-o ../dist/SoftBox.exe ./cmd/softbox
|
||||
|
||||
echo "==> Test and build Win7 target with Go 1.20.14"
|
||||
GOTOOLCHAIN=go1.20.14 GOWORK="$ROOT_DIR/app-win7/go.work" CGO_ENABLED=0 \
|
||||
go -C app-win7 test -count=1 ./ui/gio ./platform/windows
|
||||
GOTOOLCHAIN=go1.20.14 GOWORK="$ROOT_DIR/app-win7/go.work" CGO_ENABLED=0 \
|
||||
GOOS=windows GOARCH=amd64 \
|
||||
go -C app-win7 build -trimpath -ldflags="-H=windowsgui" \
|
||||
-o ../dist/SoftBox-win7.exe ./cmd/softbox
|
||||
|
||||
echo "Phase 0 verification passed."
|
||||
Reference in New Issue
Block a user