Пример #1
0
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
}
Пример #2
0
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
}