prow/pjutil/abort.go
func TerminateOlderPresubmitJobs(pjc prowClient, log *logrus.Entry, pjs []prowapi.ProwJob,
	cleanup ProwJobResourcesCleanup) error {
	dupes := map[jobIndentifier]int{}
	for i, pj := range pjs {
		if pj.Complete() || pj.Spec.Type != prowapi.PresubmitJob {
			continue
		}

		ji := jobIndentifier{
			job:          pj.Spec.Job,
			organization: pj.Spec.Refs.Org,
			repository:   pj.Spec.Refs.Repo,
			pullRequest:  pj.Spec.Refs.Pulls[0].Number,
		}
		prev, ok := dupes[ji]
		if !ok {
			dupes[ji] = i
			continue
		}
		cancelIndex := i
		if (&pjs[prev].Status.StartTime).Before(&pj.Status.StartTime) {
			cancelIndex = prev
			dupes[ji] = i
		}
		toCancel := pjs[cancelIndex]

		// TODO cancel the prow job before cleaning up its resources and make this system
		// independent.
		// See this discussion for more details:  https://github.com/kubernetes/test-infra/pull/11451#discussion_r263523932
		if err := cleanup(toCancel); err != nil {
			log.WithError(err).WithFields(ProwJobFields(&toCancel)).Warn("Cannot clean up job resources")
		}

		toCancel.SetComplete()
		prevState := toCancel.Status.State
		toCancel.Status.State = prowapi.AbortedState
		log.WithFields(ProwJobFields(&toCancel)).
			WithField("from", prevState).
			WithField("to", toCancel.Status.State).Info("Transitioning states")

		npj, err := pjc.ReplaceProwJob(toCancel.ObjectMeta.Name, toCancel)
		if err != nil {
			return err
		}
		pjs[cancelIndex] = npj
	}

	return nil
}
func TerminateOlderPresubmitJobs(pjc prowClient, log *logrus.Entry, pjs []prowapi.ProwJob,
	cleanup ProwJobResourcesCleanup) error {
	dupes := map[jobIndentifier]int{}
	for i, pj := range pjs {
		if pj.Complete() || pj.Spec.Type != prowapi.PresubmitJob {
			continue
		}

		ji := jobIndentifier{
			job:          pj.Spec.Job,
			organization: pj.Spec.Refs.Org,
			repository:   pj.Spec.Refs.Repo,
			pullRequest:  pj.Spec.Refs.Pulls[0].Number,
		}
		prev, ok := dupes[ji]
		if !ok {
			dupes[ji] = i
			continue
		}
		cancelIndex := i
		if (&pjs[prev].Status.StartTime).Before(&pj.Status.StartTime) {
			cancelIndex = prev
			dupes[ji] = i
		}
		toCancel := pjs[cancelIndex]

		// TODO cancel the prow job before cleaning up its resources and make this system
		// independent.
		// See this discussion for more details:  https://github.com/kubernetes/test-infra/pull/11451#discussion_r263523932
		if err := cleanup(toCancel); err != nil {
			log.WithError(err).WithFields(ProwJobFields(&toCancel)).Warn("Cannot clean up job resources")
		}

		toCancel.SetComplete()
		prevState := toCancel.Status.State
		toCancel.Status.State = prowapi.AbortedState
		log.WithFields(ProwJobFields(&toCancel)).
			WithField("from", prevState).
			WithField("to", toCancel.Status.State).Info("Transitioning states")

		npj, err := pjc.ReplaceProwJob(toCancel.ObjectMeta.Name, toCancel)
		if err != nil {
			return err
		}
		pjs[cancelIndex] = npj
	}

	return nil
}
// TerminateOlderPresubmitJobs aborts all presubmit jobs from the given list that have a newer version. It calls
// the cleanup callback for each job before updating its status as aborted.