waitForBuild polls the specified build until its provisioner job completes or the context expires.
( ctx context.Context, db database.Store, buildID uuid.UUID, )
| 527 | // waitForBuild polls the specified build until its provisioner job |
| 528 | // completes or the context expires. |
| 529 | func waitForBuild( |
| 530 | ctx context.Context, |
| 531 | db database.Store, |
| 532 | buildID uuid.UUID, |
| 533 | ) error { |
| 534 | buildCtx, cancel := context.WithTimeout(ctx, buildTimeout) |
| 535 | defer cancel() |
| 536 | |
| 537 | ticker := time.NewTicker(buildPollInterval) |
| 538 | defer ticker.Stop() |
| 539 | |
| 540 | for { |
| 541 | build, err := db.GetWorkspaceBuildByID(buildCtx, buildID) |
| 542 | if err != nil { |
| 543 | return xerrors.Errorf("get build: %w", err) |
| 544 | } |
| 545 | |
| 546 | job, err := db.GetProvisionerJobByID(buildCtx, build.JobID) |
| 547 | if err != nil { |
| 548 | return xerrors.Errorf("get provisioner job: %w", err) |
| 549 | } |
| 550 | |
| 551 | switch job.JobStatus { |
| 552 | case database.ProvisionerJobStatusSucceeded: |
| 553 | return nil |
| 554 | case database.ProvisionerJobStatusFailed: |
| 555 | errMsg := "build failed" |
| 556 | if job.Error.Valid { |
| 557 | errMsg = job.Error.String |
| 558 | } |
| 559 | var code codersdk.JobErrorCode |
| 560 | if job.ErrorCode.Valid { |
| 561 | code = codersdk.JobErrorCode(job.ErrorCode.String) |
| 562 | } |
| 563 | return &workspaceBuildError{message: errMsg, code: code} |
| 564 | case database.ProvisionerJobStatusCanceled: |
| 565 | return xerrors.New("build was canceled") |
| 566 | case database.ProvisionerJobStatusPending, |
| 567 | database.ProvisionerJobStatusRunning, |
| 568 | database.ProvisionerJobStatusCanceling: |
| 569 | // Still in progress — keep waiting. |
| 570 | default: |
| 571 | return xerrors.Errorf("unexpected job status: %s", job.JobStatus) |
| 572 | } |
| 573 | |
| 574 | select { |
| 575 | case <-buildCtx.Done(): |
| 576 | return xerrors.Errorf( |
| 577 | "timed out waiting for workspace build: %w", |
| 578 | buildCtx.Err(), |
| 579 | ) |
| 580 | case <-ticker.C: |
| 581 | } |
| 582 | } |
| 583 | } |
| 584 | |
| 585 | func templateHasExternalAgent( |
| 586 | ctx context.Context, |
no test coverage detected