prow/jenkins/controller.go
func (c *Controller) Sync() error {
	pjs, err := c.prowJobClient.List(metav1.ListOptions{LabelSelector: c.selector})
	if err != nil {
		return fmt.Errorf("error listing prow jobs: %v", err)
	}
	// Share what we have for gathering metrics.
	c.pjLock.Lock()
	c.pjs = pjs.Items
	c.pjLock.Unlock()

	// TODO: Replace the following filtering with a field selector once CRDs support field selectors.
	// https://github.com/kubernetes/kubernetes/issues/53459
	var jenkinsJobs []prowapi.ProwJob
	for _, pj := range pjs.Items {
		if pj.Spec.Agent == prowapi.JenkinsAgent {
			jenkinsJobs = append(jenkinsJobs, pj)
		}
	}
	jbs, err := c.jc.ListBuilds(getJenkinsJobs(jenkinsJobs))
	if err != nil {
		return fmt.Errorf("error listing jenkins builds: %v", err)
	}

	var syncErrs []error
	if err := c.terminateDupes(jenkinsJobs, jbs); err != nil {
		syncErrs = append(syncErrs, err)
	}

	pendingCh, triggeredCh := pjutil.PartitionActive(jenkinsJobs)
	errCh := make(chan error, len(jenkinsJobs))
	reportCh := make(chan prowapi.ProwJob, len(jenkinsJobs))

	// Reinstantiate on every resync of the controller instead of trying
	// to keep this in sync with the state of the world.
	c.pendingJobs = make(map[string]int)
	// Sync pending jobs first so we can determine what is the maximum
	// number of new jobs we can trigger when syncing the non-pendings.
	maxSyncRoutines := c.config().MaxGoroutines
	c.log.Debugf("Handling %d pending prowjobs", len(pendingCh))
	syncProwJobs(c.log, c.syncPendingJob, maxSyncRoutines, pendingCh, reportCh, errCh, jbs)
	c.log.Debugf("Handling %d triggered prowjobs", len(triggeredCh))
	syncProwJobs(c.log, c.syncTriggeredJob, maxSyncRoutines, triggeredCh, reportCh, errCh, jbs)

	close(errCh)
	close(reportCh)

	for err := range errCh {
		syncErrs = append(syncErrs, err)
	}

	var reportErrs []error
	reportTemplate := c.config().ReportTemplate
	reportTypes := c.cfg().GitHubReporter.JobTypesToReport
	for report := range reportCh {
		if err := reportlib.Report(c.ghc, reportTemplate, report, reportTypes); err != nil {
			reportErrs = append(reportErrs, err)
			c.log.WithFields(pjutil.ProwJobFields(&report)).WithError(err).Warn("Failed to report ProwJob status")
		}
	}

	if len(syncErrs) == 0 && len(reportErrs) == 0 {
		return nil
	}
	return fmt.Errorf("errors syncing: %v, errors reporting: %v", syncErrs, reportErrs)
}
func (c *Controller) Sync() error {
	pjs, err := c.prowJobClient.List(metav1.ListOptions{LabelSelector: c.selector})
	if err != nil {
		return fmt.Errorf("error listing prow jobs: %v", err)
	}
	// Share what we have for gathering metrics.
	c.pjLock.Lock()
	c.pjs = pjs.Items
	c.pjLock.Unlock()

	// TODO: Replace the following filtering with a field selector once CRDs support field selectors.
	// https://github.com/kubernetes/kubernetes/issues/53459
	var jenkinsJobs []prowapi.ProwJob
	for _, pj := range pjs.Items {
		if pj.Spec.Agent == prowapi.JenkinsAgent {
			jenkinsJobs = append(jenkinsJobs, pj)
		}
	}
	jbs, err := c.jc.ListBuilds(getJenkinsJobs(jenkinsJobs))
	if err != nil {
		return fmt.Errorf("error listing jenkins builds: %v", err)
	}

	var syncErrs []error
	if err := c.terminateDupes(jenkinsJobs, jbs); err != nil {
		syncErrs = append(syncErrs, err)
	}

	pendingCh, triggeredCh := pjutil.PartitionActive(jenkinsJobs)
	errCh := make(chan error, len(jenkinsJobs))
	reportCh := make(chan prowapi.ProwJob, len(jenkinsJobs))

	// Reinstantiate on every resync of the controller instead of trying
	// to keep this in sync with the state of the world.
	c.pendingJobs = make(map[string]int)
	// Sync pending jobs first so we can determine what is the maximum
	// number of new jobs we can trigger when syncing the non-pendings.
	maxSyncRoutines := c.config().MaxGoroutines
	c.log.Debugf("Handling %d pending prowjobs", len(pendingCh))
	syncProwJobs(c.log, c.syncPendingJob, maxSyncRoutines, pendingCh, reportCh, errCh, jbs)
	c.log.Debugf("Handling %d triggered prowjobs", len(triggeredCh))
	syncProwJobs(c.log, c.syncTriggeredJob, maxSyncRoutines, triggeredCh, reportCh, errCh, jbs)

	close(errCh)
	close(reportCh)

	for err := range errCh {
		syncErrs = append(syncErrs, err)
	}

	var reportErrs []error
	reportTemplate := c.config().ReportTemplate
	reportTypes := c.cfg().GitHubReporter.JobTypesToReport
	for report := range reportCh {
		if err := reportlib.Report(c.ghc, reportTemplate, report, reportTypes); err != nil {
			reportErrs = append(reportErrs, err)
			c.log.WithFields(pjutil.ProwJobFields(&report)).WithError(err).Warn("Failed to report ProwJob status")
		}
	}

	if len(syncErrs) == 0 && len(reportErrs) == 0 {
		return nil
	}
	return fmt.Errorf("errors syncing: %v, errors reporting: %v", syncErrs, reportErrs)
}
// Sync does one sync iteration.