GitLab Merge Request pipeline에서 Job으로 실행되는 AI 코드 리뷰.
별도 리뷰 서버를 두지 않고, 각 GitLab repository의 MR pipeline job이 Docker image를 pull한 뒤 ai-code-review CLI를 실행한다. CLI는 GitLab API로 MR 변경 내용을 읽고 Gemini에 리뷰를 요청한 뒤, MR summary note와 added line comment를 GitLab에 작성한다.
현재 사용중인 모델 : Gemini 3.1 Flash Lite model - 무료 토큰 제한이 높고, 빠르고 경량화 모델 중 성능이 우수함.
- GitLab API를 통한 MR 메타데이터, 최신 diff 버전, 변경 파일 조회
- 인라인 리뷰 코멘트 작성을 위한 코멘트 가능한 추가 라인(added lines) 만 매핑
- 안전한 교체 라인이 있을 때 added-line comment에 GitLab single-line suggestion block 추가
- diff 이해도 향상을 위한 변경 파일 주변 제한된 로컬 워크스페이스 컨텍스트 조회
- Gemini 기반 MR 수준의 코드 요약(code summary), 실행 가능한 라인 단위 지적 사항, 리뷰 제한/노트 포함 구조화 결과 생성
- MR draft note(요약 + 라인 코멘트) 생성
- 기본 동작: 동일 head_sha 중복 리뷰 방지 / 선택 동작: AI_REVIEW_FORCE=true 시 재리뷰 허용
- 오래된 코멘트 방지를 위한 posting/publishing 전 stale head_sha 검사
- 대규모 MR 정책 기반 처리: 한도 내 일반 라인 리뷰, soft-limit 초과 시 summary-only 모드, hard-limit 초과 시 hard skip
- 노이즈 감소를 위한 리뷰 제외 파일(lock/generated/binary/build outputs 등) 필터링
- 언어/프레임워크에 따라 조합할 수 있는 rule pack 지원: default(항상 적용), spring, node-express, react-nextjs, python-django-fastapi, nestjs, go-gin-echo, vue-nuxt
- AI_REVIEW_MAX_COMMENTS, AI_REVIEW_MAX_COMMENTS_PER_FILE 기반 코멘트 볼륨 제어
- non-blocking 리뷰(allow_failure: true) 유지로 AI 장애 시에도 파이프라인 진행 차단 방지
- 추적성 확보를 위한 실행 artifact(ai-review-result.json) 상시 기록
GitLab Merge Request
|
v
MR Pipeline
|
v
ai-code-review job
|
v
Docker image: ghcr.io/squatboy/gitlab-code-review:<tag>
|
v
ai-code-review CLI
|
+--> GitLab API: MR 정보, diff version, 변경 파일 조회
|
+--> Gemini API: structured review result 생성
|
+--> GitLab API: draft note 생성 후 bulk publish
|
+--> ai-review-result.json artifact 저장
대상 repository의 .gitlab-ci.yml에 아래 job을 추가한다.
ai-code-review:
stage: test
image: ghcr.io/squatboy/gitlab-code-review:v0.1.0-rc3
variables:
AI_REVIEW_ENABLED: "true"
AI_REVIEW_FORCE: "false"
AI_REVIEW_LANGUAGE: "ko"
AI_REVIEW_MODEL: "gemini-3.1-flash-lite-preview"
AI_REVIEW_MAX_COMMENTS: "10"
AI_REVIEW_MAX_COMMENTS_PER_FILE: "3"
AI_REVIEW_RULE_PACKS: "default"
AI_REVIEW_RESULT_PATH: "ai-review-result.json"
allow_failure: true
script:
- ai-code-review
artifacts:
when: always
expire_in: 7 days
paths:
- ai-review-result.json
rules:
- if: '$AI_REVIEW_ENABLED == "false"'
when: never
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_SOURCE_PROJECT_ID == $CI_PROJECT_ID && $CI_MERGE_REQUEST_TITLE !~ /^(Draft:|WIP:)/'
when: on_success
- when: neverrunner 설정:
tags필드는 선택사항입니다. Runner가 untagged job을 지원하지 않으면 추가하세요.tags: - <your-runner-tag>
Group level variable로 등록하는 것을 기본으로 한다.
AI_CODE_REVIEW_GITLAB_TOKEN
AI_REVIEW_API_KEY
AI_CODE_REVIEW_GITLAB_TOKEN:
- 권장: GitLab Group Access Token
- 대안: 전용 bot 계정의 Personal Access Token
- 권한: 대상 project에 Developer 이상
- scope:
api - 용도:
- MR 읽기
- MR discussion/note 조회
- draft note 생성
- draft note bulk publish
- 같은 project 내부 MR pipeline에서 사용하려면 protected variable로 두지 않는다.
AI_REVIEW_API_KEY:
- Gemini API key 원문
- GitLab CI variable에서는 masked/hidden 설정 권장
| Variable | Default | 설명 |
|---|---|---|
AI_REVIEW_ENABLED |
true |
false면 job 내부에서 리뷰를 스킵한다. |
AI_REVIEW_FORCE |
false |
true면 같은 head_sha도 다시 리뷰한다. |
AI_REVIEW_LANGUAGE |
en |
리뷰 결과 언어. 한국어는 ko 로 선언 |
AI_REVIEW_MODEL |
gemini-3.1-flash-lite-preview |
Gemini 모델명. |
AI_REVIEW_MAX_COMMENTS |
10 |
MR 전체 line comment 최대 개수. |
AI_REVIEW_MAX_COMMENTS_PER_FILE |
3 |
파일당 line comment 최대 개수. |
AI_REVIEW_RULE_PACKS |
default |
적용할 rule pack. comma-separated string. default는 항상 적용됨. |
AI_REVIEW_RESULT_PATH |
ai-review-result.json |
결과 artifact 파일 경로. |
지원 rule pack:
default: 언어/프레임워크 공통 기준(정합성, 보안, 무결성, 회귀 위험)spring: Spring/JPA/MyBatis/REST 중심 점검node-express: Node.js/Express API 및 미들웨어 중심 점검react-nextjs: React/Next.js 렌더링 경계 및 계약 중심 점검python-django-fastapi: Django/FastAPI ORM·검증·권한 중심 점검nestjs: NestJS 모듈/DI 경계, guard/interceptor/pipe 흐름, DTO 검증, 권한 점검go-gin-echo: Go Gin/Echo 컨텍스트 타임아웃·취소, 고루틴 안전성, 검증, API 계약 점검vue-nuxt: Vue/Nuxt SSR-CSR 경계, hydration 불일치, 라우트 가드/인증 흐름, XSS 위험 점검
동작 정책:
- 알 수 없는 rule pack은 무시하고 리뷰를 계속 진행한다.
- 무시된 pack 이름은 리뷰 summary의 제한 항목에 표시된다.
- 예시:
AI_REVIEW_RULE_PACKS=spring,nestjs,go-gin-echo
- MR pipeline에서만 실행한다.
- fork MR은 제외한다.
Draft:또는WIP:제목의 MR은 제외한다.- 같은
head_sha에 이미 summary note가 있으면duplicate_head_sha로 스킵한다. AI_REVIEW_FORCE=true면 같은head_sha도 다시 리뷰한다.- line comment는 added line에만 작성한다.
- 정확한 단일 교체 라인이 있을 때만 added-line comment에 suggestion을 첨부한다.
- 삭제 line, context line, multi-line range에는 comment하지 않는다.
- AI 리뷰 실패는 pipeline을 막지 않는다.
- 실행 결과는 항상
ai-review-result.jsonartifact로 남긴다.
의존성 설치:
pnpm install빌드:
pnpm build테스트:
pnpm testlint:
pnpm lint로컬 non-network smoke:
AI_REVIEW_ENABLED=false pnpm dev기대 결과:
- CLI가 실행된다.
ai-review-result.json이 생성된다.- status가
skipped로 기록된다.
GitHub Actions workflow는 quality check 통과 후 GHCR에 multi-arch image를 publish한다.
- Pull request:
pnpm build,pnpm test,pnpm lint, Docker build 검증만 실행하고 push하지 않는다. mainpush:ghcr.io/squatboy/gitlab-code-review:sha-<short_sha>를 push한다.v*tag push: version tag (예:v0.1.0)만 push한다.latesttag는 사용하지 않는다.
로컬 테스트:
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t ghcr.io/squatboy/gitlab-code-review:<version> \
--push .manifest 확인:
docker manifest inspect ghcr.io/squatboy/gitlab-code-review:<version>