Flutter多分支打包持续化集成
创始人
2024-05-10 02:43:17
0

一、使用效果演示

1.1、选择参数打包

以下为参数使用说明。

  • packingType枚举
android、ios
android
ios
android&ios (新功能:并行打包)

备注:

android、ios:串行打包,即先打一个再打一个

android&ios:为并行打包

  • useOnlineConfig

勾选这个会使用线上配置打包app,专门用于发生产打包

image-20220127202810611
  • brandName

选择git分支,脚本会自动切分支打包

  • 其他

此外,你也可以添加app“默认api环境”、“代理ip”等,由于我们这块都集成到app内部调试页中了,可以用户手动切换,所以不需要就没列举出来。

1.2、任务细节展示

image-20220127202810611

1.3、结果输出

  • 保存历史记录到打包机器

一共四份文件(android 32位包、64位包、ios包、打包信息.txt)

小技巧:对于关键的打包,你也可以使用mac标签为红色,这样方便你下次查找。

image-20220127202810611
  • 同步到钉钉
image-20220127202810611

二、实现步骤

2.1、配置jenkins

创建任务后,选择参数化构建过程,添加参数:

packingType:选择选项参数

useOnlineConfig:选择布尔值参数

image-20220127202810611

branchName:选择Git参数

image-20220127202810611

选择源码管理tab添加项目参数

image-20220127202810611

其中Credentials凭证如果没有需要添加

我这边用的http,只需要添加用户名、密码即可,描述可以随便填一个方便自己查看

image-20220127202810611

最后切换到构建tab

选择执行shell,cd到指定目录执行本地脚本

cd /Users/mac/Desktop/diamond-app/PackageShellFiles
sh buildApp.sh
image-20220127202810611

2.2、编写脚本

这里脚本我拆成了两个,一个打包脚本,一个上传文件脚本

打包脚本:buildApp.sh

#!/bin/bashexport ANDROID_SDK_ROOT="${HOME}/Library/Android/sdk"
export ANDROID_HOME="${HOME}/Library/Android/sdk"#获取workspace名称
projectName=jiyueji#文件导出目录(projectName/workspace名称+当前时间)
exportPath=~/Desktop/${projectName}/$(date +"%F日%H-%M-%S秒")#apk路径(取到apk的路径)
appAndroidPath=${exportPath}/${projectName}.apk
appIosPath=${exportPath}/${projectName}.ipa#git更新信息
gitUpdateInformation=''# jenkins选择的分支: origin/dev
echo "打包分支全称:${branchName}"# jenkins选择的分支简称: dev
selectBranch=${branchName#*/}#创建文件夹
createDir() {echo "创建文件目录"if [ ! -d "${exportPath}" ]; thenmkdir -p ${exportPath}fiecho "文件夹创建成功,打包中间产物将全部导出到:${exportPath}目录下\n"
}# android包
buildApk() {#    flutter cleanflutter build apkmv ../build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk $appAndroidPathmv ../build/app/outputs/flutter-apk/app-arm64-v8a-release.apk ${exportPath}/app-arm64-v8a-release.apkecho "android打包结束\n"currentBranch=$(git symbolic-ref --short -q HEAD)packageString=''if [ $useOnlineConfig == true ]; thenpackageString='类型:android线上包\n分支:'$currentBranch'\n更新:'$gitUpdateInformationelsepackageString='类型:android测试包\n分支:'$currentBranch'\n更新:'$gitUpdateInformationfi./uploadApp.sh $appAndroidPath $packageString
}
# ios包
buildIpa() {#flutter cleancd ../iospod installflutter build ipa --export-options-plist=PackageShellFiles/ExportOptions.plistcd ../PackageShellFilesmv ../build/ios/ipa/己悦己租包.ipa $appIosPathecho "ios打包结束\n"currentBranch=$(git symbolic-ref --short -q HEAD)packageString=''if [ $useOnlineConfig == true ]; thenpackageString='类型:ios线上包\n分支:'$currentBranch'\n更新:'$gitUpdateInformationelsepackageString='类型:ios测试包\n分支:'$currentBranch'\n更新:'$gitUpdateInformationfi./uploadApp.sh $appIosPath $packageString
}#打印git commit信息
echoGitCommitId() {cd ..echo 拉取git信息# 更新远程分支git fetch origin# 选择的分支是否本地存在exists=$(git show-ref refs/heads/${selectBranch})if [ -n "$exists" ]; thengit checkout "${selectBranch}"elsegit checkout -b "${selectBranch}" "${branchName}"fi# 当前分支currentBranch=$(git symbolic-ref --short -q HEAD)echo "切换分支完成,当前分支为:${branchName}"git pullecho "拉取最新代码"echo 当前编译包使用的Git分支为:$(git describe --contains --all HEAD | tr -s '\n')echo 当前编译包使用的Git commit短id为:$(git rev-parse --short HEAD)gitId=$(git rev-parse HEAD)echo 当前编译包使用的Git commit完整id为:$gitIdgitUpdateInformation=$(git log origin dev --pretty=format:“%s” $gitId -3)cd PackageShellFilesecho 即将开始打包~
}# 还原中间产物
resetConfig() {if [ -f "./tempConfig.dart" ]; thencp ./tempConfig.dart ../lib/config.dartrm -f ./tempConfig.dartfi
}# 判断是否打线上包
checkUseOnlineConfig() {if [ $useOnlineConfig == true ]; thencp ../lib/config.dart ./tempConfig.dartcp ./onlineConfig.dart ../lib/config.dartecho '正在打线上包'elseecho '正在打测试包'fi
}buildApp() {#  打包信息.txtif [ $useOnlineConfig == true ]; thenpackageString='类型:线上包\n分支:'$currentBranch'\n更新:'$gitUpdateInformationecho $packageString > ${exportPath}/"打包信息.txt"elsepackageString='类型:测试包\n分支:'$currentBranch'\n更新:'$gitUpdateInformationecho $packageString > ${exportPath}/"打包信息.txt"fi# 选择打包if [ $packingType == android ]; thenecho '当前只有打android包'buildApkelif [ $packingType == ios ]; thenecho '当前只有打ios包'buildIpaelif [ $packingType == 'android、ios' ]; thenecho 'android、ios串行打包'buildIpabuildApkelseecho 'android、ios并行打包'buildIpa &buildApkwaitfi
}# 前置操作
resetConfig
echoGitCommitId
createDir# 打包
checkUseOnlineConfig
buildApp# 还原中间产物
resetConfig

首先我们拉取到最下面,看到我们有调用这几个方法

resetConfig:判断本地是否有保存配置文件tempConfig.dart,如果有则还原到项目中,起到一个重置的作用

echoGitCommitId:切换分支并拉取最新分支,branchName为用户选择的远程分支(例如origin/dev),我们转换为本地分支{branchName}为用户选择的远程分支(例如origin/dev),我们转换为本地分支branchName为用户选择的远程分支(例如origin/dev),我们转换为本地分支{branchName#*/}(例如dev),然后判断本地是否有dev分支,如果有直接切换分支checkout,没有则checkout创建dev本地分支,然后执行git pull拉取最新代码,当然在这之前我们一定要先获取远程分支git fetch origin,否则会出现没有找不到远程分支的情况。

createDir:则是按照时间戳创建文件夹

checkUseOnlineConfig:判断是否是需要打线上包,如果是线上包,则使用拷贝命令cp,将内置文件配置文件覆盖到项目配置文件

buildApp:则根据packingType参数选择是android,还是ios的包。

buildIpa &
buildApk
wait

buildIpa &:表示开启后台线程运行

wait:表示等待前面子线程

需要注意的是如果你没有linux基础,一定要记得并行打包需要wait,因为在linux中主线程结束,进程会被销毁,即现象安卓打包线程结束,ios打包线程会被强制结束,同时cd命令在各个线程是分开的互不影响的

上传文件脚本:uploadApp.sh

上传文件脚本相对简单,可以0基础直接上手,主要是涉及到账号的申请找起来稍微麻烦:

钉钉key:在下面叙述

蒲公英key:右侧手机号 -> API信息

image-20220127202810611
#!/bin/bash#待上传app路径
appPath=$1#a更新信息
updateInformation=$2#蒲公英上传结果
result=''#蒲公英key
AKEY="428c221853ed052ca74846e5bfe4填自己账号"
UKEY="38951568cffd3426e9e8b5e59b66填自己账号"#钉钉key
DKEY="3761c70fd171bf4726385b6176b053d1465f72e4bd43daf3463e6f77fb1填自己账号"#上传蒲公英
uploadPgyer(){echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>上传蒲公英"result="$(curl -F "file=@$appPath" -F "uKey=$UKEY" -F "buildUpdateDescription=$updateInformation" -F "_api_key=$AKEY" -F 'buildInstallType=1' -F 'buildPassword=000000'  https://www.pgyer.com/apiv2/app/upload)"echo "app详细信息:\n"$resultecho "\n\n\n\n"
}#上传钉钉
uploadDingTalk(){echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>上传钉钉"data=$(echo $result | jq -r ".data")appName=$(echo $data | jq -r ".buildName")appVersion=$(echo $data | jq -r ".buildVersion")appQRCodeURL=$(echo $data | jq -r ".buildQRCodeURL")appShortcutUrl=$(echo $data | jq -r ".buildShortcutUrl")curl "https://oapi.dingtalk.com/robot/send?access_token=$DKEY" \-H 'Content-Type: application/json' \-d '{"msgtype": "link","link": {"title": "'$appName''$appVersion'","text": "'$updateInformation'","picUrl": "'$appQRCodeURL'","messageUrl": "https://www.pgyer.com/'$appShortcutUrl'"},}'echo "\n\n\n\n"
}uploadPgyer
uploadDingTalk

2.3、输出到钉钉

在钉钉中创建群聊,添加机器人使用手机 -> 群设置 -> 只能群助手,选择webhook机器人即可,在创建过程中会生成机器人的key

image-20220127202810611

2.4、配置打包电脑历史记录

FileShare网页分享

image-20220127202810611

我们需要在打包电脑安装utools软件,utools里面有一款局域网分享插件FileShare,然后我们把想分享的文件夹拖进去即可。

缺点:不是很稳定,我这边用过了一个星期可能需要重启这个服务,即关闭再打开。优点是网页可以内网穿透放到外网去

image-20220127202810611

smb服务共享

我们在打包电脑上设置 -> 共享 -> 文件共享,添加共享文件夹

image-20220127202810611

然后使用局域网服务器访问:访达 -> 已连接的服务器 -> 打包机器

这样我们就相当于把磁盘共享了,可以很方便的编辑,也不用拷贝来拷贝去了

image-20220127202810611

ssh连接

如果喜欢ssh远程连接的同学也可以使用这个

设置 -> 共享 -> 远程登录,拷贝右侧的登录命令输入在终端即可,密码为打包电脑的登录密码

image-20220127202810611

可以看到这种操作也是非常的爽,有逼格

image-20220127202810611

2.5、问题修复

如果你的jenkins卡在拉取代码过程中,如下所示:

image-20220127202810611

我们需要配置全局的name、email,选择 系统管理 ->系统配置 -> Git plugin

image-20220127202810611 image-20220127202810611

三、不足与改进

3.1、持续化打包

关于jenkins,你可以设置定时打包、提交代码就打包,由于我这里暂时没有这个需求,就没加

3.2、oss存储

由于我这里使用的是蒲公英作为三方存储,二维码都是同一个,每次从钉钉上点旧的包进去也是最新的包。这点可以考虑使用阿里云的oss作为存储方案,一个二维码对应一个包

3.3、钉钉界面

image-20220127202810611

界面上我们使用的是钉钉的默认app分享界面,这点有较大的优化控件,我们可以考虑使用自定义消息UI来改善这个问题

四、源码文件

这里给到的源码文件是完整的PackageShellFiles文件夹,点击下载

各个文件作用解释如下:

tempConfig.dart:临时生成文件 (这里没有显示),在打正式包过程中临时生成,以保存项目的config.dart配置

buildApp.sh :jenkins打包脚本入口

buildLocalApp.sh:手动打包脚本入口

ExportOptions.plist:ios配置清单

onlineConfig.dart:默认的线上配置清单,在打正式包时替换config.dart

uploadApp.sh:上传文件到蒲公英、钉钉脚本

image-20220127202810611

相关内容

热门资讯

lol神秘商店在哪(lol神秘... 今天给各位分享lol神秘商店在哪的知识,其中也会对lol神秘商店神秘钥匙怎么获得进行解释,如果能碰巧...
【数据结构与算法】ArrayL... ✨个人主页:bit me ✨当前专栏:数据结构 ✨每日一语:...
浅灰砖配什么颜色的走边线好看图... 今天给各位分享浅灰砖配什么颜色的走边线好看图片的知识,其中也会对浅灰砖美缝什么颜色好看进行解释,如果...
Centos 7 安装 wge... 文章目录1. wget命令详解:2.查看帮助手册3.使用 wget 下载单个文件4.使用 wget ...
东方甄选抖音号粉丝量连续负增长 第三方数据显示,1月1日至15日期间,东方甄选抖音号粉丝量连续负增长。1月9日至15日,与辉同行粉丝...
计算长颈鹿身上的斑点数量 计算长颈鹿身上的斑点数量是一个非常具体和具体的问题,因为每只长颈鹿的斑点数量和分布都是独一无二的。在...
Linux内核与SMP(对称多... 什么 是SMP? SMP的全称是“对称多处理“(Symmetrical ...
数据结构之二叉树(前提知识) 文章目录前言**一、树****二、树的相关概念****节点的度****叶节点****分支节点****...
【Linux】深刻理解进程概念... 文章目录1、什么是进程?1.1 PCB的概念1.2 程序加载到内存2、初识进程2.1 进程相关的指令...
对MMVAE中IWAE代码实现... 原始的IWAE 优化目标: LIWAE(x1:M)=Ez1:K∼qΦ(z∣x1...