v0.284.0 — a box deletes old app images (decision 53, R-736); an after_install app is held until its known login is replaced (R-741)
gates / gates (push) Successful in 27s
gates / gates (push) Successful in 27s
Image retention: after a done/undone guarded Update and at remove, an app's images older than its running and previous one are deleted — never an image any container, installed compose or installed/previous record names (box-wide keep set read at delete time); exact id, never forced or pruned; paused while any update runs; a one-time sweep of catalog app images at the first start. Install hold: an after_install app is installed behind the setup gate's door and opens when after_install succeeds or the household says it changed the login. Tests TestImageRetention_* and TestInstallHold_* with red-proofs; parity fixture for the held card. MinAgent: 0.131.0 (unchanged). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -345,6 +345,16 @@ func (m *Manager) SetupGateHost(host string) (name string, closed bool, found bo
|
||||
host = strings.ToLower(host)
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
// R-741: a closed install hold answers first (its routers outrank the gate's); an app with both is closed while
|
||||
// either is.
|
||||
for n, st := range m.stacks {
|
||||
if st.AppConfig == nil || !st.AppConfig.InstallHold.Closed() {
|
||||
continue
|
||||
}
|
||||
if containsStr(st.AppConfig.InstallHold.Hosts, host) {
|
||||
return n, true, true
|
||||
}
|
||||
}
|
||||
for n, st := range m.stacks {
|
||||
if st.AppConfig == nil || st.AppConfig.SetupGate == nil {
|
||||
continue
|
||||
@@ -486,6 +496,7 @@ func (m *Manager) SetupGateTick() {
|
||||
}
|
||||
}
|
||||
m.reconcileSignupBlocks()
|
||||
m.installHoldTick()
|
||||
}
|
||||
|
||||
// RunSetupGateLoop runs SetupGateTick every interval until ctx ends.
|
||||
@@ -521,5 +532,8 @@ func (m *Manager) MarkDefaultLoginChanged(name, by string) error {
|
||||
return fmt.Errorf("%s: app.yaml could not be read", name)
|
||||
}
|
||||
m.logger.Printf("[INFO] [stacks] %s: the household says it changed the default login by hand — the page stops naming it", name)
|
||||
if err := m.OpenInstallHold(name, InstallHoldByHousehold); err != nil { // R-741
|
||||
m.logger.Printf("[ERROR] [stacks] %s: %v — the loop retries", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user