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
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Thumbs.db
*.log
npm-debug.log*

# Environment files (use Railway/Vercel environment variables)
# Environment files
.env
.env.*
!.env.example
Expand Down
102 changes: 102 additions & 0 deletions .github/workflows/bot-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: 🤖 Bot Build & Deploy

on:
push:
branches: [dev]
paths:
- 'packages/bot/**'
- 'packages/shared/**'
- 'packages/bot/Dockerfile'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: bot-deploy-${{ github.ref }}
cancel-in-progress: true

env:
ECR_REPOSITORY: study-admin-bot
AWS_REGION: ap-northeast-2

jobs:
ci:
name: CI Gate
runs-on: ubuntu-latest
steps:
- name: ✅ 코드 체크아웃
uses: actions/checkout@v4

- name: 📦 pnpm 설정
uses: pnpm/action-setup@v4

- name: 🟢 Node.js 설정
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'

- name: 📥 의존성 설치
run: pnpm install --frozen-lockfile

- name: 🔨 shared 빌드
run: pnpm --filter @blog-study/shared build

- name: 🔍 린트
run: pnpm --filter @blog-study/bot lint

- name: 🔎 타입 체크
run: pnpm --filter @blog-study/bot typecheck

- name: 🧪 테스트
run: pnpm --filter @blog-study/bot test

build-and-push:
name: Build and Push to ECR
needs: ci
runs-on: ubuntu-latest
steps:
- name: ✅ 코드 체크아웃
uses: actions/checkout@v4

- name: 🏗️ Docker Buildx 설정
uses: docker/setup-buildx-action@v3

- name: 🔐 AWS 자격 증명 설정
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}

- name: 🐳 ECR 로그인
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2

- name: 🐳 Docker 이미지 빌드 및 푸시 (ARM64)
uses: docker/build-push-action@v6
with:
context: .
file: ./packages/bot/Dockerfile
push: true
platforms: linux/arm64
tags: |
${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}
${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max

deploy:
name: Deploy to EC2
needs: build-and-push
runs-on: ubuntu-latest
steps:
- name: 🚀 SSH로 배포 스크립트 실행
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
~/study-admin-bot/deploy.sh ${{ github.sha }}
19 changes: 17 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@

```
packages/
├── bot/ # Discord 봇 (스케줄러 + 이벤트 핸들러만, 슬래시 커맨드 없음) → AWS EC2 배포
├── bot/ # Discord 봇 (스케줄러 + 이벤트 핸들러만, 슬래시 커맨드 없음) → AWS EC2 (Docker)
├── web/ # Next.js 16 대시보드 → Vercel 배포
└── shared/ # 공유 코드 (DB 스키마, 타입, 유틸)
deploy/
└── bot/ # EC2 배포 스크립트 (deploy.sh) — 리포에 커밋하지 않음, EC2에 직접 배치
```

**모노레포**: pnpm workspace (`pnpm-workspace.yaml`)
Expand All @@ -22,7 +24,8 @@ packages/
| Web | Next.js 16 App Router, React 19, shadcn/ui, Tailwind CSS v4, Tiptap (리치 에디터), sonner (토스트), Framer Motion (랜딩 애니메이션) |
| DB | Supabase PostgreSQL + Drizzle ORM (Transaction Pooler, `prepare: false`) |
| Auth | Supabase Auth (Discord OAuth) + `@supabase/ssr` |
| 배포 | AWS EC2 (bot), Vercel (web), Supabase (DB + Auth) |
| 배포 | AWS EC2 Docker (bot), Vercel (web), Supabase (DB + Auth) |
| CI/CD | GitHub Actions → ECR → SSH deploy (bot), Vercel Git Integration (web) |

## 개발 명령어

Expand Down Expand Up @@ -102,6 +105,9 @@ pnpm --filter @blog-study/bot rss-collect # 수동 RSS 수집 (봇 없이)
| `packages/web/src/components/landing/landing-client.tsx` | 랜딩 페이지 클라이언트 (7섹션: Hero, Stats, Bento, HowItWorks, Marquee, CTA, Footer) |
| `packages/web/src/components/landing/motion.tsx` | 랜딩 애니메이션 컴포넌트 (FadeUp, StaggerContainer, CountUp, DrawLine) |
| `packages/web/public/logo.svg` | 풀 로고 SVG (픽토그램 + 텍스트) |
| `packages/bot/Dockerfile` | 봇 Docker 이미지 (multi-stage, node:22-alpine) |
| `.github/workflows/bot-deploy.yml` | 봇 CI/CD (CI Gate → ECR 빌드/푸시 → SSH 배포) |
| `.github/workflows/ci.yml` | PR/push CI (lint, typecheck, test, build) |

## 인증 구조

Expand Down Expand Up @@ -219,6 +225,15 @@ npx drizzle-kit push --force
| `docs/plans/26-03-08-landing-page-redesign-design.md` | 랜딩 페이지 리디자인 디자인 문서 |
| `docs/plans/26-03-08-landing-page-redesign.md` | 랜딩 페이지 구현 플랜 |

## 봇 배포 (CI/CD)

- **파이프라인**: `dev` push → CI Gate (lint+typecheck+test) → ECR 빌드(ARM64) → SSH 배포
- **트리거**: `packages/bot/**`, `packages/shared/**` 변경 시 + `workflow_dispatch`
- **EC2**: illdan-mgmt (t4g ARM64), `~/study-admin-bot/deploy.sh` + `.env`
- **ECR**: `101548339709.dkr.ecr.ap-northeast-2.amazonaws.com/study-admin-bot`
- **deploy.sh**: ECR 로그인 → pull → 컨테이너 교체 → health check → Discord 웹훅 알림
- **주의**: `deploy/bot/deploy.sh`는 커밋하지 않음 (EC2에 직접 배치)

## docs 파일명 컨벤션

`yy-mm-dd-{설명}.md` — 예: `26-03-03-system-architecture.md`
Expand Down
23 changes: 19 additions & 4 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ graph TB
end
end

subgraph Bot["Discord Bot · AWS EC2"]
subgraph Bot["Discord Bot · AWS EC2 (Docker)"]
SCH["Schedulers<br/>pg-boss"]
EVT["Event Handlers<br/>discord.js v14"]
SVC["Service Layer<br/>RSS · Fine · Curation · Score"]
Expand Down Expand Up @@ -126,7 +126,7 @@ graph LR
| 패키지 | 설명 | 배포 |
|--------|------|------|
| `packages/shared` | Drizzle 스키마, 타입, 유틸 | npm (workspace 내부) |
| `packages/bot` | Discord 봇 (스케줄러 + 이벤트 핸들러, 슬래시 커맨드 없음) | AWS EC2 |
| `packages/bot` | Discord 봇 (스케줄러 + 이벤트 핸들러, 슬래시 커맨드 없음) | AWS EC2 (Docker) |
| `packages/web` | Next.js 대시보드, API Routes | Vercel |

## 인증 아키텍처
Expand Down Expand Up @@ -435,19 +435,34 @@ erDiagram

```mermaid
graph LR
subgraph GHA["GitHub Actions"]
CI["CI Gate<br/>(lint+typecheck+test)"]
ECR_PUSH["Docker Build<br/>→ ECR Push (ARM64)"]
SSH["SSH Deploy"]
end

subgraph Vercel["Vercel (ICN)"]
WEB_DEPLOY["@blog-study/web<br/>Next.js"]
end

subgraph EC2["AWS EC2"]
BOT_DEPLOY["@blog-study/bot<br/>discord.js + pm2"]
subgraph EC2["AWS EC2 (t4g)"]
BOT_DEPLOY["@blog-study/bot<br/>Docker Container"]
end

subgraph AWS["AWS"]
ECR["ECR<br/>study-admin-bot"]
end

subgraph Supabase["Supabase (ap-northeast-2)"]
PG["PostgreSQL"]
SA["Supabase Auth"]
end

CI --> ECR_PUSH
ECR_PUSH --> ECR
ECR_PUSH --> SSH
SSH --> BOT_DEPLOY
BOT_DEPLOY -->|pull| ECR
WEB_DEPLOY --> PG
WEB_DEPLOY --> SA
BOT_DEPLOY --> PG
Expand Down
36 changes: 0 additions & 36 deletions packages/bot/.dockerignore

This file was deleted.

18 changes: 5 additions & 13 deletions packages/bot/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Build stage
FROM node:20-alpine AS builder
FROM node:22-alpine AS builder

# Install pnpm
RUN corepack enable && corepack prepare pnpm@9.0.0 --activate

WORKDIR /app
Expand All @@ -11,40 +10,33 @@ COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
COPY packages/shared/package.json ./packages/shared/
COPY packages/bot/package.json ./packages/bot/

# Install dependencies
RUN pnpm install --frozen-lockfile

# Copy source code
COPY tsconfig.json ./
COPY packages/shared ./packages/shared
COPY packages/bot ./packages/bot

# Build shared package first, then bot
RUN pnpm --filter @blog-study/shared build
RUN pnpm --filter @blog-study/bot build
# Build shared bot
RUN pnpm --filter @blog-study/shared build && \
pnpm --filter @blog-study/bot build

# Production stage
FROM node:20-alpine AS runner
FROM node:22-alpine AS runner

# Install pnpm
RUN corepack enable && corepack prepare pnpm@9.0.0 --activate

WORKDIR /app

# Copy workspace configuration
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
COPY packages/shared/package.json ./packages/shared/
COPY packages/bot/package.json ./packages/bot/

# Install production dependencies only
RUN pnpm install --frozen-lockfile --prod

# Copy built files
COPY --from=builder /app/packages/shared/dist ./packages/shared/dist
COPY --from=builder /app/packages/bot/dist ./packages/bot/dist

# Set environment
ENV NODE_ENV=production

# Run the bot
CMD ["node", "packages/bot/dist/index.js"]
18 changes: 0 additions & 18 deletions packages/bot/railway.json

This file was deleted.

Loading