Skip to content

Commit bb94faf

Browse files
authored
Merge pull request #55 from RestTest-App/release
[Feat] deploy.yml ์ˆ˜์ • ์˜์กด์„ฑ ์ถฉ๋Œ ๊ด€๋ จ ๋ฐฐํฌ ์Šคํฌ๋ฆฝํŠธ ์ˆ˜์ •
2 parents ee793e8 + 4dac6a1 commit bb94faf

10 files changed

Lines changed: 89 additions & 15 deletions

File tree

โ€Ž.github/workflows/deploy.ymlโ€Ž

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,23 @@ jobs:
5555
cache-from: type=local,src=/tmp/.buildx-cache
5656
cache-to: type=local,dest=/tmp/.buildx-cache-new
5757

58+
- name: Copy Docker Compose file via SCP
59+
uses: appleboy/scp-action@v0.1.7
60+
with:
61+
host: ${{ secrets.GCE_HOST }}
62+
username: ${{ secrets.GCE_SSH_USER }}
63+
key: ${{ secrets.GCE_SSH_KEY }}
64+
source: "docker-compose.prod.yml"
65+
target: "~/app-path"
66+
5867
- name: Deploy to GCE via SSH
5968
uses: appleboy/ssh-action@v1.0.0
6069
with:
6170
host: ${{ secrets.GCE_HOST }}
6271
username: ${{ secrets.GCE_SSH_USER }}
6372
key: ${{ secrets.GCE_SSH_KEY }}
6473
script: |
74+
mkdir -p ~/app-path
6575
cd ~/app-path
6676
6777
cat << 'EOF' > .env
@@ -70,7 +80,9 @@ jobs:
7080
7181
gcloud auth configure-docker ${{ env.ARTIFACT_REGISTRY }} --quiet
7282
73-
docker-compose -f docker-compose.prod.yml down
74-
docker-compose -f docker-compose.prod.yml pull
75-
docker-compose -f docker-compose.prod.yml run --rm -e MODE=prod fastapi alembic upgrade head
76-
docker-compose -f docker-compose.prod.yml up -d
83+
docker compose -f docker-compose.prod.yml down
84+
docker compose -f docker-compose.prod.yml pull
85+
86+
docker compose -f docker-compose.prod.yml run --rm -e MODE=prod fastapi alembic upgrade head
87+
88+
docker compose -f docker-compose.prod.yml up -d

โ€Žapi/v1/auth/auth_router.pyโ€Ž

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ async def sign_up(request: SignUpRequest, db: AsyncSession = Depends(get_db)):
4141
print(info.values())
4242

4343
user_dto = UserCreateDTO(
44-
**request.model_dump(exclude={"kakao_token"}),
45-
**info
44+
**{**request.model_dump(exclude={"kakao_token"}), **info}
4645
)
4746

4847
user = await SignUpUseCase(db).execute(user_dto)
49-
token_data = TokenUseCase.generate_tokens(user_id=user.id)
48+
token_uc = TokenUseCase()
49+
token_data = token_uc.generate_tokens(user_id=user.id)
5050

5151
return created(data=token_data, message="ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต")
5252

โ€Žapi/v1/test/test_router.pyโ€Ž

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
from app.test.dto.request.create_dummy_data_request import CreateDummyDataRequest
4242
#์‹œํ—˜๋ชจ๋“œ ๋ฌธ์ œ ๋ฆฌ์ŠคํŠธ ์ถœ๋ ฅ
4343
from app.test.dto.response.get_certificates_exam_list_response import GetCertificatesExamListResponse
44+
from app.test.usecase.test_usecase import get_exam_list_by_certificate_id_usecase
4445
from app.test.usecase.exam_usecase import get_certificates_exam_list_usecase
4546
from app.test.usecase.exam_usecase import create_exam_usecase
4647
from app.test.usecase.exam_usecase import get_exam_info_usecase
@@ -171,6 +172,10 @@ async def get_questions_by_exam_id(
171172
result = await get_questions_by_exam_id_usecase(exam_id, db)
172173
return ok(data=[item.dict() for item in result], message="๋ฌธ์ œ ๋ชฉ๋ก ์กฐํšŒ ์„ฑ๊ณต")
173174

175+
@router.get("/list/{certificate_id}")
176+
async def get_exam_list(certificate_id: int = Path(...), db: AsyncSession = Depends(get_db)):
177+
return await get_exam_list_by_certificate_id_usecase(certificate_id, db)
178+
174179
@router.post("/dummy-data", summary="์œ ํ˜•๋ณ„ Dummy Data ์ƒ์„ฑ API")
175180
async def create_dummy_data(
176181
request: CreateDummyDataRequest, # โ† ์—ฌ๊ธฐ์— request ์ถ”๊ฐ€ ํ•„์š”!
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import List
1+
from typing import List, Optional
22

33
from pydantic import BaseModel
44

@@ -7,5 +7,5 @@
77

88
class ReviewNoteListResponseDto(BaseModel):
99
category: List[str]
10-
selected_category: str
10+
selected_category: Optional[str] = None
1111
exams: List[ExamItemInfo]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from pydantic import BaseModel
2+
3+
class ExamResponseDTO(BaseModel):
4+
id: int
5+
name: str
6+
year: int
7+
month: int
8+
trial: int | None
9+
time: int
10+
pass_rate: float | None
11+
question_count: int
12+
13+
class Config:
14+
from_attributes = True

โ€Žapp/test/usecase/test_usecase.pyโ€Ž

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
from sqlalchemy.ext.asyncio import AsyncSession
1+
from sqlalchemy import func
22
from sqlalchemy.future import select
33
from domain.test.entity.exam import Exam
44
from domain.test.entity.question import Question
55
from domain.user.entity.user import User
6+
from app.utils.dto.success import ok
7+
from sqlalchemy.ext.asyncio import AsyncSession
8+
from app.test.dto.response.exam_response_dto import ExamResponseDTO
9+
from domain.test.repository.test_repository import TestRepository
610
from exception.client_exception import NotFoundException
7-
from app.utils.dto.success import created, ok
811

912
async def get_test_mode_usecase(
1013
exam_id: int,
@@ -44,3 +47,31 @@ async def get_test_mode_usecase(
4447
},
4548
message="์‹œํ—˜ ์กฐํšŒ ์„ฑ๊ณต"
4649
)
50+
51+
async def get_exam_list_by_certificate_id_usecase(certificate_id: int, db: AsyncSession):
52+
repo = TestRepository(db)
53+
exams = await repo.get_exams_by_certificate_id(certificate_id)
54+
55+
if not exams:
56+
raise NotFoundException("ํ•ด๋‹น ์ž๊ฒฉ์ฆ์— ๋Œ€ํ•œ ์‹œํ—˜์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")
57+
58+
exam_list = []
59+
60+
for exam in exams:
61+
stmt = select(func.count()).where(Question.exam_id == exam.id)
62+
result = await db.execute(stmt)
63+
question_count = result.scalar_one()
64+
65+
dto = ExamResponseDTO(
66+
id=exam.id,
67+
name=exam.name,
68+
year=exam.year,
69+
month=exam.month,
70+
trial=exam.trial,
71+
time=exam.time,
72+
pass_rate=exam.pass_rate,
73+
question_count=question_count
74+
)
75+
exam_list.append(dto.model_dump())
76+
77+
return ok(data={"exams": exam_list}, message="์‹œํ—˜ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ ์„ฑ๊ณต")

โ€Ždomain/review/service/review_note_test_service.pyโ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ async def list_review_notes(
6969

7070
return ReviewNoteListResponseDto(
7171
category = categories,
72-
selected_category = selected,
72+
selected_category = selected or "",
7373
exams = exams
7474
)
7575

โ€Ždomain/test/repository/test_repository.pyโ€Ž

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,11 @@ async def get_question_count_by_exam_id(self, exam_id: int) -> int:
161161
)
162162
return result.scalar()
163163

164+
async def get_exams_by_certificate_id(self, certificate_id: int) -> list[Exam]:
165+
stmt = select(Exam).where(Exam.certificate_id == certificate_id)
166+
result = await self.db.execute(stmt)
167+
return result.scalars().all()
168+
164169
async def get_exams_by_certificate_ids(self, certificate_ids: list[int]) -> list[Exam]:
165170
result = await self.db.execute(
166171
select(Exam)
@@ -179,4 +184,5 @@ async def get_exam_by_id(self, exam_id: int) -> Exam | None:
179184
result = await self.db.execute(
180185
select(Exam).where(Exam.id == exam_id)
181186
)
182-
return result.scalars().first()
187+
return result.scalars().first()
188+

โ€Ždomain/test/service/test_service.pyโ€Ž

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,17 @@ async def check_user_submit(
3535
if is_correct:
3636
correct_count += 1
3737

38+
raw_list = question.option_explanations or []
39+
option_explanations_dict: dict[str, str] = {
40+
key: val
41+
for item in raw_list
42+
for key, val in item.items()
43+
}
44+
3845
# ๋ฌธ์ œ๋ณ„ ํ•ด์„ค DTO
3946
info_list.append(AnswerInfoDto(
4047
answer=question.answer,
41-
option_explanations=question.option_explanations
48+
option_explanations=option_explanations_dict
4249
))
4350

4451
# ๋ฌธ์ œ๋ณ„ ์‚ฌ์šฉ์ž ์‘๋‹ต ๊ธฐ๋ก

โ€Žrequirements.txtโ€Ž

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ boto3~=1.38.32
2121
python-jose[cryptography]~=3.5.0
2222
requests-oauthlib
2323
requests~=2.32.3
24-
starlette>=0.49.1
2524

2625
# test
2726
pytest

0 commit comments

Comments
ย (0)