From 5ab20eb1a533d06da6a7b2e1ad45c85c2d27e7d9 Mon Sep 17 00:00:00 2001 From: Javier David Carnelli Date: Wed, 16 Sep 2026 13:09:10 -0300 Subject: [PATCH] fix: support audit log pagination for both GHEC and GHES --- pkg/connector/usage_event_feed.go | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/pkg/connector/usage_event_feed.go b/pkg/connector/usage_event_feed.go index d86dc02f..01be314c 100644 --- a/pkg/connector/usage_event_feed.go +++ b/pkg/connector/usage_event_feed.go @@ -203,9 +203,11 @@ func (f *usageEventFeed) ListEvents( events = append(events, evt) } - if resp != nil && resp.NextPageToken != "" && !reachedBoundary { - cursor.AuditLogCursor = resp.NextPageToken - continue + if resp != nil && !reachedBoundary { + if nextPage := nextAuditLogPage(resp); nextPage != "" { + cursor.AuditLogCursor = nextPage + continue + } } // Done with this org for this pass - advance to the next one. @@ -237,6 +239,23 @@ func (f *usageEventFeed) ListEvents( return events, &pagination.StreamState{Cursor: tokenStr, HasMore: true}, annos, nil } +// nextAuditLogPage returns the token to request the next audit-log page, or +// "" if there isn't one. GitHub's org audit-log endpoint returns opaque +// cursor pagination on github.com/GHEC (go-github parses the Link header's +// non-numeric "page" value into Response.NextPageToken), but GHES-style +// numeric "page=N" Link headers parse into Response.NextPage (int) instead, +// leaving NextPageToken empty. Checking only NextPageToken silently truncates +// GHES audit logs to a single page. +func nextAuditLogPage(resp *github.Response) string { + if resp.NextPageToken != "" { + return resp.NextPageToken + } + if resp.NextPage != 0 { + return strconv.Itoa(resp.NextPage) + } + return "" +} + // usageEventFromAuditEntry converts one audit-log entry into a usage event // targeting the usage-app resource (see usage_app.go). Returns ok=false when // the entry can't be attributed to a synced user.