先说结论
一个人维护的产品,发布流程必须"一条命令、可重复、可回滚"。手工打包一定会漏文件。
版本号只有一个来源
VERSION 文件是唯一真相。安装器、健康检查、构建脚本都从它读。
VERSION → 2.0.0
Install::version() → 读 VERSION
build.ps1 → 读 VERSION
改版本只改一个文件,避免"代码是 1.3.0,包里写 1.2.7"。
构建产物就是上传目录
dist/
├── app/
├── public_html/ ← Web 根目录
├── vendor/
├── writable/
├── spark
├── .env
├── VERSION
└── docs/
客户拿到 dist 的内容,直接整个上传,不用理解目录结构。
构建时清理什么
writable/cache/*writable/logs/*writable/session/*install.lock- 开发期的上传文件
.git、node_modules、测试脚本
清理后做完整性校验:关键文件存在、VERSION 一致、没有残留的开发配置。
为什么不用 CI/CD
客户环境不可控:有的在共享主机,有的在内网,有的连 Git 都没有。发布包是唯一可靠的交付物。
CI 可以做(跑测试、生成 dist),但"交付"这一步永远是压缩包 + FTP/SFTP。
升级怎么做
- 备份数据库与 uploads
- 覆盖文件(保留 .env 与 writable/uploads)
- 跑
php spark migrate - 清缓存
- 访问
/health确认
一次构建约 60–90 秒;完整升级(备份 + 覆盖 + 迁移 + 清缓存)15–25 分钟。一年发了 20 多个版本,真正回滚过 2 次,都是迁移脚本写错——所以现在升级前必须先备份数据库。