Skip to content

Commit 51574ed

Browse files
authored
Merge pull request #201 from Pseudo-Lab/deploy/cert-develop-rebased
chore: resolve merge conflicts in deploy/cert-develop
2 parents b20bb75 + 2692d49 commit 51574ed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+8411
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Deploy GetCloser
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
9+
# ๊ฐ™์€ ๋ธŒ๋žœ์น˜ ๋™์‹œ ์‹คํ–‰ ์‹œ ์ด์ „ ์žก ์ทจ์†Œ(๊ฒฝ์Ÿ ๋ฐฐํฌ ๋ฐฉ์ง€)
10+
concurrency:
11+
group: cert-${{ github.ref }}
12+
cancel-in-progress: true
13+
14+
jobs:
15+
# ========================================
16+
# ๐Ÿš€ Deploy GetCloser Service
17+
# ========================================
18+
deploy-prod:
19+
if: github.ref_name == 'main'
20+
name: ๐Ÿš€ Deploy GetCloser
21+
runs-on: oracle
22+
environment: getcloser
23+
defaults:
24+
run:
25+
working-directory: ./getcloser
26+
27+
steps:
28+
- name: Checkout branch
29+
uses: actions/checkout@v3
30+
31+
- name: Set up Docker Buildx
32+
uses: docker/setup-buildx-action@v3
33+
34+
- name: Create .env file for PROD
35+
run: |
36+
set -e
37+
echo "DB_USER=${{ secrets.DB_USER }}" > .env
38+
echo "DB_PASSWORD=${{ secrets.DB_PASSWORD }}" >> .env
39+
echo "DB_DATABASE=${{ vars.DB_DATABASE }}" >> .env
40+
echo "APP_HOST=${{ vars.APP_HOST }}" >> .env
41+
42+
- name: ๐Ÿš€ Deploy to PROD
43+
run: |
44+
docker compose -f docker-compose.yaml -p getcloser-${{ github.ref_name }} down --remove-orphans || true
45+
docker compose -f docker-compose.yaml -p getcloser-${{ github.ref_name }} up -d --build
File renamed without changes.

โ€Žgetcloser/.env.exampleโ€Ž

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# === Database Config ===
2+
DB_USER=user
3+
DB_PASSWORD=password
4+
DB_DATABASE=app_db
5+
6+
# === Auth (currently unused) ===
7+
# SECRET_KEY=secret_key
8+
# ACCESS_TOKEN_EXPIRE_MINUTES=60
9+
10+
# === App Host ===
11+
APP_HOST=localhost

โ€Žgetcloser/.gitignoreโ€Ž

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
node_modules
2+
.vite
3+
4+
5+
# Python
6+
__pycache__/
7+
*.py[cod]
8+
*$py.class
9+
*.so
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
*.egg-info/
24+
.installed.cfg
25+
*.egg
26+
MANIFEST
27+
28+
# PyInstaller
29+
*.manifest
30+
*.spec
31+
32+
# Unit test / coverage reports
33+
htmlcov/
34+
.tox/
35+
.coverage
36+
.coverage.*
37+
.cache
38+
nosetests.xml
39+
coverage.xml
40+
*.cover
41+
.hypothesis/
42+
.pytest_cache/
43+
44+
# Environments
45+
.env
46+
.venv
47+
env/
48+
venv/
49+
ENV/
50+
env.bak/
51+
venv.bak/
52+
53+
# IDE
54+
.vscode/
55+
.cursor/
56+
.idea/
57+
*.swp
58+
*.swo
59+
*~
60+
61+
# OS
62+
.DS_Store
63+
.DS_Store?
64+
._*
65+
.Spotlight-V100
66+
.Trashes
67+
ehthumbs.db
68+
Thumbs.db
69+
70+
# Logs
71+
*.log
72+
73+
# Temporary files
74+
*.tmp
75+
*.temp

โ€Žgetcloser/LICENSEโ€Ž

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 ๊ฐ€์งœ์—ฐ๊ตฌ์†Œ (Pseudo Lab)
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
FROM python:3.10-slim
2+
3+
WORKDIR /app
4+
5+
# ์‹œ์Šคํ…œ ์˜์กด์„ฑ ์„ค์น˜
6+
RUN apt-get update && apt-get install -y build-essential libpq-dev gcc --no-install-recommends && rm -rf /var/lib/apt/lists/*
7+
8+
COPY requirements.txt .
9+
RUN pip install --no-cache-dir -r requirements.txt
10+
11+
COPY ./app .
12+
13+
EXPOSE 8000
14+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM python:3.10-slim
2+
3+
WORKDIR /app
4+
5+
# ์‹œ์Šคํ…œ ์˜์กด์„ฑ ์„ค์น˜
6+
RUN apt-get update && apt-get install -y build-essential libpq-dev gcc --no-install-recommends && rm -rf /var/lib/apt/lists/*
7+
8+
COPY requirements.txt .
9+
RUN pip install --no-cache-dir -r requirements.txt
10+
RUN pip install --no-cache-dir uvicorn[standard] debugpy watchdog
11+
12+
COPY ./app .
13+
14+
EXPOSE 8000 5678
15+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
2+
### Backend ์„œ๋ฒ„ ์„ธํŒ…
3+
1. docker ์„ค์น˜
4+
2. ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ(`getcloser/`)์—์„œ ๋„์ปค ๋นŒ๋“œ ๋ฐ ์‹คํ–‰: `docker compose up --build`
5+
6+
3. API ๋ฌธ์„œ:
7+
`http://localhost:${BACKEND_PORT:-8000}/docs`
8+
9+
4. ์ดˆ๊ธฐ ๊ตฌ์„ฑ:
10+
- FastAPI ๊ธฐ๋ฐ˜ REST API ์„œ๋ฒ„
11+
- PostgreSQL (Docker) ์—ฐ๊ฒฐ ๋ฐ SQLAlchemy ์ง€์›
12+
- `/test/ping_db` ์—”๋“œํฌ์ธํŠธ๋กœ DB ์—ฐ๊ฒฐ ์ƒํƒœ ํ™•์ธ
13+
- `/health` ํ—ฌ์Šค์ฒดํฌ, `/` ๋ฃจํŠธ ์ƒํƒœ ์‘๋‹ต
14+
15+
16+
### ์‹คํ–‰ ์ „ ์ค€๋น„ (.env)
17+
`getcloser/` ๋ฃจํŠธ์— ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•œ `.env` ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์„ธ์š”. ์—†์œผ๋ฉด ์ผ๋ถ€ ๊ธฐ๋ณธ๊ฐ’์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.
18+
19+
์˜ˆ์‹œ:
20+
```
21+
# ์„œ๋ฒ„
22+
BACKEND_PORT=8000
23+
CORS_ORIGINS=http://localhost:5173
24+
25+
# Postgres (docker-compose์˜ db ์„œ๋น„์Šค์™€ ์ผ์น˜)
26+
DB_USER=app_user
27+
DB_PASSWORD=app_password
28+
DB_DATABASE=app_db
29+
30+
# ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ค์ •
31+
SECRET_KEY=secret_key
32+
ACCESS_TOKEN_EXPIRE_MINUTES=60
33+
34+
# ์„ ํƒ: ์ง์ ‘ ์—ฐ๊ฒฐ๋ฌธ์ž์—ด์„ ์“ฐ๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜๋กœ ๋ฎ์–ด์“ฐ๊ธฐ
35+
# DATABASE_URL=postgresql+psycopg2://app_user:app_password@db:5432/app_db
36+
```
37+
38+
### ์‹คํ–‰ ๋ฐฉ๋ฒ•
39+
ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ(`getcloser/`)์—์„œ ์•„๋ž˜ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜์„ธ์š”.
40+
41+
```
42+
docker compose up --build
43+
```
44+
45+
์ •์ƒ ์‹คํ–‰ ์‹œ:
46+
- ๋ฐฑ์—”๋“œ: `http://localhost:${BACKEND_PORT:-8000}`
47+
- ๋ฌธ์„œ: `http://localhost:${BACKEND_PORT:-8000}/docs`
48+
- DB๋Š” ๋‚ด๋ถ€ ๋„คํŠธ์›Œํฌ์—์„œ ํ˜ธ์ŠคํŠธ๋ช… `db`, ํฌํŠธ `5432`๋กœ ์ ‘๊ทผํ•ฉ๋‹ˆ๋‹ค.
49+
50+
51+
### ์œ ์šฉํ•œ ์—”๋“œํฌ์ธํŠธ
52+
- `/` : ์„œ๋ฒ„ ์ƒํƒœ
53+
- `/health` : ํ—ฌ์Šค ์ฒดํฌ
54+
- `/test/ping_db` : DB ์—ฐ๊ฒฐ ํ™•์ธ (SELECT 1)
55+
56+
57+
### Backend ํด๋” ๊ตฌ์กฐ
58+
```
59+
.
60+
โ”œโ”€โ”€ Dockerfile
61+
โ”œโ”€โ”€ README.md
62+
โ””โ”€โ”€ src
63+
โ”œโ”€โ”€ __init__.py
64+
โ”œโ”€โ”€ assets
65+
โ”œโ”€โ”€ config.py
66+
โ”œโ”€โ”€ database.py
67+
โ”œโ”€โ”€ main.py
68+
โ”œโ”€โ”€ models
69+
โ”œโ”€โ”€ requirements.txt
70+
โ”œโ”€โ”€ routers
71+
โ”‚ โ””โ”€โ”€ test_db.py
72+
โ”œโ”€โ”€ services
73+
โ””โ”€โ”€ utils
74+
```
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from api.v1.users import users
2+
from api.v1.challenge import assign_challenge
3+
from api.v1.teams import teams
4+
from fastapi import APIRouter
5+
6+
api_router = APIRouter()
7+
api_router.include_router(users.router, prefix="/users", tags=["users"])
8+
api_router.include_router(assign_challenge.router, prefix="/challenge", tags=["challenge"])
9+
api_router.include_router(teams.router, prefix="/teams", tags=["teams"])
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from fastapi import APIRouter, HTTPException, Depends
2+
from sqlalchemy.orm import Session
3+
from schemas.challenge_schema import ChallengeRequest, ChallengeResponse
4+
from services.challenge_service import assign_challenges_logic
5+
from services.user_service import parse_user_id
6+
from core.database import get_db
7+
8+
router = APIRouter()
9+
10+
@router.post("/assign-challenges", response_model=ChallengeResponse)
11+
def assign_challenges(request: ChallengeRequest, db: Session = Depends(get_db)):
12+
try:
13+
# my_id = parse_user_id(request.my_id).get("id")
14+
# if not my_id:
15+
# raise HTTPException(status_code=400, detail="์˜ฌ๋ฐ”๋ฅธ ํ˜•์‹์˜ ์œ ์ € ํƒœ๊ทธ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์˜ˆ: ๊น€๋ฏผ์ค€#0001")
16+
17+
# members_ids = [request.my_id] # ํŒ€์›์— ์ž๊ธฐ ์ž์‹  ํฌํ•จ
18+
# for tag in request.members_ids:
19+
# parsed = parse_user_id(tag)
20+
# if "error" in parsed:
21+
# raise HTTPException(status_code=400, detail=parsed["error"])
22+
# members_ids.append(parsed["id"])
23+
24+
members_ids = [request.my_id] + request.members_ids
25+
assigned = assign_challenges_logic(request.my_id, members_ids, db)
26+
return ChallengeResponse(team_id=request.team_id, my_assigned=assigned)
27+
28+
except ValueError as e:
29+
raise HTTPException(status_code=400, detail=str(e))

0 commit comments

Comments
ย (0)