feat: move distribution builds to platform Docker builder
This commit is contained in:
@@ -100,7 +100,7 @@ func TestCoreServiceGeneratesRunDistributionWithEncryptedSingletonKey(t *testing
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreServiceBuildsDedicatedRunOnDeploymentTarget(t *testing.T) {
|
||||
func TestCoreServiceBuildsDedicatedRunInPlatformBuilder(t *testing.T) {
|
||||
svc, session, instance := newDistributionTestFixture(t)
|
||||
targetID := instance.RunEndpointID
|
||||
instance.State = domain.ServerInstanceStateDraft
|
||||
@@ -115,14 +115,14 @@ func TestCoreServiceBuildsDedicatedRunOnDeploymentTarget(t *testing.T) {
|
||||
t.Fatalf("generate dedicated Run: %v", err)
|
||||
}
|
||||
job, err := svc.GetJob(distribution.BuildJobID)
|
||||
if err != nil || job.RunEndpointID != targetID || distribution.RunEndpointID != instance.RunEndpointID {
|
||||
t.Fatalf("expected build on target %q for dedicated Run %q, job=%+v distribution=%+v err=%v", targetID, instance.RunEndpointID, job, distribution, err)
|
||||
if err != nil || job.RunEndpointID != platformDistributionBuilderEndpointID || distribution.RunEndpointID != instance.RunEndpointID {
|
||||
t.Fatalf("expected platform build for dedicated Run %q, job=%+v distribution=%+v err=%v", instance.RunEndpointID, job, distribution, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreServicePromotesLegacyRunBindingBeforeDistributionBuild(t *testing.T) {
|
||||
svc, session, instance := newDistributionTestFixture(t)
|
||||
builderID := instance.RunEndpointID
|
||||
legacyEndpointID := instance.RunEndpointID
|
||||
instance.State = domain.ServerInstanceStateFailed
|
||||
if err := svc.store.ServerInstances().Update(instance); err != nil {
|
||||
t.Fatalf("mark legacy server failed: %v", err)
|
||||
@@ -136,36 +136,37 @@ func TestCoreServicePromotesLegacyRunBindingBeforeDistributionBuild(t *testing.T
|
||||
if err != nil {
|
||||
t.Fatalf("get migrated server: %v", err)
|
||||
}
|
||||
if migrated.DeploymentTargetID != builderID || migrated.RunEndpointID != "server-run-"+instance.ID {
|
||||
if migrated.DeploymentTargetID != legacyEndpointID || migrated.RunEndpointID != "server-run-"+instance.ID {
|
||||
t.Fatalf("expected legacy binding promotion, got %+v", migrated)
|
||||
}
|
||||
job, err := svc.GetJob(distribution.BuildJobID)
|
||||
if err != nil || job.RunEndpointID != builderID || distribution.RunEndpointID != migrated.RunEndpointID {
|
||||
t.Fatalf("expected build target %q and dedicated package endpoint %q, job=%+v distribution=%+v err=%v", builderID, migrated.RunEndpointID, job, distribution, err)
|
||||
if err != nil || job.RunEndpointID != platformDistributionBuilderEndpointID || distribution.RunEndpointID != migrated.RunEndpointID {
|
||||
t.Fatalf("expected platform build and dedicated package endpoint %q, job=%+v distribution=%+v err=%v", migrated.RunEndpointID, job, distribution, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreServiceRejectsDistributionBuildForStaleRunEndpoint(t *testing.T) {
|
||||
func TestCoreServiceDistributionBuildIgnoresStaleRunEndpoint(t *testing.T) {
|
||||
svc, session, instance := newDistributionTestFixture(t)
|
||||
svc.now = func() time.Time { return fixedTime.Add(capacityHeartbeatStaleAfter + time.Second) }
|
||||
|
||||
_, err := svc.GenerateRunDistributionForSession(session, domain.RunDistributionGenerateRequest{
|
||||
distribution, err := svc.GenerateRunDistributionForSession(session, domain.RunDistributionGenerateRequest{
|
||||
ServerInstanceID: instance.ID,
|
||||
TargetOS: "linux",
|
||||
TargetArch: "amd64",
|
||||
IdempotencyKey: "idem-stale-run-endpoint",
|
||||
})
|
||||
if err == nil || !strings.Contains(err.Error(), "heartbeat is stale") {
|
||||
t.Fatalf("expected stale Run endpoint rejection, got %v", err)
|
||||
if err != nil {
|
||||
t.Fatalf("platform build must ignore stale Run endpoint: %v", err)
|
||||
}
|
||||
completeDistributionBuild(t, svc, distribution, nil)
|
||||
|
||||
actions, err := svc.GetServerRuntimeActionsForSession(session, instance.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("get runtime actions: %v", err)
|
||||
}
|
||||
for _, action := range actions.Actions {
|
||||
if action.Key == "generate-run" && action.Available {
|
||||
t.Fatalf("stale Run endpoint must not expose generate-run as available: %+v", action)
|
||||
if action.Key == "generate-run" && !action.Available {
|
||||
t.Fatalf("stale Run endpoint must not gate platform build availability: %+v", action)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,14 +207,13 @@ func TestCoreServiceRuntimeActionsGateDependenciesOnPluginPermission(t *testing.
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreServiceDistributionBuildRejectsPrematureSuccessAndCanRetryAfterUpload(t *testing.T) {
|
||||
t.Setenv("PLATFORM_RUN_RELEASE_URL", "https://scum.npc0.com")
|
||||
func TestCoreServiceMachineEndpointCannotClaimPlatformDistributionBuild(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",
|
||||
IdempotencyKey: "idem-platform-build-ownership",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("generate run distribution: %v", err)
|
||||
@@ -223,7 +223,7 @@ func TestCoreServiceDistributionBuildRejectsPrematureSuccessAndCanRetryAfterUplo
|
||||
helloRequest.CapabilityReport.Capabilities = append(helloRequest.CapabilityReport.Capabilities, domain.JobCapabilityDistributionBuild)
|
||||
hello, err := svc.RegisterRunHello(helloRequest)
|
||||
if err != nil {
|
||||
t.Fatalf("register build worker: %v", err)
|
||||
t.Fatalf("register machine endpoint: %v", err)
|
||||
}
|
||||
claim, err := svc.ClaimRunJob(domain.RunJobClaim{
|
||||
RunEndpointID: instance.RunEndpointID,
|
||||
@@ -231,50 +231,21 @@ func TestCoreServiceDistributionBuildRejectsPrematureSuccessAndCanRetryAfterUplo
|
||||
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)
|
||||
}
|
||||
buildInput, err := svc.GetDistributionBuildInput(domain.DistributionBuildInputRequest{
|
||||
RunEndpointID: claim.Job.RunEndpointID,
|
||||
SessionToken: hello.SessionToken,
|
||||
JobID: claim.Job.JobID,
|
||||
LeaseToken: claim.Job.LeaseToken,
|
||||
Attempt: claim.Job.Attempt,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("get distribution build input: %v", err)
|
||||
t.Fatalf("claim machine-side build: %v", err)
|
||||
}
|
||||
if buildInput.PlatformURL != "https://scum.npc0.com" || buildInput.PackageFormat != "raw-executable" || buildInput.AuthKey == "" || len(buildInput.AuthKey) < 80 {
|
||||
t.Fatalf("expected raw executable build input with release URL and long key, got %+v", buildInput)
|
||||
}
|
||||
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 claim.HasJob {
|
||||
t.Fatalf("machine-side endpoint must not receive platform build job: %+v", claim)
|
||||
}
|
||||
|
||||
if _, err := svc.createPlatformArtifactPayload(distribution.ArtifactID, domain.ArtifactOwnerKindJob, distribution.BuildJobID, []byte("actual compiled archive")); err != nil {
|
||||
t.Fatalf("publish uploaded build output: %v", err)
|
||||
distribution = completeDistributionBuild(t, svc, distribution, nil)
|
||||
job, err := svc.GetJob(distribution.BuildJobID)
|
||||
if err != nil || job.State != domain.JobStateSucceeded || job.RunEndpointID != platformDistributionBuilderEndpointID {
|
||||
t.Fatalf("expected completed platform build job, job=%+v err=%v", job, 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)
|
||||
artifact, err := svc.GetArtifact(distribution.ArtifactID)
|
||||
if err != nil || artifact.OwnerKind != domain.ArtifactOwnerKindJob || artifact.OwnerID != job.ID {
|
||||
t.Fatalf("expected build job-owned artifact, artifact=%+v err=%v", artifact, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,6 +319,8 @@ func TestCoreServiceRunDistributionRetryReusesPartialArtifact(t *testing.T) {
|
||||
|
||||
func TestCoreServicePushRunUpdateReusesExistingUpdateJob(t *testing.T) {
|
||||
svc, session, instance := newDistributionTestFixture(t)
|
||||
payload := []byte("compiled run archive")
|
||||
svc.ConfigureDistributionBuilder(staticDistributionBuilder{payload: payload})
|
||||
distribution, err := svc.GenerateRunDistributionForSession(session, domain.RunDistributionGenerateRequest{
|
||||
ServerInstanceID: instance.ID,
|
||||
TargetOS: "linux",
|
||||
@@ -357,7 +330,7 @@ func TestCoreServicePushRunUpdateReusesExistingUpdateJob(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("generate run distribution: %v", err)
|
||||
}
|
||||
distribution = completeDistributionBuild(t, svc, distribution, []byte("compiled run archive"))
|
||||
distribution = completeDistributionBuild(t, svc, distribution, payload)
|
||||
|
||||
request := domain.RunUpdateRequest{
|
||||
ServerInstanceID: instance.ID,
|
||||
@@ -624,7 +597,6 @@ func newDistributionTestFixture(t *testing.T) (*CoreService, string, domain.Serv
|
||||
t.Fatalf("update plugin fixture: %v", err)
|
||||
}
|
||||
endpoint.Capabilities = append(endpoint.Capabilities,
|
||||
domain.JobCapabilityDistributionBuild,
|
||||
domain.JobCapabilityRunSelfUpdate,
|
||||
domain.JobCapabilityDependenciesCheck,
|
||||
domain.JobCapabilityDependenciesInstall,
|
||||
@@ -704,58 +676,44 @@ func readGeneratedPackageConfig(t *testing.T, svc *CoreService, session string,
|
||||
return generatedPackageConfig{}
|
||||
}
|
||||
|
||||
func completeDistributionBuild(t *testing.T, svc *CoreService, distribution domain.RunDistribution, payload []byte) domain.RunDistribution {
|
||||
func completeDistributionBuild(t *testing.T, svc *CoreService, distribution domain.RunDistribution, _ []byte) domain.RunDistribution {
|
||||
t.Helper()
|
||||
artifact, err := svc.createPlatformArtifactPayload(distribution.ArtifactID, domain.ArtifactOwnerKindJob, distribution.BuildJobID, payload)
|
||||
if err != nil {
|
||||
t.Fatalf("publish run build artifact: %v", err)
|
||||
deadline := time.Now().Add(time.Second)
|
||||
for time.Now().Before(deadline) {
|
||||
updated, err := svc.store.RunDistributions().Get(distribution.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("get run distribution: %v", err)
|
||||
}
|
||||
if updated.Status == domain.DistributionStatusAvailable {
|
||||
return updated
|
||||
}
|
||||
if updated.Status == domain.DistributionStatusFailed {
|
||||
t.Fatalf("platform run build failed: %+v", updated)
|
||||
}
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
job, err := svc.GetJob(distribution.BuildJobID)
|
||||
if err != nil {
|
||||
t.Fatalf("get run build job: %v", err)
|
||||
}
|
||||
job.State = domain.JobStateSucceeded
|
||||
job.Progress = domain.JobProgress{Percent: 100, Message: "package_finalize: build artifact available"}
|
||||
job.ResultRef = "artifact://" + artifact.ID
|
||||
job.UpdatedAt = svc.now()
|
||||
if err := svc.store.Jobs().Update(job); err != nil {
|
||||
t.Fatalf("update run build job: %v", err)
|
||||
}
|
||||
if err := svc.projectDistributionBuildResult(job, svc.now()); err != nil {
|
||||
t.Fatalf("project run build: %v", err)
|
||||
}
|
||||
updated, err := svc.store.RunDistributions().Get(distribution.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("get completed run distribution: %v", err)
|
||||
}
|
||||
return updated
|
||||
t.Fatalf("platform run build did not complete")
|
||||
return domain.RunDistribution{}
|
||||
}
|
||||
|
||||
func completeClientDistributionBuild(t *testing.T, svc *CoreService, distribution domain.ClientManagerDistribution, payload []byte) domain.ClientManagerDistribution {
|
||||
func completeClientDistributionBuild(t *testing.T, svc *CoreService, distribution domain.ClientManagerDistribution, _ []byte) domain.ClientManagerDistribution {
|
||||
t.Helper()
|
||||
artifact, err := svc.createPlatformArtifactPayload(distribution.ArtifactID, domain.ArtifactOwnerKindJob, distribution.BuildJobID, payload)
|
||||
if err != nil {
|
||||
t.Fatalf("publish client build artifact: %v", err)
|
||||
deadline := time.Now().Add(time.Second)
|
||||
for time.Now().Before(deadline) {
|
||||
updated, err := svc.store.ClientManagerDistributions().Get(distribution.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("get client distribution: %v", err)
|
||||
}
|
||||
if updated.Status == domain.DistributionStatusAvailable {
|
||||
return updated
|
||||
}
|
||||
if updated.Status == domain.DistributionStatusFailed {
|
||||
t.Fatalf("platform client build failed: %+v", updated)
|
||||
}
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
job, err := svc.GetJob(distribution.BuildJobID)
|
||||
if err != nil {
|
||||
t.Fatalf("get client build job: %v", err)
|
||||
}
|
||||
job.State = domain.JobStateSucceeded
|
||||
job.Progress = domain.JobProgress{Percent: 100, Message: "package_finalize: build artifact available"}
|
||||
job.ResultRef = "artifact://" + artifact.ID
|
||||
job.UpdatedAt = svc.now()
|
||||
if err := svc.store.Jobs().Update(job); err != nil {
|
||||
t.Fatalf("update client build job: %v", err)
|
||||
}
|
||||
if err := svc.projectDistributionBuildResult(job, svc.now()); err != nil {
|
||||
t.Fatalf("project client build: %v", err)
|
||||
}
|
||||
updated, err := svc.store.ClientManagerDistributions().Get(distribution.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("get completed client distribution: %v", err)
|
||||
}
|
||||
return updated
|
||||
t.Fatalf("platform client build did not complete")
|
||||
return domain.ClientManagerDistribution{}
|
||||
}
|
||||
|
||||
func TestCoreServiceDeniesRunDistributionWithoutPluginDeclaration(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user