
一说到 CI/CD,很多人第一反应是公司里才搞的东西,个人站用不上。我一开始也这么想,直到有一次改了个小功能,忘了跑一个检查,上线之后首页白屏了两小时才发现。从那以后我给自己搭了一套最小的流水线,不复杂,但确实少踩了很多坑。
个人站做这套东西,到底图什么
图的不是快,是稳。手工上线最容易出的问题不是慢,是漏步骤:忘了清缓存、忘了传某个文件、忘了改配置,每次漏的东西还不一样。
流水线的作用是把这些步骤固定下来,每次都按同样的顺序跑,人不用记,也就不会漏。
第二个作用是拦住低级错误。语法错误、引用了不存在的文件、配置写错,这些在本地不一定暴露,但在自动检查里一跑就露馅。
第三个作用是留痕。每次上线有记录,什么时候上的、改了什么、谁触发的,出问题能倒查。手工部署完全没有这个。
所以哪怕你只有一个站、一天改一次,这套东西也值。成本是一次性搭好,收益是长期不用为低级错误买单。
最小可用方案长什么样
别一上来就想搞完整的测试加构建加部署。个人站的最小方案只有三步:拉代码、跑一个语法检查、部署到服务器。
用 GitHub Actions 的话,一个 yaml 文件就能搞定。触发条件是 push 到 main,第一步 checkout,第二步装依赖跑检查,第三步用 ssh 连服务器执行部署脚本。
关键是第三步的连接方式。别把服务器密码明文写在配置里,用仓库的 Secrets 存一个 SSH 私钥,Action 里引用变量。私钥泄露的风险比密码小得多,而且随时可以换。
整条流程跑完一般一两分钟,比手工快不了多少,但每次都是同样的步骤,不会漏。
那个 yaml 文件具体怎么写
文件放在仓库的 .github/workflows 目录下,名字随便起,后缀是 yml。开头写触发条件,on push branches main。
然后是 jobs,定义一个 build 任务,runs-on 用 ubuntu-latest。steps 里第一段用 actions/checkout 拉代码,第二段跑你的检查命令。
第三段连服务器。用 ssh-action 这类现成的动作,把 host、username、key 从 Secrets 里读出来,command 写你要执行的部署脚本路径。
有个细节容易踩:Secrets 里的私钥要包含完整的头尾行,很多人复制的时候漏了 BEGIN 那行,连不上还找不到原因。
还有,第一次跑之前先在本地把部署脚本手工执行一遍,确认它能独立跑通。脚本本身有问题,流水线只会把问题放大。
构建产物怎么传到服务器
两种思路。一种是服务器上直接拉代码,Action 只负责触发一个远程命令,服务器自己 git pull。另一种是 Action 里构建好,把产物用 scp 或者 rsync 传上去。
前一种简单,适合纯 PHP 这类不需要编译的项目。后一种适合前端项目,本地构建出静态文件再传,服务器上不用装 node。
传文件用 rsync 比 scp 好,它只传改动的部分,第二次部署往往几秒钟就完。命令里加 -avz 和 --delete,注意 --delete 会删目标端多余的文件,第一次先加 dry-run 看看。
如果产物里有需要在服务器上生成的东西,比如缓存目录、日志目录,把它们加到 rsync 的排除列表,不然每次部署都被清掉。
自动化测试别做过头
个人站没必要追求覆盖率。写几个关键的检查就够:语法能不能过、关键页面能不能打开、配置文件有没有语法错误。
最实用的一个检查是跑一遍静态分析。PHP 用 php -l 检查语法,Python 用 py_compile,前端用构建命令。这些命令跑起来几秒钟,能拦住八成的低级错误。
再进一步可以加一个冒烟测试:部署完之后 curl 首页和两个关键页面,返回码不是 200 就当失败。这一步能立刻发现白屏。
别去写单元测试覆盖业务逻辑,个人站代码变得快,测试维护成本比收益高。把力气花在冒烟测试上更划算。
失败了要能知道
流水线最怕的是静默失败。跑失败了没人管,你以为部署成功,实际线上还是旧版本。
GitHub Actions 默认会给仓库管理员发邮件,但邮件容易被忽略。建议加一个通知步骤,失败时往你的微信或者钉钉推一条消息,用 webhook 就行。
更重要的是一条:部署失败时不要留下半成品。部署脚本要设计成失败就停在旧版本,别出现文件传了一半的情况。rsync 天然满足这点,它先传临时文件再替换。
如果部署脚本里包含清缓存、重启服务这类步骤,把它们放在最后,前面任何一步失败都不执行,避免出现清了缓存但代码没更新的尴尬状态。
搭好之后怎么维护
流水线不是搭完就一劳永逸。服务器换 IP、密钥轮换、依赖升级,任何一样变了都可能让它跑不起来。
最简单的维护办法是每个月看一次最近的执行记录。连续成功说明一切正常,出现零星失败要顺手修掉,别等到彻底坏了才发现。
密钥这一类东西建议半年换一次。换的时候不要直接删旧的,先把新的加到 Secrets 里,跑一次成功之后再删旧值,中间不会断。
还有,Action 里引用到的第三方动作都是别人维护的,版本会变。写死主版本号,不要用 latest,某天作者改了接口你的流水线就会突然挂掉。
最后留一条保底手段:万一流水线彻底坏掉,你还能手工上线。所以手工部署的步骤要写成文档,别只存在于脑子里。
什么情况下别折腾这套
如果你的站一年改不了几次,搭流水线的时间比省下的时间还多,那就别搭。手工部署加上一份 checklist,一样能稳。
如果服务器网络很差、经常连不上,自动部署反而更麻烦,因为失败了你不知道是网络问题还是代码问题。
还有,如果你的部署涉及大量手工操作,比如要改数据库、要动配置、要重启好几个服务,这套简单的流水线覆盖不了,硬套只会出更多问题。这种场景老老实实按步骤来,写成文档照着做更靠谱。
