Repository: cli/cli
File: pkg/cmd/issue/edit/edit.go (Go)

Code before:
	editable := opts.Editable
	if opts.Interactive {
		err = opts.FieldsToEditSurvey(opts.Prompter, &editable)
		if err != nil {
			return err
		}
	}

	lookupFields := []string{"id", "number", "title", "body", "url"}
	if editable.Assignees.Edited {
		lookupFields = append(lookupFields, "assignees")
	}
	if editable.Labels.Edited {
		lookupFields = append(lookupFields, "labels")
	}
	if editable.Projects.Edited {
		lookupFields = append(lookupFields, "projectCards")
		lookupFields = append(lookupFields, "projectItems")
	}
	if editable.Milestone.Edited {
		lookupFields = append(lookupFields, "milestone")
	}

	// Get all specified issues and make sure they are within the same repo.
	issues, err := shared.FindIssuesOrPRs(httpClient, baseRepo, opts.IssueNumbers, lookupFields)
	if err != nil {
		return err
	}

	// Fetch editable shared fields once for all issues.
	apiClient := api.NewClientFromHTTP(httpClient)
	opts.IO.StartProgressIndicatorWithLabel("Fetching repository information")
	err = opts.FetchOptions(apiClient, baseRepo, &editable)
	opts.IO.StopProgressIndicator()
	if err != nil {
		return err
	}

	// Update all issues in parallel.
	editedIssueChan := make(chan string, len(issues))
	failedIssueChan := make(chan string, len(issues))
	g := sync.WaitGroup{}

	// Only show progress if we will not prompt below or the survey will break up the progress indicator.
	if !opts.Interactive {
		opts.IO.StartProgressIndicatorWithLabel(fmt.Sprintf("Updating %d issues", len(issues)))
	}

	for _, issue := range issues {
		// Copy variables to capture in the go routine below.
		editable := editable.Clone()

Review comment (refactor):
This has been repeated a few times. I'd rather rely on a non-`nil` `opts.Detector` (if it makes sense), or at least use a shared helper function.

Code after:
		return err
	}

	// Prompt the user which fields they'd like to edit.
	editable := opts.Editable
	if opts.Interactive {
		err = opts.FieldsToEditSurvey(opts.Prompter, &editable)
		if err != nil {
			return err
		}
	}

	lookupFields := []string{"id", "number", "title", "body", "url"}
	if editable.Assignees.Edited {
		lookupFields = append(lookupFields, "assignees")
	}
	if editable.Labels.Edited {
		lookupFields = append(lookupFields, "labels")
	}
	if editable.Projects.Edited {
		// TODO projectsV1Deprecation
		// Remove this section as we should no longer add projectCards
		if opts.Detector == nil {
			cachedClient := api.NewCachedHTTPClient(httpClient, time.Hour*24)
			opts.Detector = fd.NewDetector(cachedClient, baseRepo.RepoHost())
		}

		projectsV1Support := opts.Detector.ProjectsV1()
		if projectsV1Support == gh.ProjectsV1Supported {
			lookupFields = append(lookupFields, "projectCards")
		}

		lookupFields = append(lookupFields, "projectItems")
	}
	if editable.Milestone.Edited {
		lookupFields = append(lookupFields, "milestone")
	}

	// Get all specified issues and make sure they are within the same repo.
	issues, err := shared.FindIssuesOrPRs(httpClient, baseRepo, opts.IssueNumbers, lookupFields)
	if err != nil {
		return err
	}

	// Fetch editable shared fields once for all issues.
	apiClient := api.NewClientFromHTTP(httpClient)
	opts.IO.StartProgressIndicatorWithLabel("Fetching repository information")
	err = opts.FetchOptions(apiClient, baseRepo, &editable)
	opts.IO.StopProgressIndicator()
	if err != nil {
		return err