手动构建、签名和上传 Flutter 应用的过程既繁琐又容易出错。你得找到正确的签名密钥,记住密码,运行构建命令,然后小心翼翼地将生成的 .aab 或 .apk 文件上传到 Google Play Console。这个过程不仅耗时,而且严重拖慢了版本更新的速度。
持续集成与持续部署(CI/CD) 就是解决之道。通过建立一条自动化流水线,我们可以确保每一次代码推送到仓库后,都能自动完成分析、测试、构建,甚至部署。
本指南将带领你使用 Bitbucket Pipelines 和 Fastlane,为你的 Flutter 应用搭建一条完整的 CI/CD 流水线。我们将从基础的测试和签名应用包构建开始,逐步实现完全自动部署到 Google Play 商店的内部测试轨道。
准备工作
- 一个已在 Bitbucket 仓库中的 Flutter 项目。
- 一个 Android 签名密钥(
.jks 文件)及其凭证(密钥库密码、密钥别名、密钥密码)。
- 你的 Bitbucket 仓库的管理权限。
第一部分:奠定基础 — 每次推送都进行构建和测试
首先,让我们创建一个能够在每次代码推送时,验证代码并构建已签名的 Android App Bundle 的流水线。
步骤 1:启用 Bitbucket Pipelines
这是最简单的一步:
- 在 Bitbucket 上导航到你的仓库。
- 在左侧边栏,点击 仓库设置(Repository settings) 。
- 在“Pipelines”部分下,点击 设置(Settings) 。
- 切换开关以启用 Pipelines。Bitbucket 会提供一些模板,目前你可以先忽略。
步骤 2:创建 bitbucket-pipelines.yml 文件
在你的 Flutter 项目的根目录(与 pubspec.yaml 同级),创建一个名为 bitbucket-pipelines.yml 的新文件。这个文件是自动化流程的核心,包含流水线的所有指令。
步骤 3:定义 Docker 镜像和缓存
YAML 文件的第一部分是定义执行环境。我们将使用一个社区维护的Flutter Docker 镜像的特定版本(这里以 Flutter 3.32.7 为例)。同时,缓存也至关重要,它可以避免每次构建时都重新下载 Flutter SDK 和 pub 包,从而加快构建速度。
image: ghcr.io/cirruslabs/flutter:3.32.7
definitions:
caches:
# Cache the Flutter SDK between builds
flutter: /flutter
# Cache the pub packages
pub: $HOME/.pub-cache
clone:
depth: 1 # Perform a shallow clone for faster checkout
步骤 4:创建第一个流水线(分析与测试)🧪
现在,我们来配置一个简单的流水线,让它在推送到任意分支时自动运行。这条流水线将负责拉取依赖项、分析代码并运行测试。
请将以下内容添加到你的 bitbucket-pipelines.yml 文件中:
pipelines:
default:
- step:
name: Analyze and Test
caches:
- pub
script:
# Get Flutter packages
- flutter pub get
# Run the linter/analyzer
- flutter analyze
# Run all widget tests (you can comment this out if you don't have tests)
- flutter test
步骤 4:创建第一个流水线(分析与测试)🧪
现在,我们来配置一条简单流水线,让它在代码推送到任意分支时自动运行。这条流水线将负责获取依赖项、分析代码,并运行测试。
请将以下内容添加到你的 bitbucket-pipelines.yml 文件中:
pipelines:
default:
- step:
name: Analyze and Test
caches:
- pub
script:
# Get Flutter packages
- flutter pub get
# Run the linter/analyzer
- flutter analyze
# Run all widget tests (you can comment this out if you don't have tests)
- flutter test
配置详解 ⚙️
让我们来分解一下这段配置的含义:
-
pipelines > default: 定义了一个流水线,它会在每一次提交(commit) 被推送时运行。
-
step: 一个流水线由一个或多个步骤组成,每个步骤都在一个全新的 Docker 容器中运行。
-
name: 一个描述性的名称,它将显示在 Bitbucket 的用户界面(UI)中。
-
caches: 指定此步骤应该使用我们在前面定义过的 pub 缓存。
-
script: 需要按顺序执行的 Shell 命令列表。
提交并推送这个文件。你应该就能在仓库的 “Pipelines” (流水线)部分看到你的第一个流水线开始运行了。
步骤 5:处理 Android 构建所需的密钥信息 🔑
你绝不应该将你的签名密钥或密码直接提交到仓库中。Bitbucket 提供了一种安全的方式来处理这些敏感信息,那就是**“仓库变量”(Repository variables)**。
5a. 编码你的 Keystore 文件和凭证
你的 .jks 文件是一个二进制文件。为了将其作为变量存储,我们必须使用 Base64 将其编码成文本格式。打开终端并运行相应的命令:
# On macOS/Linux
base64 -i my-upload-key.jks -o key.txt
# On Windows (using PowerShell)
[Convert]::ToBase64String([IO.File]::ReadAllBytes("my-upload-key.jks")) | Out-File -FilePath "key.txt"
运行上述命令会生成一个名为 key.txt 的文件,其中包含一个很长的字符串。请复制整个字符串。
现在,我们用同样的方法来处理 key.properties 文件,以便编码访问 .jks 文件所需的凭证。
# On macOS/Linux
base64 -i key.properties -o properties.txt
# On Windows (using PowerShell)
[Convert]::ToBase64String([IO.File]::ReadAllBytes("key.properties")) | Out-File -FilePath "properties.txt"
5b. 将变量添加到 Bitbucket 🔐
前往 仓库设置(Repository settings) -> 流水线(Pipelines) -> 仓库变量(Repository variables) 。
添加以下变量。至关重要的一点是,请为每个变量都勾选“已保护”(Secured)框。
| Variable Name | Value |
| ------------------------- | -------------------------------------------------- |
| `ANDROID_KEYSTORE_BASE64` | Paste the entire base64 string from `key.txt`. |
| `ANDROID_KEYPROPERTIES_BASE64` | Paste the entire base64 string from `properties.txt`. |
步骤 6:构建已签名的 Android 应用包(AAB)✅
现在,让我们创建一个新的流水线,让它在每次推送到 development 分支时,自动构建一个已签名的 .aab 文件。
请将以下代码块添加到你的 .yml 文件的 pipelines 键下:
# ... (image, definitions, and default pipeline from above) ...
pipelines:
# ... (default pipeline here) ...
branches:
development:
- step:
name: Analyze and Build App Bundle
size: 2x # Use a larger build container for performance
caches:
- pub
script:
- rm -f pubspec.lock
- flutter pub get
- flutter analyze
- flutter test
# Decode and write the keystore file from the repository variable
- echo $ANDROID_KEYSTORE_BASE64 | base64 -d > android/app/keystore.jks
# Create the key.properties file with the keystore credentials
- echo $ANDROID_KEYPROPERTIES_BASE64 | base64 -d > android/key.properties
# Build the app bundle
- flutter build appbundle --obfuscate --split-debug-info=./debug_info -t lib/main_dev.dart --release
artifacts:
# Save the built app bundle so it can be downloaded
- build/app/outputs/bundle/release/app-release.aab
关键新增内容解析 💡
-
branches > development: 这条流水线只会在代码推送到 development 分支时运行。
-
size: 2x: 构建 Flutter 应用是资源密集型的。设置 2x 会分配双倍内存,这能防止构建错误并加快速度。
-
echo … | base64 -d …: 这是至关重要的命令,它反转了我们之前的步骤。它取出安全的变量,将其从 Base64 解码,并重新写入一个二进制的 .jks 或 .properties 文件。
-
flutter build appbundle …: 我们使用标准的构建命令,带有混淆(obfuscation)和一个特定的入口点(-t lib/main_dev.dart)。
-
artifacts: 这告诉 Bitbucket 保存指定的文件(app-release.aab),你可以在流水线结果页面下载它。
第二部分:最后冲刺 — 使用 Fastlane 自动化部署到 Play Store 🚀
构建应用固然很好,但真正的魔力在于自动化部署。为此,我们将集成 Fastlane——一个专为自动化应用发布而设计的开源平台。
新工作流程概览
-
本地设置: 我们将先在本地设置 Fastlane,确保它可以正确地与 Google Play 商店通信。
-
Google 凭证: 我们将创建一个 Google Cloud 服务账号,Fastlane 将使用它进行身份验证。
-
安全变量: 我们将对秘密的服务账号 JSON 密钥进行编码,并将其安全地存储在 Bitbucket 中。
-
流水线更新: 我们将修改
.yml 文件,使其安装并运行 Fastlane,由 Fastlane 处理构建和部署工作。
步骤 1:获取 Google Play API 凭证 🔑
Fastlane 需要一个服务账号才能代表你执行操作。
创建服务账号
- 在 Google Cloud Console 中,导航到 IAM 与管理(IAM & Admin) -> 服务账号(Service Accounts) 。
- 点击 + 创建服务账号(+ CREATE SERVICE ACCOUNT) ,给它命名(例如:
bitbucket-ci-cd-deploys),然后点击 创建并继续(CREATE AND CONTINUE) 。
- 在“授予此服务账号对项目的访问权限”下,添加角色 “服务账号用户”(Service Account User) 。点击 继续(CONTINUE) ,然后 完成(DONE) 。
创建并下载 JSON 密钥
- 找到你刚创建的服务账号。点击旁边的三个点菜单,选择 管理密钥(Manage keys) 。
- 点击 添加密钥(ADD KEY) -> 创建新密钥(Create new key) 。选择 JSON 并点击 创建(CREATE) 。
- 一个 JSON 文件(例如:
your-service-account-key.json)将被下载。这个文件就是你的密码,务必保持安全,不要提交到仓库中。
在 Play Console 中授予权限
- 前往 Google Play Console 的 用户与权限(Users & Permissions) 页面,点击 邀请新用户(Invite new users) 。
- 粘贴服务账号的电子邮件地址,并授予所需的权限(例如:管理员(Admin) 或特定的 发布经理(Release Manager) 角色)。点击 邀请用户(Invite user) 。
步骤 2:在本地安装和配置 Fastlane 🛠️
我们将在你的 Flutter 项目的 android 目录中设置 Fastlane。
安装 Fastlane
请遵循 Fastlane 官方设置指南。强烈建议使用 Bundler。
初始化 Fastlane
- 在终端中进入你的项目
android 目录:cd android。
- 运行
fastlane init。
- 它会要求输入你的应用的包名和秘密 JSON 文件的路径(例如:
./your-service-account-key.json)。
配置 fastlane/Appfile
确保其中的路径设置是正确的。
# fastlane/Appfile
json_key_file("./your-service-account-key.json") # Path to your JSON key
package_name("com.your.app.package")
4. 安装 flutter_version 插件 🛠️
为了能自动从 pubspec.yaml 文件中获取应用的版本名称(version name) 和版本代码(version code) ,请在 android 目录下运行此命令:
bundle exec fastlane add_plugin flutter_version
5. 配置 fastlane/Fastfile 🛠️
这里就是你定义 “快车道”(lanes) 的地方。请用以下内容替换掉文件中的原有内容:
# fastlane/Fastfile
default_platform(:android)
platform :android do
desc "Builds and deploys to the Google Play internal testing track"
lane :deploy_internal do
# Go up to the root to run Flutter commands
Dir.chdir("..") do
sh("flutter", "build", "appbundle", "--obfuscate", "--split-debug-info=./debug_info", "-t", "lib/main_dev.dart", "--release")
end
version_info = flutter_version()
version_name = version_info["version_name"] # e.g., "1.2.3"
build_number = version_info["version_code"] # e.g., "45"
# Upload to the Play Store
upload_to_play_store(
track: 'internal', # Deploy to the internal testing track
aab: '../build/app/outputs/bundle/release/app-release.aab',
version_name: "#{version_name}(#{build_number})"
)
end
end
6. 在本地进行测试(强烈推荐)✅
在你的终端(仍需位于 android 目录中)运行命令:fastlane deploy_internal。如果这条命令成功运行,那么你就准备好进行自动化部署了。
更新 .gitignore 文件 🔒
确保你的根目录下的 .gitignore 文件包含了那个秘密的 JSON 密钥文件:
/android/your-service-account-key.json
/android/gemfile.lock
步骤 4:更新 Bitbucket Pipelines 以进行部署 🚀
最后一步,让我们把 Fastlane 集成到 bitbucket-pipelines.yml 文件中。
将 JSON 密钥添加为安全变量 🔒
像处理 Keystore 文件一样,你需要对 JSON 密钥文件进行编码:
base64 -i your-service-account-key.json -o play-key.txt
将字符串从 play-key.txt 文件中复制出来。
前往 仓库设置(Repository settings) -> 仓库变量(Repository variables) ,添加一个新的受保护变量,命名为 GPLAY_SERVICE_ACCOUNT_KEY_BASE64,并将复制的字符串粘贴为它的值。
修改 bitbucket-pipelines.yml 文件 ⚙️
用这个新版本的流水线替换掉你原有的 development 分支流水线。它会简化很多,因为 Fastlane 替我们处理了大部分逻辑。
branches:
development:
- step:
name: Build and Deploy to Internal Testing
size: 2x
caches:
- pub
script:
# Basic setup and analysis
- rm -f pubspec.lock
- flutter pub get
- flutter analyze
# Restore Android Keystore for the build
- echo $ANDROID_KEYSTORE_BASE64 | base64 -d > android/app/keystore.jks
# Create the key.properties file with the keystore credentials
- echo $ANDROID_KEYPROPERTIES_BASE64 | base64 -d > android/key.properties
# Restore Google Play API key for Fastlane
- echo $GPLAY_SERVICE_ACCOUNT_KEY_BASE64 | base64 -d > android/your-service-account-key.json
# --- Deployment via Fastlane ---
- cd android
- bundle install
- bundle exec fastlane deploy_internal
artifacts:
# Save the built artifact just in case
- build/app/outputs/bundle/release/app-release.aab
结论 🎉
恭喜! 你现在拥有了一条强大且完全自动化的 CI/CD 流水线。
今后,每一次推送到你的 development 分支的代码,都将无需任何手动干预,自动完成分析、构建、签名,并部署到 Google Play 商店的内部测试人员手中。
这套设置不仅为你节省了无数时间,还确保了发布流程的一致性、可靠性和安全性,让你能够专注于你最擅长的事情:构建出色的应用!