How Multiple Reviewers Assigned to a Single Pull Request Are Processed by the GitHub-Asana Integration
When multiple reviewers are assigned to a single pull request, the GitHub-Asana integration creates a separate Asana sub-task for each individual reviewer, ensuring every review request is tracked independently.
The keitap/github-asana-request-review-action repository automates synchronization between GitHub pull requests and Asana project tasks. When multiple reviewers are assigned to a single pull request, the action processes each reviewer sequentially rather than grouping them, generating distinct tracking sub-tasks that reflect each person's individual review responsibilities.
Event Detection and Reviewer List Retrieval
The workflow triggers on pull_request events with the action type review_requested. In handler.go, the updateReviewers function (lines 97-105) orchestrates the initial response by determining whether to use reviewers from the webhook payload or fetch them from GitHub's API:
// handler.go:97-105
if hasRequestedReviewersFields {
ghReviewers = pr.PullRequest.RequestedReviewers
} else {
ghReviewers, err = getRequestedReviewers(h.gh,
pr.GetRepo().GetOwner().GetLogin(),
pr.GetRepo().GetName(),
pr.GetNumber())
}
If the event payload lacks the RequestedReviewers field, the code calls getRequestedReviewers (defined in github.go) to query the current reviewer list directly from GitHub's API.
Processing Each Reviewer Individually
Once the reviewer list is obtained, the handler iterates through every github.User object to resolve Asana accounts and create tracking entries. This loop at lines 124-136 in handler.go ensures no reviewer is skipped and no batching occurs:
// handler.go:115-136
reviewers = make([]*Account, len(ghReviewers))
for i, r := range ghReviewers {
reviewers[i], err = h.fetchAccount(r.GetLogin())
if err != nil {
return err
}
log.Printf("reviewer: %s", reviewers[i])
}
for _, reviewer := range reviewers {
if err := h.upsertReviewer(pr, requester, reviewer, taskID); err != nil {
return err
}
}
The fetchAccount function maps GitHub usernames to Asana user GIDs using the configuration defined in config.go. Each resolved account is then passed individually to upsertReviewer.
Sub-Task Creation and Update Logic
The upsertReviewer function (lines 49-78 in handler.go) handles the actual Asana task manipulation for each reviewer separately:
func (h *Handler) upsertReviewer(pr *github.PullRequestEvent, requester *Account, reviewer *Account, taskID string) error {
// Lines 49-53: Skip unlinked accounts
if reviewer.AsanaUserGID == "" {
return nil
}
// Search for existing sub-task by reviewer name
subtask, _ := FindSubtaskByName(h.ac, taskID, reviewer.Name)
if subtask == nil {
// Lines 63-71: Create new sub-task for this specific reviewer
subtask, err = AddCodeReviewSubtask(h.ac, taskID, pr.GetNumber(),
requester, reviewer, due, pr)
} else {
// Lines 73-78: Update existing sub-task
err = UpdateCodeReviewSubtask(h.ac, subtask, requester, pr)
}
return err
}
Key implementation details for multiple reviewers:
- Individual Tracking: Each reviewer receives a dedicated sub-task under the parent Asana feature task, named specifically for that reviewer.
- Due Date Assignment: Every sub-task is automatically assigned a due date of the next business day, creating individual deadlines per reviewer.
- Selective Processing: If
reviewer.AsanaUserGIDis empty (indicating no mapping exists inconfig.go), that specific reviewer is ignored while processing continues for others.
Handling Reviewer List Modifications
When reviewers are added or removed after the initial assignment, subsequent review_requested events trigger the same updateReviewers flow. The action re-fetches the complete reviewer list and reconciles the Asana sub-tasks:
- New reviewers trigger
AddCodeReviewSubtask(lines 63-71) viaupsertReviewer. - Existing reviewers trigger
UpdateCodeReviewSubtask(lines 73-78), refreshing metadata and PR links. - Removed reviewers are handled implicitly through the absence of their names in the current reviewer list during the next sync cycle.
Summary
- Multiple reviewers assigned to a single pull request generate one Asana sub-task per reviewer, not a single consolidated task.
- The
updateReviewersfunction inhandler.go(lines 97-136) iterates through theRequestedReviewersarray, processing eachgithub.UserviafetchAccountandupsertReviewer. - Reviewers lacking linked Asana accounts (
AsanaUserGID == "") are silently skipped at lines 49-53 while valid reviewers continue processing. - The system uses
FindSubtaskByName(fromasana.go) to detect existing entries, then calls eitherAddCodeReviewSubtaskorUpdateCodeReviewSubtaskto maintain synchronization. - Each generated sub-task contains reviewer-specific metadata, individual due dates, and direct links back to the GitHub pull request.
Frequently Asked Questions
Does the integration create one sub-task or multiple sub-tasks when several reviewers are assigned to a single pull request?
The integration creates multiple sub-tasks—one dedicated sub-task for each reviewer. According to the loop implementation in handler.go lines 124-136, the code processes every requested reviewer individually through upsertReviewer, resulting in separate Asana sub-tasks that track each person's review status independently.
What happens if one assigned reviewer doesn't have an Asana account linked?
That specific reviewer is bypassed without affecting the others. In upsertReviewer (handler.go lines 49-53), the code checks if reviewer.AsanaUserGID == "" and returns immediately, allowing the main loop to continue processing remaining reviewers who have valid Asana mappings defined in config.go.
How does the action handle changes to the reviewer list after the initial assignment?
The action treats every review_requested event as a full synchronization. GitHub sends new webhooks when reviewers are added or removed, triggering updateReviewers to fetch the current list via getRequestedReviewers or the event payload. The handler then reconciles Asana sub-tasks by creating new ones for additions and updating existing ones for current reviewers.
Is there a limit to how many reviewers can be processed on a single pull request?
There is no coded limit in handler.go. The implementation uses a standard for loop over the ghReviewers slice (lines 124-136), processing entries sequentially. Practical limits depend on GitHub API rate limits and Asana API throttling rather than constraints within the action logic itself.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →