You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
CI: GitHub App API rate limit 소진으로 게이트 잡이 저장소 전체에서 실패한다 #1465
오늘 develop 에 30건 넘게 병합되면서 PR 당 워크플로가 동시에 돌았다. 이 저장소의 게이트들은 잡마다 gh api 를 여러 번 부른다 — merge-order-guard 는 closing 이슈마다 blocked_by 를, review-debt-guard 는 열린 PR 전수를, Classify pull request impact 는 PR 메타를 조회한다. PR 수 × 잡 수 × 잡당 호출수가 곱해져 installation 한도(시간당 15,000)를 넘긴 것으로 보인다.
✅ 수용 기준
게이트 스크립트의 gh api 호출 수를 잡 단위로 줄인다 — 같은 PR 메타를 잡마다 다시 부르지 않고 한 번 조회해 job output 으로 넘긴다
rate limit(HTTP 403 + rate limit exceeded) 을 일반 실패와 구분한다. 지금은 「가드가 사실을 확인하고 거절함」과 구분되지 않아, 빨간 체크를 보고도 원인을 로그까지 들어가야 안다
한도 소진 시 재시도 대기(x-ratelimit-reset 까지 backoff) 또는 명시적 neutral 종료로 바꾼다 — 지금은 즉시 exit 1 이라 재실행이 quota 를 더 태운다
gh api rate_limit 을 주기적으로 찍어 남은 quota 를 관측 가능하게 한다
📍 Note
이 이슈는 관측 보고다. .github/ 는 내 담당 area 가 아니라 조치는 담당자 몫으로 남긴다.
당장 급한 PR 은 한도가 회복될 때까지(installation 한도는 시간당 리셋) 기다리는 것 외에 방법이 없어 보인다. 재실행을 반복하면 회복이 더 늦어진다.
#1526 의 커밋 메시지가 «이 PR 범위 밖» 이라고 명시하고 넘겼습니다. merge-order-guard.yml 이 base 이름을 pulls/<n>(REST)로 물은 뒤 같은 PR 을 GraphQL 로 다시 물었고, 닫는 이슈마다 issues/<n> 을 더 불렀습니다
ensure-api-quota.mjs classify 가 덮지만 merge-order-guard.yml · review-debt-guard.yml 두 곳에만 배선돼 있었습니다. 정작 위 표에서 함께 빨개진 Repository Quality · Classify CodeQL impact 는 무방비였습니다
gh api 를 부르는 워크플로 10개 중 PR 이벤트마다 도는 게이트는 4개이고, 재판정 시점에 그중
2개만 보호되고 있었습니다. PR #1598 이 나머지 2개를 덮어 4/4 가 됩니다. 나머지 6개는 PR
이벤트 경로에서 돌지 않거나(스케줄·dispatch·릴리스) 게이트가 아니어서 곱셈에 들어가지 않습니다.
(집계에서 정책 테스트 *.test.mjs 안의 gh api 문자열은 뺐습니다 — 실행되는 호출이 아닙니다.)
본문에서 낡은 것
📍 Note 의 «.github/ 는 내 담당 area 가 아니라 조치는 담당자 몫으로 남긴다» — 작성 시점
기준입니다. 이 이슈는 지금 area:platform / @1hyok 로 어사인돼 있어 제 몫이 맞고, 그렇게
진행했습니다.
«재실행 외에 방법이 없어 보인다» — ensure 가 리셋까지 기다리거나 «한도 소진» 을 명시하고
끝내므로, 사람이 재실행을 걸어 quota 를 더 태우는 경로는 이제 게이트 4곳에서 닫힙니다.
곁들여 관측된 둘
수용 기준에 들어 있지 않아 이 PR 의 범위가 아닙니다.
mergeability 가 CONFLICTING/DIRTY 로 표시된 것 — 한도 소진의 증상으로 봅니다. GitHub 이
한도 아래에서 mergeability 를 재계산하지 못하면 마지막 값이 그대로 남습니다.
Managed Device exit 124 — 한도와 별개 축이라 따로 진단해야 합니다. 잡 로그만으로는 OOM 과
adb timeout 이 갈리지 않습니다.
줄일 것이 없다고 판정한 두 자리
Repository Quality 와 Classify CodeQL impact 의 pulls/<n>/files 중복. 같은 데이터를
두 번 받지만 서로 다른 workflow run 이라 job output 으로 넘길 수 없습니다. 캐시·아티팩트로
우회하면 두 run 이 동시에 돌아 경합하고, git diff 로 바꾸면 truncation 대조와 rename 처리를
잃습니다 — CodeQL 분석 범위를 정하는 자리라 그 위험이 이득보다 큽니다. PR 이벤트당 1회짜리
중복이라 그대로 둡니다.
review-debt-guard 의 열린 PR 순회. 본문의 가설은 이 루프가 PR 마다 여러 번씩 태운다는
것이었는데, 코드를 전수로 읽어 보니 대부분의 PR 은 reviews 한 번을 받고 «아무도 판정하지
않음» 으로 continue 합니다. 커밋·커밋별 파일·코멘트 2종까지 가는 무거운 경로는 최신 판정이
변경요청이면서 같은 리뷰어에게 재요청까지 걸린 소수뿐이라, 열린 PR 30건 기준 호출은 30여 회이지
150회가 아닙니다. 사람의 PR 을 닫는 가드라 이득 없는 재작성은 위험만 늘립니다.
Activity
github-actions commentedon Aug 29, 2026
이 이슈는 필수 메타데이터를 판정할 수 없어 자동으로 닫았습니다.
작업 유형이 없거나 허용된 값이 아닙니다.주 담당 모듈이 없거나 허용된 값이 아닙니다.이슈 등록 양식에 맞게 본문을 보완한 뒤 다시 열어 주세요.
Sadturtleman commentedon Aug 29, 2026
곁들여 — GMD 잡이 결과 없이 timeout 으로 죽는 일이 반복됩니다
rate limit 과 별개 증상이라 같이 적어 둡니다. 오늘 제 PR 세 곳에서 같은 형태로 나왔습니다.
124는 timeout 이고 XML 이 아예 안 나옵니다 — 테스트가 실패한 것이 아니라 실행이 끝나기 전에 잘린 것입니다. 같은 커밋을 로컬pixel2Api30에서 돌리면 통과합니다(#1265 는 2/2, #1055 는 41/41).재실행하면 대체로 통과하지만, 승인된 PR 이 인프라 사정으로 매번 한두 번씩 더 돌아야 머지되는 상태입니다. 한도(
timeout-minutes)를 늘릴 자리인지, 에뮬레이터 부팅이 오래 걸리는 것인지 한 번 봐 주시면 좋겠습니다 — 지금은 재실행이 유일한 대처입니다.ci: quota 게이트가 부트스트랩 한 번을 건너뛰게 한다 (#1465)
Merge pull request #1526 from Afternote/ci/1465-gate-api-quota
1hyok commentedon Aug 30, 2026
현행성 재판정 — 수용 기준 4개 항목별
본문이 쓰인 뒤 #1526 이 머지되면서 일부가 이미 착륙했습니다. 지금 기준으로 다시 세어 봤습니다.
gh api호출 수 감축merge-order-guard.yml이 base 이름을pulls/<n>(REST)로 물은 뒤 같은 PR 을 GraphQL 로 다시 물었고, 닫는 이슈마다issues/<n>을 더 불렀습니다ensure-api-quota.mjs classify가 덮지만merge-order-guard.yml·review-debt-guard.yml두 곳에만 배선돼 있었습니다. 정작 위 표에서 함께 빨개진Repository Quality·Classify CodeQL impact는 무방비였습니다ensure가 리셋까지 대기하거나(evaluateQuota의wait) «한도 소진» 을 명시하고 끝냅니다(exhausted). 배선된 곳이 2/4 였습니다gh api rate_limit주기 관측gh api를 부르는 워크플로 전수 (origin/develop기준)gh api줄 수merge-order-guard.ymlreview-debt-guard.ymlcodeql.ymlrepository-quality.ymlrelease-aab-preflight.ymlreview-request-all.ymlandroid-managed-device.ymlrelease-distribution.ymlscreenshot-baseline-generate.ymlunit-test.ymlgh api를 부르는 워크플로 10개 중 PR 이벤트마다 도는 게이트는 4개이고, 재판정 시점에 그중2개만 보호되고 있었습니다. PR #1598 이 나머지 2개를 덮어 4/4 가 됩니다. 나머지 6개는 PR
이벤트 경로에서 돌지 않거나(스케줄·dispatch·릴리스) 게이트가 아니어서 곱셈에 들어가지 않습니다.
(집계에서 정책 테스트
*.test.mjs안의gh api문자열은 뺐습니다 — 실행되는 호출이 아닙니다.)본문에서 낡은 것
.github/는 내 담당 area 가 아니라 조치는 담당자 몫으로 남긴다» — 작성 시점기준입니다. 이 이슈는 지금 area:platform / @1hyok 로 어사인돼 있어 제 몫이 맞고, 그렇게
진행했습니다.
ensure가 리셋까지 기다리거나 «한도 소진» 을 명시하고끝내므로, 사람이 재실행을 걸어 quota 를 더 태우는 경로는 이제 게이트 4곳에서 닫힙니다.
곁들여 관측된 둘
수용 기준에 들어 있지 않아 이 PR 의 범위가 아닙니다.
CONFLICTING/DIRTY로 표시된 것 — 한도 소진의 증상으로 봅니다. GitHub 이한도 아래에서 mergeability 를 재계산하지 못하면 마지막 값이 그대로 남습니다.
adb timeout 이 갈리지 않습니다.
줄일 것이 없다고 판정한 두 자리
Repository Quality와Classify CodeQL impact의pulls/<n>/files중복. 같은 데이터를두 번 받지만 서로 다른 workflow run 이라 job output 으로 넘길 수 없습니다. 캐시·아티팩트로
우회하면 두 run 이 동시에 돌아 경합하고,
git diff로 바꾸면 truncation 대조와 rename 처리를잃습니다 — CodeQL 분석 범위를 정하는 자리라 그 위험이 이득보다 큽니다. PR 이벤트당 1회짜리
중복이라 그대로 둡니다.
review-debt-guard의 열린 PR 순회. 본문의 가설은 이 루프가 PR 마다 여러 번씩 태운다는것이었는데, 코드를 전수로 읽어 보니 대부분의 PR 은
reviews한 번을 받고 «아무도 판정하지않음» 으로
continue합니다. 커밋·커밋별 파일·코멘트 2종까지 가는 무거운 경로는 최신 판정이변경요청이면서 같은 리뷰어에게 재요청까지 걸린 소수뿐이라, 열린 PR 30건 기준 호출은 30여 회이지
150회가 아닙니다. 사람의 PR 을 닫는 가드라 이득 없는 재작성은 위험만 늘립니다.
PR #1598 이 머지되면 이 이슈는
Closes로 함께 닫힙니다.Merge pull request #1598 from Afternote/ci/1465-quota-coverage