Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
72 changes: 72 additions & 0 deletions .github/workflows/cd-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: CD on Dev

on:
push:
branches:
- develop
paths:
- 'src/**'
- 'build.gradle.kts'
- 'docker/**'
- 'cd.yml'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

워크플로우 파일 경로가 잘못되었습니다.

Line 11에서 cd.yml을 참조하고 있지만, 실제 파일명은 cd-dev.yml입니다. 이로 인해 워크플로우 파일 변경 시 자동 배포가 트리거되지 않습니다.

🔧 제안하는 수정안
     paths:
       - 'src/**'
       - 'build.gradle.kts'
       - 'docker/**'
-      - 'cd.yml'
+      - '.github/workflows/cd-dev.yml'
🤖 Prompt for AI Agents
In @.github/workflows/cd-dev.yml around lines 7 - 11, The workflow currently
references 'cd.yml' in the paths list which is incorrect; update the paths array
in .github/workflows/cd-dev.yml to replace 'cd.yml' with the actual filename
'cd-dev.yml' so changes to the deployment workflow trigger correctly (edit the
entry that currently reads 'cd.yml' to 'cd-dev.yml').


workflow_dispatch:
inputs:
environment:
description: 'Deploy environment'
required: true
type: choice
options:
- dev
- prod

jobs:
# 1. 공통 빌드/테스트 워크플로우 호출 (ci.yml 재사용)
ci-and-build:
uses: ./.github/workflows/ci.yml
with:
environment: ${{ inputs.environment }}

# 2. Deploy Job
deploy:
needs: ci-and-build
runs-on: ubuntu-latest
# 빌드 단계에서 결정된 환경 사용
environment: ${{ needs.ci-and-build.outputs.environment }}

env:
ENVIRONMENT: ${{ needs.ci-and-build.outputs.environment }}
REPO_OWNER: ${{ needs.ci-and-build.outputs.repo_owner }}
IMAGE_TAG: ${{ needs.ci-and-build.outputs.image_tag }}

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: SSH 접속 및 스크립트 실행
uses: appleboy/ssh-action@v1
env:
APPLICATION_PROD: ${{ secrets.APPLICATION_PROD }}
APPLICATION_DEV: ${{ secrets.APPLICATION_DEV }}
APPLICATION_SECRET: ${{ secrets.APPLICATION_SECRET }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
with:
host: ${{ secrets.SERVER_SSH_HOST }}
username: ${{ secrets.SERVER_SSH_USERNAME }}
key: ${{ secrets.SERVER_SSH_PRIVATE_KEY }}
port: ${{ secrets.SERVER_SSH_PORT }}
envs: APPLICATION_PROD,APPLICATION_DEV,APPLICATION_SECRET,ENVIRONMENT,IMAGE_TAG,REPO_OWNER,DOCKER_IMAGE_NAME,DOCKERHUB_TOKEN,DOCKERHUB_USERNAME
script_path: scripts/cd-dev.sh

- name: Deployment Summary
if: always()
run: |
echo "### Deployment Summary :rocket:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Environment:** ${{ env.ENVIRONMENT }}" >> $GITHUB_STEP_SUMMARY
echo "- **Branch:** ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
echo "- **Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
echo "- **Image:** ${{ secrets.DOCKER_IMAGE_NAME }}:${{ env.ENVIRONMENT }}-latest" >> $GITHUB_STEP_SUMMARY
echo "- **Server:** ${{ secrets.SERVER_SSH_HOST }}" >> $GITHUB_STEP_SUMMARY
echo "- **Status:** ${{ job.status }}" >> $GITHUB_STEP_SUMMARY
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Shellcheck 스타일 경고를 개선할 수 있습니다.

Deployment Summary 스크립트에서 여러 개의 echo 명령이 같은 파일로 리다이렉션됩니다. 이를 하나의 블록으로 묶으면 더 효율적이고 가독성이 좋아집니다.

♻️ 제안 수정사항
       - name: Deployment Summary
         if: always()
         run: |
-          echo "### Deployment Summary :rocket:" >> $GITHUB_STEP_SUMMARY
-          echo "" >> $GITHUB_STEP_SUMMARY
-          echo "- **Environment:** ${{ env.ENVIRONMENT }}" >> $GITHUB_STEP_SUMMARY
-          echo "- **Branch:** ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
-          echo "- **Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
-          echo "- **Image:** ${{ secrets.DOCKER_IMAGE_NAME }}:${{ env.ENVIRONMENT }}-latest" >> $GITHUB_STEP_SUMMARY
-          echo "- **Server:** ${{ secrets.SERVER_SSH_HOST }}" >> $GITHUB_STEP_SUMMARY
-          echo "- **Status:** ${{ job.status }}" >> $GITHUB_STEP_SUMMARY
+          {
+            echo "### Deployment Summary :rocket:"
+            echo ""
+            echo "- **Environment:** ${{ env.ENVIRONMENT }}"
+            echo "- **Branch:** ${{ github.ref_name }}"
+            echo "- **Commit:** ${{ github.sha }}"
+            echo "- **Image:** ${{ secrets.DOCKER_IMAGE_NAME }}:${{ env.ENVIRONMENT }}-latest"
+            echo "- **Server:** ${{ secrets.SERVER_SSH_HOST }}"
+            echo "- **Status:** ${{ job.status }}"
+          } >> "$GITHUB_STEP_SUMMARY"
🧰 Tools
🪛 actionlint (1.7.10)

65-65: shellcheck reported issue in this script: SC2086:info:1:43: Double quote to prevent globbing and word splitting

(shellcheck)


65-65: shellcheck reported issue in this script: SC2086:info:2:12: Double quote to prevent globbing and word splitting

(shellcheck)


65-65: shellcheck reported issue in this script: SC2086:info:3:53: Double quote to prevent globbing and word splitting

(shellcheck)


65-65: shellcheck reported issue in this script: SC2086:info:4:48: Double quote to prevent globbing and word splitting

(shellcheck)


65-65: shellcheck reported issue in this script: SC2086:info:5:43: Double quote to prevent globbing and word splitting

(shellcheck)


65-65: shellcheck reported issue in this script: SC2086:info:6:87: Double quote to prevent globbing and word splitting

(shellcheck)


65-65: shellcheck reported issue in this script: SC2086:info:7:56: Double quote to prevent globbing and word splitting

(shellcheck)


65-65: shellcheck reported issue in this script: SC2086:info:8:43: Double quote to prevent globbing and word splitting

(shellcheck)


65-65: shellcheck reported issue in this script: SC2129:style:1:1: Consider using { cmd1; cmd2; } >> file instead of individual redirects

(shellcheck)

🤖 Prompt for AI Agents
In @.github/workflows/cd-dev.yml around lines 65 - 73, Multiple sequential echo
statements appending to $GITHUB_STEP_SUMMARY are inefficient and trigger
shellcheck style warnings; replace the repeated echo lines with a single
here-document that appends the entire Deployment Summary to $GITHUB_STEP_SUMMARY
(use an unquoted heredoc like cat <<EOF >> $GITHUB_STEP_SUMMARY so environment
variables like ${env.ENVIRONMENT} and ${github.sha} expand) to improve
readability and reduce subprocess calls, keeping the same content and ordering
as the original echo lines.

175 changes: 175 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
name: Backend CI & Build

on:
pull_request:
branches:
- develop
- main

workflow_call:
inputs:
environment:
description: 'Deploy environment (optional)'
required: false
type: string
outputs:
environment:
description: "Determined environment"
value: ${{ jobs.build-and-test.outputs.environment }}
repo_owner:
description: "Repository owner"
value: ${{ jobs.build-and-test.outputs.repo_owner }}
image_tag:
description: "Docker image tag"
value: ${{ jobs.build-and-test.outputs.image_tag }}

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # 이전 실행 취소

jobs:
# Job 1: 빌드 및 테스트 (한 번만 실행)
build-and-test:
runs-on: self-hosted

permissions:
contents: read
checks: write
pull-requests: write

outputs:
environment: ${{ steps.set-env.outputs.environment }}
repo_owner: ${{ steps.set-env.outputs.repo_owner }}
image_tag: ${{ steps.set-env.outputs.image_tag }}

strategy:
matrix:
platform: [ linux/amd64, linux/arm64 ]
include:
- platform: linux/amd64
tag-suffix: amd64
- platform: linux/arm64
tag-suffix: arm64
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: matrix strategy와 outputs 설정이 충돌합니다. matrix를 사용하면 job이 여러 번 실행되지만(linux/amd64, linux/arm64), outputs는 마지막 실행 결과만 저장됩니다. 따라서 environment, repo_owner, image_tag 값이 의도와 다르게 설정될 수 있습니다.

environment, repo_owner, image_tag는 플랫폼과 무관하게 동일한 값이므로, 별도의 job으로 분리하거나 matrix를 사용하지 않는 초기 단계에서 설정해야 합니다. 예를 들어:

  • 빌드 전 준비 job을 별도로 만들어 outputs 설정
  • 또는 create-manifest job에서 outputs를 재설정

Copilot uses AI. Check for mistakes.

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set deployment environment
id: set-env
run: |
INPUT_ENV="${{ inputs.environment }}"
# PR일 때는 'test' 환경으로 설정
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "Running in PR mode - Setting test environment for build"
ENVIRONMENT="test"
elif [[ -n "$INPUT_ENV" ]]; then
ENVIRONMENT="$INPUT_ENV"
# CD에서 호출한 경우 branch에 따라서 환경 결정
elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
ENVIRONMENT="prod"
elif [[ "${{ github.ref }}" == "refs/heads/develop" ]]; then
ENVIRONMENT="dev"
else
ENVIRONMENT="test"
fi
Comment on lines +77 to +87
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: 환경 변수 검증 로직에 else 분기가 누락되어 있습니다. 조건문이 elif로만 연결되어 있어, 마지막 elif 조건도 만족하지 않을 경우 ENVIRONMENT 변수가 설정되지 않은 상태로 다음 단계로 진행될 수 있습니다.

마지막 elif를 else로 변경하거나, 조건문 이후에 ENVIRONMENT 변수 검증을 추가해야 합니다.

Copilot uses AI. Check for mistakes.
echo "environment=${ENVIRONMENT}" >> $GITHUB_OUTPUT
REPO_OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
echo "repo_owner=${REPO_OWNER}" >> $GITHUB_OUTPUT
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
IMAGE_TAG="${ENVIRONMENT}-${SHORT_SHA}"
echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT
Comment on lines +68 to +96
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

환경 결정 로직에 else 절이 누락되었습니다.

Line 77-79의 조건문에 else 절이 없어, 특정 경우에 ENVIRONMENT 변수가 설정되지 않을 수 있습니다. Line 86의 else가 전체 if-elif 체인의 최종 else로 작동하므로 로직상 문제는 없지만, 가독성을 위해 구조를 명확히 하는 것이 좋습니다.

♻️ 제안하는 수정안
           # PR일 때는 'test' 환경으로 설정
           if [[ "${{ github.event_name }}" == "pull_request" ]]; then
             echo "Running in PR mode - Setting test environment for build"
             ENVIRONMENT="test"
           elif [[ -n "$INPUT_ENV" ]]; then
             ENVIRONMENT="$INPUT_ENV"
-          
-          # CD에서 호출한 경우 branch에 따라서 환경 결정
           elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
             ENVIRONMENT="prod"
           elif [[ "${{ github.ref }}" == "refs/heads/develop" ]]; then
             ENVIRONMENT="dev"
           else
             ENVIRONMENT="test"
           fi
🧰 Tools
🪛 actionlint (1.7.10)

70-70: shellcheck reported issue in this script: SC2086:info:19:38: Double quote to prevent globbing and word splitting

(shellcheck)


70-70: shellcheck reported issue in this script: SC2086:info:22:36: Double quote to prevent globbing and word splitting

(shellcheck)


70-70: shellcheck reported issue in this script: SC2086:info:26:34: Double quote to prevent globbing and word splitting

(shellcheck)

🤖 Prompt for AI Agents
In @.github/workflows/ci.yml around lines 68 - 96, The if/elif chain inside the
"set-env" step can leave ENVIRONMENT unset due to a missing else after the
INPUT_ENV check; ensure every branch sets ENVIRONMENT by adding an explicit else
or restructuring the conditionals so that when INPUT_ENV is empty the subsequent
branch checks (github.ref for main/develop) always run; update the logic around
INPUT_ENV, ENVIRONMENT and the github.event_name/github.ref checks so
ENVIRONMENT is always assigned before it's echoed to GITHUB_OUTPUT (refer to
variables INPUT_ENV, ENVIRONMENT, github.event_name, github.ref and the
"set-env" step).

- name: Setup JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'corretto'
cache: gradle

- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Compile Check
run: ./gradlew compileJava compileTestJava

- name: Run Tests
run: ./gradlew test

- name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: build/test-results/test/*.xml
check_name: "Backend Test Results"

- name: Build JAR
run: ./gradlew bootJar

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: 두 개의 Dockerfile이 존재하는데 (docker/kyeoungwoon/dockerfile과 docker/app/dockerfile), 목적과 사용처가 명확하지 않습니다.

  • kyeoungwoon/dockerfile: CI에서 사용 (eclipse-temurin 기반)
  • app/dockerfile: 사용처 불명확 (amazoncorretto 기반)

하나의 Dockerfile만 유지하거나, 각 파일의 목적을 README나 주석으로 명확히 문서화해야 합니다. 또한 CI 워크플로우에서 docker/kyeoungwoon/dockerfile을 사용하는 이유를 설명하는 주석을 추가하는 것이 좋습니다.

Suggested change
context: .
context: .
# CI용 이미지 빌드를 위해 eclipse-temurin 기반 Dockerfile 사용
# (amazoncorretto 기반 docker/app/dockerfile은 런타임/기타 용도로 별도 관리)

Copilot uses AI. Check for mistakes.
file: docker/kyeoungwoon/dockerfile
push: true
tags: |
${{ secrets.DOCKER_IMAGE_NAME }}:${{ steps.set-env.outputs.image_tag }}-${{ matrix.tag-suffix }}
platforms: ${{ matrix.platform }}
cache-from: type=gha,scope=${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=${{ matrix.platform }}

Comment on lines 141 to 153
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: PR 모드일 때 Docker 이미지를 빌드하고 푸시하는 것은 불필요한 리소스 사용입니다. PR은 코드 검증 목적이므로 테스트만 실행하고, 이미지 빌드와 푸시는 실제 배포가 필요한 경우에만 수행하는 것이 효율적입니다.

다음과 같이 조건부로 실행하도록 개선할 수 있습니다:

- name: Build and push Docker image
  if: github.event_name != 'pull_request'
  uses: docker/build-push-action@v6

또는 PR의 경우 push: false로 설정하여 빌드만 검증하도록 할 수 있습니다.

Copilot uses AI. Check for mistakes.
# Job 3: Multi-arch manifest 생성
create-manifest:
needs: [ build-and-test ]
runs-on: self-hosted
steps:
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Create and push manifest
run: |
IMAGE_TAG="${{ needs.build-and-test.outputs.image_tag }}"
ENVIRONMENT="${{ needs.build-and-test.outputs.environment }}"
# 특정 커밋용 manifest 생성
docker buildx imagetools create -t ${{ secrets.DOCKER_IMAGE_NAME }}:${IMAGE_TAG} \
${{ secrets.DOCKER_IMAGE_NAME }}:${IMAGE_TAG}-amd64 \
${{ secrets.DOCKER_IMAGE_NAME }}:${IMAGE_TAG}-arm64
# 환경별 latest manifest 생성
docker buildx imagetools create -t ${{ secrets.DOCKER_IMAGE_NAME }}:${ENVIRONMENT}-latest \
${{ secrets.DOCKER_IMAGE_NAME }}:${IMAGE_TAG}-amd64 \
${{ secrets.DOCKER_IMAGE_NAME }}:${IMAGE_TAG}-arm64
echo "✅ Created manifests:"
echo " - ${{ secrets.DOCKER_IMAGE_NAME }}:${IMAGE_TAG}"
echo " - ${{ secrets.DOCKER_IMAGE_NAME }}:${ENVIRONMENT}-latest"
- name: Build Summary
if: always()
run: |
echo "### Build Summary :package:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Environment:** ${{ steps.set-env.outputs.environment }}" >> $GITHUB_STEP_SUMMARY
echo "- **Image Tag:** ${{ steps.set-env.outputs.image_tag }}" >> $GITHUB_STEP_SUMMARY
Comment on lines +159 to +160
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Build Summary 단계가 잘못된 위치에 있습니다. steps.set-env는 build-and-test job에 속하지만, 현재 이 단계는 create-manifest job에 있습니다. steps.set-env.outputs는 다른 job에서 접근할 수 없으므로 항상 빈 값이 출력됩니다.

needs를 통해 전달받은 값을 사용해야 합니다:

echo "- **Environment:** ${{ needs.build-and-test.outputs.environment }}" >> $GITHUB_STEP_SUMMARY
echo "- **Image Tag:** ${{ needs.build-and-test.outputs.image_tag }}" >> $GITHUB_STEP_SUMMARY
Suggested change
echo "- **Environment:** ${{ steps.set-env.outputs.environment }}" >> $GITHUB_STEP_SUMMARY
echo "- **Image Tag:** ${{ steps.set-env.outputs.image_tag }}" >> $GITHUB_STEP_SUMMARY
echo "- **Environment:** ${{ needs.build-and-test.outputs.environment }}" >> $GITHUB_STEP_SUMMARY
echo "- **Image Tag:** ${{ needs.build-and-test.outputs.image_tag }}" >> $GITHUB_STEP_SUMMARY

Copilot uses AI. Check for mistakes.
echo "- **Platforms:** linux/amd64, linux/arm64" >> $GITHUB_STEP_SUMMARY
Comment on lines +154 to +161
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Build Summary 단계에서 존재하지 않는 step 출력을 참조하고 있습니다.

steps.set-env.outputs를 참조하고 있지만, create-manifest 잡에는 set-env라는 id를 가진 step이 없습니다. build-and-test 잡의 출력을 참조해야 합니다.

🔧 수정 방법 (create-manifest 잡을 유지하는 경우)
       - name: Build Summary
         if: always()
         run: |
           echo "### Build Summary :package:" >> $GITHUB_STEP_SUMMARY
           echo "" >> $GITHUB_STEP_SUMMARY
-          echo "- **Environment:** ${{ steps.set-env.outputs.environment }}" >> $GITHUB_STEP_SUMMARY
-          echo "- **Image Tag:** ${{ steps.set-env.outputs.image_tag }}" >> $GITHUB_STEP_SUMMARY
+          echo "- **Environment:** ${{ needs.build-and-test.outputs.environment }}" >> $GITHUB_STEP_SUMMARY
+          echo "- **Image Tag:** ${{ needs.build-and-test.outputs.image_tag }}" >> $GITHUB_STEP_SUMMARY
           echo "- **Platforms:** linux/amd64, linux/arm64" >> $GITHUB_STEP_SUMMARY

Static analysis 도구의 지적사항을 기반으로 함.

📝 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.

Suggested change
- name: Build Summary
if: always()
run: |
echo "### Build Summary :package:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Environment:** ${{ steps.set-env.outputs.environment }}" >> $GITHUB_STEP_SUMMARY
echo "- **Image Tag:** ${{ steps.set-env.outputs.image_tag }}" >> $GITHUB_STEP_SUMMARY
echo "- **Platforms:** linux/amd64, linux/arm64" >> $GITHUB_STEP_SUMMARY
- name: Build Summary
if: always()
run: |
echo "### Build Summary :package:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Environment:** ${{ needs.build-and-test.outputs.environment }}" >> $GITHUB_STEP_SUMMARY
echo "- **Image Tag:** ${{ needs.build-and-test.outputs.image_tag }}" >> $GITHUB_STEP_SUMMARY
echo "- **Platforms:** linux/amd64, linux/arm64" >> $GITHUB_STEP_SUMMARY
🧰 Tools
🪛 actionlint (1.7.10)

186-186: property "set-env" is not defined in object type {}

(expression)

🤖 Prompt for AI Agents
In @.github/workflows/ci.yml around lines 184 - 191, The Build Summary step is
referencing nonexistent step outputs (steps.set-env.outputs.environment and
steps.set-env.outputs.image_tag); update the echo lines in the Build Summary
step to use the outputs from the build-and-test job instead
(needs.build-and-test.outputs.environment and
needs.build-and-test.outputs.image_tag), and ensure the create-manifest job
declares needs: build-and-test so those job outputs are available.

40 changes: 40 additions & 0 deletions docker/kyeoungwoon/dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# =================================
# Run stage only
# =================================
FROM eclipse-temurin:21-jre-jammy
WORKDIR /app

LABEL maintainer="UMC PRODUCT TEAM SERVER TEAM"
LABEL description="UMC PRODUCT Official SpringBoot Backend Server"

# Create non-root user
RUN groupadd -r spring && useradd -r -g spring spring

# 이미 build된 jar 파일을 docker 안으로 복사
COPY --chown=spring:spring build/libs/*.jar app.jar
RUN chmod 444 app.jar

# 로그 디렉토리 생성 및 권한 설정
RUN mkdir -p /app/logs && chown -R spring:spring /app/logs

# Switch to non-root user
USER spring:spring

# Expose application port
EXPOSE 8080

# JVM options
ENV JAVA_OPTS="-XX:+UseContainerSupport \
-XX:MaxRAMPercentage=75.0 \
-XX:+UseG1GC \
-XX:+ExitOnOutOfMemoryError \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/tmp/heapdump.hprof \
-Duser.timezone=Asia/Seoul \
-Djava.security.egd=file:/dev/./urandom"

# Use exec form with sh -c so JAVA_OPTS is expanded and signals forwarded
ENTRYPOINT ["sh", "-c", "exec java $JAVA_OPTS -jar app.jar"]

# Optional healthcheck (uncomment if actuator/health endpoint exists)
# HEALTHCHECK --interval=30s --timeout=5s CMD curl -f http://localhost:8080/actuator/health || exit 1
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: HEALTHCHECK 주석에 actuator/health 엔드포인트 존재 확인이 필요하다고 명시되어 있는데, build.gradle.kts를 확인한 결과 spring-boot-starter-actuator가 포함되어 있으므로 주석을 해제해도 됩니다.

다만 health check를 활성화하려면 다음을 확인해야 합니다:

  1. application.yml에서 actuator health 엔드포인트가 노출되어 있는지 확인
  2. Security 설정에서 /actuator/health가 인증 없이 접근 가능한지 확인

Copilot uses AI. Check for mistakes.
87 changes: 87 additions & 0 deletions scripts/cd-dev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/bin/bash
set -e
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

에러 핸들링 개선을 고려하세요.

set -e가 설정되어 있어 좋습니다. 추가로 set -u(미설정 변수 감지)와 set -o pipefail(파이프라인 에러 전파)을 추가하면 스크립트의 안정성을 더욱 향상시킬 수 있습니다.

♻️ 제안하는 수정안
 #!/bin/bash
-set -e
+set -euo pipefail
📝 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.

Suggested change
#!/bin/bash
set -e
#!/bin/bash
set -euo pipefail
🤖 Prompt for AI Agents
In @scripts/cd-dev.sh around lines 1 - 2, The script currently enables "set -e"
but should also enable strict error handling; add "set -u" and "set -o pipefail"
alongside the existing "set -e" (i.e., in the top of the script near the
existing set -e) so that unset variables cause failures and pipeline errors
propagate, improving robustness of the cd-dev.sh entrypoint.


# ------------------------------------------------------------------
# 변수 할당 (GitHub Actions에서 envs로 넘어온 값들)
# ------------------------------------------------------------------
# 주의: YAML에서 envs로 넘겨준 변수 이름과 정확히 일치해야 합니다.
# ------------------------------------------------------------------

echo "=============================="
echo "🚀 배포 시작: $ENVIRONMENT 환경"
echo "=============================="

# [1] Docker 설치 확인
echo "[1] Docker 설치 확인"
if which docker > /dev/null 2>&1; then
echo "✅ Docker 인식됨: $(which docker)"
else
echo "⚠️ PATH에 /usr/local/bin 추가"
export PATH="$PATH:/usr/local/bin"
if which docker > /dev/null 2>&1; then
echo "✅ Docker 인식됨: $(which docker)"
else
echo "❌ Docker를 찾을 수 없습니다"
exit 1
fi
fi

# [2] 환경별 배포 디렉토리 설정
# YAML의 ${{ secrets... }} 대신 환경변수 $APP_DIR_PRODUCTION 등을 사용
if [[ "$ENVIRONMENT" == "prod" ]]; then
APP_DIR=$APP_DIR_PRODUCTION
else
APP_DIR=$APP_DIR_DEVELOPMENT
fi

echo "📂 배포 경로: $APP_DIR"

# [3] 설정 파일 생성
mkdir -p $APP_DIR/config
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Shellcheck 경고: 변수를 인용 부호로 감싸세요.

$APP_DIR 변수가 공백이나 특수문자를 포함할 경우 의도하지 않은 동작이 발생할 수 있습니다. Shellcheck가 지적한 대로 변수를 큰따옴표로 감싸는 것이 안전합니다.

♻️ 제안 수정사항
 # [3] 설정 파일 생성
-mkdir -p $APP_DIR/config
-echo "$APPLICATION_PROD" > $APP_DIR/config/application-prod.yml
-echo "$APPLICATION_DEV" > $APP_DIR/config/application-dev.yml
-echo "$APPLICATION_SECRET" > $APP_DIR/config/application-secret.yml
+mkdir -p "$APP_DIR/config"
+echo "$APPLICATION_PROD" > "$APP_DIR/config/application-prod.yml"
+echo "$APPLICATION_DEV" > "$APP_DIR/config/application-dev.yml"
+echo "$APPLICATION_SECRET" > "$APP_DIR/config/application-secret.yml"
 
 # 보안을 위해 권한 설정 (선택사항)
-chmod 600 $APP_DIR/config/application-*.yml
+chmod 600 "$APP_DIR"/config/application-*.yml
 echo "✅ 환경 설정 파일 생성 완료"
 # [5] Docker Compose 실행
-cd $APP_DIR
+cd "$APP_DIR"

Also applies to: 62-62, 78-78

🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 56-56: Double quote to prevent globbing and word splitting.

(SC2086)

🤖 Prompt for AI Agents
In @scripts/cd-dev.sh at line 56, The mkdir and other calls that use the APP_DIR
variable (e.g., the mkdir -p $APP_DIR/config usages) should quote the variable
to prevent word-splitting and globbing; update every occurrence where $APP_DIR
is used in shell commands (including the other instances flagged) to use
"$APP_DIR"/config or "$APP_DIR" as appropriate so paths with spaces or special
characters are handled safely.

echo "$APPLICATION_PROD" > $APP_DIR/config/application-prod.yml
echo "$APPLICATION_DEV" > $APP_DIR/config/application-dev.yml
echo "$APPLICATION_SECRET" > $APP_DIR/config/application-secret.yml

# 보안을 위해 권한 설정 (선택사항)
chmod 600 $APP_DIR/config/application-*.yml
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: 민감한 설정 파일에 대한 권한 설정이 600으로 되어 있지만, 파일이 생성되는 디렉토리($APP_DIR/config)의 권한은 설정하지 않았습니다. 디렉토리가 공개 권한으로 생성되면 파일 목록이 노출될 수 있습니다.

디렉토리 권한도 함께 설정하는 것을 권장합니다:

mkdir -p $APP_DIR/config
chmod 700 $APP_DIR/config
Suggested change
mkdir -p $APP_DIR/config
echo "$APPLICATION_PROD" > $APP_DIR/config/application-prod.yml
echo "$APPLICATION_DEV" > $APP_DIR/config/application-dev.yml
echo "$APPLICATION_SECRET" > $APP_DIR/config/application-secret.yml
# 보안을 위해 권한 설정 (선택사항)
chmod 600 $APP_DIR/config/application-*.yml
mkdir -p "$APP_DIR/config"
chmod 700 "$APP_DIR/config"
echo "$APPLICATION_PROD" > "$APP_DIR/config/application-prod.yml"
echo "$APPLICATION_DEV" > "$APP_DIR/config/application-dev.yml"
echo "$APPLICATION_SECRET" > "$APP_DIR/config/application-secret.yml"
# 보안을 위해 권한 설정 (선택사항)
chmod 600 "$APP_DIR/config"/application-*.yml

Copilot uses AI. Check for mistakes.
echo "✅ 환경 설정 파일 생성 완료"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

변수를 따옴표로 감싸야 합니다.

$APP_DIR 변수가 따옴표 없이 사용되고 있습니다. 경로에 공백이나 특수문자가 포함될 경우 예상치 못한 동작이 발생할 수 있습니다.

🔧 제안하는 수정안
 # [3] 설정 파일 생성
-mkdir -p $APP_DIR/config
-echo "$APPLICATION_PROD" > $APP_DIR/config/application-prod.yml
-echo "$APPLICATION_DEV" > $APP_DIR/config/application-dev.yml
-echo "$APPLICATION_SECRET" > $APP_DIR/config/application-secret.yml
+mkdir -p "$APP_DIR/config"
+echo "$APPLICATION_PROD" > "$APP_DIR/config/application-prod.yml"
+echo "$APPLICATION_DEV" > "$APP_DIR/config/application-dev.yml"
+echo "$APPLICATION_SECRET" > "$APP_DIR/config/application-secret.yml"
 
 # 보안을 위해 권한 설정 (선택사항)
-chmod 600 $APP_DIR/config/application-*.yml
+chmod 600 "$APP_DIR"/config/application-*.yml
 echo "✅ 환경 설정 파일 생성 완료"
📝 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.

Suggested change
# [3] 설정 파일 생성
mkdir -p $APP_DIR/config
echo "$APPLICATION_PROD" > $APP_DIR/config/application-prod.yml
echo "$APPLICATION_DEV" > $APP_DIR/config/application-dev.yml
echo "$APPLICATION_SECRET" > $APP_DIR/config/application-secret.yml
# 보안을 위해 권한 설정 (선택사항)
chmod 600 $APP_DIR/config/application-*.yml
echo "✅ 환경 설정 파일 생성 완료"
# [3] 설정 파일 생성
mkdir -p "$APP_DIR/config"
echo "$APPLICATION_PROD" > "$APP_DIR/config/application-prod.yml"
echo "$APPLICATION_DEV" > "$APP_DIR/config/application-dev.yml"
echo "$APPLICATION_SECRET" > "$APP_DIR/config/application-secret.yml"
# 보안을 위해 권한 설정 (선택사항)
chmod 600 "$APP_DIR"/config/application-*.yml
echo "✅ 환경 설정 파일 생성 완료"
🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 53-53: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 54-54: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 55-55: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 56-56: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 59-59: Double quote to prevent globbing and word splitting.

(SC2086)

🤖 Prompt for AI Agents
In @scripts/cd-dev.sh around lines 52 - 60, Wrap the $APP_DIR variable in double
quotes wherever it’s used to avoid issues with spaces/special chars: update
mkdir -p $APP_DIR/config, the three echo redirects that write to
"$APP_DIR/config/application-*.yml" (specifically the echo lines that write
application-prod.yml, application-dev.yml, application-secret.yml), and the
chmod/echo lines to reference "$APP_DIR/config/application-*.yml" or the
explicit paths (e.g., "$APP_DIR/config/application-prod.yml") so all path
expansions use quoted "$APP_DIR" consistently.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

민감한 설정 파일의 보안 처리를 강화하세요.

환경 변수의 민감한 정보를 디스크에 기록한 후 권한을 600으로 설정한 것은 좋은 시작이지만, 배포 후에도 이 파일들이 서버에 영구적으로 남아있어 보안 위험이 있습니다. 또한 SECRET 내용이 비어있는지 검증하지 않고 있습니다.

🔒 제안: 보안 강화 방안
  1. 민감한 정보가 비어있지 않은지 검증 추가:
 # [3] 설정 파일 생성
+
+# 민감한 정보 검증
+if [[ -z "$APPLICATION_PROD" || -z "$APPLICATION_DEV" || -z "$APPLICATION_SECRET" ]]; then
+  echo "❌ 설정 파일 내용이 비어있습니다"
+  exit 1
+fi
+
 mkdir -p $APP_DIR/config
  1. 또는 Docker secrets나 환경 변수를 직접 컨테이너에 전달하는 방식을 고려:
  • Docker Compose의 secrets 기능 활용
  • 환경 변수를 파일로 저장하지 않고 직접 컨테이너에 전달
  • 배포 후 설정 파일을 안전하게 삭제하는 트랩 핸들러 추가
# 스크립트 종료 시 설정 파일 삭제
trap 'rm -f $APP_DIR/config/application-*.yml' EXIT
📝 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.

Suggested change
mkdir -p $APP_DIR/config
echo "$APPLICATION_PROD" > $APP_DIR/config/application-prod.yml
echo "$APPLICATION_DEV" > $APP_DIR/config/application-dev.yml
echo "$APPLICATION_SECRET" > $APP_DIR/config/application-secret.yml
# 보안을 위해 권한 설정 (선택사항)
chmod 600 $APP_DIR/config/application-*.yml
echo "✅ 환경 설정 파일 생성 완료"
# 민감한 정보 검증
if [[ -z "$APPLICATION_PROD" || -z "$APPLICATION_DEV" || -z "$APPLICATION_SECRET" ]]; then
echo "❌ 설정 파일 내용이 비어있습니다"
exit 1
fi
mkdir -p "$APP_DIR/config"
echo "$APPLICATION_PROD" > "$APP_DIR/config/application-prod.yml"
echo "$APPLICATION_DEV" > "$APP_DIR/config/application-dev.yml"
echo "$APPLICATION_SECRET" > "$APP_DIR/config/application-secret.yml"
# 보안을 위해 권한 설정 (선택사항)
chmod 600 "$APP_DIR/config/application-*.yml"
echo "✅ 환경 설정 파일 생성 완료"
🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 56-56: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 57-57: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 58-58: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 59-59: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 62-62: Double quote to prevent globbing and word splitting.

(SC2086)

🤖 Prompt for AI Agents
In @scripts/cd-dev.sh around lines 56 - 63, Validate that APPLICATION_SECRET
(and other sensitive vars like APPLICATION_PROD/DEV) are non-empty before
writing to disk and fail fast with an error message if any required secret is
missing; write files with restrictive permissions (use umask or create temporary
files then chmod 600) and ensure you only create the secret file when
APPLICATION_SECRET is present; add a trap that removes
$APP_DIR/config/application-*.yml on EXIT (or on ERR/INT) to delete files after
deployment; optionally document switching to Docker secrets or passing env vars
directly so the code paths that write application-secret.yml can be removed
later.


# [4] Docker Hub 로그인
echo ""
echo "[2] Docker Hub 로그인"
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: 스크립트 제목 번호가 일관되지 않습니다. Docker 설치 확인은 "[1]"로 시작하지만, Docker Hub 로그인은 "[2]"로 표시되어 있습니다. 그러나 실제로는 [3] 설정 파일 생성 단계가 먼저 실행되므로 번호가 순서와 맞지 않습니다.

단계 번호를 실제 실행 순서에 맞게 수정하거나, 번호를 제거하는 것을 권장합니다.

Suggested change
echo "[2] Docker Hub 로그인"
echo "[4] Docker Hub 로그인"

Copilot uses AI. Check for mistakes.
echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin

if [ $? -eq 0 ]; then
echo "✅ Docker Hub 로그인 성공"
else
echo "❌ Docker Hub 로그인 실패"
exit 1
fi
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Docker 로그인 시 비밀번호가 프로세스 인자로 전달되어 프로세스 목록에 노출될 수 있습니다. 현재는 --password-stdin을 사용하여 안전하게 처리하고 있지만, $? 검사 방식이 안전하지 않습니다.

셸 스크립트에서 'set -e'가 설정되어 있어 docker login이 실패하면 자동으로 스크립트가 종료되므로, 54-59행의 조건문이 실행되지 않습니다. 이 검증 로직은 불필요하거나, 'set -e'를 제거하고 명시적인 오류 처리를 수행해야 합니다.

Copilot uses AI. Check for mistakes.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

종료 코드 검사를 직접적으로 수행하세요.

$?를 사용한 간접적인 검사보다 명령어를 직접 조건문에서 실행하는 것이 더 관용적입니다.

♻️ 제안하는 수정안
 # [4] Docker Hub 로그인
 echo ""
 echo "[2] Docker Hub 로그인"
-echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
-
-if [ $? -eq 0 ]; then
+if echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin; then
   echo "✅ Docker Hub 로그인 성공"
 else
   echo "❌ Docker Hub 로그인 실패"
   exit 1
 fi
📝 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.

Suggested change
# [4] Docker Hub 로그인
echo ""
echo "[2] Docker Hub 로그인"
echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
if [ $? -eq 0 ]; then
echo "✅ Docker Hub 로그인 성공"
else
echo "❌ Docker Hub 로그인 실패"
exit 1
fi
# [4] Docker Hub 로그인
echo ""
echo "[2] Docker Hub 로그인"
if echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin; then
echo "✅ Docker Hub 로그인 성공"
else
echo "❌ Docker Hub 로그인 실패"
exit 1
fi
🧰 Tools
🪛 Shellcheck (0.11.0)

[style] 67-67: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

(SC2181)

🤖 Prompt for AI Agents
In @scripts/cd-dev.sh around lines 62 - 72, Replace the indirect exit-code check
that uses `$?` after running the piped `docker login` with a direct conditional
that runs the piped command inside the `if` (i.e., use `if echo
"$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin;
then ... fi`), removing the separate `$?` test and leaving the success and
failure echo/exit branches intact so the script directly evaluates the command's
exit status.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

스타일 개선: 종료 코드 확인 방식을 직접적으로 변경하세요.

$?를 사용하여 간접적으로 종료 코드를 확인하는 대신, 명령을 직접 if 조건에서 실행하는 것이 더 명확하고 관용적입니다.

♻️ 제안 수정사항
 # [4] Docker Hub 로그인
 echo ""
 echo "[2] Docker Hub 로그인"
-echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
-
-if [ $? -eq 0 ]; then
+if echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin; then
   echo "✅ Docker Hub 로그인 성공"
 else
   echo "❌ Docker Hub 로그인 실패"
   exit 1
 fi
 # 기존 컨테이너 중지 및 최신 이미지 Pull & 실행
 docker compose pull
-docker compose up -d
-
-if [ $? -eq 0 ]; then
+if docker compose up -d; then
   echo "✅ 컨테이너 재시작 성공"
 else
   echo "❌ 컨테이너 재시작 실패"
   exit 1
 fi

Also applies to: 88-93

🧰 Tools
🪛 Shellcheck (0.11.0)

[style] 70-70: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

(SC2181)

🤖 Prompt for AI Agents
In @scripts/cd-dev.sh around lines 70 - 75, Replace the indirect exit-code check
using "$?" after the docker login command with a direct conditional that runs
the command in the if statement (e.g., change the pattern "if [ $? -eq 0 ]; then
... else ... fi" to "if docker login ...; then echo '✅ Docker Hub 로그인 성공'; else
echo '❌ Docker Hub 로그인 실패'; exit 1; fi"), and apply the same replacement for the
other occurrence that follows the same pattern; ensure you keep the original
echo messages and the exit 1 on failure.


Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Docker Hub 로그인 상태를 확인하는 조건문이 불필요합니다. docker login은 실패 시 0이 아닌 exit code를 반환하므로, 스크립트 상단의 'set -e'에 의해 자동으로 종료됩니다.

if [ $? -eq 0 ] 블록을 제거하고 간단하게 처리할 수 있습니다:

echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
echo "✅ Docker Hub 로그인 성공"
Suggested change
if [ $? -eq 0 ]; then
echo "✅ Docker Hub 로그인 성공"
else
echo "❌ Docker Hub 로그인 실패"
exit 1
fi
echo "✅ Docker Hub 로그인 성공"

Copilot uses AI. Check for mistakes.
# [5] Docker Compose 실행
cd $APP_DIR

# 롤백 및 버전 관리를 위해 태그 지정 (docker-compose.yml에서 ${TAG}를 쓴다고 가정)
export TAG=$IMAGE_TAG
export DOCKER_IMAGE_NAME=$DOCKER_IMAGE_NAME

# 기존 컨테이너 중지 및 최신 이미지 Pull & 실행
docker compose pull
docker compose up -d
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: 배포 스크립트가 원격 서버의 docker-compose.yml 파일에 의존하고 있지만, 이 파일을 생성하거나 전송하는 단계가 없습니다. 'docker compose up -d' 명령은 실행 경로에 docker-compose.yml이 있어야 하는데, 현재 워크플로우에서는 이를 보장하지 않습니다.

배포 디렉토리($APP_DIR)에 docker-compose.yml 파일을 생성하거나 리포지토리에서 복사하는 단계를 추가해야 합니다.

Copilot uses AI. Check for mistakes.

if [ $? -eq 0 ]; then
echo "✅ 컨테이너 재시작 성공"
else
echo "❌ 컨테이너 재시작 실패"
exit 1
fi
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, verify the script file exists and check its content around lines 74-90
git ls-files scripts/cd-dev.sh | head -20

Repository: UMC-PRODUCT/umc-product-server

Length of output: 91


🏁 Script executed:

# Check the actual content of lines 74-90 in the script
sed -n '74,90p' scripts/cd-dev.sh

Repository: UMC-PRODUCT/umc-product-server

Length of output: 397


🏁 Script executed:

# Search for docker-compose.yml files in the repository
fd -t f "docker-compose.yml"

Repository: UMC-PRODUCT/umc-product-server

Length of output: 92


🏁 Script executed:

# Check for any docker-compose files with different patterns
fd -t f "docker-compose"

Repository: UMC-PRODUCT/umc-product-server

Length of output: 92


🏁 Script executed:

# Search for APP_DIR references in the script to understand its value
rg "APP_DIR" scripts/cd-dev.sh -A 2 -B 2

Repository: UMC-PRODUCT/umc-product-server

Length of output: 1067


🏁 Script executed:

# Check if docker-compose.yml uses the environment variables mentioned
cat docker-compose.yml

Repository: UMC-PRODUCT/umc-product-server

Length of output: 1272


🏁 Script executed:

# Check the broader context of the script to see if APP_DIR might have spaces
head -n 80 scripts/cd-dev.sh | tail -n 20

Repository: UMC-PRODUCT/umc-product-server

Length of output: 474


🏁 Script executed:

# Search for how APP_DIR is used elsewhere in the script
rg "APP_DIR" scripts/cd-dev.sh

Repository: UMC-PRODUCT/umc-product-server

Length of output: 621


변수 인용 및 도커 구성 파일 검증이 필요합니다.

  1. 75번 줄의 cd $APP_DIR과 59번 줄의 mkdir -p $APP_DIR/config 등에서 변수가 인용되지 않았습니다. APP_DIR에 공백이 포함되면 문제가 발생합니다.
  2. 도커 컴포즈 파일의 존재를 런타임에 확인하지 않고 있습니다. APP_DIR 배포 경로에 docker-compose.yml 파일이 실제로 있는지 검증해야 합니다.
  3. 85번 줄의 if [ $? -eq 0 ]는 직접 조건으로 변경하는 것이 좋습니다.
  4. 중요: 스크립트 주석은 docker-compose.yml에서 ${TAG}, ${DOCKER_IMAGE_NAME} 변수를 사용한다고 가정하지만, 실제 파일에는 이러한 변수가 없습니다. 배포 환경에 맞는 올바른 docker-compose.yml 파일을 사용하고 있는지 확인하세요.
🔧 제안하는 수정안
 # [5] Docker Compose 실행
-cd $APP_DIR
+cd "$APP_DIR" || exit 1
+
+# docker-compose.yml 파일 확인
+if [ ! -f "docker-compose.yml" ]; then
+  echo "❌ docker-compose.yml 파일을 찾을 수 없습니다"
+  exit 1
+fi
 
 # 롤백 및 버전 관리를 위해 태그 지정 (docker-compose.yml에서 ${TAG}를 쓴다고 가정)
 export TAG=$IMAGE_TAG
 export DOCKER_IMAGE_NAME=$DOCKER_IMAGE_NAME
 
 # 기존 컨테이너 중지 및 최신 이미지 Pull & 실행
 docker compose pull
-docker compose up -d
-
-if [ $? -eq 0 ]; then
+if docker compose up -d; then
   echo "✅ 컨테이너 재시작 성공"
 else
   echo "❌ 컨테이너 재시작 실패"
   exit 1
 fi
📝 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.

Suggested change
# [5] Docker Compose 실행
cd $APP_DIR
# 롤백 및 버전 관리를 위해 태그 지정 (docker-compose.yml에서 ${TAG}를 쓴다고 가정)
export TAG=$IMAGE_TAG
export DOCKER_IMAGE_NAME=$DOCKER_IMAGE_NAME
# 기존 컨테이너 중지 및 최신 이미지 Pull & 실행
docker compose pull
docker compose up -d
if [ $? -eq 0 ]; then
echo "✅ 컨테이너 재시작 성공"
else
echo "❌ 컨테이너 재시작 실패"
exit 1
fi
# [5] Docker Compose 실행
cd "$APP_DIR" || exit 1
# docker-compose.yml 파일 확인
if [ ! -f "docker-compose.yml" ]; then
echo "❌ docker-compose.yml 파일을 찾을 수 없습니다"
exit 1
fi
# 롤백 및 버전 관리를 위해 태그 지정 (docker-compose.yml에서 ${TAG}를 쓴다고 가정)
export TAG=$IMAGE_TAG
export DOCKER_IMAGE_NAME=$DOCKER_IMAGE_NAME
# 기존 컨테이너 중지 및 최신 이미지 Pull & 실행
docker compose pull
if docker compose up -d; then
echo "✅ 컨테이너 재시작 성공"
else
echo "❌ 컨테이너 재시작 실패"
exit 1
fi
🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 75-75: Double quote to prevent globbing and word splitting.

(SC2086)


[style] 85-85: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

(SC2181)

🤖 Prompt for AI Agents
In @scripts/cd-dev.sh around lines 74 - 90, Ensure variables are quoted and
docker-compose validated: wrap APP_DIR in quotes wherever used (e.g., "cd
\"$APP_DIR\"" and "mkdir -p \"$APP_DIR/config\""), check for the presence of the
docker-compose.yml file in "$APP_DIR" before running docker compose (validate
that the file contains the expected ${TAG}/${DOCKER_IMAGE_NAME} variables or
adjust to the actual compose file), replace the post-command status check "if [
$? -eq 0 ]" with a direct command conditional (e.g., if docker compose up -d;
then ...) and fail fast with descriptive error messages if any validation
(missing file, missing variables, or docker compose failure) detects a problem.

Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: docker compose up -d 실패 시 확인 로직도 불필요합니다. 'set -e'에 의해 명령 실패 시 자동으로 스크립트가 종료되므로, if 조건문이 중복입니다.

간단하게 처리할 수 있습니다:

docker compose pull
docker compose up -d
echo "✅ 컨테이너 재시작 성공"

Copilot uses AI. Check for mistakes.

# 미사용 이미지 정리
docker image prune -f

echo ""
echo "=============================="
echo "🎉 배포 완료!"
echo "=============================="
echo "환경: $ENVIRONMENT"
echo "이미지: $DOCKER_IMAGE_NAME:$ENVIRONMENT-latest"