Example #1
0
// 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
}
Example #2
0
// 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
}
Example #3
0
// 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
}