# What Happens When a Reviewer Is Removed from a Pull Request in the GitHub‑Asana Action

> Understand the GitHub-Asana action flow when a reviewer is removed from a pull request. Learn how `review_request_removed` webhooks keep Asana sub-tasks in sync without altering reviewer artifacts.

- Repository: [Keita Kitamura/github-asana-request-review-action](https://github.com/keitap/github-asana-request-review-action)
- Tags: internals
- Published: 2026-03-05

---

**When a reviewer is removed from a pull request, the GitHub‑Asana Request Review Action processes a `review_request_removed` webhook event to synchronize the remaining reviewers with Asana sub-tasks while leaving the removed reviewer's artifacts untouched.**

The `keitap/github-asana-request-review-action` repository automates the creation and management of Asana sub-tasks for GitHub pull request reviewers. When a reviewer is removed from a pull request, the action executes a specific synchronization flow in [`handler.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/handler.go) to ensure the Asana project reflects the current reviewer list without explicitly deleting orphaned sub-tasks.

## Detecting the review_request_removed Event

The flow begins when GitHub dispatches a **`review_request_removed`** webhook event to the action. In [`handler.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/handler.go), the `updateReviewers` function checks the incoming pull request action against the constant **`prEventActionReviewRequestedRemoved`** to identify removal events.

This detection occurs at **lines 13‑19** of [`handler.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/handler.go), where the action constants are defined. Once identified, the handler sets `hasRequestedReviewersFields` to `true`, signaling that the payload contains a pre-filtered reviewer list.

## Retrieving the Current Reviewer List

Because the event type is `review_request_removed`, GitHub's payload already excludes the removed reviewer from the **`RequestedReviewers`** slice. The handler leverages this behavior at **lines 101‑108** of [`handler.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/handler.go) to obtain the authoritative list of remaining reviewers.

Rather than maintaining a local cache or diffing against previous states, the action relies entirely on the GitHub API's current snapshot. This approach simplifies state management by treating each webhook event as the source of truth.

## Mapping GitHub Users to Asana Accounts

For each reviewer present in the filtered list, the action must resolve the GitHub login to an Asana GID. The **`fetchAccount`** function handles this translation at **lines 124‑135** of [`handler.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/handler.go).

This mapping is critical for ensuring that sub-tasks are assigned to the correct Asana users. If a GitHub user lacks a configured Asana mapping, the function handles the lookup gracefully to prevent the entire synchronization from failing.

## Synchronizing Sub-Tasks via Upsert Operations

The core synchronization logic resides in the **`upsertReviewer`** function, called for each remaining reviewer at **lines 138‑143** of [`handler.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/handler.go). This function implements an idempotent upsert pattern against the Asana API:

- **Update existing sub-tasks**: If a code-review sub-task already exists under the feature task for a given reviewer, the action calls **`UpdateCodeReviewSubtask`** to refresh metadata.
- **Create missing sub-tasks**: If no sub-task exists for the reviewer, the action invokes **`AddCodeReviewSubtask`** to create a new code-review sub-task in Asana.

These operations are defined in [`asana.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/asana.go), which handles the actual API communication with Asana's task management endpoints.

## Preservation of Removed Reviewer Artifacts

Notably, the action does **not** delete sub-tasks belonging to reviewers who were removed from the pull request. The synchronization process exclusively ensures that the current set of reviewers is accurately reflected in Asana.

This design choice means that sub-tasks for removed reviewers persist in the Asana project, requiring manual cleanup if necessary. The action treats removal events purely as synchronization triggers rather than deletion commands.

## Code Example

The following simplified Go code illustrates the removal handling logic implemented in [`handler.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/handler.go):

```go
func (h *Handler) updateReviewers(pr *github.PullRequestEvent, requester *Account, taskID string) error {
    // 1️⃣ Detect removal event
    hasRequestedReviewersFields := pr.GetAction() == prEventActionReviewRequestedRemoved

    // 2️⃣ Get current reviewers (GitHub already omitted the removed one)
    var ghReviewers []*github.User
    if hasRequestedReviewersFields {
        ghReviewers = pr.PullRequest.RequestedReviewers
    }

    // 3️⃣ Resolve to Asana accounts
    reviewers := make([]*Account, len(ghReviewers))
    for i, r := range ghReviewers {
        reviewers[i], _ = h.fetchAccount(r.GetLogin())
    }

    // 4️⃣ Upsert each reviewer sub-task (create if missing, update otherwise)
    for _, reviewer := range reviewers {
        _ = h.upsertReviewer(pr, requester, reviewer, taskID)
    }
    return nil
}

```

## Summary

- **Event detection**: The action identifies `review_request_removed` events using the `prEventActionReviewRequestedRemoved` constant in [`handler.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/handler.go) (lines 13‑19).
- **Stateless retrieval**: Current reviewers are fetched directly from GitHub's pre-filtered `RequestedReviewers` slice at lines 101‑108.
- **Account resolution**: GitHub logins are mapped to Asana GIDs via `fetchAccount` (lines 124‑135).
- **Idempotent sync**: `upsertReviewer` creates or updates sub-tasks via `AddCodeReviewSubtask` and `UpdateCodeReviewSubtask` without deleting removed reviewer artifacts.
- **Source files**: Core logic resides in [`handler.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/handler.go) (lines 97‑146) with Asana API operations in [`asana.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/asana.go).

## Frequently Asked Questions

### Does the action delete Asana sub-tasks when a reviewer is removed from a pull request?

No. The action does not implement deletion logic for sub-tasks when processing `review_request_removed` events. It only synchronizes the remaining reviewers' sub-tasks, leaving orphaned tasks in Asana for manual cleanup if desired.

### How does the action know which reviewer was removed?

The action does not track which specific reviewer was removed. Instead, it relies on GitHub's `RequestedReviewers` slice in the webhook payload, which already excludes the removed user. The handler at lines 101‑108 of [`handler.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/handler.go) processes this filtered list as the authoritative current state.

### What happens if a removed reviewer is re-added to the pull request?

If a reviewer is re-added, GitHub sends a `review_request` event, and the action treats this as a standard reviewer addition. The `upsertReviewer` function will recreate the sub-task via `AddCodeReviewSubtask` if it was previously removed manually, or update it via `UpdateCodeReviewSubtask` if it still exists.

### Where is the event handling logic implemented?

The primary event handling logic is implemented in **[`handler.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/handler.go)** within the `updateReviewers` function (lines 97‑146). Constants for event types like `prEventActionReviewRequestedRemoved` are defined at lines 13‑19, while the actual Asana API operations reside in **[`asana.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/asana.go)**.