Conversation
WalkthroughGitHub Actions CD 워크플로우를 EC2 SCP/SSH 배포로 교체하고 Java 17 + bootJar 빌드, Gradle 및 Docker Compose 관련 설정과 일부 애플리케이션 프로퍼티를 업데이트했습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Runner as GitHub Actions Runner
participant Gradle as Gradle (./gradlew bootJar)
participant SCP as appleboy/scp-action
participant SSH as appleboy/ssh-action
participant EC2 as EC2 Instance (Docker Compose)
Runner->>Gradle: checkout + setup-java(17)\n./gradlew bootJar
Gradle-->>Runner: build/libs/mse-project.jar (mse-project.jar)
Runner->>SCP: scp mse-project.jar -> /home/ec2-user/app (SSH key)
SCP-->>EC2: 업로드된 JAR 저장
Runner->>SSH: ssh -> docker-compose -f /home/ec2-user/app/docker-compose.yaml up -d --build
SSH-->>EC2: 컨테이너 중지/재빌드/시작 명령 실행
EC2-->>Runner: 배포 완료 응답 / 로그
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 분 Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
build.gradle (1)
45-47:⚠️ Potential issue | 🔴 Critical비공식 테스트 의존성을 제거하고 표준 Spring Boot 테스트 의존성으로 변경해야 합니다.
공식 Spring Boot 문서에 따르면
spring-boot-starter-data-jpa-test,spring-boot-starter-security-test,spring-boot-starter-webmvc-test는 공식적으로 권장되는 스타터가 아닙니다. 대신 다음 의존성을 사용하세요:권장 변경 사항
- testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa-test' - testImplementation 'org.springframework.boot:spring-boot-starter-security-test' - testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.security:spring-security-test'
spring-boot-starter-test는 JUnit, AssertJ, Mockito, JSONassert, JsonPath 등 일반적인 테스트 라이브러리를 포함하고,spring-security-test는 Spring Security 테스트 지원(예:@WithMockUser)을 제공합니다.
🤖 Fix all issues with AI agents
In @.github/workflows/cd_template.yaml:
- Line 66: The deployment script's jar lookup uses the glob ${APP_NAME}-*.jar
which doesn't match the actual artifact name set in build.gradle
(archiveFileName = "mse-project.jar"), so update the lookup to use the exact
artifact name or a matching glob; specifically change the JAR discovery logic
(symbol: JAR_NAME) to look for ${APP_DIR}/${APP_NAME}.jar or adjust
build.gradle's archiveFileName to include the dash pattern so the existing
${APP_NAME}-*.jar glob will match.
- Around line 28-29: The workflow uses the GitHub Action reference
appleboy/scp-action@master which is unsafe; update that reference to a fixed
release tag (e.g., appleboy/scp-action@v1.0.0) so the step named "copy jar to
server" pins to a specific, audited version instead of `@master`.
In `@src/main/resources/application.properties`:
- Line 2: The hardcoded spring.profiles.active=docker in application.properties
reduces environment flexibility; remove that line from application.properties
and rely on runtime config (SPRING_PROFILES_ACTIVE env var or
-Dspring.profiles.active JVM arg) so different environments (local, CI, EC2) can
supply the appropriate profile; update deployment/CI scripts (startup command or
workflow) and any README/IDE run configurations to set the profile via
SPRING_PROFILES_ACTIVE or -Dspring.profiles.active instead of relying on the
application.properties value.
🧹 Nitpick comments (3)
.github/workflows/ci_template.yaml (1)
28-28: CI와 CD 간setup-java액션 버전이 불일치합니다.CI에서는
actions/setup-java@v2를 사용하고 CD(cd_template.yamlLine 17)에서는@v4를 사용합니다. 일관성과 최신 기능/보안 패치를 위해@v4로 통일하는 것을 권장합니다.제안
- uses: actions/setup-java@v2 + uses: actions/setup-java@v4.github/workflows/cd_template.yaml (2)
72-75: 배포 후 애플리케이션 기동 확인(health check)이 없습니다.
nohup으로 백그라운드 실행 후 프로세스가 정상 기동되었는지 확인하지 않습니다. 앱이 즉시 크래시해도 워크플로우는 성공으로 표시됩니다.간단한 health check 추가를 권장합니다:
제안: 기동 확인 추가
nohup java -jar $JAR_NAME > $APP_DIR/app.log 2>&1 & + NEW_PID=$! + sleep 5 + if ! ps -p $NEW_PID > /dev/null; then + echo "Error: Application failed to start. Check $APP_DIR/app.log" + tail -50 $APP_DIR/app.log + exit 1 + fi echo "Deployment submitted successfully."
53-53:pgrep패턴이 배포 프로세스 자체를 매칭할 수 있습니다.
pgrep -f "java.*$APP_NAME"은 SSH 세션에서 실행 중인 현재 스크립트의 환경 변수나 다른 Java 프로세스까지 매칭할 가능성이 있습니다. 보다 정확한 매칭을 위해 PID 파일 사용을 고려해 보세요.
| - name: copy jar to server | ||
| uses: appleboy/scp-action@master |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
appleboy/scp-action latest release GitHub
💡 Result:
The latest GitHub release of appleboy/scp-action is v1.0.0 (tag: v1.0.0), published Apr 27 (04:42) and marked Latest on the repo’s Releases page. [1]
GitHub Marketplace also shows the latest version as v1.0.0. [2]
Use in workflow: uses: appleboy/scp-action@v1 (or pin @v1.0.0). [2]
Sources: [1] [2]
appleboy/scp-action@master를 특정 버전으로 고정하세요.
@master를 사용하면 업스트림 변경이나 공급망 공격에 취약합니다. ssh-action은 특정 버전으로 고정되어 있으므로 scp-action도 동일하게 버전을 고정해야 합니다. 현재 최신 버전은 v1.0.0입니다.
제안
- uses: appleboy/scp-action@master
+ uses: appleboy/scp-action@v1.0.0📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: copy jar to server | |
| uses: appleboy/scp-action@master | |
| - name: copy jar to server | |
| uses: appleboy/scp-action@v1.0.0 |
🤖 Prompt for AI Agents
In @.github/workflows/cd_template.yaml around lines 28 - 29, The workflow uses
the GitHub Action reference appleboy/scp-action@master which is unsafe; update
that reference to a fixed release tag (e.g., appleboy/scp-action@v1.0.0) so the
step named "copy jar to server" pins to a specific, audited version instead of
`@master`.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @.github/workflows/cd_template.yaml:
- Around line 38-48: The deployment step "Deploy with Docker Compose" currently
runs docker-compose down/up but only the JAR is copied to EC2, so transfer the
missing artifacts or change the deployment approach: either update the workflow
to SCP (or use appleboy/scp-action) to copy docker-compose.yaml, Dockerfile and
.env to the EC2 app directory before the SSH `script:` block; or replace the SSH
`script:` commands to run the JAR directly (e.g., `java -jar`) instead of
docker-compose; or modify CI to build and push a Docker image to a registry and
change the SSH `script:` to `docker-compose pull` and `docker-compose up -d` so
EC2 doesn’t need source files. Ensure the chosen fix updates the "script:" block
and the preceding copy step so docker-compose.yaml and Dockerfile are present on
EC2 when `docker-compose up --build` runs.
- Around line 35-36: The SCP action preserves source directories so using
source: "build/libs/*.jar" places files under /home/ec2-user/app/build/libs/...,
fix by adding the strip_components option for appleboy/scp-action (set
strip_components: 2) to flatten the path so the jar lands directly in the target
directory; update the workflow block containing the source/target keys to
include strip_components: 2.
In `@docker-compose.yaml`:
- Around line 17-27: The MySQL service (service name "mysql", container_name
"mse-mysql") lacks a persistent volume so its data is lost on recreate; add a
named volume (e.g., "mysql_data") and mount it to the container MySQL data dir
(/var/lib/mysql) by adding a volumes: entry under the mysql service (e.g.,
volumes: - mysql_data:/var/lib/mysql) and declare the named volume at the
top-level volumes: section (e.g., mysql_data: {}), ensuring Docker persists DB
files across docker-compose down/up cycles.
🧹 Nitpick comments (3)
src/main/resources/application-local.properties (1)
1-6: DB 자격 증명이 누락되어 있습니다.
spring.datasource.username과spring.datasource.password가 이 파일에 없으므로,application-local-secret.properties에 반드시 포함되어야 합니다. 로컬 개발 시 해당 파일이 없으면 연결에 실패합니다. README 또는 주석으로 필요한 속성을 안내하면 좋겠습니다.docker-compose.yaml (1)
4-15:depends_on만으로는 MySQL/Redis 준비 완료를 보장하지 않습니다.
depends_on은 컨테이너 시작 순서만 보장하며, MySQL이 실제로 연결을 수락할 준비가 되었는지는 확인하지 않습니다. Spring Boot 앱이 DB 연결 실패로 시작에 실패할 수 있습니다.제안: healthcheck 조건 추가
depends_on: - - mysql - - redis + mysql: + condition: service_healthy + redis: + condition: service_healthy그리고 mysql, redis 서비스에 healthcheck를 추가하세요:
mysql: image: mysql:8.0 healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 5s retries: 5.github/workflows/cd_template.yaml (1)
38-48: SSH 단계의 들여쓰기가 일관되지 않습니다.
with:블록 내부의 속성들이 4칸 들여쓰기를 사용하고 있으나, 다른 단계들은 2칸을 사용합니다. YAML 파싱에는 문제가 없지만 일관성을 위해 통일하는 것이 좋습니다.
| source: "build/libs/*.jar" | ||
| target: "/home/ec2-user/app" |
There was a problem hiding this comment.
SCP 전송 시 디렉토리 구조가 보존되어 파일 경로가 의도와 다릅니다.
appleboy/scp-action은 기본적으로 소스의 디렉토리 구조를 유지합니다. source: "build/libs/*.jar"로 전송하면 EC2에서 실제 경로가 /home/ec2-user/app/build/libs/mse-project.jar가 됩니다. strip_components 옵션을 사용하여 경로를 평탄화하세요.
제안
- name: copy jar to server
- uses: appleboy/scp-action@master
+ uses: appleboy/scp-action@v1.0.0
with:
host: ${{ secrets.SSH_HOST }}
username: ec2-user
key: ${{ secrets.SSH_KEY }}
port: 22
source: "build/libs/*.jar"
target: "/home/ec2-user/app"
+ strip_components: 2🤖 Prompt for AI Agents
In @.github/workflows/cd_template.yaml around lines 35 - 36, The SCP action
preserves source directories so using source: "build/libs/*.jar" places files
under /home/ec2-user/app/build/libs/..., fix by adding the strip_components
option for appleboy/scp-action (set strip_components: 2) to flatten the path so
the jar lands directly in the target directory; update the workflow block
containing the source/target keys to include strip_components: 2.
| - name: Deploy with Docker Compose | ||
| uses: appleboy/ssh-action@v0.1.6 | ||
| with: | ||
| host: ${{ secrets.SSH_HOST }} | ||
| username: ec2-user | ||
| key: ${{ secrets.SSH_KEY }} | ||
| port: 22 | ||
| script: | | ||
| cd /home/ec2-user/app | ||
| docker-compose down | ||
| docker-compose up -d --build No newline at end of file |
There was a problem hiding this comment.
EC2에 docker-compose.yaml과 Dockerfile이 전송되지 않아 배포가 실패합니다.
워크플로우는 JAR 파일만 EC2로 복사하지만, SSH 단계에서 docker-compose down / up --build를 실행합니다. docker-compose.yaml의 app 서비스는 build: .을 사용하므로 EC2에 Dockerfile과 docker-compose.yaml이 모두 필요합니다. 현재 이 파일들이 전송되지 않으므로 배포가 실패합니다.
해결 방안:
- 방법 A:
docker-compose.yaml,Dockerfile,.env등 필요한 파일도 함께 SCP로 전송 - 방법 B: EC2에서
docker-compose를 사용하지 않고 JAR를 직접 실행 (java -jar) - 방법 C: Docker 이미지를 CI에서 빌드하여 레지스트리에 푸시하고, EC2에서
docker-compose pull로 배포
🤖 Prompt for AI Agents
In @.github/workflows/cd_template.yaml around lines 38 - 48, The deployment step
"Deploy with Docker Compose" currently runs docker-compose down/up but only the
JAR is copied to EC2, so transfer the missing artifacts or change the deployment
approach: either update the workflow to SCP (or use appleboy/scp-action) to copy
docker-compose.yaml, Dockerfile and .env to the EC2 app directory before the SSH
`script:` block; or replace the SSH `script:` commands to run the JAR directly
(e.g., `java -jar`) instead of docker-compose; or modify CI to build and push a
Docker image to a registry and change the SSH `script:` to `docker-compose pull`
and `docker-compose up -d` so EC2 doesn’t need source files. Ensure the chosen
fix updates the "script:" block and the preceding copy step so
docker-compose.yaml and Dockerfile are present on EC2 when `docker-compose up
--build` runs.
| mysql: | ||
| image: mysql:latest | ||
| image: mysql:8.0 | ||
| container_name: mse-mysql | ||
| ports: | ||
| - "23306:3306" | ||
| environment: | ||
| MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} | ||
| MYSQL_DATABASE: ${MYSQL_DATABASE} | ||
| MYSQL_USER: ${MYSQL_USER} | ||
| MYSQL_PASSWORD: ${MYSQL_PASSWORD} | ||
|
|
There was a problem hiding this comment.
MySQL 데이터 영속성을 위한 볼륨이 없습니다.
docker-compose down 또는 컨테이너 재생성 시 MySQL 데이터가 모두 삭제됩니다. CD 워크플로우에서 매 배포마다 docker-compose down → up --build를 실행하므로 배포할 때마다 DB가 초기화됩니다.
제안: 볼륨 추가
mysql:
image: mysql:8.0
container_name: mse-mysql
ports:
- "23306:3306"
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
+ volumes:
+ - mysql-data:/var/lib/mysql
+
+volumes:
+ mysql-data:📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| mysql: | |
| image: mysql:latest | |
| image: mysql:8.0 | |
| container_name: mse-mysql | |
| ports: | |
| - "23306:3306" | |
| environment: | |
| MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} | |
| MYSQL_DATABASE: ${MYSQL_DATABASE} | |
| MYSQL_USER: ${MYSQL_USER} | |
| MYSQL_PASSWORD: ${MYSQL_PASSWORD} | |
| mysql: | |
| image: mysql:8.0 | |
| container_name: mse-mysql | |
| ports: | |
| - "23306:3306" | |
| environment: | |
| MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} | |
| MYSQL_DATABASE: ${MYSQL_DATABASE} | |
| MYSQL_USER: ${MYSQL_USER} | |
| MYSQL_PASSWORD: ${MYSQL_PASSWORD} | |
| volumes: | |
| - mysql-data:/var/lib/mysql | |
| volumes: | |
| mysql-data: |
🤖 Prompt for AI Agents
In `@docker-compose.yaml` around lines 17 - 27, The MySQL service (service name
"mysql", container_name "mse-mysql") lacks a persistent volume so its data is
lost on recreate; add a named volume (e.g., "mysql_data") and mount it to the
container MySQL data dir (/var/lib/mysql) by adding a volumes: entry under the
mysql service (e.g., volumes: - mysql_data:/var/lib/mysql) and declare the named
volume at the top-level volumes: section (e.g., mysql_data: {}), ensuring Docker
persists DB files across docker-compose down/up cycles.
📌 변경 내용
🛠 작업 상세
✅ 체크 포인트
📎 참고 사항
Summary by CodeRabbit
Chores
New Features
Tests