From 21f971bbab322e5d184727c59c02cb8e5ffeac5f Mon Sep 17 00:00:00 2001 From: Siddharth Balyan <52913345+alt-glitch@users.noreply.github.com> Date: Sat, 18 Jul 2026 19:17:09 +0530 Subject: [PATCH] fix(ci): null-safe files iteration in the paginated compare (#66867) A PR more than 100 commits ahead of its merge-base paginates the compare endpoint; pages after the first carry files: null, so the bare .files[] made jq die with 'cannot iterate over: null' on every retry and forced the classifier's fail-open path (all lanes on, ci_review gate demanding a label with zero CI-sensitive files in the diff). .files[]? keeps the page-one file list and ignores the null tail. --- .github/actions/detect-changes/action.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/actions/detect-changes/action.yml b/.github/actions/detect-changes/action.yml index 106379428eca..7d95ba76c9a2 100644 --- a/.github/actions/detect-changes/action.yml +++ b/.github/actions/detect-changes/action.yml @@ -72,12 +72,19 @@ runs: # Retried: a rate-limit blip or eventual-consistency 404 on a # freshly-pushed HEAD would otherwise silently fall open (all lanes # run — safe, but wasteful and it masks the API failure). + # + # `.files[]?` (null-safe): with --paginate, a PR more than 100 + # commits ahead of its merge-base paginates the compare, and pages + # after the first carry `files: null` — bare `.files[]` makes jq + # die with "cannot iterate over: null", which fails every retry + # and forces the fail-open path (seen on stacked PRs). The full + # file list (up to the API's 300-file cap) is on page one. CHANGED="" for i in 1 2 3; do if CHANGED="$(gh api \ --paginate \ "repos/${REPO}/compare/${BASE_SHA}...${HEAD_SHA}" \ - --jq '.files[].filename')"; then + --jq '.files[]?.filename')"; then break fi if [ "$i" = 3 ]; then