描述符 schema 解耦框架 — 为什么 6 字段就够了
UniversalAppDescriptor 6 字段(runtime / build / start / env / pre_deploy / health),不依赖任何具体框架。扫描器、改写器、部署 agent 三方都只看描述符。
做工具最大的诱惑是 — 「我们再加一个字段处理这个特殊情况」。下面是我们设计 UniversalAppDescriptor 时刻意抵制的几个诱惑。
6 字段够了
schema_version: '1.0'
runtime: node # 大类
build: # 编译命令
install: npm install
command: npm run build
start: # 启动 + 健康检查
command: npm start
port: 3000
health_path: /healthz
env: # 环境变量约定
required_keys: [DATABASE_URL]
defaults: { NODE_ENV: production }
pre_deploy: [] # 数据库迁移等
health: {} # 健康检查策略 (Phase 2)诱惑 1:加 framework 字段
"runtime 太粗,加个 framework=nextjs 不就清楚了吗?" 不行。因为 framework 列表会一直变,而我们的代码(扫描器 / 改写器 / 部署 agent)只能识别一个固定有限的 framework 集合。一旦 framework 字段进 schema,所有代码都得知道每个 framework 长什么样。
替代:framework 信息塞进 detected_stack 字段(scanner 给 UI 用,改写器不读)。改写器只看 runtime+start+build,与 framework 解耦。
诱惑 2:加 deploy_strategy 字段
"用户可能要蓝绿、金丝雀、滚动 — 加个 strategy 字段吧?" 不行。因为 strategy 是 Update 流程的事,不是描述符的事。描述符描述「这个应用长什么样」,不描述「怎么上它」。
诱惑 3:加 dependencies 字段
"应用可能依赖 redis / postgres / kafka,加个 dependencies 列表吧?" 不行。因为依赖配置本来就是 env 字段的工作 — DATABASE_URL=postgres://... / REDIS_URL=redis://...。扫描器不知道你用的是哪个数据库,只知道你需要 DATABASE_URL。
改写器为什么能用同一描述符服务所有 node 项目
因为 node runtime + npm start + port 3000 这三个字段,无论你用 Next.js 还是 Nuxt 还是 Vanilla Express,改写器吐的产物完全一样:.env.production + pm2 ecosystem + nginx vhost。
// pm2 ecosystem.config.js — 改写器从描述符生成
module.exports = {
apps: [{
name: '<%= project_slug %>',
cwd: '<%= server_app_root %>',
script: 'npm',
args: 'start', // 来自 descriptor.start.command
env: { NODE_ENV: 'production' },
instances: 1,
autorestart: true,
}]
};演进策略
v1.0 6 字段就够了。如果未来真需要加,加之前先问:能不能塞进现有字段?如果不能再加,而且要在 schema_version 升 v2.0 时做。永远不要在 v1.x 内悄悄加字段 — 这会破坏向后兼容。
schema 不是越多字段越好,而是越少越好。少 = 易于实现、易于演进、易于约定。