Skip to content

Commit

Permalink
Merge pull request #405 from woowacourse-teams/develop
Browse files Browse the repository at this point in the history
[All] 모모의 세번째 배포를 축하해요 : )
  • Loading branch information
hw0603 authored Oct 15, 2024
2 parents d2c3435 + f01a403 commit 31f6088
Show file tree
Hide file tree
Showing 56 changed files with 1,532 additions and 444 deletions.
24 changes: 7 additions & 17 deletions .github/workflows/backend-dev-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Backend Dev CD
on:
workflow_dispatch:
push:
branches: ['develop']
branches: [ 'develop' ]

jobs:
detect-changes:
Expand Down Expand Up @@ -83,7 +83,7 @@ jobs:

be-depoly:
needs: be-build
runs-on: [self-hosted, linux, ARM64, dev]
runs-on: [ self-hosted, linux, ARM64, dev ]
defaults:
run:
shell: bash
Expand All @@ -103,20 +103,10 @@ jobs:
- name: docker pull
run: docker pull ${{ secrets.DOCKERHUB_USERNAME }}/momo-api-dev

# 2. 기존 컨테이너 중지
- name: docker stop container
run: docker stop $(docker ps -q) 2>/dev/null || true

# 3. 도커 컨테이너 실행
- name: docker run new container
run: >-
docker run --name momo-api-dev
--rm -d -p 8080:8080
--volume=$HOME/security:/momo/security:ro
--volume=$HOME/logs:/momo/logs
--env SPRING_PROFILE=dev
${{ secrets.DOCKERHUB_USERNAME }}/momo-api-dev
# 4. 미사용 이미지를 정리
# 2. 실행 컨테이너 중 app 서비스만 재시작
- name: Restart app service
run: docker compose -f $HOME/security/docker-compose-dev.yml restart app --no-deps

# 3. 미사용 이미지를 정리
- name: delete old docker image
run: docker system prune -f
2 changes: 1 addition & 1 deletion .github/workflows/frontend-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Frontend CI

on:
pull_request:
branches: ['develop']
branches: ['main', 'develop']

permissions:
checks: write
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class RoutingDataSource extends AbstractRoutingDataSource {
protected Object determineCurrentLookupKey() {
boolean currentTransactionReadOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
String key = currentTransactionReadOnly ? DataSourceConfig.REPLICA_SERVER : DataSourceConfig.SOURCE_SERVER;
log.info("Activated Datasource: {}", key);
log.debug("Activated Datasource: {}", key);
return key;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,4 @@ public ResponseEntity<Void> logout(@PathVariable String uuid) {
public MomoApiResponse<List<String>> findAttendeesOfMeeting(@PathVariable String uuid) {
return new MomoApiResponse<>(attendeeService.findAll(uuid));
}

/**
* TEMP: 비밀번호 마이그레이션 이후 삭제될 메서드입니다.
*/
@PostMapping("/api/v1/attendee/update-password")
public MomoApiResponse<Integer> updatePassword() {
return new MomoApiResponse<>(attendeeService.updateAllPassword());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import kr.momo.service.meeting.MeetingConfirmService;
import kr.momo.service.meeting.MeetingService;
import kr.momo.service.meeting.dto.ConfirmedMeetingResponse;
import kr.momo.service.meeting.dto.MeetingHomeResponse;
import kr.momo.service.meeting.dto.MeetingConfirmRequest;
import kr.momo.service.meeting.dto.MeetingConfirmResponse;
import kr.momo.service.meeting.dto.MeetingCreateRequest;
Expand Down Expand Up @@ -73,6 +74,12 @@ public MomoApiResponse<ConfirmedMeetingResponse> findConfirmedMeeting(@PathVaria
return new MomoApiResponse<>(response);
}

@GetMapping("/api/v1/meetings/{uuid}/home")
public MomoApiResponse<MeetingHomeResponse> findMeetingHome(@PathVariable String uuid) {
MeetingHomeResponse response = meetingService.findMeetingHome(uuid);
return new MomoApiResponse<>(response);
}

@PatchMapping("/api/v1/meetings/{uuid}/lock")
public void lock(@PathVariable String uuid, @AuthAttendee long id) {
meetingService.lock(uuid, id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import kr.momo.service.meeting.dto.MeetingConfirmResponse;
import kr.momo.service.meeting.dto.MeetingCreateRequest;
import kr.momo.service.meeting.dto.MeetingCreateResponse;
import kr.momo.service.meeting.dto.MeetingHomeResponse;
import kr.momo.service.meeting.dto.MeetingResponse;
import kr.momo.service.meeting.dto.MeetingSharingResponse;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -147,4 +148,11 @@ ResponseEntity<Void> cancelConfirmedMeeting(
@PathVariable @Schema(description = "약속 UUID") String uuid,
@AuthAttendee @Schema(hidden = true) long id
);

@Operation(summary = "약속 입장 정보 조회", description = "약속 입장에 필요한 정보를 조회하는 API 입니다.")
@ApiSuccessResponse.NoContent("약속 입장 정보 조회 성공")
@ApiErrorResponse.BadRequest(ERROR_CODE_TABLE_HEADER + """
| NOT_FOUND_MEETING | 존재하지 않는 약속 정보 입니다. |
""")
MomoApiResponse<MeetingHomeResponse> findMeetingHome(@PathVariable @Schema(description = "약속 UUID") String uuid);
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,24 +63,4 @@ public List<String> findAll(String uuid) {
.map(Attendee::name)
.toList();
}

/**
* TEMP: 비밀번호 마이그레이션 이후 삭제될 메서드입니다.
*/
@Transactional
public Integer updateAllPassword() {
List<Attendee> attendees = attendeeRepository.findAll();
List<Attendee> rawAttendees = attendees.stream()
.filter(attendee -> attendee.getPassword().getPassword().length() < 15)
.toList();
rawAttendees.forEach(
attendee -> {
String rawPassword = attendee.getPassword().getPassword();
String encodedPassword = passwordEncoder.encode(rawPassword);
attendee.updatePassword(encodedPassword);
}
);
attendeeRepository.saveAll(rawAttendees);
return rawAttendees.size();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import kr.momo.exception.code.AttendeeErrorCode;
import kr.momo.exception.code.MeetingErrorCode;
import kr.momo.service.auth.JwtManager;
import kr.momo.service.meeting.dto.MeetingHomeResponse;
import kr.momo.service.meeting.dto.MeetingCreateRequest;
import kr.momo.service.meeting.dto.MeetingCreateResponse;
import kr.momo.service.meeting.dto.MeetingResponse;
Expand Down Expand Up @@ -110,6 +111,13 @@ public MeetingSharingResponse findMeetingSharing(String uuid) {
return MeetingSharingResponse.from(meeting);
}

@Transactional(readOnly = true)
public MeetingHomeResponse findMeetingHome(String uuid) {
Meeting meeting = meetingRepository.findByUuid(uuid)
.orElseThrow(() -> new MomoException(MeetingErrorCode.NOT_FOUND_MEETING));
return MeetingHomeResponse.from(meeting);
}

@Transactional
public void lock(String uuid, long id) {
Meeting meeting = meetingRepository.findByUuid(uuid)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package kr.momo.service.meeting.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import kr.momo.domain.meeting.Meeting;

@Schema(description = "약속 입장 응답")
public record MeetingHomeResponse(

@Schema(description = "약속 이름")
String meetingName,

@Schema(description = "약속 유형")
String type
) {
public static MeetingHomeResponse from(Meeting meeting) {
return new MeetingHomeResponse(meeting.getName(), meeting.getType().name());
}
}
2 changes: 1 addition & 1 deletion backend/src/main/resources/security
Original file line number Diff line number Diff line change
Expand Up @@ -689,4 +689,18 @@ private MeetingConfirmRequest getValidFindRequest(AvailableDate tomorrow) {
Timeslot.TIME_0600.startTime()
);
}

@DisplayName("약속 입장 정보를 조회하면 200 상태 코드를 응답한다.")
@Test
void findMeetingHome() {
Meeting meeting = MeetingFixture.MOVIE.create();
meeting = meetingRepository.save(meeting);

RestAssured.given().log().all()
.pathParam("uuid", meeting.getUuid())
.contentType(ContentType.JSON)
.when().get("/api/v1/meetings/{uuid}/home")
.then().log().all()
.statusCode(HttpStatus.OK.value());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.List;
import java.util.UUID;
import kr.momo.domain.attendee.Attendee;
import kr.momo.domain.attendee.AttendeeRepository;
import kr.momo.domain.availabledate.AvailableDate;
Expand All @@ -24,6 +25,7 @@
import kr.momo.exception.code.MeetingErrorCode;
import kr.momo.fixture.AttendeeFixture;
import kr.momo.fixture.MeetingFixture;
import kr.momo.service.meeting.dto.MeetingHomeResponse;
import kr.momo.service.meeting.dto.MeetingCreateRequest;
import kr.momo.service.meeting.dto.MeetingResponse;
import kr.momo.service.meeting.dto.MeetingSharingResponse;
Expand Down Expand Up @@ -258,4 +260,28 @@ void throwsExceptionWhenUnlockAttendeeGuest() {
.isInstanceOf(MomoException.class)
.hasMessage(AttendeeErrorCode.ACCESS_DENIED.message());
}

@DisplayName("UUID로 약속 입장 정보를 조회한다.")
@Test
void findMeetingHome() {
Meeting meeting = meetingRepository.save(MeetingFixture.GAME.create());
String uuid = meeting.getUuid();

MeetingHomeResponse result = meetingService.findMeetingHome(uuid);

assertAll(
() -> assertThat(result.meetingName()).isEqualTo(meeting.getName()),
() -> assertThat(result.type()).isEqualTo(meeting.getType().name())
);
}

@DisplayName("약속 입장 정보를 조회시 UUID가 존재하지 않으면 예외가 발생한다.")
@Test
void throwsExceptionWhenFindHomeNoMeeting() {
String uuid = UUID.randomUUID().toString();

assertThatThrownBy(() -> meetingService.findMeetingHome(uuid))
.isInstanceOf(MomoException.class)
.hasMessage(MeetingErrorCode.NOT_FOUND_MEETING.message());
}
}
5 changes: 5 additions & 0 deletions frontend/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@ module.exports = {
},
setupFiles: ['./jest.polyfills.js'],
reporters: ['default', ['jest-junit', { outputDirectory: 'reports', outputName: 'report.xml' }]],

moduleNameMapper: {
'^@utils/(.*)$': '<rootDir>/src/utils/$1',
'^@constants/(.*)$': '<rootDir>/src/constants/$1',
},
};
6 changes: 4 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
"scripts": {
"prod": "webpack server --open --config webpack.prod.js",
"dev": "webpack server --open --config webpack.dev.js",
"build:prod": "NODE_ENV=production webpack --config webpack.prod.js && npm run sentry:sourcemaps",
"build:dev": "NODE_ENV=production webpack --config webpack.prod.js",
"build:prod-analyzer": "NODE_ENV=production USE_BUNDLE_ANALYZER=true webpack --config webpack.prod.js && npm run sentry:sourcemaps",
"build:prod": "NODE_ENV=production USE_BUNDLE_ANALYZER=false webpack --config webpack.prod.js && npm run sentry:sourcemaps",
"build:dev-analyzer": "NODE_ENV=production USE_BUNDLE_ANALYZER=true webpack --config webpack.prod.js && npm run sentry:sourcemaps",
"build:dev": "NODE_ENV=production USE_BUNDLE_ANALYZER=false webpack --config webpack.prod.js",
"sentry:sourcemaps": "sentry-cli sourcemaps inject ./dist && sentry-cli sourcemaps upload -o momo2024 -p momo-harry-test /dist",
"lint:css": "stylelint '**/*.styles.ts' --fix",
"test": "jest",
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/assets/images/attendeeCheck.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion frontend/src/assets/images/check.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions frontend/src/assets/images/exclamation.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 6 additions & 1 deletion frontend/src/assets/images/logoSunglass.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion frontend/src/components/Schedules/Schedules.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export const s_container = css`
export const s_relativeContainer = css`
position: relative;
flex: 1;
max-height: fit-content;
`;

export const s_selectModeButtonsContainer = css`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { css } from '@emotion/react';

export const s_bottomFixedStyles = css`
width: calc(100% + 1.6rem * 2);
max-width: 43rem;
/* 버튼 컴포넌트의 full variants를 사용하려고 했으나 6rem보다 height값이 작아 직접 높이를 정의했어요(@해리)
full 버튼에 이미 의존하고 있는 컴포넌트들이 많아서 높이를 full 스타일을 변경할 수는 없었습니다.
*/
height: 6rem;
box-shadow: 0 -4px 4px rgb(0 0 0 / 25%);
`;

export const s_bottomFixedButtonContainer = (height = 0) => css`
position: fixed;
bottom: 0;
left: 0;
transform: translateY(-${height}px);
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 6rem;
background-color: transparent;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { ButtonHTMLAttributes } from 'react';
import React from 'react';

import { Button } from '../Button';
import { s_bottomFixedButtonContainer, s_bottomFixedStyles } from './BottomFixedButton.styles';

interface BottomFixedButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children: React.ReactNode;
height?: number;
isLoading?: boolean;
}

export default function BottomFixedButton({
children,
height = 0,
isLoading = false,
...props
}: BottomFixedButtonProps) {
return (
<div css={s_bottomFixedButtonContainer(height)}>
<Button
variant="primary"
size="full"
isLoading={isLoading}
borderRadius={0}
customCss={s_bottomFixedStyles}
{...props}
>
{children}
</Button>
</div>
);
}
Loading

0 comments on commit 31f6088

Please sign in to comment.