Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 27 additions & 21 deletions .github/workflows/ci-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,49 @@ name: CI-PROD

on:
pull_request:
branches: [ main, dev ] # main 브랜치에 pr 했을때 트리거
branches: [ main ]
push:
branches: [ main, dev ] # main 브랜치에 push 했을때 트리거

permissions:
contents: read # 내 코드를 읽을 수 있게(코드이동) 접근 권한을 준다.
id-token: write # OIDC 토큰을 발급할 수 있게 한다.
branches: [ main ]
Comment thread
githyj-jang marked this conversation as resolved.

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

steps:
- name: Checkout # 내 코드 이동 깃허브 컴퓨터로
- name: Checkout
uses: actions/checkout@v4

- name: Set up JDK 17 # jdk 환경 설치
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "17"

- name: Set up Gradle => gradle 설치
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4

- name: Grant execute permission for gradlew # 실행 권한 설정
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew

- name: Run tests # 테스트 실행
- name: Run tests
run: ./gradlew test --no-daemon -Dspring.profiles.active=test

- name: Generate image tag # pr이 아닌 push 일때 이미지 태그 생성
if: github.event_name == 'push' # 커밋 기반으로 어떤 코드 버전이 배포됐는지 정확히 추적 가능
run: echo "IMAGE_TAG=$(git rev-parse --short HEAD)" >> $GITHUB_ENV # 태그란? 이미지 버전 이름
build-and-push:
if: github.event_name == 'push'
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Generate image tag
run: echo "IMAGE_TAG=$(git rev-parse --short HEAD)" >> $GITHUB_ENV

- name: Configure AWS credentials (OIDC) # OIDC 기반으로 역할 자격증명
if: github.event_name == 'push'
Expand All @@ -44,16 +53,13 @@ jobs:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ vars.AWS_REGION }}

- name: Login to Amazon ECR # 위에서 자격증명하고 ecr 로그인
if: github.event_name == 'push'
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v2

- name: Build Docker image # 이미지 빌드해서
if: github.event_name == 'push'
- name: Build Docker image
run: |
docker build -t ${{ vars.ECR_REGISTRY }}/${{ vars.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }} .

- name: Push Docker image to ECR # 이미지 ecr로 업로드
if: github.event_name == 'push'
- name: Push Docker image to ECR
run: |
docker push ${{ vars.ECR_REGISTRY }}/${{ vars.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,9 @@ public void complete(LocalDateTime now) {
if (this.status == ReservationStatus.COMPLETED) {
return; // 이미 완료된 경우 멱등 처리
}
if (state.status() != ReservationStatus.CONFIRMED) {
throw new BusinessException(ReservationErrorCode.INVALID_STATUS_TRANSITION);
}
LocalDateTime windowStart = noshowDeadline.minusMinutes(60); // noshowDeadline - 60min (= slotStart - 30min)
if (now.isBefore(windowStart)) {
throw new BusinessException(ReservationErrorCode.CHECK_IN_TOO_EARLY);
}
if (now.isAfter(noshowDeadline)) {
throw new BusinessException(ReservationErrorCode.CHECK_IN_TOO_LATE);
}
this.status = state.complete();
this.state = ReservationStateFactory.from(this.status);
state.assertCompletable(now, noshowDeadline);
this.status = state.complete();
this.state = ReservationStateFactory.from(this.status);
this.checkedInAt = now;
}

Expand All @@ -138,13 +129,11 @@ public boolean requiresSlotReturn() {
}

public boolean isCancellable() {
return state.status() == ReservationStatus.CONFIRMED
&& !LocalDate.now().isAfter(cancelDeadline);
return state.isCancellable(cancelDeadline);
}

public boolean isModifiable() {
return state.status() == ReservationStatus.CONFIRMED
&& !LocalDate.now().isAfter(modifyDeadline);
return state.isModifiable(modifyDeadline);
}

public boolean requiresRefund() {
Expand All @@ -157,18 +146,13 @@ public void modify(
GuestCount newGuestCount,
LocalDateTime newNoshowDeadline
) {
if (state.status() != ReservationStatus.CONFIRMED) {
throw new BusinessException(ReservationErrorCode.INVALID_STATUS_TRANSITION);
}
if (LocalDate.now().isAfter(modifyDeadline)) {
throw new BusinessException(ReservationErrorCode.MODIFY_DEADLINE_EXCEEDED);
}
this.timeSlotId = newTimeSlotId;
this.reservedDate = newReservedDate;
this.guestCount = newGuestCount;
this.cancelDeadline = newReservedDate.minusDays(2);
this.modifyDeadline = newReservedDate.minusDays(2);
this.noshowDeadline = newNoshowDeadline;
state.assertModifiable(modifyDeadline);
this.timeSlotId = newTimeSlotId;
this.reservedDate = newReservedDate;
this.guestCount = newGuestCount;
this.cancelDeadline = newReservedDate.minusDays(2);
this.modifyDeadline = newReservedDate.minusDays(2);
this.noshowDeadline = newNoshowDeadline;
}

private static void validateCreateInput(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.michelet.reservation.domain.enums.ReservationStatus;
import com.michelet.reservation.domain.exception.ReservationErrorCode;
import java.time.LocalDate;
import java.time.LocalDateTime;

public class ConfirmedState implements ReservationState {

Expand All @@ -25,6 +26,34 @@ public ReservationStatus markNoShow() {
return ReservationStatus.NO_SHOW;
}

@Override
public boolean isCancellable(LocalDate cancelDeadline) {
return !LocalDate.now().isAfter(cancelDeadline);
}

@Override
public boolean isModifiable(LocalDate modifyDeadline) {
return !LocalDate.now().isAfter(modifyDeadline);
}

@Override
public void assertModifiable(LocalDate modifyDeadline) {
if (LocalDate.now().isAfter(modifyDeadline)) {
throw new BusinessException(ReservationErrorCode.MODIFY_DEADLINE_EXCEEDED);
}
}

@Override
public void assertCompletable(LocalDateTime now, LocalDateTime noshowDeadline) {
LocalDateTime windowStart = noshowDeadline.minusMinutes(60);
if (now.isBefore(windowStart)) {
throw new BusinessException(ReservationErrorCode.CHECK_IN_TOO_EARLY);
}
if (now.isAfter(noshowDeadline)) {
throw new BusinessException(ReservationErrorCode.CHECK_IN_TOO_LATE);
}
}
Comment thread
githyj-jang marked this conversation as resolved.

@Override
public boolean requiresSlotReturn() { return true; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.michelet.reservation.domain.enums.ReservationStatus;
import com.michelet.reservation.domain.exception.ReservationErrorCode;
import java.time.LocalDate;
import java.time.LocalDateTime;

public interface ReservationState {

Expand All @@ -28,6 +29,23 @@ default ReservationStatus markNoShow() {
throw new BusinessException(ReservationErrorCode.INVALID_STATUS_TRANSITION);
}

// 조건 판단 메서드 — CONFIRMED 외 상태는 false / 예외
default boolean isCancellable(LocalDate cancelDeadline) {
return false;
}

default boolean isModifiable(LocalDate modifyDeadline) {
return false;
}

default void assertModifiable(LocalDate modifyDeadline) {
throw new BusinessException(ReservationErrorCode.INVALID_STATUS_TRANSITION);
}

default void assertCompletable(LocalDateTime now, LocalDateTime noshowDeadline) {
throw new BusinessException(ReservationErrorCode.INVALID_STATUS_TRANSITION);
}

// 정책 메서드 — 상태별 구현 필수
boolean requiresSlotReturn();
boolean requiresRefund();
Expand Down

This file was deleted.

Loading