// GetNextConfigBuild returns the build that will be executed next for the given // build configuration. It also returns the indication whether there are // currently running builds, to make sure there is no race-condition between // re-listing the builds. func GetNextConfigBuild(lister buildclient.BuildLister, namespace, buildConfigName string) (*buildapi.Build, bool, error) { var ( nextBuild *buildapi.Build hasRunningBuilds bool previousBuildNumber int64 ) builds, err := buildutil.BuildConfigBuilds(lister, namespace, buildConfigName, func(b buildapi.Build) bool { switch b.Status.Phase { case buildapi.BuildPhasePending, buildapi.BuildPhaseRunning: hasRunningBuilds = true return false } // Only 'new' build can be scheduled to run next return b.Status.Phase == buildapi.BuildPhaseNew }) if err != nil { return nil, hasRunningBuilds, err } for i, b := range builds.Items { buildNumber, err := buildutil.BuildNumber(&b) if err != nil { return nil, hasRunningBuilds, err } if previousBuildNumber == 0 || buildNumber < previousBuildNumber { nextBuild = &builds.Items[i] previousBuildNumber = buildNumber } } return nextBuild, hasRunningBuilds, nil }
// cancelPreviousBuilds cancels all queued builds that have the build sequence number // lower than the given build. It retries the cancellation in case of conflict. func (s *SerialLatestOnlyPolicy) cancelPreviousBuilds(build *buildapi.Build) []error { bcName := buildutil.ConfigNameForBuild(build) if len(bcName) == 0 { return []error{} } currentBuildNumber, err := buildutil.BuildNumber(build) if err != nil { return []error{NewNoBuildNumberAnnotationError(build)} } builds, err := buildutil.BuildConfigBuilds(s.BuildLister, build.Namespace, bcName, func(b buildapi.Build) bool { // Do not cancel the complete builds, builds that were already cancelled, or // running builds. if buildutil.IsBuildComplete(&b) || b.Status.Phase == buildapi.BuildPhaseRunning { return false } // Prevent race-condition when there is a newer build than this and we don't // want to cancel it. The HandleBuild() function that runs for that build // will cancel this build. buildNumber, _ := buildutil.BuildNumber(&b) return buildNumber < currentBuildNumber }) if err != nil { return []error{err} } var result = []error{} for _, b := range builds.Items { err := wait.Poll(500*time.Millisecond, 5*time.Second, func() (bool, error) { b.Status.Cancelled = true err := s.BuildUpdater.Update(b.Namespace, &b) if err != nil && errors.IsConflict(err) { glog.V(5).Infof("Error cancelling build %s/%s: %v (will retry)", b.Namespace, b.Name, err) return false, nil } return true, err }) if err != nil { result = append(result, err) } } return result }
// GetNextConfigBuild returns the build that will be executed next for the given // build configuration. It also returns the indication whether there are // currently running builds, to make sure there is no race-condition between // re-listing the builds. func GetNextConfigBuild(lister buildclient.BuildLister, namespace, buildConfigName string) ([]*buildapi.Build, bool, error) { var ( nextBuild *buildapi.Build hasRunningBuilds bool previousBuildNumber int64 ) builds, err := buildutil.BuildConfigBuilds(lister, namespace, buildConfigName, func(b buildapi.Build) bool { switch b.Status.Phase { case buildapi.BuildPhasePending, buildapi.BuildPhaseRunning: hasRunningBuilds = true return false } // Only 'new' build can be scheduled to run next return b.Status.Phase == buildapi.BuildPhaseNew }) if err != nil { return nil, hasRunningBuilds, err } nextParallelBuilds := []*buildapi.Build{} for i, b := range builds.Items { buildNumber, err := buildutil.BuildNumber(&b) if err != nil { return nil, hasRunningBuilds, err } if buildutil.BuildRunPolicy(&b) == buildapi.BuildRunPolicyParallel { nextParallelBuilds = append(nextParallelBuilds, &builds.Items[i]) } if previousBuildNumber == 0 || buildNumber < previousBuildNumber { nextBuild = &builds.Items[i] previousBuildNumber = buildNumber } } nextBuilds := []*buildapi.Build{} // if the next build is a parallel build, then start all the queued parallel builds, // otherwise just start the next build if there is one. if nextBuild != nil && buildutil.BuildRunPolicy(nextBuild) == buildapi.BuildRunPolicyParallel { nextBuilds = nextParallelBuilds } else if nextBuild != nil { nextBuilds = append(nextBuilds, nextBuild) } return nextBuilds, hasRunningBuilds, nil }