func Job(dbJob db.SavedJob, job atc.JobConfig, groups atc.GroupConfigs, finishedBuild, nextBuild *db.Build) atc.Job { generator := rata.NewRequestGenerator("", routes.Routes) req, err := generator.CreateRequest( routes.GetJob, rata.Params{"job": job.Name, "pipeline_name": dbJob.PipelineName}, nil, ) if err != nil { panic("failed to generate url: " + err.Error()) } var presentedNextBuild, presentedFinishedBuild *atc.Build if nextBuild != nil { presented := Build(*nextBuild) presentedNextBuild = &presented } if finishedBuild != nil { presented := Build(*finishedBuild) presentedFinishedBuild = &presented } groupNames := []string{} for _, group := range groups { for _, name := range group.Jobs { if name == job.Name { groupNames = append(groupNames, group.Name) } } } return atc.Job{ Name: job.Name, URL: req.URL.String(), Paused: dbJob.Paused, FinishedBuild: presentedFinishedBuild, NextBuild: presentedNextBuild, Inputs: job.Inputs(), Outputs: job.Outputs(), Groups: groupNames, } }
func (s *Scheduler) BuildLatestInputs(logger lager.Logger, job atc.JobConfig, resources atc.ResourceConfigs) error { logger = logger.Session("build-latest") inputs := job.Inputs() if len(inputs) == 0 { // no inputs; no-op return nil } latestInputs, err := s.PipelineDB.GetLatestInputVersions(job.Name, inputs) if err != nil { if err == db.ErrNoVersions { logger.Debug("no-input-versions-available") return nil } logger.Error("failed-to-get-latest-input-versions", err) return err } checkInputs := []db.BuildInput{} for _, input := range latestInputs { for _, ji := range inputs { if ji.Name == input.Name { if ji.Trigger { checkInputs = append(checkInputs, input) } break } } } if len(checkInputs) == 0 { logger.Debug("no-triggered-input-versions") return nil } existingBuild, err := s.PipelineDB.GetJobBuildForInputs(job.Name, checkInputs) if err == nil { logger.Debug("build-already-exists-for-inputs", lager.Data{ "existing-build": existingBuild.ID, }) return nil } build, created, err := s.PipelineDB.CreateJobBuildForCandidateInputs(job.Name) if err != nil { logger.Error("failed-to-create-build", err) return err } if !created { logger.Debug("waiting-for-existing-build-to-determine-inputs", lager.Data{ "existing-build": build.ID, }) return nil } logger.Debug("created-build", lager.Data{"build": build.ID}) // NOTE: this is intentionally serial within a scheduler tick, so that // multiple ATCs don't do redundant work to determine a build's inputs. s.scheduleAndResumePendingBuild(logger, build, job, resources) return nil }
func (s *Scheduler) scheduleAndResumePendingBuild(logger lager.Logger, build db.Build, job atc.JobConfig, resources atc.ResourceConfigs) engine.Build { logger = logger.WithData(lager.Data{"build": build.ID}) scheduled, err := s.PipelineDB.ScheduleBuild(build.ID, job) if err != nil { logger.Error("failed-to-schedule-build", err) return nil } if !scheduled { logger.Debug("build-could-not-be-scheduled") return nil } buildInputs := job.Inputs() for _, input := range buildInputs { scanLog := logger.Session("scan", lager.Data{ "input": input.Name, "resource": input.Resource, }) err := s.Scanner.Scan(scanLog, input.Resource) if err != nil { scanLog.Error("failed-to-scan", err) err := s.BuildsDB.ErrorBuild(build.ID, err) if err != nil { logger.Error("failed-to-mark-build-as-errored", err) } return nil } scanLog.Info("done") } inputs, err := s.PipelineDB.GetLatestInputVersions(job.Name, buildInputs) if err != nil { logger.Error("failed-to-get-latest-input-versions", err) return nil } err = s.PipelineDB.UseInputsForBuild(build.ID, inputs) if err != nil { logger.Error("failed-to-use-inputs-for-build", err) return nil } plan, err := s.Factory.Create(job, resources, inputs) if err != nil { logger.Error("failed-to-create-build-plan", err) return nil } createdBuild, err := s.Engine.CreateBuild(build, plan) if err != nil { logger.Error("failed-to-create-build", err) return nil } if createdBuild != nil { logger.Info("building") go createdBuild.Resume(logger) } return createdBuild }
func (s *Scheduler) BuildLatestInputs(logger lager.Logger, job atc.JobConfig, resources atc.ResourceConfigs) error { logger = logger.Session("build-latest") inputs := job.Inputs() if len(inputs) == 0 { // no inputs; no-op return nil } latestInputs, err := s.PipelineDB.GetLatestInputVersions(inputs) if err != nil { if err == db.ErrNoVersions { logger.Debug("no-input-versions-available") return nil } logger.Error("failed-to-get-latest-input-versions", err) return err } checkInputs := []db.BuildInput{} for _, input := range latestInputs { for _, ji := range inputs { if ji.Name == input.Name { if ji.Trigger { checkInputs = append(checkInputs, input) } break } } } if len(checkInputs) == 0 { logger.Debug("no-triggered-input-versions") return nil } existingBuild, err := s.PipelineDB.GetJobBuildForInputs(job.Name, checkInputs) if err == nil { logger.Debug("build-already-exists-for-inputs", lager.Data{ "existing-build": existingBuild.ID, }) return nil } build, created, err := s.PipelineDB.CreateJobBuildForCandidateInputs(job.Name) if err != nil { logger.Error("failed-to-create-build", err) return err } if !created { logger.Debug("did-not-create-build-as-it-already-is-pending") return nil } logger = logger.WithData(lager.Data{"build": build.ID}) logger.Debug("created-build") createdBuild := s.scheduleAndResumePendingBuild(logger, build, job, resources) if createdBuild != nil { logger.Info("building") go createdBuild.Resume(logger) } return nil }