diff --git a/.github/workflows/release-cd.yml b/.github/workflows/release-cd.yml new file mode 100644 index 00000000..2dbb0e24 --- /dev/null +++ b/.github/workflows/release-cd.yml @@ -0,0 +1,70 @@ +name: AWS EC2 Deploy + +on: + push: + branches: + - main + +jobs: + build: + # ubuntu 버전 지정 + runs-on: ubuntu-22.04 + steps: + # Checkout 진행 + - uses: actions/checkout@v3 + + # JDK 17 설치 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'corretto' + + # Gradle 캐싱 + - 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 권한 부여 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + # application.yml 반영 + - name: Make application.yml + run: | + cd ./src/main/resources + touch ./application.yml + echo "${{ secrets.APPLICATION_SECRET}}" > ./application.yml + shell: bash + + # Gradle BootJar + - name: BootJar with Gradle + run: ./gradlew clean bootJar -Dspring.profiles.active=release + + # Docker Image Push + - name: Docker Image push + run: | + docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }} + docker build -t ${{ secrets.DOCKERHUB_USERNAME}}/${{ secrets.DOCKERHUB_REPOSITORY}} ./ + docker push ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPOSITORY}} + + # Docker Compose + - name: Docker Compose + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.EC2_SERVER_IP }} + username: ${{ secrets.SSH_USERNAME }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + script: | + sudo docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }} + sudo docker-compose stop ${{ secrets.DOCKER_SERVICE_NAME }} + sudo docker-compose rm -f ${{ secrets.DOCKER_SERVICE_NAME }} + sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPOSITORY}} + sudo docker tag ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPOSITORY}} ${{ secrets.DOCKER_IMAGE_NAME }} + sudo docker-compose up -d \ No newline at end of file diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml new file mode 100644 index 00000000..efc4fa3c --- /dev/null +++ b/.github/workflows/release-ci.yml @@ -0,0 +1,50 @@ +name: CI with Gradle + +on: + pull_request: + branches: + - main + +permissions: write-all + +jobs: + build: + # ubuntu 버전 지정 + runs-on: ubuntu-22.04 + steps: + # Checkout 진행 + - uses: actions/checkout@v3 + + # JDK 17 설치 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'corretto' + + # Gradle 캐싱 + - 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 권한 부여 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + # yml 반영 + - name: Make application-secret.yml + run: | + cd ./src/main/resources + touch ./application.yml + echo "${{ secrets.APPLICATION_SECRET}}" > ./application.yml + shell: bash + + # Gradle clean bootJar + - name: Build with Gradle + run: ./gradlew clean bootJar \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..583663f5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:17-alpine +ARG JAR_FILE=./build/libs/server-0.0.1-SNAPSHOT.jar +COPY ${JAR_FILE} app.jar +ENTRYPOINT ["sh", "-c", "java -Duser.timezone=Asia/Seoul -jar /app.jar"] \ No newline at end of file diff --git a/build.gradle b/build.gradle index 6e393e57..6709d05a 100644 --- a/build.gradle +++ b/build.gradle @@ -34,6 +34,9 @@ dependencies { // MySQL runtimeOnly 'com.mysql:mysql-connector-j' + // Redis + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + // Swagger UI - spring doc implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' diff --git a/src/main/java/com/gongjakso/server/global/config/RedisConfig.java b/src/main/java/com/gongjakso/server/global/config/RedisConfig.java new file mode 100644 index 00000000..f8093cb4 --- /dev/null +++ b/src/main/java/com/gongjakso/server/global/config/RedisConfig.java @@ -0,0 +1,36 @@ +package com.gongjakso.server.global.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +@EnableRedisRepositories +public class RedisConfig { + + @Value("${spring.redis.host}") + private String host; + + @Value("${spring.redis.port}") + private Integer port; + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + return new LettuceConnectionFactory(host, port); + } + + @Bean + public RedisTemplate redisTemplate() { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory()); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + + return redisTemplate; + } +} diff --git a/src/main/java/com/gongjakso/server/global/util/redis/RedisClient.java b/src/main/java/com/gongjakso/server/global/util/redis/RedisClient.java new file mode 100644 index 00000000..446d74cf --- /dev/null +++ b/src/main/java/com/gongjakso/server/global/util/redis/RedisClient.java @@ -0,0 +1,45 @@ +package com.gongjakso.server.global.util.redis; + +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.util.Objects; + +@Component +@RequiredArgsConstructor +public class RedisClient { + + private final RedisTemplate redisTemplate; + + /** + * Redis에 값 삽입하는 메소드 + * @param key - 삽입하고자 하는 데이터의 key + * @param value - 삽입하고자 하는 데이터의 value + * @param timeout - 삽입하고자 하는 데이터의 유효 시간 + */ + public void setValue(String key, String value, Long timeout) { + ValueOperations values = redisTemplate.opsForValue(); + values.set(key, value, Duration.ofMinutes(timeout)); + } + + /** + * Redis에서 key값을 기반으로 value를 찾아서 반환하는 메소드 + * @param key - value를 찾을 데이터의 key 값 + * @return - 해당 데이터의 value 반환 + */ + public String getValue(String key) { + ValueOperations values = redisTemplate.opsForValue(); + return Objects.requireNonNull(values.get(key)).toString(); + } + + /** + * Redis에서 key에 해당하는 데이터를 삭제하는 메소드 + * @param key - 삭제할 데이터의 key를 의미 + */ + public void deleteValue(String key) { + redisTemplate.delete(key); + } +} diff --git a/src/main/resources/.gitkeep b/src/main/resources/.gitkeep new file mode 100644 index 00000000..e69de29b