fix(ci): unblock Windows main-v2 full suite before v1.23.0 / 修复 Windows 全量 CI 以便发布 v1.23.0 (#8255)

* fix(ci): unblock Windows main-v2 full suite before v1.23.0

Problem
main-v2 push CI has a red Windows streak that blocks Stable tagging:
internal/agent, internal/boot, and internal/control hit the 3m package
timeout on loaded runners, sessioninbox asserted Unix 0700 modes on
Windows (reports 0777), and cold PowerShell hooks timed out at 60s.

Root cause
The PR smoke suite was already raised to 8m after measured 2.2x runner
variance, but the full push suite still used -timeout=3m with a 10m step
budget. Session-inbox permission checks did not gate on GOOS. Nested
PowerShell spawn shared the default 60s real-spawn budget under -p 4.

Fix
- Raise Windows full push suite to -timeout=8m and timeout-minutes: 20.
- Gate session-inbox directory mode assertion to non-Windows.
- Allow 2m for the nested PowerShell hook spawn under Windows load.

Verification
- go test ./internal/sessioninbox/ -count=1
- GOOS=windows go test -c ./internal/hook/

* fix(sessioninbox): keep store_test under repolint file-size ceiling

Problem
The Windows mode-gate edit pushed store_test.go to 801 lines and failed
repolint test-file-size (800-line ceiling).

Root cause
Extra comment lines around the GOOS permission assertion.

Fix
Collapse the comment to one line so the file stays at 800 lines.

Verification
go run ./tools/repolint

* fix(hook): clamp the Windows hook spawn timeout with max (modernize)

Problem
CI lint (golangci-lint v2.12.2, GOOS=windows leg) fails the Windows hook
test: the manual min clamp is flagged by the modernize linter
(minmax: use max).

Root cause
The 2m floor for the real-spawn budget was written as an if-statement
instead of the max builtin.

Fix
Replace the if/assign pair with max(realSpawnTimeout, 2*time.Minute).

Verification
- GOOS=windows golangci-lint run --timeout=5m ./internal/hook/...: 0 issues
- make lint (CI pin v2.12.2): 0 issues, repolint clean
- go test ./internal/hook/ -count=1: ok
This commit is contained in:
SivanCola authored and GitHub committed 2026-08-11 02:28:29 +08:00
1 parent 397ed30ec8
commit c1a3af4c99
3 files changed
+22 -10

No files matched your search

+7 -2
View File
@@ -171,9 +171,14 @@ jobs:
timeout-minutes: 5
run: go test -timeout=3m -run '^TestBashPowerShellExecuteDetailedContract$|^TestBashPowerShell51PreflightRejectsAndAndDetailed$|^TestBashPowerShellOutputIsUTF8$|^TestBashPowerShellSurfacesNonZeroExit$|^TestBashPowerShellRejectsChaining$' ./internal/tool/builtin
# Full push suite still uses the same 8m package budget as Windows smoke:
# agent/boot/control already hit 180s package timeouts under runner load,
# so 3m fails on slow machines without a code regression. Keep the step
# above normal full-suite wall time (~8-12m) so a hang still dies on the
# job budget rather than a false package timeout.
- name: test (full)
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name != 'pull_request'
timeout-minutes: 10
timeout-minutes: 20
env:
# Run the prompt-cache prefix-stability guard (TestCacheHit*) in CI: a
# regression there silently tanks the cache hit rate the project is
@@ -182,7 +187,7 @@ jobs:
# Bound sandbox helper children in Windows tests so a failed OS-level
# launch cannot pin the Actions step after Go's package timeout fires.
WINDOWS_SANDBOX_WAIT_MS: "20000"
run: go test -p 4 -timeout=3m ./...
run: go test -p 4 -timeout=8m ./...
- name: test (Scoop desktop launch)
if: env.RUN_STEPS == 'true' && runner.os == 'Windows'
+6 -1
View File
@@ -8,6 +8,7 @@ import (
"path/filepath"
"strings"
"testing"
"time"
"reasonix/internal/pluginpkg"
"reasonix/internal/sandbox"
@@ -210,11 +211,15 @@ func TestDefaultSpawnerRunsCompoundCmdShellHook(t *testing.T) {
}
func TestDefaultSpawnerRunsPowerShellHookWithNestedQuotes(t *testing.T) {
// Cold PowerShell start under the Windows full suite (-p 4) can exceed the
// default 60s real-spawn budget when the runner is already hot from
// agent/boot/control packages. Keep the assertion, give the host longer.
timeout := max(realSpawnTimeout, 2*time.Minute)
result := DefaultSpawner(context.Background(), SpawnInput{
Command: `$items = @("a b", "c'd", 'e"f', "中文", "🧪"); Write-Output ($items -join "|")`,
Mode: ExecutionShell,
Shell: "powershell",
Timeout: realSpawnTimeout,
Timeout: timeout,
})
if result.ExitCode != 0 || result.SpawnErr != nil {
t.Fatalf("PowerShell hook failed: %+v", result)
+9 -7
View File
@@ -56,13 +56,15 @@ func TestEnqueueSnapshotAndRead(t *testing.T) {
if meta.ID != rec.ItemID || env.SubmitText != "hello world" {
t.Fatalf("read = meta=%+v env=%+v", meta, env)
}
// Permissions: dir 0700, blob 0600.
info, err := os.Stat(store.SessionInboxDir(session))
if err != nil {
t.Fatal(err)
}
if info.Mode().Perm() != 0o700 {
t.Fatalf("inbox dir perm = %o", info.Mode().Perm())
// Unix: dir 0700. Windows reports 0777 and does not enforce owner-only bits.
if runtime.GOOS != "windows" {
info, err := os.Stat(store.SessionInboxDir(session))
if err != nil {
t.Fatal(err)
}
if info.Mode().Perm() != 0o700 {
t.Fatalf("inbox dir perm = %o", info.Mode().Perm())
}
}
}