Allow active deployment edits

This commit is contained in:
npc0-hue
2026-08-03 15:50:05 +08:00
parent cf4d0d0ba5
commit 5d4fca14f9
7 changed files with 65 additions and 28 deletions
+2 -2
View File
@@ -35,8 +35,8 @@ func (svc *CoreService) UpdateServerDeploymentForSession(sessionID, serverInstan
if err != nil {
return domain.ServerDeploymentView{}, err
}
if instance.State == domain.ServerInstanceStateInstalling || instance.State == domain.ServerInstanceStateRunning || instance.State == domain.ServerInstanceStateDeleted {
return domain.ServerDeploymentView{}, validationError("deployment definition cannot be changed while the server is active")
if instance.State == domain.ServerInstanceStateDeleted {
return domain.ServerDeploymentView{}, validationError("deleted server deployment definition cannot be changed")
}
seenClearFields := map[string]bool{}
for _, field := range update.ClearFields {
@@ -65,6 +65,40 @@ func TestCoreServiceSavesDraftDeploymentRedactsReadsAndDispatchesOnlyToCompatibl
}
}
func TestCoreServiceUpdatesDeploymentWhileServerIsActive(t *testing.T) {
svc, _ := newLifecycleRunService(t)
createLifecyclePlugin(t, svc)
ownerSession := createServiceUserAndLogin(t, svc, domain.User{ID: "deployment-active-owner", DisplayName: "Deployment Active Owner", Email: "deployment-active-owner@example.test", Roles: []string{"server-owner"}, PasswordHash: "secret-password"})
for _, state := range []domain.ServerInstanceState{domain.ServerInstanceStateInstalling, domain.ServerInstanceStateRunning} {
stateLabel := string(state)
created, err := svc.CreateServerInstanceWorkflowForSession(ownerSession, domain.ServerLifecycleCreate{
ID: "active-deployment-edit-" + stateLabel, PluginID: "server.scum", Name: "Active Deployment Edit " + stateLabel, IdempotencyKey: "active-deployment-edit-" + stateLabel,
Deployment: domain.ServerDeploymentDefinition{Mode: domain.ServerDeploymentModeCustom, ServerRoot: "/srv/active-server-" + stateLabel, WorkingDirectory: "/srv/active-server-" + stateLabel, StartCommand: "./start"},
})
if err != nil {
t.Fatalf("create %s deployment fixture: %v", state, err)
}
instance, err := svc.store.ServerInstances().Get(created.Instance.ID)
if err != nil {
t.Fatalf("get %s deployment fixture: %v", state, err)
}
instance.RunEndpointID = "run-local"
instance.State = state
if err := svc.store.ServerInstances().Update(instance); err != nil {
t.Fatalf("mark fixture %s: %v", state, err)
}
view, err := svc.UpdateServerDeploymentForSession(ownerSession, instance.ID, domain.ServerDeploymentUpdate{Mode: domain.ServerDeploymentModeCustom, ServerRoot: "/srv/active-server-next-" + stateLabel, StartCommand: "./start-next"})
if err != nil {
t.Fatalf("update %s deployment: %v", state, err)
}
if view.Revision != instance.Deployment.Revision+1 || !view.ServerRootConfigured || !view.StartCommandConfigured {
t.Fatalf("expected %s deployment revision and protected field flags to update, view=%+v", state, view)
}
}
}
func TestCoreServiceSCUMGuidedDeployDispatchesPluginOwnedInstallAction(t *testing.T) {
svc := newTestCoreService()
runHello := validRunControlHello()