数据库迁移: - SQLite → MySQL (mysql-8351f937d637-public.rds.volces.com) - Schema 从 drizzle-orm/sqlite-core 改为 drizzle-orm/mysql-core - 全量数据迁移完成(13 张表 525 条记录) CI/CD 流水线: - .gitea/workflows/deploy.yaml(airlabs 分支触发) - 前后端分别构建镜像推到火山引擎 CR internal 命名空间 - 自动部署到内部 K3s 集群 K8s 配置: - backend-deployment.yaml(Bun 3200 端口 + MySQL 私网连接) - web-deployment.yaml(Nginx 80 端口 + SPA fallback) - backend-ingress.yaml(devperf-api.airlabs.art + TLS) - web-ingress.yaml(devperf.airlabs.art + TLS) - cert-manager-issuer.yaml(Let's Encrypt) 其他: - 前端 Dockerfile 支持 VITE_API_BASE_URL 构建参数 - 后端 Dockerfile 改为直接运行源码(兼容 mysql2) - 侧边栏/全局样式优化 + Git 图表修复 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
42 lines
1.4 KiB
TypeScript
42 lines
1.4 KiB
TypeScript
import { z } from 'zod';
|
|
|
|
const envSchema = z.object({
|
|
JWT_SECRET: z.string().min(16, 'JWT_SECRET must be at least 16 characters'),
|
|
PORT: z.coerce.number().default(3200),
|
|
|
|
MYSQL_HOST: z.string().default('localhost'),
|
|
MYSQL_PORT: z.coerce.number().default(3306),
|
|
MYSQL_USER: z.string().default('root'),
|
|
MYSQL_PASSWORD: z.string().default(''),
|
|
MYSQL_DATABASE: z.string().default('devperf'),
|
|
|
|
PLANE_BASE_URL: z.string().url().default('http://plane-api:8000'),
|
|
PLANE_API_TOKEN: z.string().default(''),
|
|
PLANE_WORKSPACE_SLUG: z.string().default('jasonqiyuan'),
|
|
|
|
GITEA_BASE_URL: z.string().url().default('http://gitea:3000'),
|
|
GITEA_API_TOKEN: z.string().default(''),
|
|
GITEA_ORG: z.string().default('jasonqiyuan'),
|
|
|
|
SYNC_PLANE_INTERVAL: z.coerce.number().default(15),
|
|
SYNC_GITEA_INTERVAL: z.coerce.number().default(30),
|
|
|
|
ADMIN_EMAIL: z.string().email().default('admin@jasonqiyuan.com'),
|
|
ADMIN_PASSWORD: z.string().min(6).default('Admin123!'),
|
|
});
|
|
|
|
function loadConfig() {
|
|
const result = envSchema.safeParse(process.env);
|
|
if (!result.success) {
|
|
const missing = result.error.issues.map(
|
|
(i) => ` ${i.path.join('.')}: ${i.message}`
|
|
);
|
|
console.error('Environment validation failed:\n' + missing.join('\n'));
|
|
process.exit(1);
|
|
}
|
|
return result.data;
|
|
}
|
|
|
|
export const config = loadConfig();
|
|
export type Config = z.infer<typeof envSchema>;
|