label_sync/main.go
func (ru RepoUpdates) DoUpdates(org string, gc client) error {
	var numUpdates int
	for _, updates := range ru {
		numUpdates += len(updates)
	}

	updateChan := make(chan repoUpdate, numUpdates)
	for repo, updates := range ru {
		logrus.WithField("org", org).WithField("repo", repo).Infof("Applying %d changes", len(updates))
		for _, item := range updates {
			updateChan <- repoUpdate{repo: repo, update: item}
		}
	}
	close(updateChan)

	wg := sync.WaitGroup{}
	wg.Add(maxConcurrentWorkers)
	errChan := make(chan error, numUpdates)
	for i := 0; i < maxConcurrentWorkers; i++ {
		go func(updates <-chan repoUpdate) {
			defer wg.Done()
			for item := range updates {
				repo := item.repo
				update := item.update
				logrus.WithField("org", org).WithField("repo", repo).WithField("why", update.Why).Debug("running update")
				switch update.Why {
				case "missing":
					err := gc.AddRepoLabel(org, repo, update.Wanted.Name, update.Wanted.Description, update.Wanted.Color)
					if err != nil {
						errChan <- err
					}
				case "change", "rename":
					err := gc.UpdateRepoLabel(org, repo, update.Current.Name, update.Wanted.Name, update.Wanted.Description, update.Wanted.Color)
					if err != nil {
						errChan <- err
					}
				case "dead":
					err := gc.DeleteRepoLabel(org, repo, update.Current.Name)
					if err != nil {
						errChan <- err
					}
				case "migrate":
					issues, err := gc.FindIssues(fmt.Sprintf("is:open repo:%s/%s label:\"%s\" -label:\"%s\"", org, repo, update.Current.Name, update.Wanted.Name), "", false)
					if err != nil {
						errChan <- err
					}
					if len(issues) == 0 {
						if err = gc.DeleteRepoLabel(org, repo, update.Current.Name); err != nil {
							errChan <- err
						}
					}
					for _, i := range issues {
						if err = gc.AddLabel(org, repo, i.Number, update.Wanted.Name); err != nil {
							errChan <- err
							continue
						}
						if err = gc.RemoveLabel(org, repo, i.Number, update.Current.Name); err != nil {
							errChan <- err
						}
					}
				default:
					errChan <- errors.New("unknown label operation: " + update.Why)
				}
			}
		}(updateChan)
	}

	wg.Wait()
	close(errChan)

	var overallErr error
	if len(errChan) > 0 {
		var updateErrs []error
		for updateErr := range errChan {
			updateErrs = append(updateErrs, updateErr)
		}
		overallErr = fmt.Errorf("failed to list labels: %v", updateErrs)
	}

	return overallErr
}
func (ru RepoUpdates) DoUpdates(org string, gc client) error {
	var numUpdates int
	for _, updates := range ru {
		numUpdates += len(updates)
	}

	updateChan := make(chan repoUpdate, numUpdates)
	for repo, updates := range ru {
		logrus.WithField("org", org).WithField("repo", repo).Infof("Applying %d changes", len(updates))
		for _, item := range updates {
			updateChan <- repoUpdate{repo: repo, update: item}
		}
	}
	close(updateChan)

	wg := sync.WaitGroup{}
	wg.Add(maxConcurrentWorkers)
	errChan := make(chan error, numUpdates)
	for i := 0; i < maxConcurrentWorkers; i++ {
		go func(updates <-chan repoUpdate) {
			defer wg.Done()
			for item := range updates {
				repo := item.repo
				update := item.update
				logrus.WithField("org", org).WithField("repo", repo).WithField("why", update.Why).Debug("running update")
				switch update.Why {
				case "missing":
					err := gc.AddRepoLabel(org, repo, update.Wanted.Name, update.Wanted.Description, update.Wanted.Color)
					if err != nil {
						errChan <- err
					}
				case "change", "rename":
					err := gc.UpdateRepoLabel(org, repo, update.Current.Name, update.Wanted.Name, update.Wanted.Description, update.Wanted.Color)
					if err != nil {
						errChan <- err
					}
				case "dead":
					err := gc.DeleteRepoLabel(org, repo, update.Current.Name)
					if err != nil {
						errChan <- err
					}
				case "migrate":
					issues, err := gc.FindIssues(fmt.Sprintf("is:open repo:%s/%s label:\"%s\" -label:\"%s\"", org, repo, update.Current.Name, update.Wanted.Name), "", false)
					if err != nil {
						errChan <- err
					}
					if len(issues) == 0 {
						if err = gc.DeleteRepoLabel(org, repo, update.Current.Name); err != nil {
							errChan <- err
						}
					}
					for _, i := range issues {
						if err = gc.AddLabel(org, repo, i.Number, update.Wanted.Name); err != nil {
							errChan <- err
							continue
						}
						if err = gc.RemoveLabel(org, repo, i.Number, update.Current.Name); err != nil {
							errChan <- err
						}
					}
				default:
					errChan <- errors.New("unknown label operation: " + update.Why)
				}
			}
		}(updateChan)
	}

	wg.Wait()
	close(errChan)

	var overallErr error
	if len(errChan) > 0 {
		var updateErrs []error
		for updateErr := range errChan {
			updateErrs = append(updateErrs, updateErr)
		}
		overallErr = fmt.Errorf("failed to list labels: %v", updateErrs)
	}

	return overallErr
}
func ( ru RepoUpdates ) DoUpdates ( org string , gc client ) error { var numUpdates int for _ , updates := range ru { numUpdates += len ( updates ) } updateChan := make ( chan repoUpdate , numUpdates ) for repo , updates := range ru { logrus . WithField ( " " , org ) . WithField ( " " , repo ) . Infof ( " " , len ( updates ) ) for _ , item := range updates { updateChan <- repoUpdate { repo : repo , update : item } } } close ( updateChan ) wg := sync . WaitGroup { } wg . Add ( maxConcurrentWorkers ) errChan := make ( chan error , numUpdates ) for i := 0 ; i < maxConcurrentWorkers ; i ++ { go func ( updates <- chan repoUpdate ) { defer wg . Done ( ) for item := range updates { repo := item . repo update := item . update logrus . WithField ( " " , org ) . WithField ( " " , repo ) . WithField ( " " , update . Why ) . Debug ( " " ) switch update . Why { case " " : err := gc . AddRepoLabel ( org , repo , update . Wanted . Name , update . Wanted . Description , update . Wanted . Color ) if err != nil { errChan <- err } case " " , " " : err := gc . UpdateRepoLabel ( org , repo , update . Current . Name , update . Wanted . Name , update . Wanted . Description , update . Wanted . Color ) if err != nil { errChan <- err } case " " : err := gc . DeleteRepoLabel ( org , repo , update . Current . Name ) if err != nil { errChan <- err } case " " : issues , err := gc . FindIssues ( fmt . Sprintf ( " \" \" \" \" " , org , repo , update . Current . Name , update . Wanted . Name ) , " " , false ) if err != nil { errChan <- err } if len ( issues ) == 0 { if err = gc . DeleteRepoLabel ( org , repo , update . Current . Name ) ; err != nil { errChan <- err } } for _ , i := range issues { if err = gc . AddLabel ( org , repo , i . Number , update . Wanted . Name ) ; err != nil { errChan <- err continue } if err = gc . RemoveLabel ( org , repo , i . Number , update . Current . Name ) ; err != nil { errChan <- err } } default : errChan <- errors . New ( " " + update . Why ) } } } ( updateChan ) } wg . Wait ( ) close ( errChan ) var overallErr error if len ( errChan ) > 0 { var updateErrs [ ] error for updateErr := range errChan { updateErrs = append ( updateErrs , updateErr ) } overallErr = fmt . Errorf ( " " , updateErrs ) } return overallErr }
// DoUpdates iterates generated update data and adds and/or modifies labels on repositories
// Uses AddLabel GH API to add missing labels
// And UpdateLabel GH API to update color or name (name only when case differs)
DoUpdates iterates generated update data and adds and / or modifies labels on repositories Uses AddLabel GH API to add missing labels And UpdateLabel GH API to update color or name ( name only when case differs )