解放双手,使用Gitlab CI功能自动打包Flutter apk

前言

关于CI

在文章开始之前,首先还是简单介绍一下,CI是什么

CI——Continuous integration:持续集成。是一种软件开发实践,每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

为什么要使用CI

使用CI的原因也很简单,就像上面介绍的一样,通过CI我们可以解放双手,让项目实现自动化集成,同时它还能够保证项目的可靠性以及交付能力。

至于这里,最显而易见的好处就是可以每次提交完代码,自动编译并且上传Apk,麻麻再也不用担心我去手动操作啦!

解放双手,使用Gitlab CI功能自动打包Flutter apk_第1张图片

介绍了以上部分,就让我们来开始实际操作一波吧

使用

由于本篇文章使用的是gitlab提供的CI功能,所以在gitlab仓库中是需要存放着你的项目的。至于为什么使用gitlab的CI而不是Travis的CI,当然不是因为gitlab提供的CI免费, 只是项目刚好放在gitlab仓库里面,仅此而已!

解放双手,使用Gitlab CI功能自动打包Flutter apk_第2张图片

在开始介绍如何使用之前,你也可以直接进入到官方原文档去进行了解:【流水线入门】

解放双手,使用Gitlab CI功能自动打包Flutter apk_第3张图片

下面开始来正式操作

一、配置启动器(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)】

解放双手,使用Gitlab CI功能自动打包Flutter apk_第4张图片

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

效果如下:

解放双手,使用Gitlab CI功能自动打包Flutter apk_第5张图片

注册完成后再去设置界面,会发现多了一个“已激活的运行器”

解放双手,使用Gitlab CI功能自动打包Flutter apk_第6张图片

这表示你的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

然后根据提示一步步进行操作:

解放双手,使用Gitlab CI功能自动打包Flutter apk_第7张图片

操作成功后就可以看到项目中新生成的jks文件:

解放双手,使用Gitlab CI功能自动打包Flutter apk_第8张图片

这里可以将迁移前的 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文件的相对路径,后面配置时会使用到,现在项目结构如下:

解放双手,使用Gitlab CI功能自动打包Flutter apk_第9张图片

然后我们打开 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']
        }
    }
    ...
    
}

可以对比下面的图片,避免代码块放错位置

解放双手,使用Gitlab CI功能自动打包Flutter apk_第10张图片

这时候证书的配置就完成了!

我们可以通过本地运行 flutter build apk 命令来检测是否可以成功打包:

解放双手,使用Gitlab CI功能自动打包Flutter apk_第11张图片

如果出现异常,可以对照说明看看是否哪个步骤出现了问题

通过gitlab ci的Variables读取证书

上述过程中签名证书的密码都存放在了本地,这里可以通过gitlab的variables来导入参数,从而避免本地存放证书密码。

解放双手,使用Gitlab CI功能自动打包Flutter apk_第12张图片

上图中定义了四个变量,接下来我们修改【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功能自动打包Flutter apk_第13张图片

由于之前在 .gitlab-ci.yml 文件中限制只运行dev分支自动构建,所以前面的master分支都已自动跳过

进入到构建详情页可以看到如下内容:

解放双手,使用Gitlab CI功能自动打包Flutter apk_第14张图片

至此,使用CI构建Flutter项目并打包apk就告一段落。当然还有部分功能是暂时没有用到的,比如将生成的apk文件上传到其他地方,使用cache功能加速构建等

结束

最后放下项目地址以供参考:

【ci_test_project】

然后是参考文章:

Setting up GitLab CI for Android projects

Setup Gitlab CI in Flutter-Android Project

你可能感兴趣的:(解放双手,使用Gitlab CI功能自动打包Flutter apk)