Fix timezone drift and --json truncation in snapshot list (closes #64)
All checks were successful
check / check (pull_request) Successful in 2m24s
All checks were successful
check / check (pull_request) Successful in 2m24s
Three defects in the merged listing path, all found in review. 1. The TIMESTAMP column mixed two timezones. Remote-only rows render timestamp.UTC(); local rows come from ListRecent, whose scanner decoded Unix seconds in the host's local zone, unlike the two other snapshot scanners in that file. Both render through the same zone-less format string, so on a non-UTC host the same snapshot showed one time when locally tracked and another when remote-only, in the same column, with nothing to indicate why. Normalized at the point the timestamp enters the domain rather than at the display layer: scanSnapshotRows now decodes in UTC like its siblings, and GetIncompleteByHostname's copy of that loop was folded onto the shared scanner so the three call sites cannot drift apart again. 2. --json silently truncated. The early return skipped reportListDrift, so neither the 1000-row cap nor the unreadable-manifest count reached a machine consumer: past the cap the document was short with no signal at all. Both counts now go to stderr, where the unreachable-destination warning already goes. The document's shape is deliberately unchanged, so existing consumers keep parsing. 3. The --json stderr workaround was half-applied. Two per-snapshot log.Warn calls on the same new path were left unguarded, and the logger writes to stdout at default level, so one corrupt manifest put a log line ahead of the document and broke `| jq`. Both now route through the same JSON-aware writer. They are also collected during the concurrent manifest reads and emitted afterwards in key order, since that writer is not safe for concurrent use. Still a local workaround; the logger itself is issue #82. Also from review, non-blocking: the destination-listing failure is no longer printed twice in table mode, the identifier cell is no longer computed and discarded for locally tracked rows, and the merge sort is stable so that rows sharing the zero-timestamp fallback keep a deterministic order. Tests: each fix has a test that fails without it. The timezone tests pin time.Local to a non-UTC zone and assert Location identity, so they would have caught this on the UTC host where it was missed. The JSON stdout test redirects the process's own stdout to a pipe and rebuilds the logger over it, so it can actually observe a log line landing on stdout ahead of the document rather than asserting on an injected buffer the log never reaches.
This commit is contained in:
16
TODO.md
16
TODO.md
@@ -36,8 +36,20 @@ or delete the branch.
|
||||
`reportRemoteDrift` collapsed into the merged view. Every remote
|
||||
manifest read in the codebase now goes through
|
||||
`downloadManifestByKey`, so issue #81 has one call site to change.
|
||||
Verified with `script/cibuild` and end to end against a `file://`
|
||||
destination with no secret key present.
|
||||
Review rework: snapshot timestamps now normalize to UTC in
|
||||
`scanSnapshotRows`, the one place they enter the domain, so the merged
|
||||
TIMESTAMP column cannot show local time for a locally tracked row and
|
||||
UTC for a remote-only row on a non-UTC host; `GetIncompleteByHostname`
|
||||
was folded onto that same scanner. `--json` now reports the
|
||||
unreadable-manifest count and the 1000-row truncation on stderr
|
||||
instead of returning a silently short document (the document's shape
|
||||
is unchanged). The two per-snapshot `log.Warn` calls on the listing
|
||||
path now route through the same JSON-aware writer as the existing
|
||||
workaround, so one corrupt manifest can no longer put a log line on
|
||||
stdout ahead of the document and break `| jq` — still a local
|
||||
workaround pending issue #82. Verified with `script/cibuild` and with
|
||||
an uncached `make check` (`0 issues.`, no cached test packages), plus
|
||||
end to end against a `file://` destination with no secret key present.
|
||||
- 2026-08-09: Closed the gap between `make lint` and CI (issue #78).
|
||||
`script/lint` now runs the digest-pinned `golangci-lint` image taken
|
||||
from the `Dockerfile` lint stage, which is the single source of truth
|
||||
|
||||
Reference in New Issue
Block a user