Fix SCUM generated run deployment flow

This commit is contained in:
npc0-hue
2026-07-31 14:10:30 +08:00
parent 6d71d8d232
commit f23d18ea57
11 changed files with 291 additions and 35 deletions
@@ -65,6 +65,49 @@ func TestCoreServiceSavesDraftDeploymentRedactsReadsAndDispatchesOnlyToCompatibl
}
}
func TestCoreServiceSCUMGuidedDeployUsesScopedCapabilitiesAndDispatchesFrozenPlan(t *testing.T) {
svc := newTestCoreService()
runHello := validRunControlHello()
runHello.RunEndpointID = "run-scum-guided"
runHello.Platform = "windows"
runHello.Architecture = "amd64"
runHello.CapabilityReport.Capabilities = []string{domain.LifecycleCapabilityInstall, domain.LifecycleCapabilityStart, domain.LifecycleCapabilityStop, domain.JobCapabilityDeploymentPlan, domain.JobCapabilitySCUMDeploymentPlan}
runHello.CapabilityReport.Fingerprint = "cap-scum-guided"
session, err := svc.RegisterRunHello(runHello)
if err != nil {
t.Fatalf("register scoped SCUM Run: %v", err)
}
plugin := scumDeploymentTestPlugin()
plugin.Name = "SCUM"
plugin.Version = "1.0.0"
plugin.ServerType = "scum"
plugin.Status = domain.GamePluginStatusInstalled
plugin.RequiredRunCapabilities = []string{domain.LifecycleCapabilityInstall, domain.LifecycleCapabilityStart, domain.LifecycleCapabilityStop, "process.restart", "files.list", "files.patch", domain.JobCapabilityClientManagerDeploy, domain.JobCapabilityClientManagerControl, domain.JobCapabilityClientManagerUpdate, domain.JobCapabilityClientManagerRollback, domain.JobCapabilityClientManagerUninstall, "artifacts.read", "artifacts.write", "ai.invoke"}
plugin.LifecycleActions = domain.PluginLifecycleActions{Install: "actions/install.json", Start: "actions/start.json", Stop: "actions/stop.json"}
plugin.RuntimeProfiles.LifecycleProfiles = []domain.RuntimeLifecycleProfile{{Key: "local", Mode: "local-process", Capabilities: []string{domain.LifecycleCapabilityInstall, domain.LifecycleCapabilityStart, domain.LifecycleCapabilityStop}}}
requireManualSCUMRuntimeBindings(&plugin, "local")
plugin.RuntimeProfiles.ServerDeployments[0].SupportedTargets = []domain.RuntimeTarget{{OS: "windows", Arch: "amd64"}}
if err := svc.store.GamePlugins().Create(plugin); err != nil {
t.Fatalf("create SCUM plugin fixture: %v", err)
}
ownerSession := createServiceUserAndLogin(t, svc, domain.User{ID: "scum-guided-owner", DisplayName: "SCUM Guided Owner", Email: "scum-guided@example.test", Roles: []string{"server-owner"}, PasswordHash: "secret-password"})
created, err := svc.CreateServerInstanceWorkflowForSession(ownerSession, domain.ServerLifecycleCreate{
ID: "scum-guided-scoped", PluginID: plugin.ID, RunEndpointID: "run-scum-guided", Name: "SCUM Guided", IdempotencyKey: "scum-guided-scoped-create", ProfileKey: "local",
Deployment: domain.ServerDeploymentDefinition{Mode: domain.ServerDeploymentModeGuided, ServerRoot: "C:\\scum-guided", CreateInputs: map[string]string{"serverName": "Moon", "gamePort": "27000", "queryPort": "27015", "maxPlayers": "128"}},
})
if err != nil {
t.Fatalf("SCUM guided deployment should not require unrelated manifest capabilities: %v", err)
}
if created.Job.ExecutionInput.ServerDeploymentPlan == nil || created.Job.ExecutionInput.ServerDeploymentPlan.SteamAppID != "3792580" {
t.Fatalf("expected frozen SCUM deployment plan on queued job, got %+v", created.Job.ExecutionInput)
}
claim, err := svc.ClaimRunJob(domain.RunJobClaim{RunEndpointID: "run-scum-guided", SessionToken: session.SessionToken, Capabilities: []string{domain.LifecycleCapabilityInstall}, Capacity: domain.RunCapacity{MaxJobs: 1}})
if err != nil || !claim.HasJob || claim.Job.ExecutionInput.ServerDeploymentPlan == nil {
t.Fatalf("claimed SCUM install must include frozen deployment plan, claim=%+v err=%v", claim, err)
}
}
func TestMergeDeploymentPreservesOmittedShellAndClearsOnlyExplicitFields(t *testing.T) {
current := domain.ServerDeploymentDefinition{Mode: domain.ServerDeploymentModeCustom, ServerRoot: "/srv/game", StartCommand: "./start", StopCommand: "./stop", Shell: domain.ServerCommandShellCmd}
preserved := mergeDeploymentDefinition(current, domain.ServerDeploymentUpdate{Mode: domain.ServerDeploymentModeCustom})