diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..b5f9929 --- /dev/null +++ b/.env.example @@ -0,0 +1,18 @@ +# Database Configuration +# Use localhost for local 'bun run dev' +# docker-compose will override this with its own service name 'postgres' +DATABASE_URL=postgres://postgres:password@localhost:5432/alert_message_center + +# Feishu (Lark) App Configuration +# Make sure to ADD BOTH to your Feishu App Management console! +FEISHU_APP_ID=your_app_id +FEISHU_APP_SECRET=your_app_secret +FEISHU_VERIFICATION_TOKEN=your_verification_token +FEISHU_ENCRYPT_KEY=your_encrypt_key + +# Admin configuration (comma-separated emails) +ADMIN_EMAILS=admin@example.com + +# Optional: Frontend URL for CORS during local dev +FRONTEND_URL=http://localhost:3000 +REDIRECT_URI=http://localhost:3000/auth/callback \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c9c3d29 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,49 @@ +name: Build and Push Docker Images + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Server image + uses: docker/build-push-action@v5 + with: + context: . + file: apps/server/Dockerfile + push: true + tags: | + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-server:latest + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-server:${{ github.sha }} + + - name: Build and push Web image + uses: docker/build-push-action@v5 + with: + context: . + file: apps/web/Dockerfile + push: true + tags: | + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-web:latest + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-web:${{ github.sha }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3d0a432 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +# Build stage for web +FROM oven/bun:1-alpine AS web-builder +WORKDIR /app +COPY . . +RUN bun install --frozen-lockfile +WORKDIR /app/apps/web +RUN bun run build + +# Final stage +FROM oven/bun:1-alpine +WORKDIR /app + +# Copy the entire project for monorepo context +COPY . . + +# Install dependencies for the server (and shared workspace if any) +RUN bun install --frozen-lockfile + +# Copy built web assets to server's public directory +COPY --from=web-builder /app/apps/web/dist /app/apps/server/public + +WORKDIR /app/apps/server + +EXPOSE 3000 + +CMD ["bun", "run", "start"] diff --git a/README.md b/README.md index 100e977..3d8cd31 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,29 @@ cd apps/server && bun run db:push bun run dev ``` +### 3. Docker 部署 +项目支持使用 Docker Compose 快速部署: + +```bash +# 复制并填写环境变量 +cp apps/server/.env.example .env + +# 启动所有服务 (Postgres + Server + Web) +docker-compose up -d +``` + +--- + +## 🏗️ CI/CD + +项目通过 GitHub Actions 实现了自动化流水线: + +- **自动化构建**: 每次推送至 `main` 分支或提交 Pull Request 时,会自动触发 Docker 镜像构建。 +- **镜像仓库**: 构建生成的镜像会同步推送到 GitHub Container Registry (GHCR)。 +- **镜像路径**: + - `ghcr.io/${USER}/alert-message-center-server` + - `ghcr.io/${USER}/alert-message-center-web` + --- ## 📡 Webhook 使用指南 diff --git a/apps/server/package.json b/apps/server/package.json index 4cea1e7..d0f4851 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -2,7 +2,7 @@ "name": "@alertmessagecenter/server", "version": "1.0.0", "scripts": { - "dev": "bun run --watch src/index.ts", + "dev": "bun run --env-file .env --watch src/index.ts", "start": "bun run src/index.ts", "db:generate": "drizzle-kit generate", "db:migrate": "drizzle-kit migrate", diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts index 004a8bb..02751a6 100644 --- a/apps/server/src/index.ts +++ b/apps/server/src/index.ts @@ -1,5 +1,6 @@ import { Hono } from 'hono'; import { cors } from 'hono/cors'; +import { serveStatic } from 'hono/bun'; import { db } from './db'; import { topics } from './db/schema'; import webhook from './webhook'; @@ -14,14 +15,15 @@ app.use('/*', cors({ credentials: true, })); -app.get('/', (c) => { - return c.text('Alert Message Center API is running!'); -}); - +// API Routes const routes = app.route('/api/auth', auth) .route('/api', api) .route('/webhook', webhook); +// Serve static files (Frontend) +app.use('/*', serveStatic({ root: './public' })); +app.get('*', serveStatic({ path: './public/index.html' })); + app.onError((err, c) => { console.error(`[Global Error] ${c.req.method} ${c.req.url}:`, err); return c.json({ error: err.message || 'Internal Server Error' }, 500); diff --git a/apps/web/.env.example b/apps/web/.env.example new file mode 100644 index 0000000..d981975 --- /dev/null +++ b/apps/web/.env.example @@ -0,0 +1,2 @@ +# Backend API URL (for proxying) +VITE_API_URL=http://localhost:3000 diff --git a/apps/web/package.json b/apps/web/package.json index a0dd2de..ecec8bd 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "type": "module", "scripts": { - "dev": "vite", + "dev": "bun run --env-file .env vite", "build": "tsc && vite build", "preview": "vite preview" }, diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts index c3327c0..14e4692 100644 --- a/apps/web/vite.config.ts +++ b/apps/web/vite.config.ts @@ -13,11 +13,11 @@ export default defineConfig({ server: { proxy: { '/api': { - target: 'http://localhost:3000', + target: process.env.VITE_API_URL || 'http://localhost:3000', changeOrigin: true, }, '/webhook': { - target: 'http://localhost:3000', + target: process.env.VITE_API_URL || 'http://localhost:3000', changeOrigin: true, } } diff --git a/docker-compose.yml b/docker-compose.yml index b24ad5b..885d229 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,18 @@ services: + app: + build: + context: . + dockerfile: Dockerfile + ports: + - "3000:3000" + environment: + - DATABASE_URL=postgres://postgres:password@postgres:5432/alert_message_center + - FEISHU_APP_ID=${FEISHU_APP_ID} + - FEISHU_APP_SECRET=${FEISHU_APP_SECRET} + # ... other envs + depends_on: + - postgres + postgres: image: postgres:17-alpine restart: always diff --git a/docs/copilot-context.md b/docs/copilot-context.md index acb91b8..345ffd6 100644 --- a/docs/copilot-context.md +++ b/docs/copilot-context.md @@ -125,7 +125,7 @@ The database schema is defined in `apps/server/src/db/schema.ts`. - [ ] **Message Preview**: Preview Feishu card JSON in the UI. - [ ] **History/Logs**: Keep a log of sent alerts for auditing. - [ ] **Retry Mechanism**: Handle Feishu API failures. -- [ ] **Deployment**: Dockerfile and deployment scripts. +- [x] **Deployment**: Dockerfile and deployment scripts. ## 7. Development Conventions @@ -135,7 +135,8 @@ The database schema is defined in `apps/server/src/db/schema.ts`. - **Type Safety**: strict TypeScript usage. Backend and Frontend share types via Hono RPC or shared interfaces. - **Environment Variables**: - `FEISHU_APP_ID`, `FEISHU_APP_SECRET`, `REDIRECT_URI`, `ADMIN_EMAILS`. -- **Administrators**: - - Configured via the `ADMIN_EMAILS` environment variable (comma-separated list of emails). +- **CI/CD**: + - GitHub Actions automates the build and push of Docker images to GitHub Container Registry (GHCR). + - Images are built for both `apps/server` (Bun) and `apps/web` (Nginx). diff --git a/package.json b/package.json index a0d4b3c..a97bfaa 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ ], "scripts": { "dev": "bun run --filter '*' dev", - "build": "bun run --filter '*' build" + "build": "bun run --filter '*' build", + "start": "bun run --filter '@alertmessagecenter/server' start" }, "devDependencies": { "bun-types": "latest" diff --git a/todo.md b/todo.md index 9d6bbf5..353b022 100644 --- a/todo.md +++ b/todo.md @@ -21,5 +21,5 @@ - [x] **Admin Topic Management**: Approve, reject, and delete topics (with audit trail). - [x] **Personal Inbox**: Direct alert delivery bypassing topics. - [ ] **Retry Mechanism**: Handle Feishu API failures. -- [ ] **Deployment**: Dockerfile and deployment scripts. +- [x] **Deployment**: Dockerfile and CI/CD (GitHub Actions + GHCR).