Skip to content

[Fix] 자동화 판정이 PR 전체 이력 대신 열린 PR과 claim 브랜치별 PR만 받도록 시한폭탄 제거 - #994

Merged
AquilaXk merged 4 commits into
mainfrom
fix/bound-automation-pr-lists-993
Oct 6, 2026
Merged

AquilaXk merged 4 commits into
mainfrom
fix/bound-automation-pr-lists-993

Conversation

@AquilaXk

@AquilaXk AquilaXk commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner

Related issue

Closes #993
Refs #870
Refs #969

Summary

  • Problem: 자동화 판정 step 13곳이 gh pr list --state all --limit 1000으로 PR 전체 이력을 받는다. 자동화가 매일 PR을 열어 이력은 계속 쌓이고(지금 612건), 1000건에 닿는 순간 등록·ITX 승격·원천 재확인 판정은 *_LIST_TRUNCATED로 영구 실패하고, 나머지 판정(topology·KRIC·서울·광주·후보 갱신·파생 재결속·재확인)은 오래된 병합 PR이 잘린 목록으로 조용히 오판한다. [CI] P7D 원천 재확인 recipe(S2~S9)를 만료 전 무인 workflow로 자동화 (#969 남은 단계 1) #987 리뷰 F1(run 목록 상한)과 같은 종류의 시한폭탄이다.
  • Outcome: 판정은 열린 PR 전체(상한 도달 시 실패 유지) + 판정이 보는 claim 브랜치별 PR(전 상태)만 받는다. 이력이 5000건이어도 판정 결과가 같다.

Changes

  • tools/ci/collect-automation-prs.mjs(신규): 열린 PR(--state open --limit N, N건에 닿으면 AUTOMATION_PR_LIST_TRUNCATED)과 git ls-remote 출력의 브랜치별 PR(--state all --head <branch> --limit 100, 100건에 닿으면 같은 실패)을 번호 기준으로 합쳐 JSON으로 쓴다. claim 브랜치가 50개를 넘으면 gh 호출 전에 AUTOMATION_CLAIM_BRANCH_LIMIT로 실패하고, 조회한 브랜치 수를 로그(branch_lookups)에 남긴다. gh 실패·목록 아님·형식 오류·잘못된 인자는 대체 없이 실패한다.
  • tools/ci/decide-capital-topology-registration.mjs·decide-itx-current-promotion.mjs·decide-source-reverification.mjs: 잘림 검사(*_LIST_TRUNCATED)를 목록 길이가 아니라 열린 PR 개수에만 적용. 입력 형식과 나머지 분기는 그대로다.
  • workflow 9개의 판정·재확인 13곳(current-capital-topology-refresh.yml :50, current-capital-topology-registration.yml :80·:242, itx-current-promotion.yml :72, kric-current-facility-refresh.yml :55, nationwide-candidate-refresh.yml :61·:180, retained-gwangju-timetable-refresh.yml :41, seoul-current-accessibility-refresh.yml :46, source-derivative-rebinding.yml :53·:146, source-reverification.yml :48·:174): gh pr list --state all --limit 1000 줄을 지우고, 이미 하던 git ls-remote를 먼저 받은 뒤 그 출력을 --refs로 수집기를 호출한다(순서만 PR 목록 → ls-remote에서 ls-remote → PR 목록으로 바뀐다). 출력 파일 이름·판정 호출 인자는 그대로다. ${{ }} 식은 run에 쓰지 않았다.
  • 계약 테스트: 신규 collect-automation-prs.test.mjs·automation-pr-list-bounded.test.mjs(전수), 세 판정 테스트에 5000건 이력 케이스, workflow 계약 6개 갱신. data-test-ownership.json에 data993 등록.

판정별 전후

판정 이전 이후
decide-capital-topology-registration 전체 이력 1000건, 길이 >= 1000이면 REGISTRATION_LIST_TRUNCATED 열린 PR + 등록 claim 브랜치별 PR. 잘림은 열린 PR 개수 >= 상한일 때만
decide-itx-current-promotion 전체 이력 1000건, 길이 >= 1000이면 ITX_PROMOTION_LIST_TRUNCATED, 이력의 모든 CLOSED 승격 PR이 ITX_PROMOTION_PR_CLOSED 열린 PR + 승격 claim 브랜치별 PR. 잘림은 열린 PR에만. PR_CLOSED는 브랜치가 남은 CLOSED PR에만(아래 참고)
decide-source-reverification 전체 이력 1000건, 길이 >= 1000이면 REVERIFICATION_LIST_TRUNCATED 열린 PR + automation/* 브랜치별 PR. 잘림은 열린 PR에만. classifyClaims는 원래 claim 브랜치 키라 동일
decide-derivative-rebinding, decide-nationwide-candidate-refresh 1000건에서 조용히 잘림. cleanupBranches·pendingLedgerWriters가 claim 키 열린 PR + automation/* 브랜치별 PR. 결과 동일, 잘림 없음
decide-current-capital-topology-refresh, decide-current-kric-facility-refresh, decide-current-seoul-accessibility-refresh, classifyRetainedGwangjuRefreshDelivery 1000건에서 조용히 잘림. 판정은 claim 키 열린 PR + 각 claim 브랜치별 PR. 결과 동일
ledger-writers-idle(재확인 4곳) 1000건에서 조용히 잘림. pendingLedgerWriters가 claim 키 열린 PR + automation/* 브랜치별 PR. 결과 동일

Scope

Included

  • 수집기, 세 판정의 잘림 검사, workflow 13곳, 계약 테스트·소유 manifest.

Excluded

  • ci.yml(PR #990이 automerge 대기 중이라 건드리지 않았다).
  • automerge-queue.yml(--state open --label automerge 목록), refresh-open-pr-age·열린 PR 목록 호출(--state open), automation-pr-recreate.mjs(닫힌 PR 최근 100건 표본, overflow: return, 잘림 실패 없음, 이력 길이 무관). 전수 테스트가 이 둘만 허용 목록으로 둔다.
  • 판정 상태 이름·출력 키, 원천 수집·원장·inventory 데이터, 열린 PR 상한 값(1000).

Ownership / dependencies

Contract & Compatibility

  • Source / API / schema contract: 새 외부 API 없음. 이 저장소의 gh pr list(open·--head)만 쓴다. hub api-catalog는 공공 데이터 원천용이라 해당 없음("카탈로그에 없음"). 실측: gh pr list --state all --head <branch> --limit 100은 같은 JSON 필드를 돌려주고 없는 브랜치는 []다.
  • Artifact / provenance identity: 데이터 산출물 변경 없음.
  • Backward compatibility: 판정 입력 JSON 형식(필드)과 출력은 그대로다. 기존 판정 단위 테스트 전부 통과(잘림 테스트 둘만 "열린 PR 개수" 기준으로 바뀜).
  • 의미가 바뀌는 한 곳: ITX 승격 판정의 closed는 이력의 모든 CLOSED 승격 PR을 세던 것이라 한 번이라도 닫히면(브랜치가 지워졌어도) 영구 실패했다. 이후에는 브랜치가 남은 CLOSED PR만 이상(ITX_PROMOTION_PR_CLOSED)이다. 뒤처진 PR을 닫고 브랜치를 지운 뒤 다시 만드는 automation-pr-recreate 경로와 맞는다. 다른 판정은 원래 claim 키라 차이가 없다.
  • Migration or cutover: 없음.

Version impact

  • no version change
  • datapack release only
  • route-map artifact change
  • data contract change
  • product gate JSON change
  • CI workflow·계약 테스트 change

Product gate impact

  • release/product-gates/** 영향 없음
  • 변경한 gate의 근거를 갱신했습니다.
  • 검증되지 않은 지원 범위 claim을 추가하거나 확대하지 않습니다.

Provenance impact

  • source inventory·geometry provenance manifest 영향 없음
  • 제공처·라이선스·갱신 시점·적용 범위를 갱신했습니다.
  • 공식 source로 확인되지 않은 값을 배포 artifact에 추가하지 않습니다.

Version decision

  • datapack version: 변경 없음
  • data contract: 변경 없음
  • route-map artifact / product gate: 변경 없음
  • promotion request id: 없음

Verification

Check Result / Evidence
Focused RED → GREEN RED(커밋 573edaea2): node --test tools/ci/collect-automation-prs.test.mjs tools/ci/automation-pr-list-bounded.test.mjs tools/ci/decide-capital-topology-registration.test.mjs tools/ci/decide-itx-current-promotion.test.mjs tools/ci/decide-source-reverification.test.mjs → tests 61, pass 55, fail 6(수집기 모듈 없음 ERR_MODULE_NOT_FOUND, 세 판정의 5000건 이력 케이스 3건, 전수 계약 2건). GREEN(커밋 062f1a7ba): 같은 명령 fail 0. 리뷰 F1·F2 반영(커밋 fb5bc02dc): 수집기 테스트 12건(수집기+ITX 판정 통합 2건 추가, 브랜치 수 상한 1건 추가). 수집기가 브랜치 없는 CLOSED PR을 돌려주도록 변조(열린 목록을 --state all로)하면 통합 테스트 포함 5건이 red가 됨을 확인하고 되돌렸다. 예전 방식이 실제로 틀린다는 증명은 수집기 테스트가 한다: 닫힘·병합 5000건에서 --state all --limit 1000 목록은 오래된 claim 병합 PR을 놓쳐 ITX 판정이 고아 브랜치로 실패하고, 수집기 목록은 WAIT로 같은 결과를 낸다.
Affected integration node --test tools/ci/*.test.mjs → tests 639, pass 638, fail 1. 실패 1건은 stage-local-mobile-fixture.test.mjs로, origin/main에서도 같은 명령이 같은 이유(apply-itx-topology-to-bundled-pack.mjs --derive-fixture 실패, 로컬 mobile fixture 부재)로 실패한다(이 변경과 무관, CI는 fixture를 staging한다). automerge-queue.test.mjs(YAML block scalar 들여쓰기 계약) 29건 통과. node tools/ci/data-test-discovery.mjs verify exit 0. actionlint .github/workflows/*.yml exit 0. node tools/ci/check-documentation-fragment-sync.mjs --base origin/main 통과(등록 resource 변경 없음). 실제 저장소 대상 수집기 실행: automation pull requests: open=2 branch_lookups=1 total=2(리뷰 반영 전 출력은 claims=1), 열린 PR 상한 2로 줄이면 AUTOMATION_PR_LIST_TRUNCATED: open pull request list reached its limit 2.
Required CI head fb5bc02dc 전부 success: Data contracts 집계(shard 1~4·mobile-v19 포함, 같은 run), SonarCloud Code Analysis pass, CodeQL 3종 pass. Automation PR gates는 자동화 PR 전용이라 skipping.
Live provider / release Not required — reason: 공급자·릴리스를 부르지 않는 CI·계약 변경이다. workflow 첫 정기 실행에서 판정 step이 수집기로 돈다.
Security / data integrity Not applicable — reason: 인증·비밀·입력 경계 변경 없음. gh는 인자 배열로 호출하고(셸 없음) 브랜치 이름은 형식을 검증한다.

Not run

  • Check: 로컬 stage-local-mobile-fixture.test.mjs
  • Reason: origin/main에서도 로컬 환경(mobile fixture 부재)으로 실패하는 기존 상태이며 CI에서 fixture를 staging해 돈다.
  • Rerun owner / condition: 필수 CI Data contracts.

Risk

  • Level: High
  • Main risk: 9개 자동화 workflow의 판정 입력 수집 경로가 바뀐다. 수집 실패나 형식 오류가 판정 실패로 이어질 수 있다.
  • Failure behavior: gh 실패·열린 PR 상한 도달·브랜치별 PR 100건 도달·refs 형식 오류는 모두 AUTOMATION_PR_* 코드로 step을 실패시켜 기존 실패 보고([Fix] 원천 갱신 workflow 실패를 이슈로 드러내고 광주 보관 시간표 갱신에 수동 실행 경로 추가 #926)로 드러난다. 대체 값은 없다.
  • Candidate / admission / publication state on failure: 판정 step이 첫 단계라 수집·게시·push 전에 실패한다. 상태 변경 없음.
  • Fallback or degraded-success path introduced: No

Rollout / Recovery

  • Rollout or promotion: 병합 즉시 다음 정기 실행부터 적용된다. 병합 후 첫 정기 실행의 판정 step 결과(상태가 이전과 같은 의미로 나오는지)를 확인한다.
  • Monitoring / success signal: 판정 step 로그의 automation pull requests: open=N branch_lookups=M total=K 한 줄과 기존 판정 출력.
  • Rollback or recovery: 이 PR을 revert하면 이전 --state all --limit 1000 호출로 돌아간다(이력 1000건 전까지는 동일).
  • Existing artifact / schema compatibility after rollback: 산출물·스키마 변경 없음.

Review focus

  • 수집기가 판정이 쓰는 모든 소비자(위 표)의 필요를 덮는지: 열린 PR + claim 브랜치별 PR 외에 이력의 PR을 보는 소비자가 있는지.
  • ITX 승격 판정 closed 의미 변화(브랜치가 지워진 CLOSED PR을 더는 세지 않음)가 의도에 맞는지.
  • workflow에서 ls-remote를 PR 목록보다 먼저 받게 한 순서 변경.

Checklist

  • 이슈 범위와 실제 diff가 일치합니다.
  • 관련 없는 변경이나 다른 owner의 surface를 포함하지 않았습니다.
  • 위험에 필요한 검증과 미실행 사유를 기록했습니다.
  • 실패·호환성·promotion·recovery 동작이 명확합니다.
  • current failure를 이전·stale·alternate 결과의 성공으로 바꾸지 않습니다.
  • GitHub PR Review 객체가 있는지 확인했습니다. CodeRabbit status check만으로는 리뷰 완료로 보지 않습니다.
  • CodeRabbit Review 객체가 없으면 지원되는 Codex CLI 폴백 Review를 단일 GitHub PR Review로 게시했습니다.
  • datapack 배포 영향이 있는 경우 release workflow 상태를 확인했습니다.

닫힘·병합 PR 5000건 이력, 열린 PR 목록 상한 도달, workflow의 --state all 전수 조회 금지를 실패 테스트로 먼저 고정한다.
collect-automation-prs.mjs가 열린 PR 전체(상한 도달 시 실패)와 git ls-remote로 아는 claim 브랜치별 PR(전 상태)만 모은다.
workflow 9개의 판정·재확인 13곳이 gh pr list --state all --limit 1000 대신 이를 쓰고, 등록·ITX 승격·원천 재확인 판정의 잘림 검사는 열린 PR 개수에만 적용한다.
@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2bfc0b8a-2dd6-4205-8011-cf550d9afc0f
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@AquilaXk AquilaXk left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🎯 Linked issue & acceptance criteria audit
ID Acceptance criterion Status Evidence
AC-1 Collector merges open PRs and per branch PRs and survives 5000 history entries PASS tools/ci/collect-automation-prs.mjs
AC-2 Open PR count at the cap fails in the collector and in the three decisions PASS tools/ci/decide-itx-current-promotion.mjs
AC-3 All 13 call sites use the collector and no unbounded all state list remains PASS tools/ci/automation-pr-list-bounded.test.mjs
AC-4 ITX closed check is kept only for CLOSED PRs whose branch remains PASS tools/ci/collect-automation-prs.test.mjs
🛡️ Adversarial audit evidence
  • Falsifiability verified: Yes (Mutating the truncation check and three open count caps turned tests RED.)
  • Hollow assertions detected: 0
  • Production backdoors detected: 0
  • Ground-truth sources verified:
    • Consumer code of all ten decisions read against the branch scoped list
    • Live run of the collector against AquilaXk/easysubway-data with the real ls-remote output
    • Targeted tests: 70 of 70 passed on the PR head
  • Mutation testing evidence: probe-falsifiability on collect-automation-prs.mjs line 54 and on the open count caps in the ITX, reverification and registration decisions: all mutants killed, no survivors.
🤖 Prompt for all review comments with AI agents
Could we verify each finding against the current code and keep only those that
still apply? Could we make the smallest validated fix and briefly note why any
finding no longer applies?

Inline comments:
- `@tools/ci/collect-automation-prs.mjs:67-75`
  Could the collector log the branch count with its summary line, and fail with a
  named code once the count passes a generous bound, so runaway branch growth shows
  up as a signal instead of a slow run?
- `@tools/ci/collect-automation-prs.test.mjs:126-139`
  Could this file add two cases through the collector and decision together: a
  CLOSED claim PR with its branch present expects ITX_PROMOTION_PR_CLOSED, and a
  CLOSED PR whose branch is absent expects a normal WAIT or COLLECT result?

---

Outside diff comments:
None.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Aquila CLI invocation with repository CLAUDE.md, PR template and issue 993 text

Review profile: ASSERTIVE

Plan: Aquila fallback

Run ID: N/A (Aquila fallback)

Review source: Aquila CLI

Repository visibility: public GitHub repository

Trigger:
Discovery review requested for the current change set of this pull request

Base:
main@48c66420e11fd9e422e2dc9ebb32b2de63e44ca5

Head:
fix/bound-automation-pr-lists-993@062f1a7ba6c6d08d24cee86f01c83da435553ff4

Command:
node scripts/compile-review-payload.mjs input.json --output payload-1.json

📥 Commits

Reviewing files changed in this pull request between:

  • Base: 48c66420e11fd9e422e2dc9ebb32b2de63e44ca5
  • Head: 062f1a7ba6c6d08d24cee86f01c83da435553ff4
📒 Files selected for processing (2)
  • tools/ci/collect-automation-prs.mjs
  • tools/ci/collect-automation-prs.test.mjs
📜 Review details

Comment thread tools/ci/collect-automation-prs.mjs
Comment thread tools/ci/collect-automation-prs.test.mjs
리뷰 F1: 브랜치가 남은 CLOSED 승격 PR은 ITX_PROMOTION_PR_CLOSED, 브랜치가 지워진 CLOSED PR은 정상 진행임을 수집기+판정 통합 테스트로 고정한다.
리뷰 F2: claim 브랜치가 50개를 넘으면 AUTOMATION_CLAIM_BRANCH_LIMIT로 gh 호출 전에 실패하고, 조회한 브랜치 수를 로그에 남긴다.
@AquilaXk
AquilaXk marked this pull request as ready for review October 6, 2026 16:40
@AquilaXk AquilaXk added the automerge FIFO 병합 큐 대상 — 코디네이터가 순서대로 update-branch 후 auto-merge label Oct 6, 2026
@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

No description provided.

@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@sonarqubecloud

sonarqubecloud Bot commented Oct 6, 2026

Copy link
Copy Markdown

@AquilaXk
AquilaXk merged commit 51f2d91 into main Oct 6, 2026
12 checks passed
@AquilaXk
AquilaXk deleted the fix/bound-automation-pr-lists-993 branch October 6, 2026 23:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automerge FIFO 병합 큐 대상 — 코디네이터가 순서대로 update-branch 후 auto-merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Fix] 자동화 판정이 gh pr list --state all --limit 1000 전체 이력에 의존해 PR이 쌓이면 영구 실패하는 시한폭탄 제거

1 participant