// 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 }
// hasRunningSerialBuild indicates that there is a running or pending serial // build. This function is used to prevent running parallel builds because // serial builds should always run alone. func hasRunningSerialBuild(lister buildclient.BuildLister, namespace, buildConfigName string) bool { var hasRunningBuilds bool buildutil.BuildConfigBuilds(lister, namespace, buildConfigName, func(b buildapi.Build) bool { switch b.Status.Phase { case buildapi.BuildPhasePending, buildapi.BuildPhaseRunning: switch buildutil.BuildRunPolicy(&b) { case buildapi.BuildRunPolicySerial, buildapi.BuildRunPolicySerialLatestOnly: hasRunningBuilds = true } } return false }) return hasRunningBuilds }
// ForBuild picks the appropriate run policy for the given build. func ForBuild(build *buildapi.Build, policies []RunPolicy) RunPolicy { for _, s := range policies { switch buildutil.BuildRunPolicy(build) { case buildapi.BuildRunPolicyParallel: if _, ok := s.(*ParallelPolicy); ok { glog.V(5).Infof("Using %T run policy for build %s/%s", s, build.Namespace, build.Name) return s } case buildapi.BuildRunPolicySerial: if _, ok := s.(*SerialPolicy); ok { glog.V(5).Infof("Using %T run policy for build %s/%s", s, build.Namespace, build.Name) return s } case buildapi.BuildRunPolicySerialLatestOnly: if _, ok := s.(*SerialLatestOnlyPolicy); ok { glog.V(5).Infof("Using %T run policy for build %s/%s", s, build.Namespace, build.Name) return s } } } return nil }