8fc2b4a1a9
gates / gates (push) Successful in 26s
The guarded update gains a folder copy of the app's named volumes, taken after the pull where the app stops anyway (decision 19, chosen by the 2026-09-23 bake-off). On a failed health check the box undoes: every copy validated by its finished-marker first, volumes refilled, definition and pin from the job's own pre-update copies, the old version checked with the OLD .felhom.yml probe. It holds only if the undo fails, and the hold sentence says so and what state the data is in. Bind-mounted folders are never touched. - R-637 built; R-638/R-640/R-641 do not arise with a folder copy; R-639 (pre-update copies incl. .felhom.yml kept until the undo is over). - journal phases copying/undoing with power-cut recovery. - app.yaml last_update_undone + one line on the app page (hu/en). - R-642: start/restart never answer "completed". - Removal deletes kept undo copies. MinAgent unchanged (0.131.0). Nine red-proofs in REPORT.md. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
59 lines
2.3 KiB
Go
59 lines
2.3 KiB
Go
package backup
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// v0.263.0 — a hold after a FAILED UNDO opens with what was tried and what state the data is in, in the
|
|
// box's language; a hold with no undo attempted reads exactly as before (every pre-v0.263.0 hold).
|
|
//
|
|
// COMPANION RED-PROOF (REPORT.md): make RestoreHoldFor ignore h.UndoState (drop undoHoldPrefix) — the
|
|
// three undo cases then read the plain sentence and this test fails on the prefix.
|
|
func TestUndo_HoldSentenceSaysTheUndoWasTriedAndTheDataState(t *testing.T) {
|
|
at := time.Date(2026, 9, 23, 8, 0, 0, 0, time.UTC)
|
|
copyAt := time.Date(2026, 9, 23, 1, 30, 0, 0, time.UTC)
|
|
m := r479Manager(t, false)
|
|
m.logger = log.New(io.Discard, "", 0)
|
|
plain := fmt.Sprintf(UpdateHoldTierFmt, "app", "2026-09-23 10:00", "második meghajtó", "2026-09-23 03:30")
|
|
|
|
if err := m.HoldAfterFailedUpdateHolding("app", at, copyAt, UpdateTierSecondDrive, "", ""); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, why := m.RestoreHoldFor("app"); why != plain {
|
|
t.Errorf("no undo attempted: the sentence must be unchanged, got %q", why)
|
|
}
|
|
|
|
for state, clause := range map[string]string{
|
|
"untouched": "Az adatok az új változat által hagyott állapotban vannak.",
|
|
"half": "Az adatok visszamásolása félbeszakadt",
|
|
"not_started": "Az adatok a frissítés előtti állapotba kerültek vissza, de az előző változat nem indult el.",
|
|
} {
|
|
if err := m.HoldAfterFailedUpdateHolding("app", at, copyAt, UpdateTierSecondDrive, "", state); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, why := m.RestoreHoldFor("app")
|
|
if !strings.HasPrefix(why, "A frissítés nem sikerült, és az automatikus visszaállítás sem. "+clause) {
|
|
t.Errorf("%s: the hold must open with the undo prefix and its state, got %q", state, why)
|
|
}
|
|
if !strings.HasSuffix(why, plain) {
|
|
t.Errorf("%s: the hold must still name the copy to restore from, got %q", state, why)
|
|
}
|
|
}
|
|
|
|
if err := m.settings.SetLanguage("en"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, why := m.RestoreHoldFor("app")
|
|
if !strings.HasPrefix(why, "The update did not succeed, and the automatic undo did not either. The data is back as it was before the update") {
|
|
t.Errorf("an English box gets the English prefix, got %q", why)
|
|
}
|
|
if strings.Contains(why, "automatikus visszaállítás") {
|
|
t.Errorf("the Hungarian prefix must be GONE on an English box, got %q", why)
|
|
}
|
|
}
|