
Renovate PR의 CI 실패를 Copilot × gh-aw로 자동 수정하기
요약
Renovate로 생성된 의존성 업데이트 PR의 CI 실패를 GitHub Copilot과 gh-aw를 활용해 자동으로 수정하는 워크플로우 구축 과정을 다룹니다. 권한 문제로 인한 시행착오와 이를 해결하기 위한 접근 방식을 상세히 설명합니다.
핵심 포인트
- Renovate PR의 CI 실패를 Copilot이 자동 수정하도록 설계
- GitHub Actions의 GITHUB_TOKEN 권한 제약 문제 확인
- Bot 계정의 댓글에는 Copilot이 반응하지 않는 사양 인지
- PAT(Personal Access Token)를 통한 권한 우회 필요성
서론
Renovate는 의존성 업데이트 PR을 자동으로 생성해 주는 편리한 도구이지만, 업데이트에 따라 CI가 실패하는 경우가 있습니다. 수정 자체는 경미한 케이스가 많지만, 사람이 인지하고 직접 움직이기 전까지 PR이 방치되기 쉽습니다.
이 기사에서는 GitHub Copilot (coding agent)를 CI로부터 자동으로 기동하여 에러를 수정하게 하는 메커니즘을 **gh-aw (GitHub Agentic Workflows)**로 구축했을 때의 설계 포인트와 시행착오를 소개합니다.
전제
- 대상은 PHP 8.4 / Laravel API 프로젝트 (DB는 MySQL)
- CI에서는 phpcs / phpstan / rector / phpunit을 실행 중
- 의존성 업데이트는 Renovate에 맡기고 있음
무엇이 문제였는가
Renovate가 만드는 PR에서 CI가 실패하는 패턴은 크게 두 가지가 있습니다.
1. Lint/정적 분석 에러
패키지 업데이트에 따라 phpcs의 규칙이 바뀌었거나, Rector가 새로운 권장되지 않는(deprecated) 표기법을 검출하는 등. phpcbf나 rector process로 한 번에 해결되는 경우도 많습니다.
2. 의존성 파괴적 변경 (Breaking Changes)
라이브러리의 메이저/마이너 업데이트로 인해 타입 시그니처(type signature)나 API가 변경된 케이스. 호출 측의 코드를 새로운 API에 맞춰 수정해야 합니다.
둘 다 "할 일은 알고 있지만 직접 움직이기가 귀찮은" 작업입니다. 이를 Copilot이 자동으로 해주길 바라는 것이 동기였습니다.
완성 이미지
최종적으로 실현한 플로우는 다음과 같습니다.
Renovate가 코드를 업데이트하고, CI가 실패하면 자동으로 Copilot이 수정을 시도합니다. 성공하면 그대로 머지(merge) 가능한 상태가 됩니다.
Copilot을 CI에서 기동하는 방법을 찾는 여정
"CI 실패 시 Copilot이 수정하게 한다"를 실현하기 위해 4가지 접근 방식을 시도했습니다.
접근 방식 1: Copilot을 어사인(Assign)하기
GitHub Copilot coding agent는 PR에 @copilot을 어사이니(assignee, 담당자)로 할당하면 기동하여, PR 내용에 따라 자동으로 커밋을 쌓아주는 메커니즘이 있습니다. 그렇다면 CI의 실패를 감지했을 때 Actions에서 @copilot을 어사인하면 자동 수정이 작동할 것입니다.
gh pr edit --add-assignee @copilot
결과: ❌
GitHub Actions에서 사용할 수 있는 GITHUB_TOKEN으로는 Copilot을 PR에 어사인할 권한이 없습니다. 어사인 작업은 사용자 권한이 필요하며, Bot 토큰으로는 실행할 수 없었습니다.
접근 방식 2: @copilot 이라고 댓글 달기
Copilot coding agent에는 PR이나 Issue의 댓글로 @copilot이라고 멘션하면 반응해 주는 기능도 있습니다. 그렇다면 어사인이 아니라, CI 실패 시 GitHub Actions Bot (github-actions[bot])이 @copilot 이 CI 에러를 수정해 주세요라고 PR에 댓글을 달면 되지 않을까 생각했습니다.
결과: ❌
Bot이 게시한 댓글에는 Copilot이 반응하지 않습니다. Copilot의 멘션 기동은 인간 사용자가 작성한 댓글만을 대상으로 하며, Bot ([bot] 접미사가 붙는 계정)의 댓글은 스킵되는 사양이었습니다.
접근 방식 3: PAT (Personal Access Token) 사용하기
접근 방식 1·2의 벽은 결국 Actions의 GITHUB_TOKEN으로 할 수 있는 것과 할 수 없는 것의 제약이었습니다. 이를 회피하는 정석적인 수단이 **PAT (Personal Access Token)**입니다.
PAT는 GitHub의 개인 계정으로 발행하는 액세스 토큰으로, 리포지토리 시크릿(repository secret)에 저장하여 Actions에서 사용하면 그 작업은 발행자 본인의 계정으로 실행된 것으로 취급됩니다. 개인 계정이라면 Copilot 어사인도 할 수 있고, 댓글도 Bot이 아닌 개인 사용자로부터의 게시물이 되기 때문에 Copilot이 반응합니다.
결과: △ (작동은 하지만 미묘함)
- 토큰의 유효 기간 관리 및 로테이션(Rotation)이 필요함
- 발행한 개인이 퇴사하거나 부서를 이동하면 워크플로우가 중단됨
- 개인 계정에 종속된 작업이므로 책임 소재가 모호해짐
팀 개발에서는 피하고 싶은 운영 방식입니다.
접근 방식 4: gh-aw + copilot-requests: write ✅
지금까지의 세 가지 접근 방식은 모두 "PR에 대한 어사인(Assign)이나 댓글을 통해 Copilot을 구동하는" 간접적인 방법이었습니다. 그렇기 때문에 Bot 제한이나 PAT(Personal Access Token) 운영 문제에 부딪혔던 것입니다.
방침을 바꾸어, 그러한 GitHub상의 이벤트를 거치지 않고 Actions의 잡(Job)에서 직접 Copilot의 추론 API를 호출하는 방법을 찾던 중, **gh-aw (GitHub Agentic Workflows)**라는 GitHub 공식 CLI 확장 도구를 발견했습니다. 이것이 정답이었습니다.
gh-aw는 Markdown으로 "Copilot이 수행할 작업"을 작성하고, gh aw compile을 통해 GitHub Actions 워크플로우(.lock.yml)로 컴파일하는 구조입니다. 생성된 .lock.yml은 일반적인 Actions 워크플로우이며, 실행 시 Copilot 추론 API를 호출하여 에이전트(Agent)를 구동합니다.
fix-renovate-ci.md → gh aw compile → fix-renovate-ci.lock.yml
(사람이 작성) (Actions가 실행)
그리고 가장 중요한 포인트는 copilot-requests: write 권한입니다. 이는 GITHUB_TOKEN에 부여할 수 있는 권한 중 하나로, Actions의 빌트인(Built-in) 토큰으로부터 Copilot 추론 API를 호출할 수 있게 해줍니다. 즉, PAT를 준비하지 않아도 표준 GITHUB_TOKEN만으로 Copilot 코딩 에이전트(Coding Agent)를 구동할 수 있다는 뜻입니다.
보충: gh-aw 공식 토큰 설정에 대하여
gh-aw 공식 문서에는 COPILOT_GITHUB_TOKEN이나 GH_AW_GITHUB_TOKEN 같은 시크릿(Secret)을 설정하는 방법이 기재되어 있습니다. 이것들은 실질적으로 PAT를 사용하는 방식이며, 접근 방식 3과 동일한 과제를 안고 있습니다. 하지만 공식 문서에는 다음과 같은 내용이 이어집니다:
결제는 조직의 Copilot 플랜을 통해 처리됩니다. copilot-requests: write 권한을 부여하면, gh-aw는 빌트인 GITHUB_TOKEN을 사용하여 Copilot 추론을 수행하며, 위의 토큰 관련 시크릿들은 무시됩니다. 즉, Copilot 구독을 보유한 조직이라면 copilot-requests: write가 권장되는 방식이며, 이를 통해 PAT가 불필요해집니다.
설계상의 포인트
여기서부터는 실제로 구성한 fix-renovate-ci.md 중에서 특히 고안이 필요했던 부분을 뽑아서 소개하겠습니다. 설정 파일의 전문은 별도의 리포지토리(Repository)에서 공개하고 있습니다.
트리거: CI가 실패했을 때만 구동
on:
workflow_run:
workflows: ["CI"]
...
workflow_run 트리거를 사용하여, CI 워크플로우가 renovate/** 브랜치에서 실패하며 완료되었을 때만 발화합니다.
환경: Copilot이 코드를 수정할 수 있도록
Copilot이 에러를 재현 및 검증할 수 있도록 CI와 동등한 환경을 준비합니다.
- MySQL 서비스 컨테이너 (phpstan이 DB 스키마를 참조하기 때문)
- PHP 8.4 + Composer + 모든 의존성 패키지 설치
- 마이그레이션(Migration) 실행
도구 허용: 필요한 명령만 사용할 수 있도록
tools:
edit:
bash:
...
Copilot에게 허용할 명령어를 화이트리스트(Whitelist)로 제한하여, 불필요한 조작을 하지 못하게 합니다.
프롬프트: 실패 패턴별 수정 절차 지시
Markdown 본문이 그대로 Copilot으로 전달되는 프롬프트(Prompt)가 됩니다. 실패 패턴별로 구체적인 대처법을 기재했습니다.
- lint 실패 →
phpcbf
로 자동 수정하며, 고쳐지지 않으면 수동으로 수정합니다.
phpstan 실패 → 새로운 API에 맞춰 코드를 수정
rector 차이(diff) → rector process로 적용
테스트 실패 → Breaking Change (파괴적 변경)에 맞춰 코드를 수정
Composer 충돌 → composer why-not으로 원인 조사 → 관련 패키지를 한꺼번에 업데이트
무한 루프를 방지하기
Copilot이 수정을 push → CI 재실행 → 또 실패 → 또 Copilot 기동 → ...
이러한 무한 루프를 방지해야 합니다.
해결책: 커밋 메시지 접미사(Suffix)로 감지
gh-aw에는 Copilot이 push하는 커밋 메시지에 임의의 접미사를 붙일 수 있는 commit-title-suffix라는 설정이 있습니다. 이를 사용하여 [gh-aw]라는 표식을 붙이고, 워크플로우(Workflow) 측에서 이를 감지합니다.
# frontmatter 내 (후술할 safe-outputs와 공통)
safe-outputs:
push-to-pull-request-branch:
...
# 워크플로우의 첫 단계에서 커밋 이력을 체크
LAST_MSG=$(git log -1 --format=%s)
if [[ "$LAST_MSG" == *"[gh-aw]"* ]]; then
...
다음 workflow_run이 트리거되었을 때, 직전 커밋 메시지에 [gh-aw]가 포함되어 있다면 "이전에 Copilot이 수정하려고 시도했으나 실패했다"라고 판단하여 워크플로우를 종료합니다.
즉, 자동 수정은 최대 1회만 시도하며, 안 되면 사람에게 넘깁니다.
수정이 불가능하면 무리하지 않기
모든 CI 실패를 Copilot이 고칠 수 있는 것은 아닙니다. 무리하게 수정을 push하여 상황을 악화시키지 않도록, 철수 규칙을 명시했습니다.
다음의 경우에 해당하면 push하지 않고, PR에 댓글로 이유를 보고하게 합니다:
- 인프라/외부 서비스 기인 에러 (DB 연결, 네트워크 등)
- 수정에 파괴적 변경 (Breaking Change)이 필요하여 안전하게 판단할 수 없는 경우
- 몇 번을 시도해도 검증 명령어가 통과되지 않는 경우
- 원인을 특정할 수 없는 경우
safe-outputs:
push-to-pull-request-branch:
target: "*"
...
gh-aw의 safe-outputs를 통해 Copilot의 출력 수단을 "PR 브랜치로의 push"와 "PR에 대한 댓글"로 한정하고 있습니다. 수정하지 못했을 경우에는 댓글만 남기고 종료하므로, 사람이 PR을 보고 상황을 파악하여 수동 대응으로 전환할 수 있습니다.
요약
| 과제 | 해결책 |
|---|---|
| CI에서 Copilot을 기동하고 싶다 | gh-aw + copilot-requests: write |
| 무한 루프 방지 | [gh-aw] 커밋 접미사로 1회만 시도 |
| 수정 불가능 시 안전장치 | push하지 않고 PR 댓글로 철수 |
gh-aw를 통해, PAT 관리 없이 Copilot coding agent를 CI에서 기동할 수 있게 되었습니다. Renovate + Copilot의 조합으로 의존성 업데이트의 "마지막 수고"를 거의 자동화할 수 있습니다.
물론 만능은 아니며, 복잡한 파괴적 변경은 사람의 판단이 필요합니다. 하지만 "phpcbf를 실행하면 고쳐진다", "타입을 한 곳만 고치면 된다"와 같은 경미한 수정이 대부분을 차지하는 Renovate PR에 있어서는, 충분히 실용적인 메커니즘이라고 느낍니다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기