feat: 完整游戏运维功能

This commit is contained in:
npc0-hue
2026-07-18 09:04:01 +08:00
parent f3b14b7945
commit 48b8ad8d6c
187 changed files with 16607 additions and 1140 deletions
+61 -4
View File
@@ -14,12 +14,13 @@ func (svc *CoreService) GetDistributionBuildInput(request domain.DistributionBui
if err := validator.ValidateDistributionBuildInputRequest(request); err != nil {
return domain.DistributionBuildInput{}, err
}
if err := svc.validateRunSession(request.RunEndpointID, request.SessionToken); err != nil {
session, err := svc.validatedRunSession(request.RunEndpointID, request.SessionToken)
if err != nil {
return domain.DistributionBuildInput{}, err
}
svc.jobMu.Lock()
job, _, err := svc.activeLeasedJob(request.RunEndpointID, request.SessionToken, request.JobID, request.LeaseToken, request.Attempt)
job, err := svc.fencedJob(session, request.JobID, request.LeaseToken, request.Attempt)
svc.jobMu.Unlock()
if err != nil {
return domain.DistributionBuildInput{}, err
@@ -46,7 +47,7 @@ func (svc *CoreService) GetDistributionBuildInput(request domain.DistributionBui
if key.Generation != distribution.KeyGeneration {
return domain.DistributionBuildInput{}, validationError("run build key generation is no longer current")
}
plainKey, err := decryptRuntimeKey(key.EncryptedKey)
plainKey, err := svc.decryptRuntimeKey(key.EncryptedKey)
if err != nil {
return domain.DistributionBuildInput{}, err
}
@@ -58,6 +59,7 @@ func (svc *CoreService) GetDistributionBuildInput(request domain.DistributionBui
RunEndpointID: distribution.RunEndpointID,
TargetOS: distribution.TargetOS,
TargetArch: distribution.TargetArch,
TargetRelease: distribution.ID,
PackageFormat: distribution.PackageFormat,
ArtifactID: distribution.ArtifactID,
OutputFilename: executableFilename("run", distribution.TargetOS),
@@ -82,7 +84,7 @@ func (svc *CoreService) GetDistributionBuildInput(request domain.DistributionBui
if key.Generation != distribution.KeyGeneration {
return domain.DistributionBuildInput{}, validationError("client-manager build key generation is no longer current")
}
plainKey, err := decryptRuntimeKey(key.EncryptedKey)
plainKey, err := svc.decryptRuntimeKey(key.EncryptedKey)
if err != nil {
return domain.DistributionBuildInput{}, err
}
@@ -134,6 +136,9 @@ func (svc *CoreService) projectDistributionBuildResult(job domain.Job, stamp tim
if job.Capability != domain.JobCapabilityDistributionBuild {
return nil
}
if err := svc.validateDistributionBuildResult(job); err != nil {
return err
}
status := domain.DistributionStatusFailed
buildStatus := domain.DistributionJobStatusFailed
var artifact domain.Artifact
@@ -198,6 +203,9 @@ func (svc *CoreService) projectDistributionBuildResult(job domain.Job, stamp tim
if err := svc.store.ClientManagerDistributions().Update(distribution); err != nil {
return err
}
if err := svc.ProjectClientManagerDistribution(distribution); err != nil {
return err
}
build, err := svc.store.ClientManagerBuildJobs().Get(job.ID)
if err != nil && !errors.Is(err, repo.ErrNotFound) {
return err
@@ -221,6 +229,55 @@ func (svc *CoreService) projectDistributionBuildResult(job domain.Job, stamp tim
return repo.ErrNotFound
}
func (svc *CoreService) validateDistributionBuildResult(job domain.Job) error {
if job.Capability != domain.JobCapabilityDistributionBuild {
return nil
}
expectedArtifactID := ""
runDistributions, err := svc.store.RunDistributions().List(domain.RunDistributionFilter{ServerInstanceID: job.ServerInstanceID})
if err != nil {
return err
}
for _, distribution := range runDistributions {
if distribution.BuildJobID == job.ID {
expectedArtifactID = distribution.ArtifactID
break
}
}
if expectedArtifactID == "" {
clientDistributions, err := svc.store.ClientManagerDistributions().List(domain.ClientManagerDistributionFilter{ServerInstanceID: job.ServerInstanceID})
if err != nil {
return err
}
for _, distribution := range clientDistributions {
if distribution.BuildJobID == job.ID {
expectedArtifactID = distribution.ArtifactID
break
}
}
}
if expectedArtifactID == "" {
return repo.ErrNotFound
}
if job.State != domain.JobStateSucceeded {
return nil
}
artifactID := strings.TrimPrefix(job.ResultRef, "artifact://")
if artifactID == "" || artifactID == job.ResultRef || artifactID != expectedArtifactID {
return validationError("distribution build result must reference the expected artifact")
}
artifact, err := svc.store.Artifacts().Get(artifactID)
if err != nil {
return err
}
if artifact.State != domain.ArtifactStateAvailable || artifact.OwnerKind != domain.ArtifactOwnerKindJob || artifact.OwnerID != job.ID {
return validationError("distribution build artifact is unavailable or outside the job scope")
}
return nil
}
func executableFilename(base string, targetOS string) string {
if targetOS == "windows" {
return base + ".exe"