feat: 完整游戏运维功能
This commit is contained in:
@@ -9,6 +9,19 @@ import (
|
||||
"browser.local/platform/repo"
|
||||
)
|
||||
|
||||
type generatedPackageConfig struct {
|
||||
Kind string
|
||||
ServerInstanceID string
|
||||
PluginID string
|
||||
RunEndpointID string
|
||||
ProfileKey string
|
||||
TargetOS string
|
||||
TargetArch string
|
||||
SecretRef string
|
||||
KeyGeneration int
|
||||
AuthKey string
|
||||
}
|
||||
|
||||
func TestCoreServiceGeneratesRunDistributionWithEncryptedSingletonKey(t *testing.T) {
|
||||
svc, session, instance := newDistributionTestFixture(t)
|
||||
|
||||
@@ -83,6 +96,64 @@ func TestCoreServiceGeneratesRunDistributionWithEncryptedSingletonKey(t *testing
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreServiceDistributionBuildRejectsPrematureSuccessAndCanRetryAfterUpload(t *testing.T) {
|
||||
svc, session, instance := newDistributionTestFixture(t)
|
||||
distribution, err := svc.GenerateRunDistributionForSession(session, domain.RunDistributionGenerateRequest{
|
||||
ServerInstanceID: instance.ID,
|
||||
TargetOS: "linux",
|
||||
TargetArch: "amd64",
|
||||
IdempotencyKey: "idem-premature-result",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("generate run distribution: %v", err)
|
||||
}
|
||||
|
||||
helloRequest := validRunControlHello()
|
||||
helloRequest.CapabilityReport.Capabilities = append(helloRequest.CapabilityReport.Capabilities, domain.JobCapabilityDistributionBuild)
|
||||
hello, err := svc.RegisterRunHello(helloRequest)
|
||||
if err != nil {
|
||||
t.Fatalf("register build worker: %v", err)
|
||||
}
|
||||
claim, err := svc.ClaimRunJob(domain.RunJobClaim{
|
||||
RunEndpointID: instance.RunEndpointID,
|
||||
SessionToken: hello.SessionToken,
|
||||
Capabilities: []string{domain.JobCapabilityDistributionBuild},
|
||||
Capacity: domain.RunCapacity{MaxJobs: 1},
|
||||
})
|
||||
if err != nil || !claim.HasJob || claim.Job.JobID != distribution.BuildJobID {
|
||||
t.Fatalf("claim distribution build job: claim=%+v err=%v", claim, err)
|
||||
}
|
||||
result := domain.RunJobResult{
|
||||
RunEndpointID: instance.RunEndpointID,
|
||||
SessionToken: hello.SessionToken,
|
||||
JobID: claim.Job.JobID,
|
||||
LeaseToken: claim.Job.LeaseToken,
|
||||
Attempt: claim.Job.Attempt,
|
||||
State: domain.JobStateSucceeded,
|
||||
Progress: domain.RunJobProgressReport{Percent: 100, Message: "package_finalize: done"},
|
||||
ResultRef: "artifact://" + distribution.ArtifactID,
|
||||
Message: "done",
|
||||
}
|
||||
if _, err := svc.CompleteRunJob(result); err == nil {
|
||||
t.Fatal("expected premature success without uploaded artifact to be rejected")
|
||||
}
|
||||
stored, err := svc.GetJob(distribution.BuildJobID)
|
||||
if err != nil || stored.State != domain.JobStateAccepted {
|
||||
t.Fatalf("premature success must not make the job terminal, job=%+v err=%v", stored, err)
|
||||
}
|
||||
|
||||
if _, err := svc.createPlatformArtifactPayload(distribution.ArtifactID, domain.ArtifactOwnerKindJob, distribution.BuildJobID, []byte("actual compiled archive")); err != nil {
|
||||
t.Fatalf("publish uploaded build output: %v", err)
|
||||
}
|
||||
if _, err := svc.CompleteRunJob(result); err != nil {
|
||||
t.Fatalf("retry success after artifact upload: %v", err)
|
||||
}
|
||||
stored, err = svc.GetJob(distribution.BuildJobID)
|
||||
if err != nil || stored.State != domain.JobStateSucceeded {
|
||||
t.Fatalf("expected terminal success after upload, job=%+v err=%v", stored, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreServiceRunDistributionRetryReusesPartialArtifact(t *testing.T) {
|
||||
svc, session, instance := newDistributionTestFixture(t)
|
||||
key, plainKey, err := svc.ensureActiveComponentKey(instance.ID, domain.DistributionComponentRun, "")
|
||||
@@ -124,7 +195,7 @@ func TestCoreServicePushRunUpdateReusesExistingUpdateJob(t *testing.T) {
|
||||
svc, session, instance := newDistributionTestFixture(t)
|
||||
distribution, err := svc.GenerateRunDistributionForSession(session, domain.RunDistributionGenerateRequest{
|
||||
ServerInstanceID: instance.ID,
|
||||
TargetOS: "windows",
|
||||
TargetOS: "linux",
|
||||
TargetArch: "amd64",
|
||||
IdempotencyKey: "idem-run-before-update",
|
||||
})
|
||||
@@ -347,6 +418,11 @@ func newDistributionTestFixture(t *testing.T) (*CoreService, string, domain.Serv
|
||||
domain.JobCapabilityDependenciesCheck,
|
||||
domain.JobCapabilityDependenciesInstall,
|
||||
domain.JobCapabilityLogsBackfill,
|
||||
domain.JobCapabilityClientManagerDeploy,
|
||||
domain.JobCapabilityClientManagerControl,
|
||||
domain.JobCapabilityClientManagerUpdate,
|
||||
domain.JobCapabilityClientManagerRollback,
|
||||
domain.JobCapabilityClientManagerUninstall,
|
||||
)
|
||||
plugin.BridgeActions = append(plugin.BridgeActions,
|
||||
string(domain.PluginBridgeActionRunDistribution),
|
||||
@@ -354,6 +430,9 @@ func newDistributionTestFixture(t *testing.T) (*CoreService, string, domain.Serv
|
||||
string(domain.PluginBridgeActionDependenciesRequest),
|
||||
string(domain.PluginBridgeActionLogsBackfillRequest),
|
||||
)
|
||||
plugin.RuntimeProfiles.DependencyProbes = []domain.RuntimeDependencyProbe{{Key: "java-runtime", Kind: "command.version", TargetKey: "java", Platforms: []string{"linux"}}}
|
||||
plugin.RuntimeProfiles.InstallPlans = []domain.RuntimeInstallPlan{{Key: "java-install", Title: "Install Java", Platforms: []string{"linux"}, Steps: []domain.RuntimeInstallStep{{Type: "package", TargetKey: "java", PackageManager: "apt", PackageName: "openjdk-21-jre"}}}}
|
||||
plugin.RuntimeProfiles.ClientManagers = []domain.RuntimeClientManagerProfile{{Key: "scum-client-manager", DisplayName: "SCUM Client Manager", Version: "1.0.0", RepositoryURL: "https://github.com/F88888/scum_client.git", RevisionPolicy: "branch", Branch: "main", SupportedTargets: []domain.RuntimeTarget{{OS: "windows", Arch: "amd64"}, {OS: "linux", Arch: "amd64"}}, BuildSystem: "go", EntryRef: "main.go", OutputArtifacts: []string{"scum_client.exe"}, Deployment: domain.RuntimeClientManagerDeployment{Mode: "run-supervised", ExecutableRef: "scum_client.exe", RequiredRunCapabilities: []string{domain.JobCapabilityClientManagerDeploy, domain.JobCapabilityClientManagerControl, domain.JobCapabilityClientManagerUpdate, domain.JobCapabilityClientManagerRollback, domain.JobCapabilityClientManagerUninstall}}, Lifecycle: domain.RuntimeClientManagerLifecycle{Actions: []string{"start", "stop", "restart", "status", "update", "rollback", "uninstall"}, StartupTimeoutSeconds: 60, StopTimeoutSeconds: 30}, Health: domain.RuntimeClientManagerHealth{Mode: "component-heartbeat", IntervalSeconds: 15, DegradedAfterSeconds: 45, OfflineAfterSeconds: 120, RequiredCapabilities: []string{"component.register", "component.heartbeat", "component.health"}}, Compatibility: domain.RuntimeClientManagerCompatibility{MinimumVersion: "1.0.0"}, UpdatePolicy: domain.RuntimeClientManagerUpdatePolicy{Strategy: "manual-staged", RequireApproval: true, HealthConfirmationSeconds: 60, RetainPrevious: true}}}
|
||||
if err := svc.store.GamePlugins().Update(plugin); err != nil {
|
||||
t.Fatalf("update plugin fixture: %v", err)
|
||||
}
|
||||
@@ -363,7 +442,14 @@ func newDistributionTestFixture(t *testing.T) (*CoreService, string, domain.Serv
|
||||
domain.JobCapabilityDependenciesCheck,
|
||||
domain.JobCapabilityDependenciesInstall,
|
||||
domain.JobCapabilityLogsBackfill,
|
||||
domain.JobCapabilityClientManagerDeploy,
|
||||
domain.JobCapabilityClientManagerControl,
|
||||
domain.JobCapabilityClientManagerUpdate,
|
||||
domain.JobCapabilityClientManagerRollback,
|
||||
domain.JobCapabilityClientManagerUninstall,
|
||||
)
|
||||
endpoint.Platform = "linux"
|
||||
endpoint.Architecture = "amd64"
|
||||
if err := svc.store.RunEndpoints().Update(endpoint); err != nil {
|
||||
t.Fatalf("update endpoint fixture: %v", err)
|
||||
}
|
||||
@@ -384,6 +470,7 @@ func newDistributionTestFixture(t *testing.T) (*CoreService, string, domain.Serv
|
||||
if err != nil {
|
||||
t.Fatalf("create distribution server: %v", err)
|
||||
}
|
||||
createCompleteRuntimeBinding(t, svc, instance, "local")
|
||||
return svc, session, instance
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user