diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml new file mode 100644 index 0000000..2ef1d70 --- /dev/null +++ b/.github/workflows/cicd.yml @@ -0,0 +1,102 @@ +name: CI/CD Pipeline + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: "21" + distribution: "temurin" + + - name: Restore application.yml + run: | + mkdir -p ./blog/src/main/resources + echo "${{ secrets.APPLICATION_YML }}" | base64 --decode > ./blog/src/main/resources/application.yml + + - name: Grant execute permission for gradlew + run: chmod +x ./gradlew + + - name: Build with Gradle (skip test) + run: ./gradlew :blog:clean :blog:build -x test + + - name: Upload Build Artifact + uses: actions/upload-artifact@v4 + with: + name: build-artifact + path: blog/build/libs/*.jar + + docker-push: + runs-on: ubuntu-latest + needs: build + steps: + - uses: actions/checkout@v4 + + - name: Restore application.yml + run: | + mkdir -p ./blog/src/main/resources + echo "${{ secrets.APPLICATION_YML }}" | base64 --decode > ./blog/src/main/resources/application.yml + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and Push Docker Image + uses: docker/build-push-action@v5 + with: + context: ./blog + file: ./blog/Dockerfile + push: true + tags: sispo3314/leets-blog:latest + + deploy: + runs-on: ubuntu-latest + needs: docker-push + steps: + - uses: actions/checkout@v4 + + - name: Copy docker-compose.yml to EC2 + uses: appleboy/scp-action@master + with: + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USERNAME }} + key: ${{ secrets.EC2_SSH_KEY }} + source: "blog/docker-compose.yml" + target: "/home/ubuntu/" + + - name: Deploy to EC2 + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.EC2_HOST }} + username: ${{ secrets.EC2_USERNAME }} + key: ${{ secrets.EC2_SSH_KEY }} + script: | + cd /home/ubuntu + cat > .env << 'EOF' + MYSQL_ROOT_PASSWORD=${{ secrets.MYSQL_ROOT_PASSWORD }} + MYSQL_DATABASE=${{ secrets.MYSQL_DATABASE }} + TZ=Asia/Seoul + MYSQL_PORT=3306 + SERVER_PORT=8080 + SPRING_DATASOURCE_URL=${{ secrets.SPRING_DATASOURCE_URL }} + SPRING_DATASOURCE_USERNAME=${{ secrets.SPRING_DATASOURCE_USERNAME }} + SPRING_DATASOURCE_PASSWORD=${{ secrets.SPRING_DATASOURCE_PASSWORD }} + SPRING_JPA_HIBERNATE_DDL_AUTO=update + SPRING_JPA_SHOW_SQL=true + EOF + + docker compose -f docker-compose.yml --env-file .env down || true + docker compose -f docker-compose.yml --env-file .env pull + docker compose -f docker-compose.yml --env-file .env up -d diff --git a/.gitignore b/.gitignore index 7249259..3737850 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,7 @@ gradle/ # Other generated files out/ *.class -*.jar \ No newline at end of file +*.jar + +.pem +.env \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b65b780 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM eclipse-temurin:21-jdk-jammy + +WORKDIR /app + + +ARG JAR_FILE=build/libs/*.jar +COPY ${JAR_FILE} app.jar + +EXPOSE 8080 + +ENTRYPOINT ["java", "-jar", "app.jar"] diff --git a/application.yml b/application.yml index db1d72c..7a5e028 100644 --- a/application.yml +++ b/application.yml @@ -1,9 +1,10 @@ spring: datasource: - url: jdbc:mysql://localhost:3306/leetsdb?useSSL=false&serverTimezone=Asia/Seoul&characterEncoding=utf8 - username: root - password: "0902" + url: ${SPRING_DATASOURCE_URL} + username: ${SPRING_DATASOURCE_USERNAME} + password: ${SPRING_DATASOURCE_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver + jpa: hibernate: ddl-auto: update @@ -11,6 +12,7 @@ spring: properties: hibernate: format_sql: true + server: port: 8080 @@ -24,12 +26,12 @@ springdoc: kakao: oauth: - client-id: 832cf040e50187a709811294587535ee - client-secret: STyTYjHaJyNFryjqlbjSK6fdKmoLrEsj - redirect-uri: http://localhost:8080/auth/kakao/callback + client-id: ${KAKAO_CLIENT_ID} + client-secret: ${KAKAO_CLIENT_SECRET} + redirect-uri: ${KAKAO_REDIRECT_URI} security: jwt: - secret: g7Wn9vKzE9f3HqV4zD0OErfYh8cKq6LxT0ZzB+Q8m9GfHkP7d9Sxv2Aq9rV1p3Wn== - access-exp: 1800 - refresh-exp: 120 \ No newline at end of file + secret: ${JWT_SECRET} + access-exp: ${JWT_ACCESS_EXP} + refresh-exp: ${JWT_REFRESH_EXP} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..aa62e4c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,42 @@ +services: + mysql: + image: mysql:8.0 + container_name: leets_mysql + command: --default-authentication-plugin=mysql_native_password + environment: + MYSQL_DATABASE: ${DB_NAME} + MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} + TZ: Asia/Seoul + ports: + - "${DB_PORT}:3306" + volumes: + - leets_mysql_data:/var/lib/mysql + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 3s + timeout: 10s + retries: 10 + start_period: 20s + + api: + image: sispo3314/leets:v3 + restart: unless-stopped + depends_on: + mysql: + condition: service_healthy + ports: + - "8080:8080" + environment: + SPRING_DATASOURCE_URL: ${SPRING_DATASOURCE_URL} + SPRING_DATASOURCE_USERNAME: ${SPRING_DATASOURCE_USERNAME} + SPRING_DATASOURCE_PASSWORD: ${SPRING_DATASOURCE_PASSWORD} + + SECURITY_JWT_SECRET: ${JWT_SECRET} + KAKAO_OAUTH_CLIENT_ID: ${KAKAO_CLIENT_ID} + KAKAO_OAUTH_CLIENT_SECRET: ${KAKAO_CLIENT_SECRET} + KAKAO_OAUTH_REDIRECT_URI: ${KAKAO_REDIRECT_URI} + + TZ: Asia/Seoul + +volumes: + leets_mysql_data: