← 홈Setup Tip

Setup Tip

Setup Tip — 체크가 없는 건 체크를 통과한 게 아니다

외부 기여자가 포크에서 올린 PR 여러 개가 CI 결과 없이 병합됐다. 워크플로가 실패한 게 아니라 아예 돌지 않았다. 포크 PR의 워크플로는 저장소 설정에 따라 관리자 승인을 기다리는 상태로 멈춰 있고, 그동안 PR 화면에는 빨간불도 초록불도 없다. 병합 조건은 '실패가 없음'이 아니라 '필요한 체크가 지금 헤드에서 성공함'으로 정의하고, 승인 대기 중인 실행은 우회하지 말고 승인해서 돌린다.

상황

외부 기여자들이 각자 포크에서 올린 PR 여러 개를 한 번에 정리했다. 그중 몇 개가 병합된 뒤에야 이상한 점이 보였다. PR에 CI 결과가 하나도 없었다. 실패한 체크도, 통과한 체크도 없었다. 병합 판단은 "막는 게 없다"는 이유로 내려졌고, 실제로 그 시점에 막는 빨간불은 없었다.

원인

GitHub는 저장소 설정에 따라 외부 포크에서 온 PR의 워크플로를 바로 실행하지 않고 관리자 승인을 기다리게 한다. 이 상태의 실행은 결론이 action_required로 남고, PR의 체크 목록은 비어 보인다. 비어 있는 목록은 실패가 아니라서 "빨간불이 없으면 진행"이라는 기준을 그대로 통과한다. 체크가 없다는 건 아무것도 검증되지 않았다는 뜻인데, 기준이 그 차이를 구분하지 못했다.

팁: 병합 조건을 긍정형으로 쓴다

"실패한 체크가 없다" 대신 "필요한 체크가 현재 헤드 커밋에서 모두 성공했다"를 조건으로 삼는다. 확인할 때는 gh pr view <번호> --json headRefOid,statusCheckRollup으로 헤드 SHA와 체크 목록을 같이 본다. 목록이 비어 있으면 그 자체를 보류 사유로 취급한다. 저장소 쪽에서는 브랜치 보호의 필수 상태 체크를 켜 두면, 체크가 없는 PR은 애초에 병합 버튼이 막힌다.

팁: 승인 대기 실행을 찾아서 승인한다

gh run list --status action_required로 승인을 기다리는 실행을 찾는다. 변경 내용을 먼저 읽고 워크플로 파일이나 빌드 스크립트를 건드리는 수상한 변경이 없는지 확인한 뒤, 웹 화면의 승인 버튼이나 gh api -X POST repos/<소유자>/<저장소>/actions/runs/<실행 ID>/approve로 실행을 승인한다. 그다음 결과가 나올 때까지 기다린다. 승인 없이 돌리는 우회로는 찾지 않는다. 이 대기 단계는 외부 코드를 내 CI에서 돌리기 전에 사람이 한 번 읽으라는 장치다.

팁: 병합은 확인한 그 커밋에만

체크를 확인한 뒤 병합할 때는 gh pr merge <번호> --match-head-commit <SHA>처럼 확인한 헤드 SHA를 고정한다. 그 사이 누군가 커밋을 더 올렸다면 병합이 거부되고, 검증하지 않은 코드가 섞여 들어가지 않는다. PR을 우회해서 커밋을 기본 브랜치에 직접 옮기는 방식은 체크 자체를 건너뛰므로 쓰지 않는다.

체크리스트

1) 체크 목록이 비어 있으면 통과가 아니라 보류로 본다. 2) action_required 실행이 있는지 찾는다. 3) 변경을 읽은 뒤 실행을 승인하고 결과를 기다린다. 4) 필요한 체크가 현재 헤드에서 성공했는지 확인한다. 5) 그 헤드 SHA를 고정해서 PR 경로로 병합한다.