Claude Code로 CI 실패 로그 자동 요약해서 Slack DM 보내는 파이프라인, 로그 전처리 어떻게 하세요?
GitHub Actions에서 테스트 깨질 때마다 수백 줄짜리 로그를 직접 열어보는 게 너무 비효율적이라 자동화하려고 합니다.
원하는 흐름은 이렇습니다.
- CI가 실패하면
- 실패 job 로그를 가져와서
- LLM으로 "무엇이 왜 깨졌는지" 3~5줄로 요약
- 해당 PR 작성자에게 Slack DM
지금은 actions/github-script로 로그를 통째로 긁어서 프롬프트에 던지는데, 로그가 길면 컨텍스트가 넘치고 비용도 부담됩니다. 그리고 가끔 엉뚱한 데를 짚어요 — 진짜 원인은 npm ci 단계 실패인데 그 뒤에 줄줄이 난 테스트 실패만 요약하는 식으로요.
로그 전처리랑 프롬프트를 어떻게 잡는 게 좋을까요? 실제로 돌리시는 분들 노하우가 궁금합니다.
답변 3개
- 채택된 답변에디터 검증
전체 로그 통째로 넣는 게 제일 큰 실수예요. CI 로그는 진짜 원인이 거의 항상 "맨 처음 터진 에러"고 나머지는 그 여파(cascade)인데, 그걸 안 잘라주면 LLM이 제일 마지막에 실패한 테스트를 원인으로 착각합니다. 질문하신 "의존성 설치 실패인데 테스트 실패만 요약"이 딱 그 케이스예요.
저희가 박아둔 전처리 순서:
- ANSI 컬러코드 먼저 제거.
sed -r 's/\x1B\[[0-9;]*[mK]//g'. 이거 안 지우면 토큰만 잡아먹고 모델 가독성도 떨어짐. - 첫 에러 앵커 기준으로 윈도잉.
error|failed|exception|Error:|✕|FAIL패턴이 처음 매치되는 줄 찾아서 그 앞 30줄 + 뒤 60줄만 슬라이스. 첫 매치 기준이라는 게 포인트입니다. 마지막 매치 기준으로 자르면 cascade 끝물만 남아서 똑같이 헛짚어요. - 어느 step에서 죽었는지 메타데이터를 같이 동봉.
Install deps냐Run tests냐를 한 줄로 박아주면 모델이 "설치 단계에서 죽음" 신호를 잡습니다.
그리고 프롬프트에 이 한 줄 꼭 넣으세요 — "여러 에러가 보이면 시간순으로 가장 먼저 발생한 걸 근본 원인으로 보고, 나머지는 그 결과로 가정하라." 체감상 cascade 오진이 이 문장 하나로 절반 이하로 줄었습니다.
참고로 로그 긁는 것부터 바꾸시는 게 빠릅니다.
gh run view <run-id> --log-failed쓰면 실패한 step 로그만 떨어져서 전체 긁을 필요가 없어요. 컨텍스트 문제 절반은 여기서 해결됩니다. - ANSI 컬러코드 먼저 제거.
다들 LLM 요약에 꽂혀 계신데, 저는 반대로 요약이 필요 없는 케이스를 앞단에서 먼저 거릅니다.
lint 실패, 타입 에러, 타임아웃 이런 건 어차피 패턴 매칭으로 90% 분류돼요.
tsc에러는error TS\d+로 잡히고 줄/파일도 다 박혀 있는데 굳이 LLM 부를 이유가 없죠. 이런 건 "타입 에러 N건, 파일 X" 식으로 결정적으로 메시지 만들고, LLM은 정말 애매한 런타임/통합 테스트 실패에만 호출합니다.비용도 줄고 오진도 줄고, 결정적이라 신뢰도도 오르고. 모든 걸 LLM에 떠넘기지 마세요.
전처리는 윗분이 다 말했고, 비용 쪽으로 하나 보탤게요.
Anthropic API로 돌리면 prompt caching 꼭 켜세요. 요약 지시문(시스템 프롬프트 + few-shot 예시)은 매번 똑같으니까 그걸
cache_control블록으로 분리하고, 변하는 로그 본문만 뒤에 붙이는 구조로요. CI 자주 깨지는 레포면 5분 TTL 안에 연속으로 터지는 경우가 많아서 히트율이 생각보다 잘 나옵니다. 우리 레포는 요약 호출 비용이 눈에 띄게 떨어졌어요.그리고 Slack DM 쪽 함정 하나. PR 작성자 깃헙 계정 → Slack 유저 매핑을 미리 테이블로 들고 있어야 합니다. 없으면
users.lookupByEmail로 이메일 조회하게 되는데, 깃헙 commit email이랑 Slack 가입 email이 다른 사람이 팀에 꼭 한둘 있어서 거기서users_not_found뜨고 DM이 조용히 안 갑니다. fallback으로 채널 멘션 준비해두세요.