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:
@@ -184,6 +184,12 @@ type AppConfig struct {
|
||||
// SetupGate (v0.280.0, decision 46) is the app's setup gate: closed from a fresh install until the first
|
||||
// setup is done. A life record (carried across a restore). See setup_gate.go.
|
||||
SetupGate *SetupGateRecord `yaml:"setup_gate,omitempty" json:"setup_gate,omitempty"`
|
||||
// InstallHold (R-741, decision 45): an after_install app is held (the gate's door) from its fresh install until
|
||||
// its known first login is replaced. Same record shape as SetupGate. See install_hold.go.
|
||||
InstallHold *SetupGateRecord `yaml:"install_hold,omitempty" json:"install_hold,omitempty"`
|
||||
// PreviousImages (R-736, decision 53): per service, the image the app ran BEFORE its last done update — kept on
|
||||
// the box with the running one; older images of the app are deleted (image_retention.go).
|
||||
PreviousImages map[string]InstalledImage `yaml:"previous_images,omitempty" json:"previous_images,omitempty"`
|
||||
// DefaultLogin (v0.280.0, R-710) is the household's own word that it changed the template's known default
|
||||
// login by hand. The page stops naming the default. See internal/web/known_login.go.
|
||||
DefaultLogin *DefaultLoginRecord `yaml:"default_login,omitempty" json:"default_login,omitempty"`
|
||||
@@ -434,6 +440,20 @@ func (m *Manager) DeployStack(req DeployRequest) (string, error) {
|
||||
}
|
||||
gate = g
|
||||
}
|
||||
// R-741: an after_install template is installed HELD, the file written before the first start, like the gate.
|
||||
var hold *SetupGateRecord
|
||||
if wantsInstallHold(&meta) {
|
||||
h, err := m.prepareInstallHold(req.StackName, stack.ComposePath, env)
|
||||
if err != nil {
|
||||
clearDeploying()
|
||||
if gate != nil {
|
||||
_ = m.removeSetupGateFile(req.StackName)
|
||||
}
|
||||
m.logger.Printf("[ERROR] [stacks] Deploy %s REFUSED: the install hold could not be prepared: %v", req.StackName, err)
|
||||
return "", util.MsgError("err.stacks.setup_gate_failed", err.Error())
|
||||
}
|
||||
hold = h
|
||||
}
|
||||
|
||||
// Save app.yaml.
|
||||
// CTRL-T2-1: persist the env now, but mark the ON-DISK state Deployed:false
|
||||
@@ -455,6 +475,7 @@ func (m *Manager) DeployStack(req DeployRequest) (string, error) {
|
||||
// reverts Deployed to false — so a failed deploy can never present as an app owed a restart.
|
||||
DesiredState: DesiredStateRunning,
|
||||
SetupGate: gate,
|
||||
InstallHold: hold,
|
||||
}
|
||||
|
||||
diskCfg := *appCfg
|
||||
|
||||
Reference in New Issue
Block a user