APK 自动编译平台搭建(gitlab+jenkins+svn+dingding)

APK 自动编译平台搭建(gitlab+jenkins+svn+dingding)

搭建一个在 Jenkins 上的自动编译平台,将 apk 发布到 SVN,之后把编译结果推送到钉钉。

安装 Jenkins

这一步不赘述,网上的教程太多了,值的一提的是,你也可以通过 Docker 去安装。Docker 可以理解为搭建了一个虚拟机,在虚拟机里面运行 Jenkins。

Jenkins 上编译 APK
  1. 也有很多文档可以参考,主要注意在Jenkins配置菜单里面增加 ANDROID_HOME 环境变量
  2. 注意 Gradle 配置。同时使用./sdkmanager --list 然后再安装需要的一些 NDK 等

能够成功编译并在工作空间生成正确的APK就可以下一步了。

gitlab 触发 Jenkins 自动编译

需要打通这两个平台,让 gitlab 特定的分支收到 push 或者有 commit merge 后,主动触发编译。

  1. Jenkins 安装 Gitlab Hook Plugin 和 GitLab Plugin 两个插件。

  2. 进入 Jenkins 任务的配置界面

    Filter branches by name 填写你关注的分支。

    点击 Generate 按钮 生成 Secret token。

    保存。

  3. 把👆URL 和 Secret token 分别填写到 gitlab 项目的集成选项里,Trigger只勾选 push events就行,merge后也会触发的。勾选Enable SSL verification 后 Add webhook。添加后有 Test 按钮,选择 Push events。如果能正常触发 Jenkins 编译就说明 OK 了。

    image-20210903111908673

APK 发布到 SVN

因为历史原因,我们的待测 APK 都是存放在 SVN 上的,SVN 提交 commit 需要把应用的版本号,gitSha,commit 带上,方便追溯问题。

首先 commit 我们可以通过 Jenkins 自动就拿到了,如下操作后会增加一个名为 “SCM_CHANGELOG”的环境变量。后续脚本读取即可。

image-20210903113059522

其次,版本号和 gitSha 可以编译生成 app_1.0.2_sdjfhga.apk 这种 apk 格式然后解析获得。具体编译生成的方式如下:

//build.gradle (app)
//我这里的versionCode versionName都是随着commit提交自动递增的,比如当前的versionCode是100 versionName是1.1.100
//当你提交一个commit后,生成的apk的versionCode自动变为101,versionName为1.1.101
//可以按需使用。
def getSelfDefinedVersion(type) {//编译不过需要配置git环境变量
    Process process = "git rev-list --count HEAD".execute()//git提交数
    process.waitFor()
    int commits = process.getText().toInteger()

    if ("code" == type) {
        commits
    } else if ("name" == type) {
        "1.1.$commits"
    }
}
def gitSha = 'git rev-parse --short HEAD'.execute().text.trim()

android {
	defaultConfig {
	//xxx
	}
	compileOptions {
	//xxx
	}
	//这里指定生成的APK文件的命名
    applicationVariants.all {variant ->
        variant.outputs.all {output ->
            if (variant.buildType.name == "debug") {
                output.outputFileName = "APP-debug.apk"
            } else if (variant.buildType.name == "release") {
                output.outputFileName = "APP"+gitSha+"_"+getSelfDefinedVersion('name')+".apk"
            }
        }
    }
}

提交内容准备好了,进入服务器 jenkins相关目录,建立script目录,下面编写SVN推送的脚本svn_push_apk.sh 。

#!/bin/bash -ilex
#Jenkins 工作目录
WORKSPACE=$1
#编译生成的Apk的位置。比如app/build/outputs/apk/release/*.apk
RELEASE_APK_REG=$2
#SVN上APK的存放位置。比如app/JenkinsTest/App.apk 
SVN_APK_PATH=$3
#git commit
SCM_CHANGELOG=$4

#存放SVN的目录
COMMONAPK_PATH=${WORKSPACE}/../CommonApk
RELEASE_APK_PATH=$(ls -1 ${WORKSPACE}/${RELEASE_APK_REG})
cd ${COMMONAPK_PATH}
fl=${RELEASE_APK_PATH##*/}
fileName=${fl%.*}
apkName=$(echo $fileName | cut -d _ -f 1)
gitsha=$(echo $fileName | cut -d _ -f 2)
versionName=$(echo $fileName | cut -d _ -f 3)
svn cleanup
svn up --username "autobuild" --password "xxxxxx"
#commit 超过300 说明一次提交过多。不认为是正常的。
if [ ${#SCM_CHANGELOG} -gt 300 ];then
    echo "git commit too long"
#gitSha和上次一样,不做提交。
elif echo $(svn log ${SVN_APK_PATH} -l 1 --username "autobuild" --password "xxxxxx") |grep -q $gitsha; then
    echo "gitsha same, Don't upload."
else
    cp -rf ${RELEASE_APK_PATH} $SVN_APK_PATH
    commitlog="${apkName} version:${versionName} gitsha:${gitsha} changeLog:${SCM_CHANGELOG}"
    svn commit -m "${commitlog}" ${COMMONAPK_PATH}/${SVN_APK_PATH} --username "autobuild" --password "xxxxxx"
    echo "svn successful"
fi

回到 Jenkins 项目的配置界面,先增加两个参数,后面有用。再增加构建后操作。两个内容分别是推送到SVN 和 把相关结果发到钉钉的脚本。

image-20210903114507062

推送到 SVN。“BUILD SUCCESSFUL” 是仅编译成功才需要执行下方脚本。

image-20210903114210646

#1-WORKSPACE 2-releaseApk位置 3-svn上apk位置 4-commitlog
if [ "$push_to_svn" = "true" ]; then   
    [ ! $custom_commit ] && SCM_CHANGELOG="$custom_commit"
    echo "$SCM_CHANGELOG"
    cd $WORKSPACE/../script 
    /bin/bash svn_push_apk.sh "$WORKSPACE" app/build/outputs/apk/release/*.apk app/JenkinsTest/App.apk "$SCM_CHANGELOG"
fi
结果发送到钉钉
  1. 到钉钉的 “智能群助手” 中添加 “机器人”,选择 “自定义”(通过Webhook接入自定义服务)。安全设置选择自定义关键词,关键词填写 “点击查看”。

  2. 添加机器人后,有个WebHook地址,复制下来。后续就可以通过给这个地址发消息到群里了。

  3. 回到 Jenkins 增加构建后操作。 Log text 填写 Build 因为无论编译结果如何,都是要通知到发送到钉钉群里的。Script填写如下:

    cd $WORKSPACE/../script
    /bin/bash jenkins_to_dingding.sh "$JOB_NAME" "$BUILD_NUMBER" "$SCM_CHANGELOG" "$push_to_svn"
    
  4. 到服务器 Jenkins 之前建的 script 目录 编辑 jenkins_to_dingding.sh

    #!/bin/bash -ilex
    #################################################################
    # 钉钉消息变量定义
    #################################################################
    JOB_NAME=$1
    BUILD_NUMBER=$2
    SCM_CHANGELOG=$3
    PUSH_TO_SVN=$4
    
    BUILD_STATUS="<font color='#ff0000'>失败</font>"
    #这是我的Jenkins服务器的地址,包括下方一些服务器地址,使用的话请自行修改。
    LAST_BUILD_BUILD_XML=`curl http://192.168.10.58:8090/job/${JOB_NAME}/lastBuild/api/xml`
    BUILD_RESULT=$(echo $LAST_BUILD_BUILD_XML | grep "<result>SUCCESS</result>") 
    if [ "${BUILD_RESULT}" ];then 
        BUILD_STATUS="<font color='#00ff00'>成功</font>"
    else
        BUILD_RESULT=$(echo $LAST_BUILD_BUILD_XML | grep "<result>FAILURE</result>") 
        if [ "${BUILD_RESULT}" ];then 
            BUILD_STATUS="<font color='#ff0000'>失败</font>"
        else
            BUILD_STATUS="<font color='#ff0000'>无法获取</font>"     
        fi
    fi   
    
    JENKINS_JOB_BUILD_LOG_URL="http://192.168.10.58:8090/job/${JOB_NAME}/${BUILD_NUMBER}/console"
    JENKINS_LAST_BUILD_CONSOLE=`curl http://192.168.10.58:8090/job/${JOB_NAME}/${BUILD_NUMBER}/consoleText`
    #echo $JENKINS_LAST_BUILD_CONSOLE
    if [ "$push_to_svn" = "true" ];then
        SVN_BUILD_STATUS="<font color='#ff0000'>失败</font>"
        SVN_BUILD_RESULT=$(echo $JENKINS_LAST_BUILD_CONSOLE | grep "Committed revision") 
        if [ "${SVN_BUILD_RESULT}" ];then 
            SVN_BUILD_STATUS="<font color='#00ff00'>成功</font>"
        else
            SVN_BUILD_RESULT=$(echo $JENKINS_LAST_BUILD_CONSOLE | grep "gitsha same") 
            SVN_COMMIT_RESULT=$(echo $JENKINS_LAST_BUILD_CONSOLE | grep "git commit too long")
            if [ "${SVN_COMMIT_RESULT}" ];then
                SVN_BUILD_STATUS="<font color='#ff0000'>失败,git commit过长,请点击连接,自定义commit并触发编译。</font>"
            elif [ "${SVN_BUILD_RESULT}" ];then 
                SVN_BUILD_STATUS="<font color='#ff0000'>失败,与上次提交gitsha相同</font>"
            else
                SVN_BUILD_STATUS="<font color='#ff0000'>失败</font>"     
            fi
        fi 
    else
       SVN_BUILD_STATUS="<font color='#a9a9a9'>跳过</font>"
    fi
    
    # 机器人 webhook 地址(上文添加钉钉机器人结束时复制的webhook地址)
    DINGTALK_WEBHOOK_URL='https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxx'
    # 消息标题 # 实际不起作用,但是不能少,否则发送失败
    DINGTALK_TITLE="Jenkins平台有新的构建"
    # 消息正文
    # Jenkins Job构建日志地址
    DINGTALK_TEXT="### ${JOB_NAME} 有新的构建\n\n>\
    **【构建ID】:${BUILD_NUMBER}**\n\n>\
    **【编译状态】:${BUILD_STATUS}**\n\n>\
    **【SVN状态】:${SVN_BUILD_STATUS}**\n\n>\
    **【commit】:** ${SCM_CHANGELOG}\n\n>\
    **【Jenkins】:[点击查看更多](${JENKINS_JOB_BUILD_LOG_URL})**\n
    " 
    #  
    # 发送钉钉消息通知函数
    #################################################################
    function SEND_MESSAGE_TO_DINGTALK() {
        /usr/bin/curl "$1" -H 'Content-Type: application/json' -d "
        {
            \"markdown\": {
                \"title\": \"$2\", 
                \"text\": \"$3\"
            }, 
            \"at\": {
              \"atMobiles\": [],
              \"isAtAll\": false
            },
            \"msgtype\": \"markdown\"
        }
        " 
    }
    # 发送钉钉消息
    #################################################################
    SEND_MESSAGE_TO_DINGTALK "${DINGTALK_WEBHOOK_URL}" "${DINGTALK_TITLE}" "${DINGTALK_TEXT}"
    
  5. 最后效果如下:

    image-20210903143024939

image-20210903143103594

总结
  1. 能用 git 就尽量别用 SVN 了。 一些插件都不好用,或者满足不了需求。只能自己写。
  2. 上面的脚本其实也不一定就能满足你的需求,最好的办法就是根据需求自己改,自己定制。包括我之所以写这两个脚本,也是因为 Jenkins 版本比较低,插件不能满足需求,又担心升级出问题,只能自己编写,或者拿网上的模版改。
  3. 整个流程搞定后还是挺爽的,以前要先提交merge 合并完代码后,再用 Android Studio 编译生成 APK 后 手动提交到 SVN。整个流程繁琐,且容易不符合规定导致出错,比如不合代码,直接就先提交 SVN 了。搞定完之后,只需要验证完 提交merge就可以了。Jenkins代替你编译并提交。另外提 merge 推荐Android Studio 的插件-- GitLab Quick Merge Request 非常好用,在 Android Studio里面就可以用快捷键提交了。详细使用方法可以找我之前的文章。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值