<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>工具选型 on Liangweidong's blog</title><link>https://liangweidonggood.github.io/tags/%E5%B7%A5%E5%85%B7%E9%80%89%E5%9E%8B/</link><description>Recent content in 工具选型 on Liangweidong's blog</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Mon, 19 Jun 2023 00:00:00 +0800</lastBuildDate><atom:link href="https://liangweidonggood.github.io/tags/%E5%B7%A5%E5%85%B7%E9%80%89%E5%9E%8B/index.xml" rel="self" type="application/rss+xml"/><item><title>敏捷开发与协作：22 款主流 CI 工具选型指南</title><link>https://liangweidonggood.github.io/p/minjie-kaifa-xiezuo/</link><pubDate>Mon, 19 Jun 2023 00:00:00 +0800</pubDate><guid>https://liangweidonggood.github.io/p/minjie-kaifa-xiezuo/</guid><description>&lt;img src="https://liangweidonggood.github.io/p/minjie-kaifa-xiezuo/image/cover.jpg" alt="Featured image of post 敏捷开发与协作：22 款主流 CI 工具选型指南" /&gt;
 &lt;blockquote&gt;
 &lt;p&gt;选 CI 工具是每个研发团队的&amp;quot;必经之坑&amp;quot;——选错了，&lt;strong&gt;每次构建都在消耗工程师的耐心&lt;/strong&gt;。本文整理了 22 款主流 CI 工具的核心特点，帮你按团队规模、技术栈、部署方式快速圈定候选。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="一为什么选-ci-工具这么难"&gt;一、为什么选 CI 工具这么难
&lt;/h2&gt;&lt;p&gt;CI 工具选型不是&amp;quot;哪个最好用&amp;quot;，而是&amp;quot;&lt;strong&gt;哪个最适合&lt;/strong&gt;&amp;quot;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;团队规模&lt;/strong&gt;：3 人小团队 vs 300 人大厂，工具能力需求天差地别&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;技术栈&lt;/strong&gt;：Java/Maven vs Node/Yarn vs Python/Poetry，&lt;strong&gt;支持的 runner 生态决定成本&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;部署方式&lt;/strong&gt;：自托管 vs SaaS，&lt;strong&gt;合规要求决定能不能用云&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;集成需求&lt;/strong&gt;：Jira / Slack / Kubernetes / GitHub，&lt;strong&gt;集成越深切换成本越高&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;When to use&lt;/strong&gt;：当你的团队：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每天有 5+ 次合并&lt;/li&gt;
&lt;li&gt;跨 3+ 个服务/模块需要协调测试&lt;/li&gt;
&lt;li&gt;需要&amp;quot;提交 → 测试 → 部署&amp;quot;全链路自动化&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;→ &lt;strong&gt;必须有 CI&lt;/strong&gt;。否则问题会累积到发布日爆炸。&lt;/p&gt;
&lt;h2 id="二22-款-ci-工具横向对比"&gt;二、22 款 CI 工具横向对比
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;#&lt;/th&gt;
					&lt;th&gt;工具&lt;/th&gt;
					&lt;th&gt;类型&lt;/th&gt;
					&lt;th&gt;核心特点&lt;/th&gt;
					&lt;th&gt;适用场景&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;Buddy&lt;/td&gt;
					&lt;td&gt;SaaS&lt;/td&gt;
					&lt;td&gt;15 分钟配置，100+ ready-to-use actions，YAML 支持&lt;/td&gt;
					&lt;td&gt;Web 项目快速上手&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;2&lt;/td&gt;
					&lt;td&gt;Jenkins&lt;/td&gt;
					&lt;td&gt;自托管&lt;/td&gt;
					&lt;td&gt;海量节点、Java 编写、跨平台&lt;/td&gt;
					&lt;td&gt;大型企业、复杂流水线&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;3&lt;/td&gt;
					&lt;td&gt;TeamCity&lt;/td&gt;
					&lt;td&gt;自托管/SaaS&lt;/td&gt;
					&lt;td&gt;强大的 DSL、可在代码中配置构建&lt;/td&gt;
					&lt;td&gt;JetBrains 技术栈&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;4&lt;/td&gt;
					&lt;td&gt;Drone&lt;/td&gt;
					&lt;td&gt;自托管&lt;/td&gt;
					&lt;td&gt;原生 Docker、Kubernetes 友好&lt;/td&gt;
					&lt;td&gt;容器化项目&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;5&lt;/td&gt;
					&lt;td&gt;Travis CI&lt;/td&gt;
					&lt;td&gt;SaaS&lt;/td&gt;
					&lt;td&gt;曾经开源免费（注：2020 年后政策已变）、VM 构建、Slack/钉钉/企业微信通知&lt;/td&gt;
					&lt;td&gt;开源项目&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;6&lt;/td&gt;
					&lt;td&gt;GoCD&lt;/td&gt;
					&lt;td&gt;自托管&lt;/td&gt;
					&lt;td&gt;Value Stream Map 端到端可视化&lt;/td&gt;
					&lt;td&gt;复杂 CD 流水线&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;7&lt;/td&gt;
					&lt;td&gt;Bamboo&lt;/td&gt;
					&lt;td&gt;自托管&lt;/td&gt;
					&lt;td&gt;JIRA + Bitbucket 无缝集成&lt;/td&gt;
					&lt;td&gt;Atlassian 全家桶用户&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;8&lt;/td&gt;
					&lt;td&gt;GitLab CI&lt;/td&gt;
					&lt;td&gt;集成&lt;/td&gt;
					&lt;td&gt;与 GitLab 深度整合、API 丰富&lt;/td&gt;
					&lt;td&gt;GitLab 用户&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;9&lt;/td&gt;
					&lt;td&gt;CircleCI&lt;/td&gt;
					&lt;td&gt;SaaS/自托管&lt;/td&gt;
					&lt;td&gt;Docker 支持、并行测试、Android/iOS 商店评级优化&lt;/td&gt;
					&lt;td&gt;移动端 + 后端&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;10&lt;/td&gt;
					&lt;td&gt;Codeship&lt;/td&gt;
					&lt;td&gt;SaaS&lt;/td&gt;
					&lt;td&gt;Basic/Pro 两版、CI/CD 高度可定制&lt;/td&gt;
					&lt;td&gt;中小团队&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;11&lt;/td&gt;
					&lt;td&gt;Buildbot&lt;/td&gt;
					&lt;td&gt;自托管&lt;/td&gt;
					&lt;td&gt;分布式并行、跨平台 Job&lt;/td&gt;
					&lt;td&gt;Python 项目、大规模测试&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;12&lt;/td&gt;
					&lt;td&gt;Nevercode&lt;/td&gt;
					&lt;td&gt;SaaS&lt;/td&gt;
					&lt;td&gt;全自动云构建、无服务器维护&lt;/td&gt;
					&lt;td&gt;移动端&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;13&lt;/td&gt;
					&lt;td&gt;Integrity&lt;/td&gt;
					&lt;td&gt;自托管&lt;/td&gt;
					&lt;td&gt;仅 GitHub、HTTP/AMQP/邮件通知&lt;/td&gt;
					&lt;td&gt;小型 GitHub 项目&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;14&lt;/td&gt;
					&lt;td&gt;Strider&lt;/td&gt;
					&lt;td&gt;自托管&lt;/td&gt;
					&lt;td&gt;Node.js + MongoDB、插件丰富&lt;/td&gt;
					&lt;td&gt;JS 团队&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;15&lt;/td&gt;
					&lt;td&gt;AutoRABIT&lt;/td&gt;
					&lt;td&gt;SaaS&lt;/td&gt;
					&lt;td&gt;Salesforce 专用、120+ 元数据类型&lt;/td&gt;
					&lt;td&gt;Salesforce 项目&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;16&lt;/td&gt;
					&lt;td&gt;FinalBuilder&lt;/td&gt;
					&lt;td&gt;Windows&lt;/td&gt;
					&lt;td&gt;图形化逻辑结构、try/catch 错误处理&lt;/td&gt;
					&lt;td&gt;Windows 桌面应用&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;17&lt;/td&gt;
					&lt;td&gt;Wercker&lt;/td&gt;
					&lt;td&gt;SaaS&lt;/td&gt;
					&lt;td&gt;容器构建部署、100+ 外部工具集成&lt;/td&gt;
					&lt;td&gt;中小项目&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;18&lt;/td&gt;
					&lt;td&gt;Buildkite&lt;/td&gt;
					&lt;td&gt;自托管 agent&lt;/td&gt;
					&lt;td&gt;跨平台、密钥不读源码&lt;/td&gt;
					&lt;td&gt;安全敏感型项目&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;19&lt;/td&gt;
					&lt;td&gt;Semaphore&lt;/td&gt;
					&lt;td&gt;SaaS&lt;/td&gt;
					&lt;td&gt;配置简单、市场上最快的 CI 之一&lt;/td&gt;
					&lt;td&gt;追求速度的团队&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;20&lt;/td&gt;
					&lt;td&gt;CruiseControl&lt;/td&gt;
					&lt;td&gt;自托管&lt;/td&gt;
					&lt;td&gt;多 SCM 集成、远程管理&lt;/td&gt;
					&lt;td&gt;老牌 Java/.NET 项目&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;21&lt;/td&gt;
					&lt;td&gt;Bitrise&lt;/td&gt;
					&lt;td&gt;SaaS&lt;/td&gt;
					&lt;td&gt;移动 CI/CD 专用、虚拟机构建&lt;/td&gt;
					&lt;td&gt;移动端项目&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;22&lt;/td&gt;
					&lt;td&gt;UrbanCode&lt;/td&gt;
					&lt;td&gt;企业&lt;/td&gt;
					&lt;td&gt;混合云、审计、拖放自动化&lt;/td&gt;
					&lt;td&gt;大型企业、IBM 生态&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="三按场景选型"&gt;三、按场景选型
&lt;/h2&gt;&lt;h3 id="31-小团队10-人追求开箱即用"&gt;3.1 小团队（≤10 人）、追求开箱即用
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;推荐&lt;/strong&gt;：Buddy / GitHub Actions / GitLab CI&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;配置简单，&lt;strong&gt;15 分钟出第一条流水线&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;SaaS 免运维，&lt;strong&gt;省心&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;免费额度通常够用&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# GitHub Actions 最小示例&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;CI&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;push, pull_request]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Run tests&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;npm test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="32-中型团队10-50-人java-技术栈"&gt;3.2 中型团队（10-50 人）、Java 技术栈
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;推荐&lt;/strong&gt;：Jenkins / GitLab CI / TeamCity&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;插件丰富，&lt;strong&gt;覆盖几乎所有构建场景&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;节点可水平扩展&lt;/li&gt;
&lt;li&gt;与企业内网/制品库（Nexus / Artifactory）集成成熟&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="33-云原生团队"&gt;3.3 云原生团队
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;推荐&lt;/strong&gt;：Drone / GitLab CI / CircleCI&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;原生 Docker&lt;/strong&gt;，每一步都在容器中跑&lt;/li&gt;
&lt;li&gt;与 Kubernetes 无缝集成&lt;/li&gt;
&lt;li&gt;配置文件即代码&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Drone 最小示例&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;pipeline&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;default&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;node:18&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;npm install&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;npm test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="34-移动端团队"&gt;3.4 移动端团队
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;推荐&lt;/strong&gt;：Bitrise / CircleCI / Nevercode&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;专门为 iOS/Android 优化&lt;/li&gt;
&lt;li&gt;模拟器/真机测试支持&lt;/li&gt;
&lt;li&gt;商店发布集成&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="35-大型企业合规优先"&gt;3.5 大型企业、合规优先
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;推荐&lt;/strong&gt;：Jenkins / TeamCity / UrbanCode&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自托管，&lt;strong&gt;数据不出企业内网&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;审计日志、权限分级&lt;/li&gt;
&lt;li&gt;与企业内部系统（LDAP / SSO / 内部制品库）集成&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="36-安全敏感型"&gt;3.6 安全敏感型
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;推荐&lt;/strong&gt;：Buildkite&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;Buildkite 永远不会读取源代码或密钥&lt;/strong&gt;——CI 配置在企业侧，agent 在企业内网执行，&lt;strong&gt;源代码/密钥都不经过 CI 服务商&lt;/strong&gt;。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="四ci-工具核心能力-6-维评估"&gt;四、CI 工具核心能力 6 维评估
&lt;/h2&gt;&lt;p&gt;选型时可以按这 6 维打分（1-5 分）：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;维度&lt;/th&gt;
					&lt;th&gt;权重建议&lt;/th&gt;
					&lt;th&gt;评估点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;易用性&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;中小团队高&lt;/td&gt;
					&lt;td&gt;配置门槛、文档质量、调试体验&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;可扩展性&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;大团队高&lt;/td&gt;
					&lt;td&gt;节点扩展、并发能力、插件生态&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;集成度&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;跨工具多&lt;/td&gt;
					&lt;td&gt;VCS、IM、制品库、K8s 集成&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;成本&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;看预算&lt;/td&gt;
					&lt;td&gt;免费额度、SaaS 月费、自托管人力&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;可观测性&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;重要&lt;/td&gt;
					&lt;td&gt;构建日志、Metrics、告警&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;安全性&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;合规项目高&lt;/td&gt;
					&lt;td&gt;密钥管理、审计日志、访问控制&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="五核心-6-点提炼"&gt;五、核心 6 点提炼
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;CI 是工程效率的水电煤&lt;/strong&gt;——选错一次，&lt;strong&gt;5 年都在为它还债&lt;/strong&gt;。换 CI 比换语言还痛。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配置文件即代码&lt;/strong&gt;——CI 脚本必须&lt;strong&gt;入库、评审、版本化&lt;/strong&gt;。否则就是&amp;quot;工程师本机的玄学&amp;quot;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缓存决定成本&lt;/strong&gt;——依赖缓存（npm/node_modules、Maven .m2）&lt;strong&gt;能砍掉 50% 以上构建时间&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;并行测试是分水岭&lt;/strong&gt;——单线程跑完 30 分钟，&lt;strong&gt;没人愿意等&lt;/strong&gt;。拆 4 个 stage 并行 = 8 分钟&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;失败要快速反馈&lt;/strong&gt;——编译/单元测试 5 分钟内出结果，否则工程师已经开始刷手机&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;制品（artifact）必须可追溯&lt;/strong&gt;——CI 跑出的 jar/docker image，&lt;strong&gt;对应哪个 commit、哪个 PR&lt;/strong&gt;，必须能查&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="六常见-5-个坑"&gt;六、常见 5 个坑
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&amp;ldquo;用一个 YAML 写完所有 stage&amp;rdquo;&lt;/strong&gt;——结果 stage 越来越多，构建越来越慢。&lt;strong&gt;正确做法：拆 pipeline&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;没做依赖缓存&lt;/strong&gt;——每次 &lt;code&gt;npm install&lt;/code&gt; 5 分钟，&lt;strong&gt;工程师一天等 1 小时&lt;/strong&gt;。缓存命中 = 30 秒&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;密钥直接写在 YAML 里&lt;/strong&gt;——密钥进入 git 历史 = 公开。&lt;strong&gt;用 Vault / CI 内置 secret 管理&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CI 跑通 ≠ 测试覆盖&lt;/strong&gt;——CI 绿色但单元测试覆盖 0%，&lt;strong&gt;线上还是炸&lt;/strong&gt;。CI 必须有覆盖率门禁&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不清理老构建&lt;/strong&gt;——半年后构建历史 10 万条，磁盘爆掉。&lt;strong&gt;必须设 retention policy&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="七ci-工具的接力赛"&gt;七、CI 工具的&amp;quot;接力赛&amp;quot;
&lt;/h2&gt;&lt;p&gt;CI 工具&lt;strong&gt;不是孤立存在&lt;/strong&gt;的，它在一个更大的&amp;quot;敏捷/协作&amp;quot;链条里：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plaintext" data-lang="plaintext"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;需求 (Jira) → 代码 (Git) → CI (Jenkins/GitLab CI) 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓ ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 评审 (Code Review) 制品 (Nexus/Artifactory) 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 部署 (ArgoCD/Spinnaker) 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 监控 (Prometheus/Grafana)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;CI 工具的下一站是 CD&lt;/strong&gt;。如果选了 CI 不支持 CD，可以&lt;strong&gt;叠加一个部署工具&lt;/strong&gt;（ArgoCD / Spinnaker / Flux），但&lt;strong&gt;配置复杂度会上升&lt;/strong&gt;。所以&lt;strong&gt;一开始就选支持 CD 的 CI&lt;/strong&gt; 往往更省心。&lt;/p&gt;
&lt;h2 id="八迁移-ci-工具的代价"&gt;八、迁移 CI 工具的代价
&lt;/h2&gt;&lt;p&gt;切换 CI 工具的真实成本（&lt;strong&gt;这是大多数团队低估的&lt;/strong&gt;）：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;任务&lt;/th&gt;
					&lt;th&gt;工作量&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;重新写所有 pipeline YAML&lt;/td&gt;
					&lt;td&gt;1-2 周&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;重写所有自定义脚本/插件&lt;/td&gt;
					&lt;td&gt;2-4 周&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;迁移构建历史/Metrics&lt;/td&gt;
					&lt;td&gt;1 周&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;培训团队&lt;/td&gt;
					&lt;td&gt;1-2 周&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;总代价&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;1.5-2 个月&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;建议&lt;/strong&gt;：选 CI 工具时&lt;strong&gt;多花 2 周评估&lt;/strong&gt;，比用上 2 年再换，&lt;strong&gt;省 6 个月&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="九2024-视角5-款近-2-年主流-ci-的上手-3-步"&gt;九、2024+ 视角：5 款近 2 年主流 CI 的&amp;quot;上手 3 步&amp;quot;
&lt;/h2&gt;&lt;p&gt;2023 年后 CI 工具市场发生了一些&lt;strong&gt;显著变化&lt;/strong&gt;：Travis CI 大幅收缩免费额度、Bitrise 移动端涨价、Drone 维护节奏放缓、GitHub Actions 几乎成了&lt;strong&gt;事实标准&lt;/strong&gt;。下面是 5 款&lt;strong&gt;近 2 年仍在持续投入&lt;/strong&gt;的工具，各给一个&amp;quot;3 步跑通&amp;quot;的最小实战。&lt;/p&gt;
&lt;h3 id="91-github-actions--开源saas-首选"&gt;9.1 GitHub Actions —— 开源/SaaS 首选
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;3 步上手&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 1. 在仓库根目录创建 .github/workflows/ci.yml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;CI&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;push, pull_request]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/setup-node@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;node-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;}&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;npm ci &amp;amp;&amp;amp; npm test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;为什么选它&lt;/strong&gt;：内置在 GitHub、零运维、海量 marketplace action、Windows/Mac/Linux runner 都免费。&lt;/p&gt;
&lt;h3 id="92-gitlab-ci--自托管合规场景首选"&gt;9.2 GitLab CI —— 自托管/合规场景首选
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;3 步上手&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 1. 仓库根 .gitlab-ci.yml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;stages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;test, build]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;node:20&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;npm ci &amp;amp;&amp;amp; npm test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;build&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;docker:24&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;docker:24-dind]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;docker build -t myapp:$CI_COMMIT_SHA .&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;为什么选它&lt;/strong&gt;：和 GitLab 仓库一体、Runner 私有部署方便、CI/CD 还能继续延伸到部署。&lt;/p&gt;
&lt;h3 id="93-drone--容器原生轻量"&gt;9.3 Drone —— 容器原生、轻量
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;3 步上手&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 1. 仓库根 .drone.yml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;pipeline&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;docker&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;default&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;node:20&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;npm ci, npm test]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Server 端&lt;/strong&gt;（docker compose）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;drone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;drone/drone:2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;8080:80&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DRONE_GITHUB_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;xxx&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DRONE_GITHUB_CLIENT_SECRET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;xxx&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DRONE_RPC_SECRET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;&amp;lt;random&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DRONE_SERVER_HOST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;drone.example.com&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;drone-runner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;drone/drone-runner-docker:1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DRONE_RPC_HOST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;drone:9000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DRONE_RPC_SECRET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;&amp;lt;random&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DRONE_RUNNER_CAPACITY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;为什么选它&lt;/strong&gt;：&lt;strong&gt;单二进制&lt;/strong&gt;部署、每步天然在容器中、配置文件和 GitHub Actions 一样简单。&lt;/p&gt;
&lt;h3 id="94-buildkite--安全敏感金融政企"&gt;9.4 Buildkite —— 安全敏感/金融/政企
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;3 步上手&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 1. 仓库根 .buildkite/pipeline.yml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Test&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;npm ci &amp;amp;&amp;amp; npm test&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;}&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Agent 端&lt;/strong&gt;（在企业内网跑）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. 内网机器装 agent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -d &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e &lt;span class="nv"&gt;BUILDKITE_AGENT_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;secret&amp;gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e &lt;span class="nv"&gt;BUILDKITE_AGENT_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;hostname&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; drone/drone-runner-docker:1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 等价命令：buildkite-agent start --token &amp;lt;secret&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;3. Web 后台&lt;/strong&gt;（buildkite.com）开 Pipeline → 关联仓库 → agent 自动接活。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选它&lt;/strong&gt;：&lt;strong&gt;源代码/密钥不经过 Buildkite SaaS&lt;/strong&gt;——CI 配置在云端、构建在内网，金融/军工场景的硬要求。&lt;/p&gt;
&lt;h3 id="95-circleci--dockerorb-生态"&gt;9.5 CircleCI —— Docker/Orb 生态
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;3 步上手&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 1. 仓库根 .circleci/config.yml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;docker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;cimg/node:20.0 }]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;checkout&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;npm ci&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;npm test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;为什么选它&lt;/strong&gt;：Orb 复用机制强（类似 GitHub Actions 的 marketplace）、&lt;strong&gt;macOS M1 runner&lt;/strong&gt; 是 iOS/macOS 开发的最优解。&lt;/p&gt;
&lt;h3 id="96-2024-选型速查"&gt;9.6 2024+ 选型速查
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;场景&lt;/th&gt;
					&lt;th&gt;第一选择&lt;/th&gt;
					&lt;th&gt;备选&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;开源项目 / SaaS&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;GitHub Actions&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;CircleCI&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;自托管 + 合规&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;GitLab CI&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Drone&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;容器化云原生&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Drone&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;GitLab CI&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;金融/军工/源代码不出网&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Buildkite&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Jenkins（自建）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;iOS/macOS CI&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;CircleCI&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Bitrise&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;企业复杂流水线&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Jenkins&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;TeamCity&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="十结语"&gt;十、结语
&lt;/h2&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;以下段落为引用 Rancher 官方介绍（写作时的产品现状描述，仅作历史背景参考）&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;容器技术被越来越多地用于大型项目之中，&lt;strong&gt;如何通过一致的流程和工作流来简化大型项目的部署，变得愈发重要&lt;/strong&gt;。Rancher Kubernetes 管理平台让用户通过一个自动化的过程，即可方便快速地创建及管理多 Kubernetes 集群。Rancher 平台对 Jenkins、GitLab CI、Drone 等流行的 CI 工具都提供了优秀的支持，内嵌的 Rancher Pipeline 也有着极简的操作体验和强大的功能整合。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;作为用户，使用场景和需求都不尽相同，选择最适合自己的就好。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="参考资料"&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://buddy.works" target="_blank" rel="noopener"
 &gt;Buddy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://jenkins.io/download/" target="_blank" rel="noopener"
 &gt;Jenkins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.jetbrains.com/teamcity/" target="_blank" rel="noopener"
 &gt;TeamCity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://drone.io/" target="_blank" rel="noopener"
 &gt;Drone&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/travis-ci/travis-ci" target="_blank" rel="noopener"
 &gt;Travis CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.gocd.org/download/" target="_blank" rel="noopener"
 &gt;GoCD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.atlassian.com/software/bamboo" target="_blank" rel="noopener"
 &gt;Bamboo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://about.gitlab.com/installation/" target="_blank" rel="noopener"
 &gt;GitLab CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://circleci.com/" target="_blank" rel="noopener"
 &gt;CircleCI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://codeship.com/" target="_blank" rel="noopener"
 &gt;Codeship&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://buildbot.net/" target="_blank" rel="noopener"
 &gt;Buildbot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://nevercode.io/" target="_blank" rel="noopener"
 &gt;Nevercode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://integrity.github.io/" target="_blank" rel="noopener"
 &gt;Integrity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/Strider-CD/strider" target="_blank" rel="noopener"
 &gt;Strider&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://www.autorabit.com/tag/autorabit-download/" target="_blank" rel="noopener"
 &gt;AutoRABIT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.finalbuilder.com/downloads/finalbuilde" target="_blank" rel="noopener"
 &gt;FinalBuilder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://www.wercker.com/" target="_blank" rel="noopener"
 &gt;Wercker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://buildkite.com/" target="_blank" rel="noopener"
 &gt;Buildkite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://semaphoreci.com" target="_blank" rel="noopener"
 &gt;Semaphore&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="http://cruisecontrol.sourceforge.net/download.html" target="_blank" rel="noopener"
 &gt;CruiseControl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/bitrise-io/bitrise#install-and-setup" target="_blank" rel="noopener"
 &gt;Bitrise&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.ibm.com/ms-en/marketplace/application-release-automation" target="_blank" rel="noopener"
 &gt;UrbanCode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>