一键导入
jenkins-ci-loop
push 후 Jenkins CI 빌드를 모니터링하고 실패 시 원인 파악 → 수정 → 재push를 SUCCESS까지 반복하는 스킬입니다. "/jenkins-ci-loop", "젠킨슨 루프", "CI 루프", "빌드 실패 수정" 등을 요청할 때 사용됩니다.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
push 후 Jenkins CI 빌드를 모니터링하고 실패 시 원인 파악 → 수정 → 재push를 SUCCESS까지 반복하는 스킬입니다. "/jenkins-ci-loop", "젠킨슨 루프", "CI 루프", "빌드 실패 수정" 등을 요청할 때 사용됩니다.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | jenkins-ci-loop |
| description | push 후 Jenkins CI 빌드를 모니터링하고 실패 시 원인 파악 → 수정 → 재push를 SUCCESS까지 반복하는 스킬입니다. "/jenkins-ci-loop", "젠킨슨 루프", "CI 루프", "빌드 실패 수정" 등을 요청할 때 사용됩니다. |
git push 후 Jenkins CI 빌드 결과를 모니터링하고,
실패 시 원인 파악 → 로컬 수정 → commit → push → 재빌드를 SUCCESS가 될 때까지 자동 반복한다.
⛔ 로컬
./gradlew절대 금지. 모든 Gradle 작업(ktlint/test/build)은 AI_server 원격에서만 실행한다. 파일 편집·git commit·push만 로컬에서 수행한다.
| 항목 | 값 |
|---|---|
| Jenkins host | AI_server |
| Jenkins container | jenkins |
| Workspace 패턴 | /var/jenkins_home/workspace/bitda-back-ci_PR-{pr} |
| Build log 패턴 | /var/jenkins_home/jobs/bitda-back-ci/branches/PR-{pr}/builds/{build}/log |
| Test XML 위치 | {workspace}/modules/{module}/build/test-results/test/TEST-*.xml |
🔐 크리덴셜은 하드코딩하지 않는다. 저장소 루트의
.env.jenkins파일(git-ignored)에서 로드한다.
.env.jenkins 형식:
JENKINS_URL=https://jenkins.invigoworks.co.kr
JENKINS_USER=invigoworks
JENKINS_TOKEN=<토큰>
Jenkins API 호출 전 매 Bash 호출에서 .env.jenkins를 source 한다:
set -a; . /Users/gimjinhyeog/Desktop/coding/bitda-back/.env.jenkins; set +a
⛔ Playwright 절대 금지. Jenkins API 호출은 반드시
curl+ 위 크리덴셜로만 한다. Playwright/브라우저 자동화는 이 스킬에서 사용하지 않는다.
set -a; . /Users/gimjinhyeog/Desktop/coding/bitda-back/.env.jenkins; set +a
# 빌드 트리거
curl -s -u "$JENKINS_USER:$JENKINS_TOKEN" \
"$JENKINS_URL/job/bitda-back-ci/job/PR-{pr}/build"
# 빌드 상태 확인
curl -s -u "$JENKINS_USER:$JENKINS_TOKEN" \
"$JENKINS_URL/job/bitda-back-ci/job/PR-{pr}/lastBuild/api/json?tree=number,result,building"
# 빌드 로그 (콘솔 출력)
curl -s -u "$JENKINS_USER:$JENKINS_TOKEN" \
"$JENKINS_URL/job/bitda-back-ci/job/PR-{pr}/{build}/consoleText"
확인 없이 자동 실행:
사용자에게 질문하는 경우:
gh pr view --json number -q '.number' -R invigoworks/bitda-back
인자로 전달된 경우 (/jenkins-ci-loop #1778) 우선 사용.
병렬 작업 환경에서 다른 PR이 먼저 main에 머지되면 이 PR 브랜치가
BEHIND상태가 된다. 그대로 CI를 돌리면 낡은 base로 빌드/머지가 꼬이고 뒤늦게 rebase가 강제된다. 루프 시작 전에 미리 rebase하여 최신 main 기준으로 CI를 돌린다.
HEAD_BRANCH=$(gh pr view {pr} --json headRefName -q .headRefName -R invigoworks/bitda-back)
git fetch origin main -q
BEHIND=$(git rev-list --count origin/${HEAD_BRANCH}..origin/main 2>/dev/null)
echo "main이 PR 브랜치보다 ${BEHIND}개 커밋 앞섬"
BEHIND == 0 → 이미 최신. Step 1로 진행 (rebase 불필요).BEHIND > 0 → 0.5b 진행.mergeStateStatus로 교차 확인 가능:
gh pr view {pr} --json mergeStateStatus -q .mergeStateStatus→BEHIND면 rebase 필요.
WORKTREE_PATH={worktree-path} # git worktree list로 확인
cd ${WORKTREE_PATH}
# .omc/state 등 추적 캐시가 rebase를 막으면 정리
git checkout -- .omc/state 2>/dev/null || true
git rebase origin/main 2>&1 | tail -15
git rebase --abort 후 사용자에게 보고 (자동 충돌 해결 금지).
복잡한 충돌은 수동 개입 필요.git push --force-with-lease origin ${HEAD_BRANCH} 2>&1 | tail -5
# ⚠️ pre-push 훅이 로컬 gradle ktlint를 돌려 데몬을 남길 수 있음 → 즉시 종료
cd {메인-저장소-루트} && ./gradlew --stop 2>&1 | tail -1
force push 후 Jenkins가 새 빌드를 자동 트리거한다. 새 빌드 번호로 Step 1 진행.
예외 (rebase 생략):
BEHIND == 0 (이미 최신 main 기준).MERGED/CLOSED 상태 (정리만 필요).ssh AI_server "docker exec jenkins ls -t /var/jenkins_home/jobs/bitda-back-ci/branches/PR-{pr}/builds/ 2>/dev/null | grep -E '^[0-9]+$' | head -1"
빌드가 아직 없으면 30초 대기 후 재확인.
ssh AI_server "while ! docker exec jenkins grep -qE 'Finished: ' /var/jenkins_home/jobs/bitda-back-ci/branches/PR-{pr}/builds/{build}/log 2>/dev/null; do sleep 30; done; docker exec jenkins grep -E 'GitHub check.*completed|Finished:|FAILED' /var/jenkins_home/jobs/bitda-back-ci/branches/PR-{pr}/builds/{build}/log 2>/dev/null | grep -v 'ha:////'" 2>&1
run_in_background: true로 실행하여 완료 알림 대기.
ssh AI_server "docker exec jenkins grep -E 'Finished: ' /var/jenkins_home/jobs/bitda-back-ci/branches/PR-{pr}/builds/{build}/log 2>/dev/null | tail -1"
Finished: SUCCESS → Step 7 (완료)로 이동Finished: FAILURE → Step 4 (원인 파악)로 이동ssh AI_server "docker exec jenkins grep -E 'GitHub check.*completed|FAILED|ProductionPlan.*FAILED|\\bFAILED\\b' /var/jenkins_home/jobs/bitda-back-ci/branches/PR-{pr}/builds/{build}/log 2>/dev/null | grep -v 'ha:////' | tail -20"
# 실패한 테스트 XML 찾기
ssh AI_server "docker exec jenkins find /var/jenkins_home/workspace/bitda-back-ci_PR-{pr}/modules -name 'TEST-*.xml' -exec grep -l 'failures=\"[^0]\\|errors=\"[^0]' {} \; 2>/dev/null | head -5"
# 실패 상세 확인
ssh AI_server "docker exec jenkins grep -A 30 'failure\|error' {xml_path} | head -60"
XML에서 확인할 핵심 정보:
failure message: 예외 메시지 (예: IllegalArgumentException: 생산일자는 오늘 또는 과거여야 합니다)at {ClassName}.kt:{line}: 실패 위치ssh AI_server "docker exec jenkins grep -E 'error:|error\[|Compilation error|Type mismatch|Unresolved reference' /var/jenkins_home/jobs/bitda-back-ci/branches/PR-{pr}/builds/{build}/log 2>/dev/null | grep -v 'ha:////' | head -20"
파악된 원인에 따라 로컬 워크트리에서 파일만 수정한다 (Gradle 실행 금지):
⛔ 로컬
./gradlew절대 금지. 파일 편집·git 조작만 로컬에서 하고, ktlint/test/build 등 모든 Gradle 작업은 AI_server 원격에서만 실행한다. 로컬 Gradle은 데몬이 잔존하여 시스템을 느리게 만든다.
Read (Edit 직전 필수)Edit으로 수정ktlintCheck 확인 (AI_server 원격):
PR={pr-number}
WORKTREE_PATH={worktree-path}
# 동기화 (tar over ssh — 한글 파일명 보존). impl workdir와 충돌 방지 위해 ci 전용 디렉토리 사용
ssh AI_server "rm -rf ~/bitda-ci-${PR} && mkdir ~/bitda-ci-${PR}"
cd ${WORKTREE_PATH}
tar --exclude='.gradle' --exclude='build' --exclude='.idea' --exclude='.git' -cf - . \
| ssh AI_server "cd ~/bitda-ci-${PR} && tar -xf -"
ssh AI_server "cd ~/bitda-ci-${PR} && git init -q && git add -A \
&& git -c user.email=t@t -c user.name=t commit -q -m wip"
# ktlintCheck (원격, --no-daemon, LC_ALL 필수)
ssh AI_server "export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \
&& cd ~/bitda-ci-${PR} \
&& ./gradlew ktlintCheck --no-daemon -Dfile.encoding=UTF-8 2>&1 | tail -50"
실패 시 원격에서 ktlintFormat 실행 후 변경 파일을 로컬로 역전송:
ssh AI_server "export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \
&& cd ~/bitda-ci-${PR} \
&& ./gradlew ktlintFormat --no-daemon -Dfile.encoding=UTF-8 2>&1 | tail -50"
# 수정 파일 로컬로 동기화
ssh AI_server "cd ~/bitda-ci-${PR} && tar -cf - --exclude='.gradle' --exclude='build' --exclude='.git' ." \
| (cd ${WORKTREE_PATH} && tar -xf -)
| 에러 패턴 | 원인 | 수정 방법 |
|---|---|---|
생산일자는 오늘 또는 과거여야 합니다: YYYY-MM-DD | 테스트에 미래 날짜 하드코딩 | LocalDate.now().minusDays(N) 으로 변경 |
Type mismatch: inferred type is List<X> but MutableList<X> | List/MutableList 타입 불일치 | .toMutableList() 또는 .toList() 추가 |
Unresolved reference: XXX | import 누락 또는 잘못된 참조 | import 추가 또는 참조 수정 |
Compilation error in kaptGenerateStubsTestKotlin | 테스트 파일 구조 오류 | 중괄호 닫힘/inner class 위치 확인 |
cd {worktree-path}
git add {수정된 파일들}
git commit -m "fix: {원인 요약}"
git push
# ⚠️ pre-push 훅의 로컬 gradle 데몬 정리
cd {메인-저장소-루트} && ./gradlew --stop 2>&1 | tail -1
push 완료 후 Jenkins가 자동으로 새 빌드 트리거됨.
루프 반복 중 재점검: 루프가 길어지면 그 사이 다른 PR이 main에 머지될 수 있다. push 전
git rev-list --count origin/${HEAD_BRANCH}..origin/main이 0이 아니면 Step 0.5b(rebase)를 먼저 수행한 뒤 push한다.
Step 1로 돌아가 새 빌드 번호 확인 후 반복.
✅ Jenkins CI 통과
| 빌드 | 결과 |
|------|------|
| #{build} | SUCCESS |
모든 단계 통과:
- Build ✅
- Lint ✅
- Unit Test ✅
- Integration Test ✅
동일 원인으로 3회 실패하거나 수정 방향을 모르겠으면:
⚠️ Jenkins CI 3회 연속 실패
| 빌드 | 실패 원인 |
|------|----------|
| #N-2 | {원인} |
| #N-1 | {원인} |
| #N | {원인} |
수동 개입이 필요합니다.
사용자에게 실패 로그 전체를 공유하고 방향 결정 요청.
# Jenkins 빌드 목록 확인
ssh AI_server "docker exec jenkins ls -t /var/jenkins_home/jobs/bitda-back-ci/branches/PR-{pr}/builds/ | grep -E '^[0-9]+$'"
# 빌드 로그 tail
ssh AI_server "docker exec jenkins tail -50 /var/jenkins_home/jobs/bitda-back-ci/branches/PR-{pr}/builds/{build}/log"
# 빌드 완료 여부 확인
ssh AI_server "docker exec jenkins grep -c 'Finished: ' /var/jenkins_home/jobs/bitda-back-ci/branches/PR-{pr}/builds/{build}/log 2>/dev/null"
# 실패 테스트 XML 검색
ssh AI_server "docker exec jenkins find /var/jenkins_home/workspace/bitda-back-ci_PR-{pr}/modules -name 'TEST-*.xml' | xargs grep -l 'failures=\"[1-9]' 2>/dev/null"
# XML 실패 메시지 확인
ssh AI_server "docker exec jenkins cat {xml_path} | grep -A 20 'failure'"
# 컴파일 에러 확인
ssh AI_server "docker exec jenkins grep -E 'error:|Compilation error|Type mismatch' /var/jenkins_home/jobs/bitda-back-ci/branches/PR-{pr}/builds/{build}/log | grep -v 'ha:////'"
review-action: 리뷰 조치 후 이 스킬 자동 실행issue-impl: 구현 완료 + push 후 이 스킬 자동 실행pr-merge: Jenkins SUCCESS 확인 후 실행jh_kim dev 계정(dev Keycloak)으로 E2E API 테스트를 수행하는 스킬입니다. 로컬 main 빌드 API + dev DB + dev Keycloak PKCE 토큰 조합으로, dev API 서버에 아직 배포되지 않은 머지 코드를 실데이터 환경에서 검증할 때 사용합니다. "/e2e-test-dev", "dev 계정으로 E2E", "jh_kim으로 API 테스트", "dev DB로 E2E 테스트" 등을 요청할 때 사용됩니다. (로컬 Docker Keycloak 기반 테스트는 e2e-test 스킬 사용)
plan-master(기획용 FE 코드 + docs/specs 기획서)와 bitda-back(구현된 BE 코드) 사이의 갭을 분석하여 누락된 기능·API·정책을 GitHub 이슈로 자동 생성하는 스킬입니다. 기획서→이슈 전달 과정에서 발생하는 누락을 방지하기 위해 FE 코드를 1차 소스로 사용합니다. "/gap-analyze", "/gap-analyze BOM", "/gap-analyze production" 등을 요청할 때 사용됩니다.
plan-master FE 코드만을 유일한 1차 소스로(기획서 .md 배제) 멀티팀 에이전트가 BE가 보장해야 할 비즈니스 로직과 FE 작업에 필요한 API 항목을 도출하고, 총괄 에이전트가 bitda-back BE 구현과 실측 대조하여 누락 갭을 발굴, 직렬 verifier로 확정한 뒤 GitHub 이슈로 생성하는 스킬입니다. gap-analyze의 변종으로, 기획서가 구현완료를 선언해 갭을 가리는 오염을 제거하기 위해 기획서를 의도적으로 보지 않습니다. /gap-fe-code 생산현황, 기획서 빼고 FE 코드로 갭 분석, FE 코드만 보고 누락 API 이슈 만들어 등을 요청할 때 사용됩니다.
실제 API 서버(8080 포트)를 실행하고 Keycloak OAuth 인증을 통해 E2E API 테스트를 수행하는 스킬입니다. 테스트 결과와 요청/응답을 docs/e2e-test/{test}/ 디렉토리에 markdown 형식으로 기록합니다. 이 스킬은 다음 상황에서 사용됩니다: - 특정 API의 실제 동작을 테스트하고 싶을 때 - API 변경 후 실제 환경에서 검증이 필요할 때 - 사용자가 "E2E 테스트", "API 테스트", "/e2e-test" 등을 요청할 때
Creates phase-based feature plans with quality gates and incremental delivery structure. Use when planning features, organizing work, breaking down tasks, creating roadmaps, or structuring development strategy. Keywords: plan, planning, phases, breakdown, strategy, roadmap, organize, structure, outline.
Swagger 스냅샷(api-docs.json)과 코드베이스를 기반으로 Notion API 맵핑 DB에 API 문서를 등록하고 상세 페이지를 작성하는 스킬입니다. (notion-api.py REST wrapper 사용 버전) 이 스킬은 다음 상황에서 사용됩니다: - 특정 API를 Notion에 문서화할 때 (MCP 비활성화 환경) - mcp__notion__* 도구 deprecated/불안정한 경우 - 사용자가 "api 노션 등록 (api 모드)", "/api-to-notion-api" 등을 요청할 때