为什么很多公司的项目里会有一个 ci.yml?
为什么 GitHub 上有 .github/workflows/Build.yml?
为什么 Jenkins 又会有一个Jenkinsfile文件?上面这些文件到底是谁执行的?
为什么改一个 yml,整个项目就开始自动编译?
如果你也有这些疑问,那么希望这篇文章能给你一个完整且清晰的答案。
如果你经常逛 GitHub或者在稍微大一点公司参与Android 项目,相信一定会在项目根目录中,看到以下文件:
有的是:
ci.yml
build-ci.sh
有的是:
Jenkinsfile
还有的是:
.github/workflows/build.yml
build-ci.sh
还有的是
pipeline.yml
build-ci.sh
第一次看到它的时候,大多数人的反应都差不多:
这是什么文件?
为什么同事会说"这个 yml 别乱改"?
build-ci.sh 又是什么?为什么它会被执行?
很多开发者工作了几年,依然只是知道这个文件存在,却不知道它到底在整个项目里起什么作用。
事实上,这个不起眼的配置文件,就是整个 CI/CD 自动化流程的入口。
今天,我们就从这个 yml 文件开始,一步一步把 CI/CD、Pipeline、build-ci.sh、Jenkins 全部串起来,理解现代软件项目到底是如何实现"提交代码即可自动构建"的。
一、打开几个开源项目或公司内部项目,你会发现它们都有类似的配置文件
GitLab 的是”.gitlab-ci.yml“,内容类似:
stages:
- build
build:
stage: build
script:
- ./gradlew assembleDebug
GitHub的是:”.github/workflows/android.yml“,内容类似:
name: Android Build
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./gradlew assembleDebug
Jenkins 没有 yml,而是使用”Jenkinsfile“,内容类似
pipeline {
agent any
stages {
stage("Build") {
steps {
sh "./gradlew assembleDebug"
}
}
}
}
很多公司自研 CI,配置文件名称可能是:“pipeline.yml”或者“ci.yml”或者“build.yml”,内容类似:
Default:
profile: [ change ]
Profiles:
- profile:
name: change-build
env: UBUNTU
tool: build_submitter
command: bash -x build-ci.sh
release: true
看起来这些配置文件的:
- 文件名字不同
- 配置格式不同
- 字段名称不同
- 编写语法不同
但是它们本质上都是一个任务配置表,这个配置表包含了:
- 构建流程中有哪些任务(任务Item:任务名称+任务配置);
- 任务之间的执行关系((顺序、并行、依赖、条件);
- 每个任务的触发条件、执行环境、使用工具和脚本,以及其他配置;
CI/CD 平台拿到这个配置表就知道:先干什么、后干什么、每一步工作怎么做;当然还可以根据任务名称直接找到特定任务配置直接执行这个任务。
从另一个角度来看:CI/CD平台拿到任务配置表后,就像工厂流水线设置好各个环节参数一样,可以自动生产出来特定规格的产品。我们把这套自动执行的流程叫做流水线,这种文件也叫做 流水线配置文件。
↓
流水线配置文件xxx.yml 本身并不是一个可执行程序,真正执行是 CI/CD 平台程序(比如GitHub Runner、Jenkins Agent、公司自研CI/CD agent),xxx.yml只是CI/CD平台程序的从外部加载的配置文件。
↓
因为xxx.yml只是一个配置文件,所以单独看它不具备完整逻辑性和可读性,这就导致很多同学说这个很难看懂;要看懂xxx.yml都要结合 CI/CD 平台程序给出的配置说明,如果是开源平台可以问AI或者通过搜索引擎获取,如果是公司内部的CI/CD只能依赖公司内部CI/CD配置说明文档或者历史经验文档。
一次完整的自动构建,其实就是下面这个过程。
开发者提交代码
│
▼
Git仓库收到新的 Commit,发送通知
│
▼
CI/CD 平台收到通知
│
▼
CI/CD平台 读取项目代码中的 yml(Pipeline配置)文件
│
▼
CI/CD平台 解析yml,得到执行构建需要的环境和真正构建脚本build-ci.sh
│
▼
CI/CD平台调度一台 Linux Agent,按照yml配置好环境
│
▼
CI/CD平台调用build-ci.sh在配置好的环境中执行
│
▼
build-ci.sh 调用 Gradle
│
▼
编译 Android 工程
│
▼
生成 APK、AAR、Mapping等
│
▼
归档产物
│
▼
发送通知,CI/CD 前端页面收到通知展示编译结果
│
▼
释放执行编译机器
当第一个配置后了之后,后续整个过程中开发者唯一需要做的事情,就是:
提交代码。
剩下的一切全部自动完成。
这就是现代 CI/CD 最核心的价值。
前文提到很多CI/CD解析yml文件,根据任务名称,可以得到真正构建脚本是
build-ci.sh
很多新人都会疑惑:为什么不直接写:
./gradlew assembleRelease
而是:
bash build-ci.sh
原因其实很简单,真正的大型 Android 项目一次完整构建,远远不是一句 Gradle 命令那么简单。
build-ci.sh 往往需要完成很多准备工作。
例如:
- 开启详细日志
- 配置 JDK
- 配置 Android SDK
- 配置 NDK
- 配置 Gradle 环境
- 下载依赖
- 初始化环境变量
- 读取版本号
- 配置渠道参数
- 调用 Gradle 编译
- 收集 Mapping
- 重命名 APK
- 上传构建产物
- 清理临时目录
真正开始编译的时候。
它才会执行:
./gradlew assembleRelease
所以:
yml 调用 build-ci.sh。
build-ci.sh 再调用 Gradle。
这是大多数 Android 项目最常见的组织方式。
这样做还有一个很大的好处:
即使没有 CI 平台,开发者在 Linux 或 macOS 上,也可以直接执行。
bash build-ci.sh
完成一套和流水线完全一致的构建流程。
现在,再来简要的回答文章开头的几个问题:
1、为什么项目里都有一个 yml?
因为它是 Pipeline(流水线)的配置文件,用来描述整个自动化构建流程。
2、为什么不同公司的 yml 都长得不一样?
因为不同CI/CD平台有不同的语法,例如 GitLab CI、GitHub Actions、Jenkins、Azure DevOps、自研 CI,但它们都是Pipeline的配置文件。
3、为什么单独看 yml 看不懂?
因为 yml 只是对一个流程中可变部分的配置,真正解析和执行它的是 GitLab Runner、GitHub Runner、Jenkins Agent 或公司的 CI Agent。
4、为什么现代 CI/CD 都采用把配置文件(如 yml、Jenkinsfile)放到项目工程中,而不是在网页上直接搞一些配置按钮?
其实CI/CD 发展初期,很多平台确实都是这么做的, 所有构建逻辑都配置在平台网页里面。
后来大家发现,只要构建环境或流水线有调整 —— 像 Android 升级 Java17、升级 Gradle 大版本、新增代码检查、单元测试、APK 签名这类改动,
都会出现一堆麻烦:分不清是谁改的、改了哪些配置,出问题没法快速回滚,而且配置变更也很难进行Review。
于是,后来整个 DevOps 行业提出了一个非常重要的理念: Pipeline as Code(流水线配置代码化) ,这什么意思呢? 就是: 流水线共功能本身也应该像业务代码一样进行版本管理,把流水线可变地方写成配置文件并纳入 Git 管理,可以像业务代码一样进行版本控制、评审、协作和回滚,这就是 Pipeline as Code 的核心思想。
5、为什么还需要 build-ci.sh?
因为真实项目的构建逻辑往往非常复杂,不适合全部写在 yml 中,所以通常封装到 Shell 脚本里,由 CI/CD平台具体Pipeline 调用。
6、Jenkins 和其他CI/CD平台本质是什么?
它们既不是编译器和打包工具,也不是远程桌面,而是一个负责调度执行、展示、配置自动化软件生产线的平台。
Jenkins和其他CI/CD平台负责:
让整个自动化生产软件的流程按照代码中的配置一步一步执行下去。
真正编译代码的依然是:
- Java
- Gradle
- Android SDK
- Shell
- 各种编译工具
最后
很多开发者学习 CI/CD 时,最容易陷入一个误区:一上来就记各种新名词——CI、CD、Pipeline、Runner、Agent、Jenkins、GitHub Actions……结果名词记住了,却始终不知道它们之间是什么关系。
其实,它们都是围绕同一件事情展开的:把原本需要人工完成的构建、测试、打包、发布流程,变成一套可方便修改、可重复、可追溯、可自动执行的工程化能力。
当你理解了这一点,再回头看项目里的 .gitlab-ci.yml、Jenkinsfile 或 build-ci.sh,它们就不再是神秘的配置文件,而是现代软件工程中各司其职的一环:
- Pipeline 配置文件yml负责描述"有哪些任务要做,做每个任务需要什么环境以及找谁来做";
- build-ci.sh负责组织和执行具体的构建逻辑;
- Gradle负责真正完成 Android 项目的编译与打包;
- Jenkins、GitLab CI、GitHub Actions 等平台负责解析配置、调度机器、发起任务执行,并管理整个自动化流程。
它们共同组成了一条完整的软件构建流水线。
流水线配置文件.yml写在代码中也是现代软件工程最重要的变化之一:
不仅业务代码需要版本管理,构建流程同样需要版本管理。
这就是 Pipeline as Code(流水线配置代码化) 的核心思想