diff --git a/.ebextensions/00-makeFiles.config b/.ebextensions/00-makeFiles.config new file mode 100644 index 0000000..ac43e12 --- /dev/null +++ b/.ebextensions/00-makeFiles.config @@ -0,0 +1,12 @@ +files: + "/sbin/appstart": + mode: "000755" + owner: webapp + group: webapp + content: | + #!/usr/bin/env bash + JAR_PATH=/var/app/current/application.jar + + # run app + killall java + java -Dfile.encoding=UTF-8 -jar $JAR_PATH \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..97abd18 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,138 @@ +name: carGive Dev CI/CD + +permissions: + checks: write + pull-requests: write + +on: + pull_request: + workflow_dispatch: # (2) 수동 실행 + +jobs: + test: + runs-on: ubuntu-latest # (3) OS환경 + if: startsWith(github.head_ref, 'feature/') + + steps: + - name: Checkout + uses: actions/checkout@v2 # (4) 코드 check out : 스프링부트 프로젝트의 소스코드를 내려받는다 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: 17 + distribution: adopt-hotspot # (5) 자바 설치 + + - name: Cache Gradle packages + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Grant execute permission for gradlew + run: chmod +x ./gradlew + shell: bash # (6) 권한 부여 + + - name: Build with Gradle + run: ./gradlew clean build + shell: bash # (8) build 시작 + + - name: Get current time + uses: 1466587594/get-current-time@v2 + id: current-time + with: + format: YYYY-MM-DDTHH-mm-ss + utcOffset: "+09:00" # (9) build 시점의 시간확보 + + - name: Show Current Time + run: echo "CurrentTime=${{steps.current-time.outputs.formattedTime}}" + shell: bash # (10) 확보한 시간 보여주기 + + - name: Code Test + run: ./gradlew test + shell: bash # (11) 테스트 코드 실행 + + - name: Publish Unit Test Results + uses: EnricoMi/publish-unit-test-result-action@v1 + if: ${{ always() }} # 테스트가 실패하여도 Report를 보기 위해 `always`로 설정 + with: + files: build/test-results/**/*.xml + + - name: Cleanup Gradle Cache + if: ${{ always() }} + run: | + rm -f ~/.gradle/caches/modules-2/modules-2.lock + rm -f ~/.gradle/caches/modules-2/gc.properties + build: + runs-on: ubuntu-latest # (3) OS환경 + if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'develop' + + steps: + - name: Checkout + uses: actions/checkout@v2 # (4) 코드 check out : 스프링부트 프로젝트의 소스코드를 내려받는다 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: 17 # (5) 자바 설치 + distribution: adopt-hotspot + + - name: Cache Gradle packages + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Grant execute permission for gradlew + run: chmod +x ./gradlew + shell: bash # (6) 권한 부여 + + - name: Build with Gradle + run: ./gradlew clean build + shell: bash # (8) build 시작 + + - name: Get current time + uses: 1466587594/get-current-time@v2 + id: current-time + with: + format: YYYY-MM-DDTHH-mm-ss + utcOffset: "+09:00" # (9) build 시점의 시간확보 + + - name: Show Current Time + run: echo "CurrentTime=${{steps.current-time.outputs.formattedTime}}" + shell: bash # (10) 확보한 시간 보여주기 + + - name: Generate deployment package + run: | + mkdir -p deploy + cp build/libs/*.jar deploy/application.jar + cp Procfile deploy/Procfile + cp -r .ebextensions deploy/.ebextensions + cp -r .platform deploy/.platform + cd deploy && zip -r deploy.zip . + + - name: Beanstalk Deploy + uses: einaregilsson/beanstalk-deploy@v20 + with: + aws_access_key: ${{secrets.AWS_ACCESS_KEY}} + aws_secret_key: ${{secrets.AWS_SECRET_KEY}} + application_name: carGive + environment_name: carGive-env + version_label: github-action-${{steps.current-time.outputs.formattedTime}} + region: ap-northeast-2 + deployment_package: deploy/deploy.zip + wait_for_environment_recovery: 60 + + - name: Cleanup Gradle Cache + if: ${{ always() }} + run: | + rm -f ~/.gradle/caches/modules-2/modules-2.lock + rm -f ~/.gradle/caches/modules-2/gc.properties \ No newline at end of file diff --git a/.platform/nginx.conf b/.platform/nginx.conf new file mode 100644 index 0000000..4b3528c --- /dev/null +++ b/.platform/nginx.conf @@ -0,0 +1,58 @@ +user nginx; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; +worker_processes auto; +worker_rlimit_nofile 33282; + +events { + use epoll; + worker_connections 1024; + multi_accept on; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + include conf.d/*.conf; + + map $http_upgrade $connection_upgrade { + default "upgrade"; + } + + upstream springboot { + server 127.0.0.1:8080; + keepalive 1024; + } + + server { + listen 80 default_server; + listen [::]:80 default_server; + + location / { + proxy_pass http://springboot; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + access_log /var/log/nginx/access.log main; + + client_header_timeout 60; + client_body_timeout 60; + keepalive_timeout 60; + gzip off; + gzip_comp_level 4; + + # Include the Elastic Beanstalk generated locations + include conf.d/elasticbeanstalk/healthd.conf; + } +} \ No newline at end of file diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..58dab8d --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: appstart \ No newline at end of file diff --git a/build.gradle b/build.gradle index b6dd96e..cbe6f4d 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,11 @@ version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' + targetCompatibility = '17' +} + +wrapper { + gradleVersion = '8.3' } configurations { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..7f93135 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9f4197d..ac72c34 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index fcb6fca..0adc8e1 100755 --- a/gradlew +++ b/gradlew @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/settings.gradle b/settings.gradle index 210d079..a63e734 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -rootProject.name = 'carGive' +rootProject.name = 'carGive' \ No newline at end of file diff --git a/src/main/java/com/example/cargive/global/infra/ElasticBeanstalkHealthCheck.java b/src/main/java/com/example/cargive/global/infra/ElasticBeanstalkHealthCheck.java new file mode 100644 index 0000000..352bfeb --- /dev/null +++ b/src/main/java/com/example/cargive/global/infra/ElasticBeanstalkHealthCheck.java @@ -0,0 +1,18 @@ +package com.example.cargive.global.infra; + +import com.example.cargive.global.base.BaseResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/health") +public class ElasticBeanstalkHealthCheck { + @GetMapping + public ResponseEntity getHealthCheck() { + return BaseResponse.toResponseEntityContainsResult("It Works!"); + } +}