Skip to content

Commit

Permalink
Merge pull request #87 from Leets-Official/dev
Browse files Browse the repository at this point in the history
Chore #87 현재 진행상황 Main에 병합
  • Loading branch information
huncozyboy authored Feb 5, 2025
2 parents 7f45347 + 8e3be88 commit 2418769
Show file tree
Hide file tree
Showing 254 changed files with 8,484 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## 📌 관련 이슈
관련 이슈 번호 #
관련 이슈 번호 #
Close #


Expand Down
71 changes: 71 additions & 0 deletions .github/workflows/dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: GachTaxi-BE dev CI/CD

on:
push:
branches: [ "dev" , "feat/#57/OCICICD파이프라인구축"] # develop 브랜치에 push 시 트리거
pull_request:
branches: [ "dev", "feat/#57/OCICICD파이프라인구축" ] # develop 브랜치에 대한 PR 시 트리거
types: [opened, synchronize, reopened]

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

# 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-
- name: Build with Gradle Wrapper
run: ./gradlew build -x test

# 빌드된 JAR 파일 확인
- name: List JAR files
run: ls build/libs

# Docker 이미지 빌드 및 푸시
- name: Docker build & push
run: |
docker login -u ${{ secrets.DEV_DOCKER_USER_NAME }} -p ${{ secrets.DEV_DOCKER_USER_TOKEN }}
docker buildx create --use
docker buildx build --platform linux/amd64,linux/arm64 -f Dockerfile-dev -t ${{ secrets.DEV_DOCKER_USER_NAME }}/gachtaxi:${{ secrets.DEV_DOCKER_TAG }} --push .
deploy:
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'push'

steps:
# SSH를 사용하여 원격 서버에 배포
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.DEV_SSH_SECRET_HOST }}
username: ${{ secrets.DEV_SSH_SECRET_USER }}
port: 22
key: ${{ secrets.DEV_SSH_SECRET_PRIVATE_KEY }}
script: |
sudo docker pull ${{ secrets.DEV_DOCKER_USER_NAME }}/gachtaxi:${{ secrets.DEV_DOCKER_TAG }}
sudo docker compose up -d --no-deps gachtaxi
# 사용하지 않는 이미지 정리
echo "** 사용하지 않는 Docker 이미지 정리"
sudo docker image prune -f
71 changes: 71 additions & 0 deletions .github/workflows/prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: GachTaxi-BE prod CI/CD

on:
push:
branches: [ "main"]
pull_request:
branches: [ "main"]
types: [opened, synchronize, reopened]

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

# 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-
- name: Build with Gradle Wrapper
run: ./gradlew build -x test

# 빌드된 JAR 파일 확인
- name: List JAR files
run: ls build/libs

# Docker 이미지 빌드 및 푸시
- name: Docker build & push
run: |
docker login -u ${{ secrets.DEV_DOCKER_USER_NAME }} -p ${{ secrets.DEV_DOCKER_USER_TOKEN }}
docker buildx create --use
docker buildx build --platform linux/amd64,linux/arm64 -f Dockerfile-dev -t ${{ secrets.DEV_DOCKER_USER_NAME }}/gachtaxi:${{ secrets.PROD_DOCKER_TAG }} --push .
deploy:
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'push'

steps:
# SSH를 사용하여 원격 서버에 배포
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.PROD_SSH_SECRET_HOST }}
username: ${{ secrets.PROD_SSH_SECRET_USER }}
port: 22
key: ${{ secrets.PROD_SSH_SECRET_PRIVATE_KEY }}
script: |
sudo docker pull ${{ secrets.PROD_DOCKER_USER_NAME }}/gachtaxi:${{ secrets.PROD_DOCKER_TAG }}
sudo docker compose up -d --no-deps gachtaxi
# 사용하지 않는 이미지 정리
echo "** 사용하지 않는 Docker 이미지 정리"
sudo docker image prune -f
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,11 @@ out/

### VS Code ###
.vscode/

src/main/resources/.env

docker-compose.yml

### firebase ###
/src/main/resources/serviceAccountKey.json

7 changes: 7 additions & 0 deletions Dockerfile-dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM eclipse-temurin:17-jre-focal

ARG JAR_FILE=build/libs/*.jar

COPY ${JAR_FILE} docker-springboot.jar

ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=dev", "/docker-springboot.jar"]
14 changes: 10 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependencies {
// Spring
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
// implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-websocket'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
implementation 'org.springframework.boot:spring-boot-starter-validation'
Expand All @@ -38,17 +38,23 @@ dependencies {
// Swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'

// Java Mail Sender
implementation 'org.springframework.boot:spring-boot-starter-mail'
// AWS SES
implementation 'software.amazon.awssdk:ses:2.29.46'

// S3 Client
implementation 'software.amazon.awssdk:s3:2.20.126'
implementation 'software.amazon.awssdk:s3:2.29.46'

// MongoDB, Redis, MySQL
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
runtimeOnly 'com.mysql:mysql-connector-j'

// Kafka
implementation 'org.springframework.kafka:spring-kafka'

// Firebase
implementation 'com.google.firebase:firebase-admin:9.4.2'

// Test
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
Expand Down
Empty file modified gradlew
100644 → 100755
Empty file.
4 changes: 4 additions & 0 deletions src/main/java/com/gachtaxi/GachtaxiApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.mongodb.config.EnableMongoAuditing;

@SpringBootApplication
@EnableJpaAuditing
@EnableMongoAuditing
public class GachtaxiApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.gachtaxi.domain.chat.controller;

import com.gachtaxi.domain.chat.dto.request.ChatMessageRequest;
import com.gachtaxi.domain.chat.dto.response.ChatResponse;
import com.gachtaxi.domain.chat.dto.response.ChattingRoomCountResponse;
import com.gachtaxi.domain.chat.dto.response.ChattingRoomResponse;
import com.gachtaxi.domain.chat.service.ChattingRoomService;
import com.gachtaxi.domain.chat.service.ChattingService;
import com.gachtaxi.global.auth.jwt.annotation.CurrentMemberId;
import com.gachtaxi.global.common.response.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;

import static com.gachtaxi.domain.chat.controller.ResponseMessage.*;
import static org.springframework.http.HttpStatus.OK;

@Tag(name = "CHAT")
@RestController
@RequiredArgsConstructor
public class ChattingController {

private final ChattingService chattingService;
private final ChattingRoomService chattingRoomService;

@GetMapping("/api/chat/{roomId}")
@Operation(summary = "채팅방 재입장시 이전 메시지를 조회하기 위한 API입니다.")
public ApiResponse<ChatResponse> getChattingMessages(@PathVariable Long roomId,
@CurrentMemberId Long memberId,
@RequestParam int pageNumber,
@RequestParam int pageSize,
@RequestParam(required = false) LocalDateTime lastMessageTimeStamp) {
ChatResponse response = chattingService.getMessage(roomId, memberId, pageNumber, pageSize, lastMessageTimeStamp);

return ApiResponse.response(OK, GET_CHATTING_MESSAGE_SUCCESS.getMessage(), response);
}

@GetMapping("/api/chat/count/{roomId}")
@Operation(summary = "채팅방의 총 참여자 수를 조회하기 위한 API입니다.")
public ApiResponse<ChattingRoomCountResponse> getChattingMessageCount(@CurrentMemberId Long memberId,
@PathVariable Long roomId) {
ChattingRoomCountResponse response = chattingRoomService.getCount(memberId, roomId);

return ApiResponse.response(OK, GET_CHATTING_PARTICIPANT_COUNT_SUCCESS.getMessage(), response);
}

@DeleteMapping("/api/chat/{roomId}")
@Operation(summary = "채팅방을 퇴장하는 API입니다. 퇴장시 STOMP UNSUBSCRIBE를 꼭 해주세요")
public ApiResponse<Void> exitChattingRoom(@PathVariable Long roomId,
@CurrentMemberId Long memberId) {
chattingRoomService.exitChatRoom(roomId, memberId);

return ApiResponse.response(OK, EXIT_CHATTING_ROOM_SUCCESS.getMessage());
}

@MessageMapping("/chat/message")
public void message(@Valid ChatMessageRequest request, SimpMessageHeaderAccessor headerAccessor) {
chattingService.chat(request, headerAccessor);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.gachtaxi.domain.chat.controller;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum ResponseMessage {

CREATE_CHATTING_ROOM_SUCCESS("채팅방 생성에 성공했습니다."),
GET_CHATTING_MESSAGE_SUCCESS("이전 메시지 조회에 성공 했습니다."),
EXIT_CHATTING_ROOM_SUCCESS("채팅방 퇴장에 성공했습니다."),
GET_CHATTING_PARTICIPANT_COUNT_SUCCESS("채팅방 전체 참여자 조회에 성공했습니다.");

private final String message;
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,49 @@
package com.gachtaxi.domain.chat.dto.request;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.gachtaxi.domain.chat.dto.response.ReadMessageRange;
import com.gachtaxi.domain.chat.entity.ChattingMessage;
import com.gachtaxi.domain.chat.entity.enums.MessageType;
import lombok.Builder;

import java.time.LocalDateTime;

@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public record ChatMessage(
long roomId,
long senderId,
String messageId,
Long roomId,
Long senderId,
String senderName,
String message,
LocalDateTime timeStamp
String profilePicture,
ReadMessageRange range,
Long unreadCount,
LocalDateTime timeStamp,
MessageType messageType
) {
public static ChatMessage of(long roomId, long senderId, String message, LocalDateTime timeStamp) {
return new ChatMessage(roomId, senderId, message, timeStamp);
public static ChatMessage from(ChattingMessage chattingMessage) {
return ChatMessage.builder()
.messageId(chattingMessage.getId())
.roomId(chattingMessage.getRoomId())
.senderId(chattingMessage.getSenderId())
.senderName(chattingMessage.getSenderName())
.message(chattingMessage.getMessage())
.profilePicture(chattingMessage.getProfilePicture())
.unreadCount(chattingMessage.getUnreadCount())
.timeStamp(chattingMessage.getTimeStamp())
.messageType(chattingMessage.getMessageType())
.build();
}

public static ChatMessage of(long roomId, Long senderId, String senderName, ReadMessageRange range, MessageType messageType) {
return ChatMessage.builder()
.roomId(roomId)
.senderId(senderId)
.senderName(senderName)
.range(range)
.timeStamp(LocalDateTime.now())
.messageType(messageType)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.gachtaxi.domain.chat.dto.request;

import jakarta.validation.constraints.NotBlank;

public record ChatMessageRequest(
Long roomId,
String message
@NotBlank String message
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.gachtaxi.domain.chat.dto.response;

import com.gachtaxi.domain.chat.entity.ChattingMessage;
import lombok.Builder;
import org.springframework.data.domain.Slice;

@Builder
public record ChatPageableResponse(
int pageNumber,
int pageSize,
int numberOfElements,
boolean last,
boolean empty
) {
public static ChatPageableResponse of(int pageNumber, Slice<ChattingMessage> slice) {
return ChatPageableResponse.builder()
.pageNumber(pageNumber)
.pageSize(slice.getSize())
.numberOfElements(slice.getNumberOfElements())
.last(slice.isLast())
.empty(slice.isEmpty())
.build();
}
}
Loading

0 comments on commit 2418769

Please sign in to comment.