从一个 yml 文件开始,彻底搞懂 CI/CD、Pipeline 和 Jenkins

为什么很多公司的项目里会有一个 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.ymlJenkinsfilebuild-ci.sh,它们就不再是神秘的配置文件,而是现代软件工程中各司其职的一环:

  • Pipeline 配置文件yml负责描述"有哪些任务要做,做每个任务需要什么环境以及找谁来做";
  • build-ci.sh负责组织和执行具体的构建逻辑;
  • Gradle负责真正完成 Android 项目的编译与打包;
  • Jenkins、GitLab CI、GitHub Actions 等平台负责解析配置、调度机器、发起任务执行,并管理整个自动化流程。

它们共同组成了一条完整的软件构建流水线。

流水线配置文件.yml写在代码中也是现代软件工程最重要的变化之一:

不仅业务代码需要版本管理,构建流程同样需要版本管理。

这就是 Pipeline as Code(流水线配置代码化) 的核心思想

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容