이중 큐 사고 · 라벨 라우팅 · concurrency · 머지 레인 관측
여러 대의 임대 원격 Mac에 셀프호스팅 Runner를 올릴 때 흔한 착각은 「Merge Queue가 머신 큐까지 정리해 줄 것」이라는 기대입니다. GitHub의 머지 큐는 기본 브랜치로의 순서와 게이트를 관리하지만, Runner 백로그는 여전히 라벨과 concurrency 그룹이 결정합니다. 이 글은 제어 플레인 분담표로 두 큐를 분리하고 ci-pr / ci-merge / ci-release 라벨, concurrency와 cancel-in-progress 규칙, p95 대기로 Mac 증설과 GitHub 조정 중 무엇을 먼저 할지 기준을 제시하며 공유 빌드 풀, 좌석 뮤텍스, Mac Mesh 작업 오케스트레이션 글과 상호 링크합니다.
Merge Queue는 기본 브랜치 무결성을 지킵니다. 여러 변경을 안전한 순서로 묶어 통합하지만, 원격 Mac Runner에 항상 여유 CPU가 있다는 보장은 하지 않습니다. PR 검증과 머지 검증이 같은 runs-on 라벨을 공유하면 GitHub는 머지를 진행할 수 있어도 Runner는 선택적 PR 검증에 매몰되는 어긋남이 생깁니다.
이중 큐 오해: Actions의 Queued를 Merge Queue가 머지 작업 우선순위를 올려 준다고 착각합니다.
라벨 혼선: ci 같은 포괄 라벨에 nightly·PR·merge 트래픽이 같이 쌓입니다.
잘못된 취소: 머지 레인에 PR과 같은 cancel-in-progress: true를 써 배치가 중간에 반복해서 깨집니다.
concurrency 이름 충돌: 여러 저장소나 workflow가 같은 concurrency 문자열을 공유해 서로 취소합니다.
관측 부재: 머시 큐 대기와 Runner 바쁨을 분리하지 않아 증설 논의에 데이터가 없습니다.
Mesh 잠금 충돌: 머지 레인에 안정적인 노드 점유가 필요한데 노드 임대 체크리스트와 맞추지 않았습니다.
안내: 아직 노트북 대 원격 역할 비교에 머물러 CI 제어 면으로 내려오지 않았다면 먼저 로컬 가벼운 편집과 원격 무거운 컴파일 임계값 글을 읽어 주세요.
아래 비교표는 리뷰 회의용입니다. 둘 다 하는 것은 Runner 용량이 솔직할 때의 출발점이지 라벨 자기위안이 아닙니다.
| 제어 면 | GitHub Merge Queue | Runner backlog(머신 큐) |
|---|---|---|
| 관할 | 기본 브랜치 순서, 머지 배치, 필수 체크 의미 | 어느 Mac이 언제 어떤 workflow 잡을 돌릴지 |
| 비관할 | M4에 여유 성능 코어가 몇 개인지 | PR가 논리적으로 끼어들 자격이 있는지 |
| 전형적 실패 | 논리는 맞지만 성능 부족으로 배치 타임아웃 반복 | 큐 깊이는 짧은데 머지 잡이 오래 Queued |
| 첫 조치 | 필수 체크와 배치 가정을 조이기 | runs-on 분리, Runner 추가 또는 전용 석 |
부드러운 머지는 Merge Queue 스위치가 아니라 Runner가 머지용 용량을 솔직한 이름으로 남겼는지에 달려 있습니다.
self-hosted + macOS + ci-pr + 툴체인 핀(예 xcode-16-2).ci-merge를 추가하고 최소 한 대의 원격 Mac Runner가 받게 합니다.ci-release를 merge와 분리해 trunk를 굶기지 않습니다.다음 단계는 공유 풀 SSH 글과 병행합니다. 그 글은 Runner에 닿는가, 이 글은 누가 어떤 CPU 타임라인을 소유하는가를 다룹니다.
필수 체크 목록화: 기본 브랜치에서 실제 병합을 막는 검증을 표로 정리하고 예상 시간과 PR 단계 선행 가능 여부를 적습니다.
runs-on 분리: 머지 전용 workflow나 잡에 ci-merge를 붙입니다. 한 물리 머신에 여러 라벨은 가능하지만 시간 예약이나 전용 노드가 필요합니다.
concurrency 점검: PR은 cancel-in-progress: true로 낡은 커밋 검증을 줄이고 merge·release는 cancel-in-progress: false나 더 좁은 키를 씁니다.
concurrency 그룹 이름: 저장소·workflow·환경 접미사를 넣어 조직 전체 충돌을 막습니다.
측정: 팀 보드에서 GitHub merge queue 대기와 Runner busy minutes을 다른 시계열로 봅니다.
게이트 회고: 주 2회 이상 큐는 짧은데 머지 잡이 길게 Queued면 GitHub 병렬 논의 전에 Runner 토폴로지를 바꿉니다.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
merge-gate:
runs-on: [self-hosted, macOS, ci-merge, xcode-16-2]
timeout-minutes: 45
steps:
- run: echo "merge lane only"
아래 패턴은 흔한 사후 분석 표준입니다. 임계값은 자사 데이터로 갈아 끼우되 두 대기를 같은 축에 섞지 마십시오.
| 신호 | 유력 원인 | 첫 움직임 |
|---|---|---|
| 머시 큐는 길고 Runner는 한가함 | 필수 체크나 배치 정책이 과도함 | 체크 그래프와 병렬 가정 검토 |
| 큐는 짧은데 머지 잡이 오래 Queued | 라벨 라우팅 부족이나 Runner 수 부족 | ci-merge 분리, 노드·전용 석 추가 |
| 배치가 인프라 실패 반복 | 타임아웃, 디스크, 키체인, 네트워크 흔들림 | Runner 로그와 서명 거버넌스 체크리스트 대조 |
| PR은 빠른데 merge는 느림 | PR과 merge가 같은 라벨을 다툼 | runs-on 분리와 PR 선택 잡 정리 |
주의: 라벨을 나누지 않고 머지용으로 더 빠른 머신만 추가하면 기아는 릴리스 밤으로 미뤄질 뿐입니다. 장기적으로는 별도 용량 이름이 필요합니다.
아래 구간은 다국적 팀에서 흔한 프로그램 검토 기준입니다. SQL이나 API 필드를 내부 runbook에 박으세요.
ci-merge와 같은 Runner를 잡을 때 근무 시간 busy 분이 85% 초과면 nightly를 ci-pr 풀로 옮깁니다.| 팀 규모 | trunk 머지 빈도 | 권장 첫 수 |
|---|---|---|
| 소규모 | 하루 여러 번 | 전용 ci-merge Runner 한 대 + 엄격한 필수 체크 |
| 중간 | 배치가 끊기지 않음 | 다지역 Runner + 명시적 release 풀 |
| 플랫폼 | 다중 저장소 공유 풀 | 조직 라벨 표준 + queue 대 runner 비용 보드 분리 |
노트북을 임시 Runner로 쓰면 절전·발열·감사 불가한 대화형 로그인 리스크가 생깁니다. 자체 코로케이션 Mac은 조달·배선 부담입니다. 둘 다 머지 SLO를 계약 수준으로 추적하기 어렵습니다.
iOS CI/CD와 AI 에이전트 장시간 작업을 같은 원격 Mac 풀에서 돌릴 때 VpsMesh Mac Mini 클라우드 임대가 보통 더 낫습니다. 리전과 스펙으로 Runner Fleet을 늘리고 merge·release·일상 잡무를 이름 붙은 노드에 얹으며 가용성과 석 정책을 슬랙 암묵이 아니라 운영 조항으로 적습니다.
PR 푸시는 자연히 낡은 검증을 만료시키지만 머지 배치를 반복 취소하면 병합됐는데 자동화가 닫히지 않는 리스크가 커집니다. 정책을 YAML에 박고 고객센터에서 runbook으로 연결하세요.
먼저 공유 빌드 풀로 SSH와 Runner 등록을 닫고 이 글로 머지 레인을 나눕니다. 석 잠금 세부는 mutex TTL 글을 참고하세요.