diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml new file mode 100644 index 00000000..8388a0ab --- /dev/null +++ b/.github/workflows/dev.yml @@ -0,0 +1,80 @@ +name: Java CI with Gradle + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + types: [ opened, synchronize, reopened ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + # gradle caching + - name: Gradle Caching + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*gradle*','**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + # Gradle Build (test는 제외) + - name: Build with Gradle + run: ./gradlew build -x test + + # 도커 허브에 로그인 + - name: Docker Hub Login + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USER_NAME }} + password: ${{ secrets.DOCKER_USER_TOKEN }} + + - name: Docker build & push + run: | + docker build -t ${{ secrets.DOCKER_USER_NAME }}/blog-dev -f ./Dockerfile-dev . + docker push ${{ secrets.DOCKER_USER_NAME }}/blog-dev + + deploy: + runs-on: ubuntu-latest + needs: build + # if: github.event_name == 'push' 테스트를 위해 주석 처리 + + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + + - name: Copy deploy.sh to EC2 + uses: appleboy/scp-action@master + with: + host: ${{ secrets.DEV_HOST }} + username: ${{ secrets.DEV_EC2_USER }} + key: ${{ secrets.DEV_SSH_PRIVATE_KEY }} + port: 22 + source: "scripts/deploy.sh" + target: "/home/ubuntu" + + - name: Deploy to EC2 + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.DEV_HOST }} + username: ${{ secrets.DEV_EC2_USER }} + key: ${{ secrets.DEV_SSH_PRIVATE_KEY }} + port: 22 + script: | + chmod +x /home/ubuntu/scripts/deploy.sh + sh /home/ubuntu/scripts/deploy.sh + debug: true diff --git a/Dockerfile-dev b/Dockerfile-dev new file mode 100644 index 00000000..05aabe61 --- /dev/null +++ b/Dockerfile-dev @@ -0,0 +1,12 @@ +# open jdk 21버전 +FROM openjdk:21-jdk + +# build가 되는 시점에 JAR_FILE이라는 변수 명에 build/libs/*.jar 선언 +# build/libs - gradle로 빌드했을 때 jar 파일이 생성되는 경로 +ARG JAR_FILE=build/libs/*.jar + +# JAR_FILE을 app.jar로 복사 +COPY ${JAR_FILE} docker-springboot.jar + +# 운영 및 개발에서 사용되는 환경 설정을 분리 +ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=dev", "/docker-springboot.jar"] \ No newline at end of file diff --git a/scripts/deploy.sh b/scripts/deploy.sh new file mode 100644 index 00000000..5a657c35 --- /dev/null +++ b/scripts/deploy.sh @@ -0,0 +1,45 @@ +cd /home/ubuntu/compose + +EXIST_BLUE=$(docker inspect -f '{{.State.Running}}' spring-blue 2>/dev/null) + +if [ "$EXIST_BLUE" != "true" ]; then + docker compose up -d spring-blue + BEFORE_COLOR="green" + AFTER_COLOR="blue" + BEFORE_PORT=8081 + AFTER_PORT=8080 +else + docker compose up -d spring-green + BEFORE_COLOR="blue" + AFTER_COLOR="green" + BEFORE_PORT=8080 + AFTER_PORT=8081 +fi + +echo "===== ${AFTER_COLOR} server upc(port:${AFTER_PORT}) =====" + +for cnt in {1..10} +do + echo "===== 서버 응답 확인중(${cnt}/10) =====" + UP=$(curl -s http://localhost:${AFTER_PORT}/health-check) + if [ "$UP" != "OK" ]; then + sleep 10 + continue + else + break + fi +done + +if [ $cnt -eq 10 ]; then + echo "===== 서버 실행 실패 =====" + exit 1 +fi + +echo "===== Caddy 설정 변경 =====" +sudo sed -i "s/${BEFORE_PORT}/${AFTER_PORT}/g" /etc/caddy/Caddyfile + +sudo caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile + +echo "$BEFORE_COLOR server down(port:${BEFORE_PORT})" +docker compose stop spring-${BEFORE_COLOR} +docker compose rm -f spring-${BEFORE_COLOR} \ No newline at end of file diff --git a/src/main/java/com/blog/global/controller/StatusCheckController.java b/src/main/java/com/blog/global/controller/StatusCheckController.java new file mode 100644 index 00000000..1694e28d --- /dev/null +++ b/src/main/java/com/blog/global/controller/StatusCheckController.java @@ -0,0 +1,15 @@ +package com.blog.global.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class StatusCheckController { + + @GetMapping("/health-check") + public ResponseEntity checkHealthStatus() { + + return ResponseEntity.ok("OK"); + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 00000000..99753acb --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,13 @@ +spring: + datasource: + url: ${DB_URL} + username: ${RDS_USER_NAME} + password: ${RDS_USER_PW} + driver-class-name: com.mysql.cj.jdbc.Driver + jpa: + show-sql: true + properties: + hibernate: + dialect: org.hibernate.dialect.MySQLDialect + hibernate: + ddl-auto: update \ No newline at end of file