Skip to content

Queue delay invalidates its own dispatches: base_sha equality fails 12 of 16 validate-pr-metadata runs #1931

Description

@seonghobae

opencode-review-dispatch.yml의 메타데이터 검증이 큐 대기 시간 때문에 실패합니다. 대기가 길수록 실패율이 오르고, 실패가 재시도를 부르고, 재시도가 대기를 늘리는 자기강화 구조입니다.

#1927·#1929(낡은 인가 변수)와 독립된 원인이고, 그쪽을 고쳐도 남습니다. 수정 대상이 설정 값이 아니라 검증 의미론이라 별건으로 올립니다.

측정

opencode-review-dispatch.yml의 실패 run 중 actor=github-actions[bot]인 것(= 인가를 통과하는 신원) 44건 전수를 의존 순서로 재분류했습니다. 스텝을 run 간에 합산하면 하류 캐스케이드가 중복 계산되므로, validate-pr-metadata → coverage-source-tree → coverage-evidence → opencode-review에서 처음 실패한 job을 근본 원인으로 잡았습니다.

16  validate-pr-metadata | Bind workflow inputs...        36%
14  coverage-evidence    | Measure test and docstring     32%   ← #1883 이 해소
 6  opencode-review      | Wake exact-head required...    14%
 8  나머지 (각 1~2건)

최대 원인 16건을 ##[endgroup] 이후의 실행 출력만 읽어 다시 갈랐습니다. 그 앞은 스크립트 소스 에코라 모든 에러 문구를 포함하고 있어서 어떤 가설이든 확증됩니다.

9  repository_dispatch metadata does not match the live pull request: base_sha
3  rejected closed, missing, or malformed live metadata   (state=closed)
4  repository_dispatch authorization rejected             (#1927/#1929)

12/16이 큐 지연의 결과입니다.

실제 로그

Authorized repository_dispatch actor=github-actions[bot] sender=github-actions[bot]   ← 인가 통과
##[error]... does not match the live pull request: base_sha.
  supplied_base=main/76969152...   live_base=main/5d55a31e...
  supplied_head=...fd964d24        live_head=...fd964d24                              ← head 는 일치

head는 맞고 base만 어긋납니다. 디스패치는 보낸 시점의 base SHA를 싣는데, 큐에서 기다리는 동안 main이 전진합니다. state=closed 3건도 검증 도달 시점에 PR이 이미 닫힌 것이라 같은 기전입니다.

드리프트가 사실상 확정적입니다

오늘 origin/main의 시간당 커밋 수입니다.

09시 2 · 10시 2 · 11시 6 · 13시 5 · 14시 6 · 17시 11 · 18시 3 · 19시 1

그리고 실측된 완주 실행 하나가 **총 15시간 37분, 그중 실제 계산 약 73초(대기 99.87%)**였습니다. 시간당 1~11회 움직이는 브랜치에서 15시간을 기다리면 base가 안 움직일 확률은 사실상 0입니다.

핵심: 이 검사는 데이터 의존이 아니라 staleness 정책입니다

opencode-review-dispatch.yml의 실제 데이터 경로입니다.

:186  검증   [ "$SUPPLIED_BASE_SHA" = "$live_base_sha" ] || mismatches+=("base_sha")   ← 불일치면 exit 1
:199  출력   printf 'base_sha=%s\n' "$live_base_sha"                                    ← live 를 내보냄
:295  소비   PR_BASE_SHA: ${{ needs.validate-pr-metadata.outputs.base_sha }}
:332         git -C "$fetch_dir" checkout --detach "$PR_BASE_SHA"

SUPPLIED_BASE_SHA는 비교에만 쓰이고 버려집니다. 하류가 실제로 체크아웃하는 값은 live_base_sha입니다. 즉 supplied와 live가 달라도 파이프라인은 live로 정상 동작합니다.

동등성 요구가 지키는 것은 "디스패치 시점과 검증 시점 사이에 base가 안 움직였다"는 보장이고, 현재 조건에서 그 보장은 거의 항상 거짓입니다.

head_sha는 다릅니다. :188에서 같은 방식으로 비교하지만, 그건 "이 리뷰가 디스패치된 바로 그 커밋을 대상으로 한다"는 exact-head 규율의 근간입니다. head는 엄격히 유지되어야 합니다.

판단이 필요한 지점

base_sha 동등성을 푸는 것이 기술적으로 안전하다는 것까지가 측정으로 말할 수 있는 전부입니다. 남는 질문은 설계입니다.

  • base 드리프트를 허용하면 coverage가 디스패치 당시와 다른 base에서 측정됩니다. 그 차이가 판정에 영향을 주는지는 이 리포의 커버리지 계약이 정할 문제입니다.
  • 대안으로 허용 범위(예: live base가 supplied base의 후손이면 통과)를 두면 보장을 완전히 버리지 않고 드리프트를 흡수할 수 있습니다.

어느 쪽이든 신뢰 경계에 관한 결정이라 근거만 올립니다.

재현

R=repos/ContextualWisdomLab/.github/actions
gh api "$R/workflows/opencode-review-dispatch.yml/runs?status=failure&per_page=100" \
  --jq '.workflow_runs[] | select(.actor.login=="github-actions[bot]") | .id'
# 각 run 에 대해 validate-pr-metadata job 의 로그에서 ##[endgroup] 이후만 읽을 것.
# 그 앞은 스크립트 소스 에코이며 모든 에러 문구를 포함한다.

관련: #1927, #1929, #1925, #1883

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority: mediumNormal-priority or P2 work

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions