feat: Expose re_requested and state on merge request webhook reviewers
event_webhook_types.go models both merge-request reviewer fields with EventUser:
type MergeEvent struct {
...
Reviewers []*EventUser `json:"reviewers"`
}
type MergeEventChanges struct {
...
Reviewers MergeEventChangesReviewers `json:"reviewers"`
}
type MergeEventChangesReviewers struct {
Previous []*EventUser `json:"previous"`
Current []*EventUser `json:"current"`
}
type EventUser struct {
ID int64 `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
AvatarURL string `json:"avatar_url"`
Email string `json:"email"`
}Every reviewer object GitLab emits — in the top-level reviewers array and inside
changes.reviewers.previous / changes.reviewers.current — includes a reviewer state
and a re_requested flag that EventUser has no fields for. Both are silently discarded
on json.Unmarshal, so consumers cannot read reviewer approval state or detect
re-request-review events. Documented under
Reviewer state tracking
and
Re-request review events:
state:unreviewed,review_started,reviewed,requested_changes,approved,unapprovedre_requested:false→truewhen a reviewer is re-requested
Evidence (real captured webhook payload)
Top-level reviewers array (emails redacted):
"reviewers": [
{ "id": 23211065, "username": "m.ferreira2", "state": "approved", "re_requested": false, "avatar_url": "…", "email": "[REDACTED]" }
]changes.reviewers on a re-request (note the state transition and re_requested: true):
"changes": {
"reviewers": {
"previous": [
{ "id": 23211065, "username": "m.ferreira2", "state": "approved", "re_requested": false }
],
"current": [
{ "id": 23211065, "username": "m.ferreira2", "state": "unreviewed", "re_requested": true }
]
}
}The { "previous": [...], "current": [...] } container matches MergeEventChangesReviewers
correctly - the only gap is the missing per-reviewer fields.
Note: the GitLab public docs' Re-request review events / Submit review events examples render
changes.reviewersas a positional array of arrays ([[previous], [current]]). That is a docs inaccuracy: the actual webhook payload uses the{ previous, current }object shown above, which the Go type already models correctly.
Fix
A dedicated EventReviewer type carries the reviewer-specific fields alongside the
standard user fields:
type EventReviewer struct {
ID int64 `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
AvatarURL string `json:"avatar_url"`
Email string `json:"email"`
State string `json:"state"`
ReRequested bool `json:"re_requested"`
}MergeEvent.Reviewers and MergeEventChangesReviewers.Previous/Current now use
[]*EventReviewer. This changes exported field types, so it's a breaking change and
targets the next major (release-client-3.0).