GitLab CI 是 GitLab 内置的持续集成和交付系统,通过 YAML 配置中的流水线自动完成移动应用的构建、测试和部署。根据 GitLab 2024 年数据,该平台每月处理 超过 3 亿个流水线,并同时支持云端和自托管 runner。
要点
GitLab CI 是 GitLab 统一 DevSecOps 应用程序的一部分,涵盖持续集成、交付和部署。该系统于 2012 年作为一个独立项目出现,但后来被直接集成到 GitLab 中。基本原则是通过仓库根目录中的 .gitlab-ci.yml 文件实现配置即代码(Configuration as Code)。GitLab CI 既可在云端 SaaS 版本中使用,也可在自托管安装中使用。
对于移动开发,GitLab CI 提供 APK 和 IPA 构建的自动化、工具测试的执行、静态代码分析、应用签名以及应用商店发布。该平台支持用于自定义环境的 Docker 镜像,允许预安装 Android SDK、NDK、Xcode 和其他工具。内置的 Container Registry 简化了团队内部镜像的存储和分发。
GitLab CI 架构由三个关键组件组成。GitLab Runner 是执行任务的代理。Runner 可以是共享的(由 GitLab 提供)、组的(用于项目组)和特定的(用于单个项目)。每个 runner 注册时需要指定执行器:Shell、Docker、Kubernetes 或 VirtualBox。GitLab Runner 支持自动扩展以处理峰值负载。
Pipeline 是依次执行的 stage 的集合。在一个 stage 内,任务并行执行。移动项目的典型结构:build → test → deploy。如果 test stage 上的任务以错误结束,则不会启动 deploy。可以为部署配置手动启动(when: manual)。还支持多项目流水线触发器,用于仓库之间的复杂 CI/CD 场景。
Docker 执行器是移动应用 CI/CD 中最流行的。每个任务都在干净的 Docker 容器中启动,这保证了隔离性和可重复性。对于 Android 构建,使用带有预装 SDK 的 android-sdk 镜像;对于 iOS,使用带有 Shell 执行器的 macOS runner。
.gitlab-ci.yml 文件以 YAML 格式定义流水线。主要部分:image(Docker 镜像)、stages(阶段列表)、variables(环境变量)、before_script(每个任务之前的命令)以及带有 script、artifacts、cache 部分的任务本身。GitLab CI 支持 include — 连接外部 YAML 文件,以便在项目之间重用共享配置。
GitLab CI 中的变量可以在多个级别设置:UI 中的全局变量、配置文件中、组和项目设置中。变量的优先级由层级决定:触发变量具有最高优先级,然后是 UI 中的 CI/CD 变量,再是 .gitlab-ci.yml 中的变量。变量可以受保护(protected),使其仅对受保护的分支和标签可用。
image: openjdk:17-jdk-slim
variables:
ANDROID_SDK_VERSION: "35"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
stages:
- build
- test
- deploy
cache:
key: $CI_COMMIT_REF_SLUG
paths:
- .gradle/
generate-apk 任务构建 Gradle 项目并将 APK 保存为构件。构件在 stage 之间传递 — deploy 任务可以使用 build 中的 APK。构件的存储期限通过 expire_in 配置。
generate-apk:
stage: build
script:
- ./gradlew assembleRelease
artifacts:
paths:
- app/build/outputs/apk/release/
expire_in: 1 day
在为移动项目选择 GitLab CI 和 GitHub Actions 时,考虑团队的基础设施很重要。GitLab CI 提供了一个内置的 Container Registry,可用于存储带有 Android SDK 的 Docker 镜像。GitHub Actions 依赖于 GitHub Packages 或外部注册表。GitLab 还具有内置的 SAST(静态应用程序安全测试)用于代码漏洞分析。
GitLab CI 提供更灵活的 runner 模型 — 支持 Kubernetes 执行器、自动扩展和自定义镜像。GitHub Actions 在与 GitHub 生态系统和 Actions 市场的集成上胜出。GitLab CI 需要为许多在 GitHub Actions 中用现成 action 解决的任务进行手动配置。
从移动项目的 CI/CD 角度来看:GitLab CI 更适合已经使用 GitLab Self-Managed 并且需要带有 Docker/Kubernetes 的自托管 runner 的公司。GitHub Actions 对于使用云端 GitHub、重视现成 action 和配置简单性的小团队来说更方便。
| 特性 | GitLab CI | GitHub Actions |
|---|---|---|
| 配置 | .gitlab-ci.yml | .github/workflows/*.yml |
| Runner | 自托管 + 共享 | 托管 + 自托管 |
| 执行器 | Docker、K8s、Shell | VM(Ubuntu、macOS、Win) |
| 步骤商店 | 无(CI 模板) | 市场(15k+ action) |
| iOS 构建 | macOS runner 或 K8s | macOS 托管 runner |
Android 的完整流水线包括:lint、单元测试、构建和部署到 Firebase App Distribution。该流水线使用带有 Android SDK 的 Docker 镜像、Gradle 缓存以及在一个 stage 中并行执行 lint 和测试。这种方法缩短了流水线的总时间,因为 lint 和测试任务互不依赖。
对于 iOS 项目,由于需要 macOS runner 和代码签名,流水线结构有所不同。典型的 iOS 流水线包括:安装 CocoaPods 或 SPM、在模拟器上运行测试、归档 Xcode 项目、导出 IPA 并上传到 TestFlight。GitLab CI for iOS 使用 macOS runner — 要么是带时间限制的 GitLab SaaS macOS runner,要么是在 Mac mini 或 MacStadium 上自托管的 runner。
image: androidsdk/android-35:latest
stages:
- lint
- test
- build
- deploy
lint-check:
stage: lint
script: ./gradlew lint
unit-tests:
stage: test
script: ./gradlew test
assemble-release:
stage: build
script: ./gradlew assembleRelease
artifacts:
paths: [app/build/outputs/apk/release/]
deploy-firebase:
stage: deploy
script:
- firebase appdistribution:distribute
--app $FIREBASE_APP_ID
--token $FIREBASE_TOKEN
--groups testers
GitLab CI 中移动构建流水线的优化需要关注细节。正确配置缓存和构件可以将构建时间缩短数倍。对于性能分析,GitLab 提供 CI/CD Analytics — 一个包含流水线持续时间、runner 负载和瓶颈指标的面板。定期分析这些指标以寻找优化机会。resource_group 设置会阻止单个流水线的并行运行 — 这对于防止部署时的冲突很有用。
CI 的分支策略也很重要。建议仅对 main 和 release 分支运行完整流水线,对于功能分支仅运行 lint 和单元测试。这可以节省 runner 分钟并加快对开发人员的反馈。GitLab CI 支持 workflow:rules — 根据分支、修改的文件或环境变量来包含或排除任务的条件规则。
依赖缓存是加速的主要方式。GitLab CI 在运行之间缓存 .gradle、Pods 和 node_modules。缓存键包含 $CI_COMMIT_REF_SLUG 或锁定文件的哈希值。通过正确的缓存,Android 项目的构建时间从 10-15 分钟减少到 2-4 分钟。缓存可以是分布式的 — GitLab 支持带有回退到先前键的 cache:key。
带有预装工具的 Docker 镜像可以节省安装时间。建议创建带有 Android SDK、NDK 和所需 API 级别的自定义镜像。在不同 stage 中并行执行任务(lint、test、assemble)可以缩短流水线的总时间。镜像的拉取策略(if-not-present)可以加快任务的启动。还可以使用依赖代理在 GitLab 实例级别缓存镜像。
优化的另一个重要方面是在阶段之间使用构件。重文件 APK 和 IPA 最好通过依赖关系传递,而不是在每个任务中重新构建。对于有数十个模块的大型项目,建议在流水线级别启用 Gradle Build Cache,并在共享存储上配置远程缓存。每个任务的超时时间应根据预期的构建时间设置 — 这可以防止进程挂起。
cache:
key: $CI_COMMIT_REF_SLUG
paths:
- .gradle/
- app/build/
image:
name: registry.example.com/android-builder:3.5
pull_policy: if-not-present
常见问题
在 GitLab.com 上,免费计划包含每月 400 分钟 CI/CD 和 5 个用户。高级版(29 美元/月)提供 10000 分钟和更多并行任务。自托管 GitLab 没有分钟限制。
使用现成的 Docker 镜像 androidsdk/android-35,或者通过 before_script 中的 sdkmanager 安装 SDK。在 variables 中指定 ANDROID_SDK_ROOT 和 ANDROID_NDK_HOME 以确保 Gradle 正常运行。
GitLab CI 提供内置 Container Registry、Kubernetes 集成和自托管自动扩展。GitHub Actions 在现成 action 的数量和对小团队的简易性方面胜出。
可以,但 iOS 需要 macOS runner。可以使用 GitLab SaaS macOS runner(有限制),也可以在 Mac Mini 上配置自托管 runner。GitLab 本身不提供云端 macOS 基础设施。
通过 artifacts — 一个任务的文件在流水线框架内传递给另一个任务。通过缓存 — 用于运行之间的依赖关系。通过 CI/CD 变量 — 用于文本值和令牌。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。