/ci-audit — GitHub Actions 낭비 시간 찾기 및 수정
먼저 측정하고, 그 다음에 중요한 몇 가지를 수정하세요. 실제 감사 결과, 가장 큰 이득은 느린 테스트 스위트에서 거의 발생하지 않았습니다. 오히려, 매일 몇 달 동안 실패하던 예약된 파이프라인, 730분/월로 청구된 30초짜리 매시간 cron, 혹은 데드 요청을 세 번이나 자동 재시도하는 SDK 등이 주범이었습니다.
이 스킬 폴더에 있는 표준 라이브러리 스크립트인 scripts/ci_audit.py가 측정을 수행합니다. 사용자는 그 출력을 읽고, 무엇을 수정할 가치가 있는지 결정한 다음, 수정 사항을 제출합니다.
python3 <skill-dir>/scripts/ci_audit.py inventory <owner> # 어떤 저장소가 Actions를 실행하는지, 비공개 vs 공개
python3 <skill-dir>/scripts/ci_audit.py month <owner/repo> # 워크플로우별 청구 가능 시간, 30일
python3 <skill-dir>/scripts/ci_audit.py jobs <owner/repo> --runs 150 # 작업별 대기열/설정/실행 시간
python3 <skill-dir>/scripts/ci_audit.py steps <owner/repo> <run-id> # 단일 실행에 대한 단계별 초
python3 <skill-dir>/scripts/ci_audit.py schedules <owner/repo> # 모든 cron을 월별 실행 횟수로 표시
GitHub CLI(gh)가 로그인되어 있어야 합니다. month와 jobs는 실행당 하나의 API 호출을 수행하므로, 작업량이 많은 저장소는 1~2분 정도 걸릴 수 있습니다. 백그라운드에서 실행하세요.
0단계 — 범위 및 규칙
측정 전에 사용자와 다음 사항을 협의하세요:
- 대상 소유자와 저장소. 하나의 저장소인지, 아니면 지난 60일 동안 푸시된 모든 저장소인지.
- 제외 저장소. 다른 팀원(또 다른 에이전트)이 그곳에서 기능 개발 중인 경우. 해당 저장소에는 수치를 포함한 이슈만 생성하고, 브랜치를 푸시하지 않습니다.
- 병합 대상. 기본적으로 통합 브랜치(예:
development). 기본 브랜치로의 릴리스는 별도의 동의가 필요하며, cron 및 예약된 수정 사항은 릴리스 후에만 적용됩니다(6단계). - 범위 외: 테스트 커버리지 축소, 유료 러너, CI 공급업체 변경. 수치를 제시하여 권장만 하고, 직접 수행하지는 않습니다.
지금 references/gotchas.md를 읽으세요.
1단계 — 인벤토리 및 비용
- 각 소유자에 대해
ci_audit.py inventory <owner>를 실행합니다. 비공개 vs 공개를 기록합니다. 비용이 발생하는 것은 비공개 저장소뿐이지만, 에이전트가 CI를 기다리며 차단될 때는 모든 저장소의 대기 시간이 중요합니다. - 조직의 경우 실제 청구 정보를 가져옵니다:
gh api "/organizations/<org>/settings/billing/usage?year=YYYY&month=M". 개인 계정의 경우 각 비공개 저장소에ci_audit.py month를 사용하고 총 합계를 요금제 포함 시간과 비교합니다. - 청구 시간 기준 상위 5개 저장소를 기록합니다. 이것이 시간이 소요되는 주요 대상입니다.
2단계 — 느리기 전에 깨짐
예약된 워크플로우가 있는 모든 저장소에 대해:
- 워크플로우별로 마지막 10개의 예약된 실행을 확인합니다. 매번 실패하는 워크플로우가 있다면, 비용과 관계없이 첫 번째 발견 사항입니다. 로그를 읽습니다(
gh api repos/O/R/actions/runs/<id>/logs > logs.zip). .github/workflows/에서actionlint를 실행합니다. GitHub이 구문 분석할 수 없는 파일은 예약을 절대 실행하지 않습니다.
계층화된 오류가 예상됩니다. references/fixes.md §1을 참조하세요.
3단계 — 스케줄
cron이 있는 각 저장소에 대해 ci_audit.py schedules <repo>를 실행합니다. 월별 실행 횟수에 실행당 청구 시간(jobs 결과)을 곱합니다. 다음을 표시합니다:
- 빡빡한 일정의 짧은 작업(매시간 30초 확인은 월 730분 청구).
- 동시에 실행되어 동일한 속도 제한 API를 공격하는 여러 cron.
- 한 번에 거대한 실행을 만드는 월별 cron. 작업을 여러 날로 나눕니다.
4단계 — 작업별 분석
상위 저장소에 대해: ci_audit.py jobs <repo> --runs 150을 실행한 다음, 각 비용이 많이 드는 작업의 최근 녹색 실행 하나에 대해 steps를 실행합니다. 각 작업의 시간을 분류합니다:
| 버킷 | 지시 사항 |
|---|---|
| 대기열 높음 | 러너 경합 또는 동시성 그룹. 일반적으로 저렴하게 수정할 수 없음; 기록만 남겨둠. |
| 설정 높음 | 종속성 설치 및 캐싱 (references/fixes.md §3–4). |
| 실행 높음, 앱 테스트 | 실제 테스트 시간. 단계가 명백히 중복되지 않는 한 그대로 둠. |
| 실행 높음, 데이터 파이프라인 | 단계를 계측하고 CI가 아닌 코드를 수정 (references/fixes.md §6). |
| 실패 > 5% | 불안정한 테스트 또는 깨진 파이프라인 (references/fixes.md §1, §7). |
5단계 — 보고 및 선택
월별 예상 절약 시간으로 정렬된 하나의 테이블을 작성합니다:
| 저장소 | 발견 사항 | 증거 | 수정 | 월별 예상 절약 | 위험 |
|---|
수정하지 않을 발견 사항(제외 저장소, cron 빈도나 병렬 처리와 같은 소유자 결정)도 소유자가 결정하는 데 필요한 수치와 함께 포함합니다. 이를 사용자에게 보여주고 어떤 항목을 제출할지 동의를 얻습니다. 결과를 ${MAKERSKILLS_CONFIG:-$HOME/.config/makerskills}/ci-audit/archive/<YYYY-MM-DD>-<scope>.md에 보관합니다.
6단계 — 수정 패스
하나의 저장소, 하나의 작업자. 하위 에이전트를 지원하는 호스트에서는 동일한 브리핑(새 클론, 먼저 이슈 생성, 이슈 이름을 딴 브랜치, 작은 커밋, PR 본문에 전/후 수치)으로 저장소를 병렬로 실행합니다.
각 수정에 대해:
- 측정 결과와 함께 이슈를 엽니다.
- 브랜치에서 변경 사항을 만듭니다. 린트를 실행하고 테스트를 로컬에서 실행하여 종료 코드로 확인합니다.
- 증명: 푸시한 다음, PR의 CI를 재실행하여 캐시를 워밍업하고, 여러 과거 실행의 기준선과 비교합니다. 파이프라인 수정의 경우 브랜치에서 워크플로우를 소량 제한으로 실행합니다.
- 변경 사항이 도움이 되지 않은 경우(예: Playwright 캐시 문제), 수치와 함께 PR을 닫습니다. 그것은 결과이지 실패가 아닙니다.
- 리뷰와 녹색 체크 후 통합 브랜치에 병합합니다.
- 예약된 작업의 경우, 사용자가 동의하면 기본 브랜치로의 릴리스 PR을 엽니다. 그때까지 프로덕션에서는 아무것도 변경되지 않습니다.
7단계 — 확인 및 기록
- 다음 예약 실행 후, 실행 시간과 로그를 읽습니다. 수정 사항이 브랜치뿐만 아니라 프로덕션에서도 유지되는지 확인합니다.
- 보관 파일에 결과를 추가합니다: 저장소별 전/후, 병합 없이 닫힌 항목, 새로운 주의 사항.
- 매월 또는 CI가 느려질 때마다 감사를 다시 실행할 것을 제안합니다. 정기적인 알림(
loopify)이 효과적입니다.
함께 사용 가능한 스킬
loopify— 월별 재감사 또는 다음 날 아침 첫 예약 실행 확인을 예약합니다.castmate— 위험한 워크플로우 변경에 대해 다른 모델의 검토를 받습니다.unstuck— 효과가 있어야 할 수정이 더 느리게 측정될 때, 포기하기 전에 사용합니다.project-manager— 감사에서 발견되었지만 직접 수정되지 않은 소유자 결정(cron 빈도, 유료 러너)을 추적합니다.
품질 관련 참고 사항
- 깨짐이 느림보다 우선. 시간을 측정하기 전에 항상 실패하는 예약된 워크플로우를 확인하세요. 6개월 동안 매일 실패하는 파이프라인은 어떤 캐시보다 큰 손실입니다.
- 워밍 수치 없이는 주장하지 마세요. 단일 콜드 실행의 속도 향상만으로는 보고하지 마세요. 재실행하고, 여러 과거 실행의 기준선을 설정하며, PR에 두 수치를 모두 명시하세요.
- 초가 아닌 청구 시간. 작업당 분할 반올림은 더 적고 더 큰 작업이 비공개 저장소에서 수많은 아주 작은 작업보다 낫다는 것을 의미합니다. 병렬화는 비용이 드는 속도 결정이지, 공짜 승리가 아닙니다.
- 동일한 커버리지, 매번. PR 본문에는 전후 테스트 개수가 포함되어야 합니다. 더 적게 실행하는 더 빠른 스위트는 수정이 아닙니다.
- 예약됨은 기본 브랜치를 의미. cron 또는 파이프라인 수정이 기본 브랜치에 적용되고 하나의 예약 실행이 통과할 때까지 완료된 것으로 간주하지 마세요.
- 실패한 실험은 데이터와 함께 종료. 더 느리게 측정된 PR은 수치와 함께 닫혀서, 다음 분기에 누군가가 같은 아이디어를 다시 시도하지 않도록 합니다.
- 다른 사람의 브랜치를 존중. 제외 저장소에는 이슈만 생성하고 절대 푸시하지 않습니다.