过去三年,对CI/CD自动化的关注持续增长,2025年单年"CI/CD流水线配置"的搜索量就增加了34%。尽管如此,英国大多数开发机构仍然通过手动SSH会话或临时脚本进行部署。这一差距代表着显著的竞争劣势:拥有成熟CI/CD流水线的团队发布频率大约高出五倍,并且能在修复成本比部署后补救便宜十倍的阶段发现缺陷。
本指南涵盖了2026年英国开发团队建立CI/CD流水线的实际情况:选择平台、正确构建流水线阶段、集成安全扫描,以及处理在生产环境中真正有效的部署策略。
摘要
- CI自动构建和测试每次提交;CD在没有人工干预的情况下将经过验证的代码交付到暂存或生产环境
- GitHub Actions是2026年大多数英国团队的正确默认选择;如果需要自托管运行器或更强的审计控制,GitLab CI是更好的选择
- 生产就绪的流水线从构建到部署后监控有十一个阶段,而不仅仅是构建和测试
- 安全扫描属于流水线内部,而不是事后添加:SAST、依赖项审计和密钥扫描应在每次拉取请求时运行
CI/CD实际上是什么
这个术语使用得比较宽泛,因此值得精确定义。持续集成(CI)意味着对共享分支的每次提交都会触发一个自动化序列:在接受更改之前,代码会被构建、lint检查和测试。目标是在上下文还新鲜时立即发现集成问题,而不是在sprint结束时合并一周的分歧分支时才发现。
持续交付(CD)扩展了这种自动化,使经过验证的代码可以以最少或零手动步骤发布到暂存或生产环境。持续部署(更强的版本)意味着每条成功的流水线都会自动部署到生产环境。大多数团队从持续交付开始,在生产部署前添加人工审批门,并在对测试覆盖率和回滚机制有足够信心后转向完整的持续部署。
实际结果是,CI/CD将部署从高度紧张的多小时事件转变为每周发生数十次的常规后台流程。
选择平台
平台选择很重要,但不是永久性的。如果需要,以后再迁移,但现在为你的具体情况选择正确的默认值:
GitHub Actions 是2026年大多数英国开发团队启动新项目的正确选择。它与GitHub深度集成,拥有最大的可重用action生态系统,公共仓库有慷慨的免费时间,以及文档完善的配置格式。托管的运行器涵盖Linux、Windows和macOS。对于已经在GitHub上的团队来说,最小阻力路径的优势是真实存在的。
GitLab CI 是更好的选择,如果你需要自托管运行器(出于监管原因或访问私有网络资源)、更强的审计日志,或者你的团队更希望有一个用于源代码控制、CI、容器注册表和部署的单一平台。GitLab的.gitlab-ci.yml格式成熟且广为人知。
CircleCI 具有强大的并行性和Docker支持,其配置易于阅读。它是GitHub Actions之前的市场领导者,许多英国机构仍在使用它。如果现有的CircleCI配置运行良好,没有紧迫理由迁移。
Jenkins 是遗留系统。它可以运行,许多大型组织成功运营它,但对于2026年的新项目,维护Jenkins服务器的运营开销不值得。如果你继承了Jenkins,在长期承诺之前评估迁移成本。
Bitbucket Pipelines 在你的团队嵌入Atlassian堆栈且无法更改源代码控制时可以接受。功能集落后于GitHub Actions,但涵盖了基础功能。
流水线阶段:应包含什么以及原因
完整的生产就绪流水线比大多数教程涵盖的阶段更多。以下是每个阶段背后推理的完整序列:
阶段1:构建
编译或转译源码,安装依赖项,并生成构建产物。对于Node.js项目,这意味着npm ci(不是npm install,因为ci精确使用锁文件)和你的构建步骤。对于Python服务,这意味着创建虚拟环境并从requirements.txt安装。输出是版本化的产物:编译的二进制文件、转译的JS包或wheel文件。
在这里积极缓存你的依赖项。以package-lock.json为键的缓存与npm ci配合意味着未更改依赖项的后续流水线运行完全跳过下载。
阶段2:Lint和静态分析
ESLint、flake8、mypy、严格模式下的Pylance,或适合你语言的等价工具。这个阶段很快,通常在30秒以内,并在测试运行之前捕获大量问题。静态类型检查(Python的mypy,JS/TS的TypeScript tsc --noEmit)对于捕获单元测试经常遗漏的接口不匹配特别有价值。
在这里快速失败。如果代码不通过lint,就没有必要运行十分钟的测试套件。
阶段3:单元测试
运行你的单元测试套件。单元测试应该快速。如果完整的单元测试运行超过五分钟,拆分套件或调查原因。在测试运行器支持的地方跨测试文件并行化(Jest关闭--runInBand,Python使用pytest-xdist)。
关键点:单元测试对外部服务使用mock。CI环境在此阶段不应有真实的数据库凭据或外部API密钥。
阶段4:集成测试
集成测试针对真实服务运行:测试数据库、Redis实例、本地消息队列。大多数CI平台为此支持服务容器。在GitHub Actions中,你在作业旁边声明一个services块,在测试运行期间启动PostgreSQL或MySQL容器。
这是捕获单元测试遗漏的错误的阶段:语义错误的ORM查询、事务隔离问题、外键约束失败。针对真实数据库运行集成测试,而不是mock。
阶段5:安全扫描
安全扫描属于流水线,而不是季度计划扫描。这个阶段有三个组成部分:
SAST(静态应用程序安全测试)。 Semgrep是多语言团队最实用的选择;它有Python、JavaScript、TypeScript、Go、Java等的规则。特别针对Python,Bandit捕获常见的安全反模式。GitHub的CodeQL对公共仓库免费,捕获与模式匹配工具不同类别的漏洞。每次拉取请求至少运行其中一个。
依赖项审计。 Node.js项目使用npm audit --audit-level=high,Python使用pip-audit。这些工具根据OSV(开源漏洞)数据库检查你安装的依赖项。高危和严重发现时阻止流水线;中等发现标记供人工审查而不是阻止。
密钥扫描。 Gitleaks扫描提交历史记录中意外提交的凭据、API密钥和令牌。这是密钥到达远程之前的最后一道防线。GitHub内置的密钥扫描也值得启用,但流水线中的Gitleaks在推送之前而不是之后捕获问题。
阶段6:构建和推送Docker镜像
如果你的部署目标是容器,在这里构建Docker镜像并推送到你的注册表。用提交SHA标记,而不仅仅是latest。不可变标签意味着你始终可以准确识别哪个提交在生产环境中运行。推送到GitHub Container Registry(ghcr.io)、AWS ECR或你选择的注册表。
在推送之前对已构建的镜像运行容器镜像扫描(Trivy或Grype)。这会捕获依赖项审计遗漏的基础镜像中的操作系统级CVE。
阶段7:部署到暂存环境
将经过验证的产物部署到反映生产环境的暂存环境。基础设施即代码(Terraform、Pulumi)意味着你的暂存环境与生产环境定义相同。部署步骤应该是幂等的:运行两次不应导致问题。
阶段8:针对暂存环境的冒烟测试
部署到暂存环境后,运行最小的端到端检查:应用程序能启动吗,健康端点是否返回200,基本登录流程是否有效?这些测试应在两分钟内运行。目标不是全面覆盖,而是捕获隔离测试不会捕获的部署失败。
阶段9:人工审批门
在部署到生产环境之前,暂停等待人工审批。在GitHub Actions中,这是一个带有必需审阅者的环境保护规则。在GitLab CI中,这是一个手动作业触发器。这个门应该是轻量级的:一个审阅者确认暂存环境看起来正确,而不是漫长的签字流程。
对于向持续部署迈进的团队,一旦部署频率和测试覆盖率足够高,就可以自动化这个门,但从有门开始是更安全的默认值。
阶段10:部署到生产环境
与暂存环境相同的部署步骤,指向生产环境。有了以提交SHA标记的不可变产物,生产部署是确定性的。
阶段11:部署后监控检查
生产部署后,流水线应验证监控是否正常:错误率没有升高,健康端点正在响应,没有延迟峰值。对可观测性平台(Datadog、Grafana或甚至基本HTTP健康检查)的简单检查为你提供自动化信号,表明部署成功或触发回滚的警报。
实际的GitHub Actions配置
以下是Node.js应用程序的简化但实际的流水线结构:
1name: CI/CD Pipeline
2
3on:
4 push:
5 branches: [main, develop]
6 pull_request:
7 branches: [main]
8
9jobs:
10 build-and-lint:
11 runs-on: ubuntu-latest
12 steps:
13 - uses: actions/checkout@v4
14 - uses: actions/setup-node@v4
15 with:
16 node-version: '20'
17 cache: 'npm'
18 - run: npm ci
19 - run: npm run lint
20 - run: npx tsc --noEmit
21
22 unit-tests:
23 needs: build-and-lint
24 runs-on: ubuntu-latest
25 steps:
26 - uses: actions/checkout@v4
27 - uses: actions/setup-node@v4
28 with:
29 node-version: '20'
30 cache: 'npm'
31 - run: npm ci
32 - run: npm test -- --coverage
33
34 integration-tests:
35 needs: build-and-lint
36 runs-on: ubuntu-latest
37 services:
38 postgres:
39 image: postgres:16
40 env:
41 POSTGRES_PASSWORD: testpass
42 POSTGRES_DB: testdb
43 options: >-
44 --health-cmd pg_isready
45 --health-interval 10s
46 --health-timeout 5s
47 --health-retries 5
48 steps:
49 - uses: actions/checkout@v4
50 - uses: actions/setup-node@v4
51 with:
52 node-version: '20'
53 cache: 'npm'
54 - run: npm ci
55 - run: npm run test:integration
56 env:
57 DATABASE_URL: postgres://postgres:testpass@localhost:5432/testdb
58
59 security-scan:
60 needs: build-and-lint
61 runs-on: ubuntu-latest
62 steps:
63 - uses: actions/checkout@v4
64 with:
65 fetch-depth: 0
66 - uses: actions/setup-node@v4
67 with:
68 node-version: '20'
69 cache: 'npm'
70 - run: npm ci
71 - run: npm audit --audit-level=high
72 - uses: semgrep/semgrep-action@v1
73 - name: Run Gitleaks
74 uses: gitleaks/gitleaks-action@v2
75
76 deploy-staging:
77 needs: [unit-tests, integration-tests, security-scan]
78 runs-on: ubuntu-latest
79 environment: staging
80 if: github.ref == 'refs/heads/main'
81 steps:
82 - uses: actions/checkout@v4
83 - name: Deploy to staging
84 run: ./scripts/deploy.sh staging
85
86 deploy-production:
87 needs: deploy-staging
88 runs-on: ubuntu-latest
89 environment: production
90 steps:
91 - uses: actions/checkout@v4
92 - name: Deploy to production
93 run: ./scripts/deploy.sh production
unit-tests、integration-tests和security-scan作业在build-and-lint作业通过后并行运行。这种结构在不牺牲覆盖率的情况下减少了总流水线时间。
部署策略
如何部署与是否部署同等重要。三种策略涵盖了大多数英国团队的需求:
滚动部署。 逐一替换实例。使用大多数编排器(Kubernetes、ECS)实现简单。风险:如果新版本有缺陷,在发布窗口期间部分用户访问旧实例,部分用户访问新实例。对低流量应用程序来说是很好的默认选择。
蓝绿部署。 维护两个相同的生产环境。流量从蓝色原子性地切换到绿色。如果新版本有缺陷,在几秒钟内切换回来。代价是同时运行两个环境,对于数据库来说这不是小事。最适合停机不可接受且回滚速度至关重要的应用程序。
金丝雀发布。 将一小部分流量(5%或10%)路由到新版本,在定义的时间段内观察错误率和性能,然后将金丝雀提升到100%。对于想要在完整推出之前获得真实生产反馈的高流量应用程序来说非常出色。需要你的负载均衡器或服务网格支持流量分割。
大多数英国团队应该从滚动部署开始,在流量和关键性证明合理时添加蓝绿,并在每天多次发布且每一步都需要经过验证的生产反馈时考虑金丝雀发布。
密钥管理
密钥不属于代码、配置文件或提交到源代码控制的环境特定.env文件。正确的方法:
GitHub Secrets / GitLab CI变量 用于流水线作业需要的密钥。这些在静止时加密,在日志中被屏蔽,并通过环境变量对作业可用。
环境特定的密钥 在部署目标级别配置:AWS Parameter Store、Azure Key Vault、Google Secret Manager,或对于需求更复杂的团队使用HashiCorp Vault。应用程序在启动时从密钥存储读取密钥,而不是从通过流水线传递的环境变量读取。
轮换。 API密钥、数据库密码和服务凭据应按计划轮换。CI/CD流水线使轮换更容易,因为在一个地方(密钥存储或CI环境)更新密钥会在下次部署时自动传播。
流水线中的Gitleaks是当开发人员意外提交密钥时的安全网。已提交密钥的补救措施是立即使其无效,然后清理git历史;Gitleaks警报告诉你这个过程现在就需要开始,而不是等到有人利用它时。
流水线性能
慢流水线是被忽视的流水线。如果开发人员等待十五分钟才能获得每次推送的反馈,他们就会停止推送小提交并开始批处理工作,这违背了CI的目的。
保持流水线快速的实用步骤:
缓存依赖项安装。对于npm,将缓存键设置为package-lock.json。对于pip,使用以requirements.txt为键的pip缓存action。热缓存将两分钟的安装变成五秒的恢复。
并行运行独立作业。构建、lint、单元测试、集成测试和安全扫描并不都相互依赖。结构良好的流水线在公共构建步骤之后将它们作为并行作业运行,显著减少总的挂钟时间。
使用路径过滤器。如果你有包含多个服务的monorepo,只在服务目录中的文件更改时触发相关的流水线阶段。GitHub Actions支持推送触发器上的paths过滤器。
设置超时。卡住的作业不应在默认的六小时超时内占用运行器。为每个阶段设置适当的作业级超时:lint五分钟,单元测试十五分钟,集成测试三十分钟。
关键要点
- CI/CD将部署从高风险事件转变为常规自动化流程;大多数英国团队最大的瓶颈不是工具,而是根本没有结构化的流水线。
- GitHub Actions是新项目的正确起点;GitLab CI适用于需要自托管运行器或单一集成平台的团队。
- 生产级流水线有十一个阶段。大多数教程停留在三个阶段。你跳过的阶段是生产事故的起源。
- 安全扫描(SAST、依赖项审计、密钥扫描)属于每次拉取请求的流水线,而不是月度计划扫描。
- 部署策略不可互换:简单性用滚动部署,零停机关键性用蓝绿,需要生产验证的高频发布用金丝雀。
- 慢流水线与没有流水线一样有害。积极缓存,并行化独立作业,并对每个作业设置硬超时。
常见问题解答(FAQ)
CI/CD流水线运行应该花多长时间? 目标是从推送到暂存部署的关键路径在十分钟以内。lint和单元测试应在五分钟以内完成。如果你的流水线经常花更长时间,请调查缓存、并行化,以及测试套件是否积累了属于独立、较不频繁运行的慢测试。
我应该在每次提交时运行完整测试套件,还是只在向main的拉取请求时运行? 每次推送时运行快速检查(lint、单元测试、安全扫描)。在向main的拉取请求和合并到main时运行集成测试和暂存部署。这在反馈速度与资源成本和运行器分钟数之间取得平衡。
CI和CD有什么区别? CI(持续集成)意味着每次提交都会触发自动构建和测试序列。CD(持续交付)扩展了该自动化,将经过验证的代码部署到暂存或生产环境。它们通常一起实施,但代表不同的实践。
我需要暂存环境吗? 是的,对于任何有真实用户的应用程序。暂存是你捕获特定于部署的失败、环境之间的配置差异以及不会出现在单元测试或集成测试中的冒烟测试问题的地方。直接在生产环境中测试是CI/CD存在以消除的风险。
在CI/CD流水线中处理数据库迁移的最佳方法是什么? 作为部署步骤的一部分运行迁移,在新应用程序版本开始接收流量之前。确保迁移与先前的应用程序版本向后兼容,这样回滚就不会破坏模式。避免在使用它们的功能的同一次迁移中进行破坏性模式更改(列删除、类型更改)。
如何说服英国机构或客户CI/CD投资值得? 最有力的论据是财务方面的:在CI中捕获的错误修复成本大约比部署后发现的错误便宜十倍。运转良好的流水线还能降低每次发布的风险和压力,这直接改善了团队留存率和速度。大多数英国机构在采用CI/CD的第一季度内就看到了下班时间紧急部署的可测量减少。
评论