4、CI工具对比:Jenkins、GitLab CI、GitHub Actions、CircleCI的选型
聊到AGP版本的CI基建,选哪把“枪”其实挺头疼。我做过好几个项目,从自建Jenkins到全托管的GitHub Actions都折腾过。说实话,没有银弹。每个工具都有它舒服的姿势,也有让你踩坑的地方。
咱们今天不堆参数,我直接拿实际场景说话。你在维护多个AGP版本的构建矩阵,要考虑的是:维护成本、扩展性、容器支持、还有最关键——缓存策略。
4.1 Jenkins —— 老牌全能手,但维护成本不低
我做AGP兼容性矩阵的第一个项目用的就是Jenkins。当时团队只有3个人,要跑8个AGP版本分支。Jenkins的Pipeline as Code确实强大,而且插件生态什么都有。
但我必须说个痛点:插件版本冲突。我记得有一次升级了Kubernetes插件,结果跟旧的Blue Ocean UI不兼容,整个构建历史全丢了。嗯,这种坑我不是第一次踩。
适用场景
- 你已经有现成的Kubernetes或物理机集群
- 需要高度定制化的构建逻辑(比如动态AGP版本参数注入)
- 安全合规要求必须完全私有化部署
// Jenkinsfile 片段 —— 动态AGP版本矩阵
pipeline {
agent { docker { image 'gradle:7.5-jdk17' } }
parameters {
choice(name: 'AGP_VERSION', choices: ['7.4.0', '8.0.0', '8.1.0', '8.2.0'])
}
stages {
stage('Build') {
steps {
sh "gradle build -Pandroid.useAndroidX=true -PagpVersion=${params.AGP_VERSION}"
}
}
}
}
避坑指南
我曾经因为Jenkins主节点磁盘被日志撑爆,导致所有构建排队死锁。后来给每个Job加了buildDiscarder限制,才消停。如果你选Jenkins,务必设置日志轮转和磁盘监控。
4.2 GitLab CI —— 代码与CI一体,适合DevOps成熟团队
我最喜欢的CI工具其实是GitLab CI。为什么?因为.gitlab-ci.yml 直接和代码托管在一起,版本控制特别自然。我维护的一个老旧AGP 7.x项目,团队把构建配置和代码放在同一个仓库,回滚时CI配置也跟着回滚,这个体验真的很好。
GitLab CI的runner弹性伸缩做得不错。我们当时用Docker executor + Kubernetes autoscaling,跑AGP构建矩阵非常顺。但有一点要注意:GitLab的REST API频率限制,如果你在CI里频繁调API获取Artifact信息,很容易被限流。
小技巧
用GitLab CI的parallel:matrix可以实现AGP版本并行构建,不用再写复杂的循环。
# .gitlab-ci.yml 并行AGP版本矩阵
image: gradle:7.6-jdk17
build-matrix:
parallel:
matrix:
- AGP_VERSION: ["7.4.0", "8.0.0", "8.1.0"]
script:
- gradle build -PagpVersion=$AGP_VERSION
4.3 GitHub Actions —— 生态好,但是大矩阵要留心
GitHub Actions现在真的火。我有个开源项目就是用Actions跑AGP多版本兼容性测试,配置起来很简单。Marketplace上的复合动作(composite action)特别方便,比如setup-java、cache这些一步到位。
但有个局限:免费层的并发限制(20个job)。如果你的AGP版本矩阵有10个版本×2个维度,一下就用完了。另外Action的缓存系统是全局的,不同分支之间可能互相干扰。我遇到过缓存被旧版本覆盖导致重新下载所有依赖的情况,气得我把缓存key加上了AGP版本号。
# .github/workflows/agp-matrix.yml
name: AGP Build Matrix
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
agp: [7.4.0, 8.0.0, 8.1.0, 8.2.0]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
with: { distribution: 'zulu', java-version: '17' }
- name: Cache Gradle
uses: actions/cache@v3
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-agp${{ matrix.agp }}-${{ hashFiles('**/*.gradle*') }}
- run: gradle build -PagpVersion=${{ matrix.agp }}
注意
GitHub Actions的缓存没有过期时间,需要手动清理。如果你频繁迭代AGP版本,建议在cache key里加进AGP版本号,否则旧缓存会一直占空间。
4.4 CircleCI —— 构建速度快,但贵
CircleCI我用的次数不多,但印象很深——执行速度确实快。它内置的Docker Layer Caching和test splitting做得很成熟。一次我们要在5个AGP版本上跑快速验证,CircleCI的并行执行只用了6分钟,比GitHub Actions快了将近一倍。
不过代价也很明显:按执行分钟计费,且价格不低。AGP构建通常要下载大量依赖,如果每次都没命中缓存,账单会很难看。
CircleCI 适合场景
- 构建时间就是金钱的项目(比如频繁发版)
- 团队预算充足,追求开发者体验
- 需要强大的测试拆分(test splitting)策略
# .circleci/config.yml 片段
version: 2.1
executors:
android-executor:
docker:
- image: androidsdk/android-30:latest
environment:
AGP_VERSIONS: "7.4.0,8.0.0,8.1.0"
jobs:
build-matrix:
parameters:
agp-version:
type: string
steps:
- checkout
- run: gradle build -PagpVersion=<< parameters.agp-version >>
workflows:
all-agp:
jobs:
- build-matrix:
matrix:
parameters: [7.4.0, 8.0.0, 8.1.0]
4.5 四个工具横向对比(快速查阅)
| 维度 | Jenkins | GitLab CI | GitHub Actions | CircleCI |
|---|---|---|---|---|
| 部署方式 | 自建(主从架构) | 托管+SaaS Runner | 全托管 | 全托管 |
| 缓存机制 | 手动配置(插件) | 内置缓存+手动Key | 内置缓存(无过期) | 内置+自动Layer Caching |
| AGP矩阵并行 | Declarative Pipeline | parallel:matrix | strategy:matrix | matrix jobs |
| 成本 | 服务器+运维人力 | 免费额度+额外分钟 | 免费2000分钟/月 | 按分钟收费(较贵) |
| 适合团队 | 有运维能力的大团队 | DevOps成熟团队 | 中小团队、开源项目 | 追求速度的付费团队 |
| 我踩过的坑 | 插件冲突、磁盘爆满 | API限流、Runner扩容配置 | 缓存污染、并发限制 | 缓存未命中→高额账单 |
4.6 我的选型建议
好了,啰嗦了这么多,最后给个实在的建议。我一般在项目启动时先问三个问题:
- 有没有现成的K8s集群? 有的话优先Jenkins,没有就考虑托管。
- 代码托管在哪? 如果你已经在GitHub上,就别折腾GitLab CI了,生态绑定很舒服。
- AGP版本矩阵有多大? 超过6个版本并行,建议用CircleCI或自建Jenkins,避免被免费层限制卡脖子。
一句话总结
没有最好的CI,只有最合适的。