refactor: harden diagnostics and consolidate runtime code

This commit is contained in:
Mikhail Chusavitin
2026-09-01 13:01:28 +03:00
parent ac4bc0b2b7
commit 0a6ca8ba0f
49 changed files with 1441 additions and 837 deletions
@@ -0,0 +1,52 @@
# Support bundle: stage under a private os.MkdirTemp parent, not a time-derived path
**Date:** 2026-08-31
**Status:** active
## Context
`BuildSupportBundle` staged into
`os.TempDir()/bee-support-stage-<hostname>-<YYYYMMDD-HHMMSS>` and did
`defer os.RemoveAll(stageRoot)`. The name has one-second resolution and a
fixed hostname, so two builds started in the same wall-clock second resolve
to the same directory: one operator double-clicking "Download Support
Bundle", two operators, or an on-demand build racing the blackbox worker.
When that happened, the first build to finish ran `os.RemoveAll` on the
shared tree while the second was still populating it or archiving it. The
second build's `createSupportTarGz` then walked a half-deleted tree and
produced a truncated archive - with no error. It surfaced first as a flaky
test (`TestBuildSupportBundleIncludesExportDirContents` vs the webui
endpoint test, run in parallel by `go test ./...`), but the same race is
reachable in production.
## Decision
`BuildSupportBundle` creates a private parent with
`os.MkdirTemp(os.TempDir(), "bee-support-build-")` and stages inside it. The
leaf directory keeps the meaningful `bee-support-stage-<hostname>-<ts>` name
(it becomes the archive's top-level directory). `defer os.RemoveAll` targets
the unique parent. The output archive is created with `os.CreateTemp`, retaining
the human-readable prefix while guaranteeing a unique file for each concurrent
build. It is written under a non-published `.partial` suffix and atomically
renamed to `.tar.gz` only after tar, gzip, and file closes succeed, so retention
cleanup can only see completed archives.
Tests that exercise the real `BuildSupportBundle` set
`t.Setenv("TMPDIR", t.TempDir())` so each test's `os.TempDir()` - staging
parent, archive path, and the `cleanupOldSupportBundles` scan - is isolated
from parallel packages.
## Consequences
- Concurrent support-bundle builds are independent; neither can truncate the
other.
- DO NOT reintroduce a time-derived or otherwise non-unique staging path.
See `architecture/runtime-flows.md` (Blackbox sync flow invariants).
- The archive file itself still lands in `os.TempDir()` under a
human-readable `SupportBundleBaseName` prefix (callers `defer os.Remove` it),
with a random suffix preventing same-second writers from sharing one inode.
- Tar, gzip, source-file, and destination-file close failures are propagated;
an incomplete archive is removed instead of being returned as successful.
- DMI-derived version/model/serial components are sanitized before becoming
path components.
+1
View File
@@ -15,3 +15,4 @@ One file per decision, named `YYYY-MM-DD-short-topic.md`.
| 2026-08-31 | nvbandwidth: single all-GPU pass in Validate, per-socket matrix only in deep tier | active |
| 2026-08-31 | bee-nvidia.service: never blocking `systemctl restart` on units ordered After= itself | active |
| 2026-08-31 | "Run All" SAT planning happens on the backend, not the browser | active |
| 2026-08-31 | Support bundle uses private staging and unique atomic output | active |