PR 대화
풀 리퀘스트는 이미 코드에 관한 대화가 일어나는 곳입니다. PR 대화는 채팅
브리지가 Slack을 Control Center
워크스페이스의 표면으로 만드는 것과 같은 방식으로, 풀 리퀘스트를 그렇게
만듭니다. PR에서 서버의 GitHub App 봇을 @멘션하거나, 그 봇의 리뷰 스레드
안에서 답하거나, ai-review 레이블을 붙이면 작업은 PR의 리뷰 스페이스에서
이루어집니다. 앱에서 입력한 어떤 것과도 같은 귀속과 가드레일이 적용됩니다.
댓글은 멤버십도 확인하지만 레이블은 확인하지 않습니다. 작성자가 없기
때문입니다. 봇의 답변은 질문이 제기된 레인에서, GitHub로 돌아옵니다.
이 기능을 이루는 세 가지 결정이 있으며, 각각은 채팅 브리지가 채팅을 위해 내린 것과 같은 결정을 코드 호스트에 맞게 다시 말한 것입니다. 연결이 어느 방향으로 흐르는지, 외부에서 도착한 댓글에 무엇이 권한을 부여하는지, 각 측이 누구로 귀속되는지입니다.
폴링이 전송 방식이다
섹션 제목: “폴링이 전송 방식이다”GitHub가 앱에 제공하는 유일한 푸시 채널은 웹훅이고, 웹훅에는 인바운드 URL이 필요합니다. 이것이야말로 이 표면이 의도적으로 결코 요구하지 않는 항목입니다. 그래서 탐색은 스윕입니다. 1분에 한 번꼴로, 앱 설치마다 별칭을 붙인 검색 하나가 GitHub에 봇(또는 그 단축 슬러그)을 멘션한 PR과 리뷰 레이블을 단 열린 PR을 요청하고, 이미 리뷰 스페이스가 있는 PR은 댓글 스레드를 읽으며, 모든 것은 지난 스윕에서 본 것과 댓글 id로 비교됩니다.
이 설계가 낳는 결과는 짚어 둘 만합니다.
- 지연 시간은 이벤트가 아니라 스윕 주기입니다. 👀 확인 표시는 약 1분 안에 도착합니다. 급한 일이 여기에 실려 가지 않습니다.
- 댓글당 정확히 한 번. 댓글 id는 GitHub 전체에서 고유하며, 각 댓글은 처리 대상으로 분류되는 순간, 무언가가 그것에 작용하기 전에 기록됩니다. 크래시가 나서 그 댓글 처리를 놓칠 수는 있어도 두 번 실행되지는 않습니다.
- 오프라인 시간은 재생이 아니라 따라잡기입니다. 확인 집합이 유지되므로 재시작하면 중단된 동안 도착한 것이 전달됩니다. 유일한 예외는 최초의 스윕입니다. 비교할 기억이 없으므로 밀린 모든 것이 조용히 기록됩니다. 이 서버가 존재하기도 전에 PR 스무 개에 레이블을 붙여 둔 운영자가 돌아왔을 때 스무 개의 리뷰가 실행 중인 상황을 만나서는 안 되기 때문입니다.
- 레이블은 이벤트가 아니라 집합입니다. 검색은 레이블의 _존재_를 보고하므로, 레이블이 붙은 PR은 한 번만 트리거됩니다. 레이블을 뗐다가 다시 붙이는 것은 스윕에 보이지 않습니다. 다시 실행하는 경로는 멘션입니다.
검색은 설치 계정마다 그 소유자 자신의 클라이언트에서 한 번 실행됩니다. 설치 토큰은 자기 설치의 저장소만 볼 수 있기 때문입니다. 서버 전체에 걸친 자격 증명 하나를 쓰면 앱의 다른 설치 아래에 있는 모든 PR을 조용히 놓치게 됩니다.
댓글이 아니라 멤버십이 권한을 부여한다
섹션 제목: “댓글이 아니라 멤버십이 권한을 부여한다”PR 댓글은 작성자 로그인 외에는 거의 아무것도 싣지 않고 도착합니다. 증명되기 전까지는 인증되지 않은 외부 신원입니다. 봇은 워크스페이스 멤버와 그들이 연결한 GitHub 계정의 역색인을 기준으로 이를 확인하며, 이 색인은 서버가 실행되는 동안에도 사람들이 로그인하고 초대받으므로 TTL에 따라 다시 만들어집니다.
차단을 기본으로 하는 실패는 사다리 모양이며, 각 단계는 자신이 거부한 스레드 안에서 답합니다.
- 알 수 없는 로그인 — 연결되지 않았거나, 이 워크스페이스의 멤버가 아닌 사람이 연결한 계정 — 에게는 로그인하고 자신이 소속되어 있는지 확인하라는 안내가 전달됩니다
- 읽기 전용 멤버(
viewer또는guest)에게는 자신의 역할로는 작업을 시작할 수 없다는 안내가 전달됩니다
두 가지 알 수 없는 로그인 경우는 답변 하나를 공유합니다. 역색인은 이 워크스페이스의 멤버만 돌려주므로, 연결되지 않은 계정과 연결되었지만 멤버가 아닌 계정은 같은 실패입니다. 어느 쪽도 진행되지 않습니다. 댓글은 결코 보내지 않은 사람에게 귀속되지 않으며, 낯선 사람의 말은 그가 볼 수 없는 워크스페이스에 결코 들어가지 않습니다.
ai-review 레이블은 확인할 작성자가 없으므로 이 사다리를 오르지 않습니다.
이를 추가하면 저장소를 이미 연결해 둔 워크스페이스에서 리뷰가 시작됩니다.
의도적으로 둘인 신원
섹션 제목: “의도적으로 둘인 신원”대화의 각 측은 서로 다른 신원을 지니며, 그 차이가 곧 이 기능입니다.
- GitHub에서 봇은 서버입니다. 브리지가 게시하는 모든 댓글, 리액션, 답글은 앱의 설치 토큰을 타고 나갑니다. 아무도 클라이언트에서 아무것도 클릭하지 않았으므로 어떤 것도 개인 계정을 빌리지 않습니다. 웹훅과 폴링을 사람의 자격 증명에서 떼어 놓는 것과 같은 규칙입니다.
- 스페이스에서 질문은 당신의 것입니다. 메시지는 작성자가 확인된 멤버에게 귀속되고, 에이전트 실행은 그를 대신해 수행됩니다. 커밋은 그를 공동 작성자로 함께 기록하고, 스페이스의 자율성 다이얼과 액션 가드레일은 앱에서 입력한 메시지에 적용되는 것과 똑같이 적용됩니다. 실행에서 나가는 코드 호스트 쓰기는 위 항목과 같은 규칙에 따라 여전히 앱 자격으로 나가며, 멤버의 개인 토큰을 쓰지 않습니다.
리뷰 발견 사항을 다시 GitHub에 게시하는 일은 Control Center에서 사람이 내리는 결정으로 남습니다. 멘션은 리뷰를 _시작_할 수 있지만, 게시는 사람만 합니다.
루프 가드와 짧은 이름
섹션 제목: “루프 가드와 짧은 이름”봇 계정이 작성한 모든 것은 어떤 게이트가 실행되기 전에 버려집니다. 우리
봇은 물론이고 모든 [bot] 접미사가 그렇기 때문에, 다른 앱의 리뷰 봇도 우리
봇을 깨울 수 없습니다. 이것이 없으면 봇 자신의 답변이 새 댓글로 도착해 봇을
끝없이 다시 트리거할 것입니다.
[bot] 접미사는 단축 형식이 존재하는 이유이기도 합니다. GitHub는 앱 계정의
로그인을 <slug>[bot]으로 고정하고, 이에 대한 자동 완성을 제공하지 않으며,
@slug를 앱으로 결코 해석하지 않습니다. 그래서 순수 슬러그를 받아들이는
것은 우리 매처의 결정이고, 이를 찾아내려면 GitHub의 멘션 인덱스가 아니라
가공되지 않은 댓글 본문 검색 레인이 필요합니다. 그 대가는 얼버무리지
않고 밝힙니다. 앱의 슬러그를 함께 쓰는 사람 사용자는 자신을 짧은 형식으로
멘션할 때마다 봇에게도 말을 거는 셈입니다. 앱 이름이 독특하면 이 충돌은
가정에 불과합니다.
의도적으로 제공하지 않는 것
섹션 제목: “의도적으로 제공하지 않는 것”- 자동 게시 없음. 발견 사항은 리뷰 스페이스에 남고, GitHub에 게시하는 것은 사람이 하는 별도의 작업입니다
- 모호한 신원 없음. 작성자는 정확히 한 명의 멤버로 확인되거나 거부됩니다. 추측으로 귀속하는 일은 없습니다
- GitHub App 웹훅 없음. 이 표면은 웹훅을 결코 등록하지 않으므로 PR 댓글을 위해 노출할 인바운드 URL이 없습니다. 다른 제품 웹훅(파이프라인, 티켓 동기화)은 별도의 선택적 설정입니다.
함께 보기
섹션 제목: “함께 보기”- GitHub PR에서 Control Center와 대화: 이 모든 것에 대한 실전 안내
- 채팅 브리지: 채팅을 위해 내린 같은 세 가지 결정
- GitHub App 만들기: 봇 신원이 비롯되는 곳
- 멀티플레이어 — 신원, 멤버십, 프레즌스: 로그인이 확인되는 주체와 역할
- 가드레일: 답하는 에이전트가 할 수 있는 일
- AI 리뷰 사용: 멘션 또는 레이블이 시작하는 파이프라인