《持续交付》读后:CI/CD不是口号,是每天都能上线的底气

写在前面

大三这年,我同时维护着好几个项目:灵山胜境AI数字人导游、销售生产ERP系统、HomeBox库存管理……每过一个迭代,最怕的就是"上线"这个动作本身。

《持续交付》(Continuous Delivery,Jez Humble & David Farley 著)这本书,让我意识到:部署不应该是一场冒险,而应该是日常工作的一部分。


一、什么是"持续交付"?

很多人把持续交付等同于"有CI流水线"。书里给了一个更严格的定义:

持续交付,是让软件随时可以安全、低风险地发布到生产环境的一种能力。

注意关键词:随时安全低风险

不是"我有Jenkins在跑",而是"每次提交都能自动走到一个可发布的状态"——这才是持续交付。


二、最戳我的几个观点

1. "部署"和"发布"是两件事

这本书最让我醍醐灌顶的区分:

概念 含义
部署(Deploy) 把软件放到某个环境(测试/预发/生产)
发布(Release) 让用户看到新版本

部署是技术动作,发布是业务决策。

这意味着:你可以频繁部署到生产环境,但通过一个开关(Feature Flag)控制用户是否看到——这就是"暗发布"(Dark Launching)。

在ERP系统的飞书机器人模块里,我把DeepSeek调用链路做了开关化:

# erp/config.py
FEATURE_DEEPSEEK_QA = os.getenv("FEATURE_DEEPSEEK_QA", "enabled")

# erp/feishu_handler.py
def handle_message(event):
    if current_app.config["FEATURE_DEEPSEEK_QA"] == "enabled":
        answer = call_deepseek(event["text"])
        reply_feishu(event, answer)
    else:
        reply_feishu(event, "智能问答功能维护中,请稍后重试")

这样即使DeepSeek接口出问题,我也能秒级切回备用回复,不用回滚代码。


2. 自动化验收测试:别只测"能跑",要测"做对了"

书里强调:验收测试(Acceptance Test)验证的是"业务行为是否正确",而不只是"代码有没有报错"。

我之前写测试的习惯是:

# ❌ 以前的写法 —— 只测了"不报错"
def test_create_order():
    resp = client.post("/api/orders", json={...})
    assert resp.status_code == 200  # 只要不报错就算通过?

读完书之后,我改成:

# ✅ 改进后 —— 验证业务行为
def test_create_order_should_decrease_inventory():
    # 前置:库存有10件
    init_inventory("SKU-001", 10)

    resp = client.post("/api/orders", json={
        "sku": "SKU-001",
        "quantity": 3
    })

    assert resp.status_code == 200
    # 关键断言:库存真的减了吗?
    assert get_inventory("SKU-001") == 7
    # 关键断言:订单状态正确吗?
    assert resp.json["status"] == "PENDING"

这个转变,让我的测试从"走个过场"变成了"真正替业务逻辑把关"。


3. 流水线即文档

书里有一句话我记在笔记本上:

"如果你的交付流程只在某个人脑子里,那它就是坏的。"

我把这条原则用到了ERP系统的CI流水线上。以前部署要靠嘴说:"先跑数据库迁移,再重启Node服务,最后清Redis缓存"——现在这些步骤全部写在 .github/workflows/deploy.yml 里,新人来了照着跑就行。

# .github/workflows/deploy.yml(简化版)
name: Deploy ERP

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run tests
        run: |
          cd server && ./mvnw test
          cd node-service && npm test

  deploy:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to staging
        run: |
          ssh deploy@erp-server "cd /opt/erp && git pull && docker compose up -d"
      - name: Smoke test
        run: |
          curl -f http://erp-staging/api/health || exit 1

三、落地时的真实阻碍

道理都懂,落地时还是有一堆坑:

阻碍1:数据库迁移的恐惧

每次 ALTER TABLE 都让人紧张。书里给的方案是:让每次迁移都是可回滚的,并且先在生产环境的只读副本上验证。

我现在用的策略是:迁移脚本永远写成双向的:

-- V3__add_erp_order_index.sql
-- 升级
CREATE INDEX idx_order_created_at ON erp_order(created_at DESC);

-- 回滚(写在另一个文件里)
DROP INDEX idx_order_created_at ON erp_order;

阻碍2:测试环境≠生产环境

书里反复强调:如果你的测试环境和生产环境不一样,那你测了个寂寞。

我们测试环境用的是H2内存数据库,生产用的是MySQL 8.0——结果SQL方言差异导致上线翻车过两次。后来测试环境也换成了MySQL容器,虽然慢一点,但值得。


四、对我们学生的意义

有人会说:"持续交付是大厂的东西,学生项目用不上。"

我不这么看。

学生项目恰恰是最适合练持续交付的场景——因为没有历史包袱,可以从第一天就养成好习惯:

  1. 每次提交都触发自动化测试
  2. main 分支永远处于可部署状态
  3. 部署步骤全部写成代码,不靠"经验"

等大四实习、校招面试的时候,你能说"我有个项目从零开始就做到了持续交付"——这比"我会Spring Boot"值钱多了。


五、总结

《持续交付》不是一本"看完就能上手"的工具书,它更像是一本软件工程世界观的重建指南

它让我明白:

  • 部署频繁 = 风险低(每次变更小,出问题好定位)
  • 手动步骤 = bug的温床(能自动化的坚决不手动)
  • 流水线即信心(看着绿灯亮起,是一种踏实的快乐)

如果你也在管多个项目、也在为"上线焦虑",这本书值得翻一翻。不用全看完,把自动化验收测试流水线设计这两章先读了,就能有不少收获。


以上纯粹个人读后感,不构成技术建议。如果有不同理解,欢迎博客园评论区交流 :)

posted @ 2026-07-08 15:19  C(5,3)  阅读(1)  评论(0)    收藏  举报