Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
de0671b
fix(#31): 프로세스 누수 문제 해결 - orphan 프로세스 방지
wlgns5376 Aug 28, 2025
0a4f383
fix(#31): 리뷰 피드백 반영 - Gemini Code Assist 피드백 처리
wlgns5376 Aug 28, 2025
a0636c0
fix(#31): 리뷰 피드백 반영 - Gemini Code Assist 피드백 처리
wlgns5376 Aug 28, 2025
0b1b241
fix(#31): 리뷰 피드백 반영 - 코드 품질 개선
wlgns5376 Aug 28, 2025
75985d2
fix(#31): 리뷰 피드백 반영 - Gemini Code Assist 피드백 처리
wlgns5376 Aug 28, 2025
f55655c
fix(#31): 리뷰 피드백 반영 - Gemini Code Assist 피드백 처리
wlgns5376 Aug 28, 2025
b471ddc
fix(#31): Promise.race를 사용한 효율적인 프로세스 종료 처리
wlgns5376 Aug 28, 2025
70743c0
fix(#31): Gemini Code Assist 피드백 반영 - 코드 품질 개선
wlgns5376 Aug 28, 2025
8974e4b
fix(#31): 테스트 코드 개선 - Gemini Code Assist 피드백 반영
wlgns5376 Aug 28, 2025
8987e2e
fix(#31): Gemini Code Assist 피드백 반영 - 프로세스 관리 및 테스트 개선
wlgns5376 Aug 28, 2025
8c25206
fix(#31): Gemini Code Assist 피드백 반영 - 코드 품질 개선
wlgns5376 Aug 28, 2025
a58b763
fix(#31): Gemini Code Assist 피드백 반영 - 테스트 코드 개선
wlgns5376 Aug 28, 2025
da511ac
fix(#31): Gemini Code Assist 피드백 반영 - 타입 안정성 및 코드 품질 개선
wlgns5376 Aug 29, 2025
2f8deed
fix(#31): Gemini Code Assist 리뷰 피드백 반영
wlgns5376 Aug 29, 2025
b22bf93
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 타입 안정성 개선
wlgns5376 Aug 29, 2025
b615ba0
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 타입 안정성 개선
wlgns5376 Aug 29, 2025
28ebaab
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 타입 안정성 개선 및 주석 수정
wlgns5376 Aug 29, 2025
223f210
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 프로세스 관리 개선
wlgns5376 Aug 29, 2025
c0ad1eb
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 추가 개선사항
wlgns5376 Aug 29, 2025
ef707a7
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 타입 안정성 및 테스트 개선
wlgns5376 Aug 29, 2025
ee2061c
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 타입 안정성 개선 및 테스트 수정
wlgns5376 Aug 29, 2025
dc8d374
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 추가 개선사항
wlgns5376 Aug 29, 2025
a097d17
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 타입 안정성 개선 및 테스트 수정
wlgns5376 Aug 29, 2025
0de247a
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 타입 안정성 및 테스트 개선
wlgns5376 Aug 29, 2025
8a8f7e1
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 타입 안정성 및 테스트 개선
wlgns5376 Aug 29, 2025
d2dcb82
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 타입 안정성 및 테스트 개선
wlgns5376 Aug 29, 2025
fbb84ac
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 타입 안정성 개선 및 테스트 수정
wlgns5376 Aug 29, 2025
8d895af
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 타입 안정성 개선 및 테스트 수정
wlgns5376 Aug 30, 2025
0e6e322
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 타입 안정성 개선 및 테스트 수정
wlgns5376 Aug 30, 2025
795f3e1
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 타입 안정성 개선 및 테스트 수정
wlgns5376 Aug 30, 2025
49790f1
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 테스트 개선 및 타이밍 이슈 수정
wlgns5376 Aug 30, 2025
d79e5c9
fix(#31): Gemini Code Assist 리뷰 피드백 반영 - 테스트 개선 및 타이밍 이슈 수정
wlgns5376 Aug 30, 2025
47eaa2c
Merge pull request #32 from wlgns5376/issue-31
wlgns5376 Aug 30, 2025
ba25456
fix(#33): ACCEPTED 상태에서도 lastSyncTime 업데이트하여 중복 처리 방지
wlgns5376 Sep 8, 2025
b413a53
fix(#33): Docker 좀비 프로세스 누적 문제 해결
wlgns5376 Sep 8, 2025
706e53c
fix: 실패하는 테스트들 수정
wlgns5376 Sep 10, 2025
efc00e7
fix(test): Logger 테스트의 race condition 해결
wlgns5376 Sep 10, 2025
5c7e0b6
test: task-reassignment 테스트 수정 - mock 설정 보완
wlgns5376 Sep 10, 2025
1cdbc58
test: 실패하는 테스트들 수정
wlgns5376 Sep 11, 2025
43910ff
fix(test): ClaudeDeveloper 테스트 안정성 개선
wlgns5376 Sep 11, 2025
5a866b0
fix(test): Claude Developer 테스트 수정 - private 메서드 모킹 추가
wlgns5376 Sep 11, 2025
8fd6290
fix(test): Logger 테스트의 파일명 생성 로직 개선
wlgns5376 Sep 11, 2025
30231d0
fix(test): Logger 테스트의 일자별 로그 파일 cleanup 문제 해결
wlgns5376 Sep 11, 2025
1a09fa5
Merge pull request #35 from wlgns5376/fix-issue-33
wlgns5376 Sep 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ RUN pnpm run build
# Stage 2: Production stage
FROM node:20-alpine AS production

# Install system dependencies
# Install system dependencies including tini for zombie process handling
RUN apk add --no-cache \
git \
openssh-client \
curl \
bash \
sudo
sudo \
tini

# Install utilities
RUN apk add --no-cache \
Expand Down Expand Up @@ -109,8 +110,8 @@ USER root
RUN chmod +x /app/entrypoint.sh
USER appuser

# Set entrypoint and default command
ENTRYPOINT ["/app/entrypoint.sh"]
# Set entrypoint and default command with tini as init process
ENTRYPOINT ["/sbin/tini", "--", "/app/entrypoint.sh"]
CMD ["node", "dist/index.js"]

# Labels for metadata
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ai-devteam-node",
"version": "1.0.2",
"version": "1.0.3",
"description": "AI DevTeam automation system using Claude Code and Gemini CLI for terminal-based development",
"main": "dist/index.js",
"directories": {
Expand Down
33 changes: 30 additions & 3 deletions scripts/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
#!/bin/bash
set -e

# Signal handling for graceful shutdown
cleanup() {
echo "Received shutdown signal, cleaning up..."
# Send SIGTERM to all child processes
if [ -n "$MAIN_PID" ]; then
echo "Terminating main process (PID: $MAIN_PID)"
kill -TERM "$MAIN_PID" 2>/dev/null || true
wait "$MAIN_PID" 2>/dev/null || true
fi
echo "Cleanup completed"
exit 0
}

# Set up signal handlers
trap cleanup SIGTERM SIGINT

echo "=== AI DevTeam Starting ==="
echo "Container init process: tini (zombie process reaper enabled)"
echo "Node.js version: $(node --version)"
echo "npm version: $(npm --version)"
echo "Git version: $(git --version)"
Expand Down Expand Up @@ -56,7 +73,17 @@ if [ ! -z "$GIT_ACCEPT_HOST_KEY" ] && [ "$GIT_ACCEPT_HOST_KEY" = "true" ]; then
fi

echo "=== Configuration Complete ==="
echo "Starting application..."
echo "Starting application with PID tracking..."

# Execute the main application in background and track PID
"$@" &
MAIN_PID=$!

echo "Main application started (PID: $MAIN_PID)"

# Wait for the main process to complete
wait "$MAIN_PID"
EXIT_CODE=$?

# Execute the main application
exec "$@"
echo "Main application exited with code: $EXIT_CODE"
exit $EXIT_CODE
51 changes: 49 additions & 2 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
}

// Repository 정보 추출 헬퍼 메서드
private extractRepositoryFromBoardItem(boardItem: any, pullRequestUrl?: string): string {

Check warning on line 73 in src/app.ts

View workflow job for this annotation

GitHub Actions / test

Unexpected any. Specify a different type

Check warning on line 73 in src/app.ts

View workflow job for this annotation

GitHub Actions / test

Unexpected any. Specify a different type

Check warning on line 73 in src/app.ts

View workflow job for this annotation

GitHub Actions / test

Unexpected any. Specify a different type
return RepositoryInfoExtractor.extractRepositoryFromBoardItem(
boardItem,
pullRequestUrl,
Expand Down Expand Up @@ -370,20 +370,67 @@

// Graceful shutdown을 위한 신호 핸들러 설정
setupSignalHandlers(): void {
let shutdownInProgress = false;

const signalHandler = (signal: string) => {
if (shutdownInProgress) {
console.log(`\n⚠️ ${signal} 신호가 이미 처리 중입니다. 강제 종료하려면 다시 한 번 신호를 보내세요.`);
return;
}

shutdownInProgress = true;
console.log(`\n📡 ${signal} 신호 수신됨. Graceful shutdown 시작...`);

// 강제 종료 타이머 (30초 후)
const forceExitTimeout = setTimeout(() => {
console.error('⚠️ Graceful shutdown이 30초 내에 완료되지 않아 강제 종료합니다.');
process.exit(1);
}, 30000);

this.stop()
.then(() => {
clearTimeout(forceExitTimeout);
console.log('✅ Graceful shutdown 완료');
process.exit(0);
})
.catch((error) => {
clearTimeout(forceExitTimeout);
console.error('❌ Graceful shutdown 실패:', error);
process.exit(1);
});
};

process.on('SIGTERM', () => signalHandler('SIGTERM'));
process.on('SIGINT', () => signalHandler('SIGINT'));
// 두 번째 신호 수신 시 즉시 강제 종료
let signalCount = 0;
const forceSignalHandler = (signal: string) => {
signalCount++;

if (signalCount === 1) {
signalHandler(signal);
} else if (signalCount >= 2) {
console.log(`\n⚡ 두 번째 ${signal} 신호 수신됨. 즉시 강제 종료합니다.`);
process.exit(1);
}
};

process.on('SIGTERM', () => forceSignalHandler('SIGTERM'));
process.on('SIGINT', () => forceSignalHandler('SIGINT'));

// 처리되지 않은 promise rejection 핸들링
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
this.logger?.error('Unhandled promise rejection', { reason, promise });
});

// 처리되지 않은 예외 핸들링
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error);
this.logger?.error('Uncaught exception', { error });

// 정리 후 종료
this.stop()
.finally(() => process.exit(1))
.catch(() => process.exit(1));
});
}
}
Loading
Loading