func (s jobService) getBuildInputs(logger lager.Logger, build db.Build, buildPrep db.BuildPreparation, versions *algorithm.VersionsDB) ([]db.BuildInput, db.BuildPreparation, string, error) { buildInputs := config.JobInputs(s.JobConfig) if versions == nil { for _, input := range buildInputs { buildPrep.Inputs[input.Name] = db.BuildPreparationStatusUnknown } err := s.DB.UpdateBuildPreparation(buildPrep) if err != nil { return nil, buildPrep, "failed-to-update-build-prep-with-inputs", err } for _, input := range buildInputs { scanLog := logger.Session("scan", lager.Data{ "input": input.Name, "resource": input.Resource, }) buildPrep = s.cloneBuildPrep(buildPrep) buildPrep.Inputs[input.Name] = db.BuildPreparationStatusBlocking err := s.DB.UpdateBuildPreparation(buildPrep) if err != nil { return nil, buildPrep, "failed-to-update-build-prep-with-blocking-input", err } err = s.Scanner.Scan(scanLog, input.Resource) if err != nil { return nil, buildPrep, "failed-to-scan", err } buildPrep = s.cloneBuildPrep(buildPrep) buildPrep.Inputs[input.Name] = db.BuildPreparationStatusNotBlocking err = s.DB.UpdateBuildPreparation(buildPrep) if err != nil { return nil, buildPrep, "failed-to-update-build-prep-with-not-blocking-input", err } scanLog.Info("done") } loadStart := time.Now() vLog := logger.Session("loading-versions") vLog.Info("start") versions, err = s.DB.LoadVersionsDB() if err != nil { vLog.Error("failed", err) return nil, buildPrep, "failed-to-load-versions-db", err } vLog.Info("done", lager.Data{"took": time.Since(loadStart).String()}) } else { for _, input := range buildInputs { buildPrep.Inputs[input.Name] = db.BuildPreparationStatusNotBlocking } err := s.DB.UpdateBuildPreparation(buildPrep) if err != nil { return nil, buildPrep, "failed-to-update-build-prep-with-discovered-inputs", err } } buildPrep.InputsSatisfied = db.BuildPreparationStatusBlocking err := s.DB.UpdateBuildPreparation(buildPrep) if err != nil { return nil, buildPrep, "failed-to-update-build-prep-with-discovered-inputs", err } inputs, message, err := s.determineInputs(versions, buildInputs, build) if err != nil || message != "" { return nil, buildPrep, message, err } buildPrep.InputsSatisfied = db.BuildPreparationStatusNotBlocking err = s.DB.UpdateBuildPreparation(buildPrep) if err != nil { return nil, buildPrep, "failed-to-update-build-prep-with-inputs-satisfied", err } return inputs, buildPrep, "", nil }
func (s jobService) CanBuildBeScheduled(logger lager.Logger, build db.Build, buildPrep db.BuildPreparation, versions *algorithm.VersionsDB) ([]db.BuildInput, bool, string, error) { if build.Scheduled { return s.updateBuildPrepAndReturn(buildPrep, true, "build-scheduled") } paused, err := s.DB.IsPaused() if err != nil { return []db.BuildInput{}, false, "pause-pipeline-db-failed", err } if paused { buildPrep.PausedPipeline = db.BuildPreparationStatusBlocking return s.updateBuildPrepAndReturn(buildPrep, false, "pipeline-paused") } buildPrep.PausedPipeline = db.BuildPreparationStatusNotBlocking err = s.DB.UpdateBuildPreparation(buildPrep) if err != nil { return []db.BuildInput{}, false, "update-build-prep-db-failed-pipeline-not-paused", err } if s.DBJob.Paused { buildPrep.PausedJob = db.BuildPreparationStatusBlocking return s.updateBuildPrepAndReturn(buildPrep, false, "job-paused") } buildPrep.PausedJob = db.BuildPreparationStatusNotBlocking err = s.DB.UpdateBuildPreparation(buildPrep) if err != nil { return []db.BuildInput{}, false, "update-build-prep-db-failed-job-not-paused", err } if build.Status != db.StatusPending { return []db.BuildInput{}, false, "build-not-pending", nil } buildInputs, buildPrep, message, err := s.getBuildInputs(logger, build, buildPrep, versions) if err != nil || message != "" { return []db.BuildInput{}, false, message, err } buildPrep.MaxRunningBuilds = db.BuildPreparationStatusBlocking err = s.DB.UpdateBuildPreparation(buildPrep) if err != nil { return []db.BuildInput{}, false, "update-build-prep-db-failed-pipeline-not-paused", err } maxInFlight := s.JobConfig.MaxInFlight() if maxInFlight > 0 { builds, err := s.DB.GetRunningBuildsBySerialGroup(s.DBJob.Name, s.JobConfig.GetSerialGroups()) if err != nil { return []db.BuildInput{}, false, "db-failed", err } if len(builds) >= maxInFlight { buildPrep.MaxRunningBuilds = db.BuildPreparationStatusBlocking return s.updateBuildPrepAndReturn(buildPrep, false, "max-in-flight-reached") } nextMostPendingBuild, found, err := s.DB.GetNextPendingBuildBySerialGroup(s.DBJob.Name, s.JobConfig.GetSerialGroups()) if err != nil { return []db.BuildInput{}, false, "db-failed", err } if !found { return []db.BuildInput{}, false, "no-pending-build", nil } if nextMostPendingBuild.ID != build.ID { return []db.BuildInput{}, false, "not-next-most-pending", nil } } buildPrep.MaxRunningBuilds = db.BuildPreparationStatusNotBlocking err = s.DB.UpdateBuildPreparation(buildPrep) if err != nil { return []db.BuildInput{}, false, "update-build-prep-db-failed-not-max-running-builds", err } return buildInputs, true, "can-be-scheduled", nil }