fix(patch): gate phases on the window deadline, queue undelivered results, retry startup inventory
Agent Release / build (push) Successful in 3m40s
Agent Release / msi (push) Successful in 4m54s

The window deadline no longer kills a running package manager: it only gates
the start of each phase, and a started upgrade runs under a 2 hour backstop
that sends SIGTERM on Linux. A PatchResult whose send fails is queued and
flushed on the next command stream, retaking the reboot decision. deb822
folded Suites continuation lines are filtered with the field. The startup
static inventory report is retried until it succeeds.
This commit is contained in:
2026-09-15 13:43:03 +00:00
parent ecd703d502
commit b5b9775d2b
12 changed files with 404 additions and 46 deletions
+27 -7
View File
@@ -68,14 +68,28 @@ func filterOneLine(content string) string {
return b.String()
}
// deb822Fields groups a paragraph's lines into fields. A line that starts
// with a space or tab continues the field above it (a folded or multi-line
// value, such as a long Suites list or an inline Signed-By key block).
func deb822Fields(para string) [][]string {
var fields [][]string
for _, l := range strings.Split(strings.Trim(para, "\n"), "\n") {
if (strings.HasPrefix(l, " ") || strings.HasPrefix(l, "\t")) && len(fields) > 0 {
fields[len(fields)-1] = append(fields[len(fields)-1], l)
continue
}
fields = append(fields, []string{l})
}
return fields
}
func filterDeb822(content string) string {
var b strings.Builder
for _, para := range strings.Split(strings.ReplaceAll(content, "\r\n", "\n"), "\n\n") {
lines := strings.Split(strings.Trim(para, "\n"), "\n")
var out []string
isDeb, enabled, kept := false, true, false
for _, l := range lines {
key, val, found := strings.Cut(l, ":")
for _, field := range deb822Fields(para) {
key, val, found := strings.Cut(field[0], ":")
k := strings.ToLower(strings.TrimSpace(key))
v := strings.TrimSpace(val)
switch {
@@ -88,19 +102,25 @@ func filterDeb822(content string) string {
case found && k == "enabled":
enabled = strings.ToLower(v) != "no"
case found && k == "suites":
// The value runs across every continuation line. The filtered
// result is written back as one line and the continuation
// lines are dropped with the rest of the original field.
all := strings.Fields(strings.Join(append([]string{v}, field[1:]...), " "))
var sec []string
for _, s := range strings.Fields(v) {
for _, s := range all {
if isSecuritySuite(s) {
sec = append(sec, s)
}
}
if len(sec) == 0 {
continue // drop the line; the paragraph is dropped below
continue // drop the field; the paragraph is dropped below
}
kept = true
l = "Suites: " + strings.Join(sec, " ")
out = append(out, "Suites: "+strings.Join(sec, " "))
continue
}
out = append(out, l)
// Every other field, continuation lines included, stays verbatim.
out = append(out, field...)
}
if isDeb && enabled && kept {
b.WriteString(strings.Join(out, "\n"))