构建变体与CI/CD:在命令行中构建变体、配置Gradle任务、集成到Jenkins/GitHub Actions

说实话,很多Android开发者对构建变体的理解,就停留在「debug和release两个版本」上。但当你真正进入团队协作、自动化交付的阶段,你会发现构建变体才是整个工程体系的基石。今天我们就来聊聊,怎么在命令行里玩转构建变体,怎么配置Gradle任务,以及怎么把它们集成到Jenkins或GitHub Actions里。

一、构建变体到底是什么?

构建变体 = 构建类型 × 产品风味。这个公式我估计大家都见过,但真正理解它的人不多。我刚开始带团队时,就遇到过有人把debug和release当成两个独立APK来维护,结果代码里全是if-else判断,维护成本直线上升。

构建类型(Build Type)通常就是debug和release,控制的是签名、混淆、可调试性这些属性。产品风味(Flavor)则用来区分不同的产品版本,比如免费版和付费版,或者国内版和海外版。

核心公式:构建变体 = 构建类型 × 产品风味

举个例子:你有free和paid两个风味,debug和release两个类型,那么就会生成4个变体:freeDebug、freeRelease、paidDebug、paidRelease。

二、在命令行中构建变体

为什么要用命令行?因为CI/CD环境没有图形界面。你想想看,Jenkins服务器上哪来的Android Studio?所以掌握命令行构建是自动化部署的第一步。

2.1 基础命令

# 列出所有可用的构建变体
./gradlew assembleDebug --list

# 构建特定变体
./gradlew assembleFreeDebug

# 构建所有变体
./gradlew assemble

# 构建所有release变体
./gradlew assembleRelease

我个人习惯在本地开发时用./gradlew assembleFreeDebug,因为只构建一个变体,速度最快。但CI/CD环境里,我通常会跑./gradlew assembleRelease,一次性生成所有release版本。

小技巧:如果你只想构建某个风味的所有类型,可以用./gradlew assembleFree,它会同时构建freeDebug和freeRelease。

2.2 传递参数

命令行构建时,经常需要传递一些参数。比如指定版本号、渠道号等。

# 传递版本号
./gradlew assembleFreeRelease -PversionCode=100 -PversionName="1.0.0"

# 指定签名配置
./gradlew assemblePaidRelease -PsigningConfigName="release"

我曾经在项目中遇到过一个问题:本地构建没问题,但Jenkins上构建出来的APK签名不对。后来发现是Jenkins环境变量没传对。嗯,这里要注意,CI/CD环境里的签名文件路径和密码,最好通过环境变量注入,不要硬编码在build.gradle里。

三、配置Gradle任务

Gradle任务就像是构建流水线上的一个个工序。你可以自定义任务,也可以利用已有的任务。

3.1 自定义任务示例

// 在app/build.gradle中
task printBuildVariant {
    doLast {
        println "当前构建变体: ${android.defaultConfig.versionName}"
        println "构建类型: ${android.buildTypes.each { it.name }}"
    }
}

// 依赖关系
assembleFreeDebug.dependsOn printBuildVariant

说白了,Gradle任务就是一段Groovy代码,你可以用它做任何事情:生成版本号、上传APK到服务器、发送通知等等。

3.2 常用内置任务

任务名称 作用
assemble 构建所有变体
lint 代码静态检查
test 运行单元测试
connectedCheck 运行设备测试
clean 清理构建产物

注意:在CI/CD环境中,建议先跑./gradlew clean再构建,避免缓存导致的问题。我曾经因为没清理缓存,导致Jenkins构建出来的APK还是旧代码,排查了半天才发现是缓存问题。

四、集成到Jenkins

Jenkins是目前最流行的CI/CD工具之一。集成Android构建其实不复杂,核心就是配置好构建步骤。

4.1 Jenkins Pipeline示例

pipeline {
    agent any
    
    environment {
        ANDROID_HOME = '/opt/android-sdk'
        KEYSTORE_PATH = credentials('keystore-path')
        KEYSTORE_PASSWORD = credentials('keystore-password')
    }
    
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        
        stage('Build') {
            steps {
                sh './gradlew clean assembleRelease'
            }
        }
        
        stage('Test') {
            steps {
                sh './gradlew test'
            }
        }
        
        stage('Archive') {
            steps {
                archiveArtifacts artifacts: 'app/build/outputs/apk/**/*.apk'
            }
        }
    }
}

我个人建议在Jenkins里把构建和测试分开成不同的stage,这样如果测试失败,可以快速定位问题,不用重新跑整个构建流程。

4.2 常见问题

  • SDK路径问题:Jenkins服务器上要提前配置好ANDROID_HOME环境变量
  • 签名问题:签名文件不要放在代码仓库里,用Jenkins的凭据管理功能
  • 内存不足:Gradle构建很吃内存,建议给Jenkins分配至少4GB内存

五、集成到GitHub Actions

GitHub Actions是GitHub自带的CI/CD工具,配置起来比Jenkins简单很多。我个人更喜欢用GitHub Actions做小团队的自动化构建,因为不用自己维护服务器。

5.1 GitHub Actions Workflow示例

name: Android CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'temurin'
    
    - name: Build with Gradle
      run: ./gradlew assembleRelease
    
    - name: Upload APK
      uses: actions/upload-artifact@v3
      with:
        name: app-release
        path: app/build/outputs/apk/release/app-release.apk

你想想看,GitHub Actions最大的优势是什么?是免费!对于开源项目来说,完全不用操心服务器费用。而且它和GitHub仓库深度集成,PR触发构建、自动发布release,这些功能都是开箱即用。

5.2 多风味构建

# 构建所有风味
- name: Build all flavors
  run: |
    ./gradlew assembleFreeRelease
    ./gradlew assemblePaidRelease

提示:GitHub Actions支持矩阵构建,可以同时跑多个构建任务,大幅缩短总构建时间。比如同时构建free和paid两个风味,互不干扰。

六、构建变体与CI/CD的最佳实践

说了这么多,最后总结几条我踩过坑之后得出的经验:

  1. 版本号自动化:不要在代码里硬编码版本号,用Gradle的versionCode和versionName,通过CI/CD环境变量注入
  2. 签名分离:debug签名用默认的,release签名用CI/CD环境里的,不要混用
  3. 构建产物命名:建议用app-{flavor}-{version}-{buildNumber}.apk的格式,方便追溯
  4. 缓存优化:Gradle的缓存机制很强大,CI/CD环境里建议开启缓存,能节省50%以上的构建时间

避坑指南:我曾经在GitHub Actions里忘记配置JDK版本,结果默认的JDK 11和Android Gradle Plugin不兼容,构建一直失败。后来加了setup-java步骤才解决。所以,CI/CD配置里的每一个步骤都要仔细检查,不要想当然。

七、知识体系总览

下面这张图展示了构建变体与CI/CD的核心逻辑关系,我把它画成了流程图,方便你理解整个体系:

构建变体与CI/CD核心流程 代码仓库 CI/CD触发 Gradle构建 FreeDebug FreeRelease PaidRelease APK输出 APK输出 APK输出

从这张图可以看出,整个流程其实很清晰:代码提交触发CI/CD,然后Gradle根据配置生成不同的构建变体,最终输出对应的APK文件。每个环节都有它的作用,缺一不可。

好了,关于构建变体与CI/CD的内容就聊到这里。记住,自动化构建不是一蹴而就的,需要根据团队的实际需求逐步完善。刚开始可以只做最简单的assembleRelease,后面再慢慢加上测试、代码检查、自动发布等功能。

公众号:蓝海资料掘金营,微信deep3321