前言
关于CI
在文章开始之前,首先还是简单介绍一下,CI是什么
CI——Continuous integration:持续集成。是一种软件开发实践,每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。
为什么要使用CI
使用CI的原因也很简单,就像上面介绍的一样,通过CI我们可以解放双手,让项目实现自动化集成,同时它还能够保证项目的可靠性以及交付能力。
至于这里,最显而易见的好处就是可以每次提交完代码,自动编译并且上传Apk,麻麻再也不用担心我去手动操作啦!
介绍了以上部分,就让我们来开始实际操作一波吧
使用
由于本篇文章使用的是gitlab提供的CI功能,所以在gitlab仓库中是需要存放着你的项目的。至于为什么使用gitlab的CI而不是Travis的CI,当然不是因为gitlab提供的CI免费, 只是项目刚好放在gitlab仓库里面,仅此而已!
在开始介绍如何使用之前,你也可以直接进入到官方原文档去进行了解:【流水线入门】
下面开始来正式操作
一、配置启动器(Runner)
首先我们需要先构建好一个启动器
初始化 Runner
原文地址:【Install GitLab Runner】
这里以macOS来做说明,如果你是Windows或其他操作系统,可以在上面的地址中找到对应操作说明,大致都是一样的几行代码。
这里通过代码手动安装:
1.下载gitlab runner
sudo curl --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64
如果你的下载速度非常慢,也可以直接通过上面命令的链接下载文件,然后进入到 /usr/local/bin/ 目录将下载的文件改名为 gitlab-runner 放入到目录中
2.授权
sudo chmod +x /usr/local/bin/gitlab-runner
下载并且授权成功后,开始下一步
注册 Runner
原文地址:【Registering Runners】
注册前可以先进入到gitlab项目中的 设置-> CI/CD -> Runner
查看专用Runner的相关信息,后面会用到【URL】和【注册令牌(token)】
1.运行如下代码(这里还是是以macOS为例,其他系统代码可以通过上面链接查阅)
gitlab-runner register
2.输入上图中的URL:
https://gitlab.com
3.输入上图中的token(注册令牌)
xxxxxxx这里填入你自己的令牌
4.添加描述:
ci集成测试
5.添加tag
build
6.选择Runner的执行器(这里选择的是docker)
docker
还可以选择:ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell:
docker等
7.选择上面执行器的版本(由于上面选择了docker,所以下面是docker的版本)
alpine:latest
效果如下:
注册完成后再去设置界面,会发现多了一个“已激活的运行器”
这表示你的Runner已经注册成功了!
(注:如果没有运行在服务器上的docker,此项没必要开启,可以直接使用右边的"启用共享运行器")
启动Runner
接着上面输入以下命令,来初始化并且启动Runner服务
cd ~
gitlab-runner install
gitlab-runner start
然后我们开始准备创建 .gitlab-ci.yml 文件用于进行Runner的配置
二、创建 .gitlab-ci.yml 文件
在gitlab提供的ci指引中,首先需要在项目的根目录下创建一个 .gitlab-ci.yml 文件,用于进行CI操作的配置
这里我们主要以配置 Flutter项目 为例子,下面是文件内容:
image: openjdk:8-jdk
variables:
ANDROID_COMPILE_SDK: "28"
ANDROID_BUILD_TOOLS: "28.0.3"
ANDROID_SDK_TOOLS: "4333796"
#cache:
# key: flutter_sdk_cache
# paths:
# - .gradle/wrapper
# - .gradle/caches
before_script:
# android
- apt-get --quiet update --yes
- apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1
- wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_TOOLS}.zip
- unzip -d android-sdk-linux android-sdk.zip
- echo y | android-sdk-linux/tools/bin/sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" >/dev/null
- echo y | android-sdk-linux/tools/bin/sdkmanager "platform-tools" >/dev/null
- echo y | android-sdk-linux/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS}" >/dev/null
- export ANDROID_HOME=$PWD/android-sdk-linux
- export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/
# 暂时禁用检查错误,并使用yes接受所有许可证
- set +o pipefail
- yes | android-sdk-linux/tools/bin/sdkmanager --licenses
- set -o pipefail
# flutter
- wget --output-document=flutter-sdk.tar.xz https://storage.googleapis.com/flutter_infra/releases/stable/linux/flutter_linux_v1.5.4-hotfix.2-stable.tar.xz
- tar -xf flutter-sdk.tar.xz
- export PATH=$PATH:$PWD/flutter/bin
- export PUB_HOSTED_URL=https://pub.flutter-io.cn
- export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
- echo flutter.sdk=$PWD/flutter > android/local.properties
- cd android
- rm -rf android/.gradle
stages:
- android-build
assembleRelease:
stage: android-build
only:
- dev
script:
- cd ..
# - flutter doctor
- flutter packages get
- flutter build apk
artifacts:
paths:
- build/app/outputs/apk/release/app-release.apk
下面做一个简单的说明:
- 【image: openjdk:8-jdk】:由于前面我们选择的Runner执行器是docker,而这里是配置docker所需要的参数
- 【variables】:表示Android SDK、Tool的版本号
- 【before_script】:在执行script中的代码前执行的内容,这其中包含了Android SDK 及 Flutter SDK的下载,如果想保持Flutter为最新版,可以把下载Flutter SDK的代码换成从github上克隆flutter
- 【stages】:这里写下将要执行的各个阶段,例子中为了简便起见只写了一个
- 【only】:用于限制仓库执行的分支
- 【script】:将后面需要执行的代码放在这里,例子中表示编译一个apk
- 【artifacts】:可以将每次打包的apk直接放在流水线上下载
由于我们需要进行Flutter的Android apk打包,所以在打包之前,我们还要准备好Android的签名证书
关于如何生成证书,也可以参考官方文档:
签署您的应用
生成签名证书
进入到Flutter项目中的【android】目录,输入以下命令:
keytool -genkey -v -keystore my-release-key.jks
-keyalg RSA -keysize 2048 -validity 10000 -alias my-alias
然后根据提示一步步进行操作:
操作成功后就可以看到项目中新生成的jks文件:
这里可以将迁移前的 my-release-key.jks.old 删除掉
jks文件生成后,就可以进行证书配置了
配置签名证书
进入到下面的目录 :【Flutter项目 -> android -> app】
然后找到 build.gradle 文件,主要在这个文件中进行配置
在操作这个文件之前,我们先在 android 目录下新建另外一个文件,用来辅助后面的操作:
新建【key.properties】文件,文件中写入以下内容
storePassword=flutter
keyPassword=flutter
keyAlias=my-alias
storeFile=../my-release-key.jks
这其中的各个字段是在创建签名证书过程中你所输入的内容,而 storeFile 用于表示jks文件的相对路径,后面配置时会使用到,现在项目结构如下:
然后我们打开 app 目录下的 build.gradle 文件进行修改,分别添加以下内容:
def keystorePropertiesFile = rootProject.file("key.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android{
...
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
...
}
可以对比下面的图片,避免代码块放错位置
这时候证书的配置就完成了!
我们可以通过本地运行 flutter build apk 命令来检测是否可以成功打包:
如果出现异常,可以对照说明看看是否哪个步骤出现了问题
通过gitlab ci的Variables读取证书
上述过程中签名证书的密码都存放在了本地,这里可以通过gitlab的variables来导入参数,从而避免本地存放证书密码。
上图中定义了四个变量,接下来我们修改【Flutter项目 -> android -> app】目录下的build.gradle文件:
def appKeyPassword = System.getenv('KEY_PASSWORD')
def appStorePassword = System.getenv('STORE_PASSWORD')
def appKeyAlias = System.getenv('KEY_ALIAS')
def appStoreFile = System.getenv('STORE_FILE')
android{
...
signingConfigs {
if(System.getenv('STORE_FILE') == null){
def keystorePropertiesFile = rootProject.file("key.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
} else{
release {
keyAlias appKeyAlias
keyPassword appKeyPassword
storeFile file(appStoreFile)
storePassword appStorePassword
}
}
}
...
}
这样就可以删除掉 android 目录下的 key.properties 文件直接在gitlab上打包了
(代码中兼容了本地打包的场景,所以尚未删除掉文件,实际生产过程中可以将该文件忽略上传至仓库)
检测结果
下面,我们就可以把项目上传到gitlab,接下来我们就可以在“流水线”中看到以下内容了:
由于之前在 .gitlab-ci.yml 文件中限制只运行dev分支自动构建,所以前面的master分支都已自动跳过
进入到构建详情页可以看到如下内容:
至此,使用CI构建Flutter项目并打包apk就告一段落。当然还有部分功能是暂时没有用到的,比如将生成的apk文件上传到其他地方,使用cache功能加速构建等
结束
最后放下项目地址以供参考:
【ci_test_project】
然后是参考文章:
Setting up GitLab CI for Android projects
Setup Gitlab CI in Flutter-Android Project