• 基于jenkins进行定制化开发


    Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具,起源于Hudson(Hudson是商用的),主要用于持续、自动的构建/测试软件项目、监控外部任务的运行(这个比较抽象,暂且写上,不做解释)。Jenkins用Java语言编写,可在Tomcat等流行的servlet容器中运行,也可独立运行。通常与版本管理工具(SCM)、构建工具结合使用。常用的版本控制工具有SVN、GIT,构建工具有Maven、Ant、Gradle。

    1. 环境配置

    进入jenkins主界面,系统管理->全局工具配置 进行配置,包括 JDK,Git,Gradle,Maven等,如下,关于jdk的配置的设置。
    [图片]
    (图1)
    如上图,给定一个别名,通过下拉框选择相应的Jdk版本,也可以通过FTP工具上传已经下载到本地的Jdk包。
    如下,git配置需要指定一个本地已经下载好的路径。这种需要通过Ftp或者脚本提前下载指定版本的git工具。

    [图片]
    (图2)

    Gradle,Maven配置与jdk和git的配置雷同,不做介绍。

    2. 如何创建一个构建任务

    生成apk需要新建一个构建任务,这里构建一个自由风格的软件项目,输入任务名称后就会自动创建一个构建项。
    在这里插入图片描述

    (图 3)

    构建项包括 General,gitBucket,JobNotifications,源码管理,构建触发器,构建环境,构建,构建后操作。

    [图片]

    (图4)
    General:可以设置一些项目介绍
    gitBucket:未用到
    JobNotifications:使用 UDP、TCP 或 HTTP 协议向定义的端点发送有关作业状态的通知,设置同时并发构建数量
    源码管理:配置关联不同的源码仓库,git,svn,scms等
    构建触发器:可以hook一些事件进行自动构建,比如定时构建,提交构建,轮询scm构建等
    构建环境:允许在构建之前进行一些操作,比如更新lfs,清除上一次构建缓存等
    构建:指定构建脚本
    构建后操作:主要配置构建后可以触发的操作,如发布单元测试报告,发送邮件通知,发布工件到蒲公英,fir等

    3. 生成apk

    基于步骤1,步骤2,只需要进行简单的配置即可打包apk,如图5
    [图片]

    (图5)
    配置tasks clean debugDebug

    4. 生成二维码

    为了方便apk的下载安装,将apk包的路径生成可直接下载的二维码图片。主要使用一个二维码生成的jar包。

    主要实现步骤:
    通过 jq工具,解析gradle生成apk时的output-metadata.json,获取apk名称,进行输出,找到输出的apk之后根据条件执行不同的逻辑,比如加固。使用cp 命令将apk副本拷贝到指定目录,然后通过QRcode.jar对目录中的apk路径生成二维码。在构建后操作 build description 插件指定二维码路径,就可以在指定位置显示二维码。(可以使用html调整二维码大小)

    output-metadata.json
    {
      "version": 3,
      "artifactType": {
        "type": "APK",
        "kind": "Directory"
      },
      "applicationId": "com.codeview.takumi",
      "variantName": "debug",
      "elements": [
        {
          "type": "SINGLE",
          "filters": [],
          "attributes": [],
          "versionCode": 1,
          "versionName": "1.0.0",
          "outputFile": "app-debug.apk"
        }
      ],
      "elementType": "File"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    使用方法需要用到 java -jar 命令

    java -jar /data/service/tomcat/QRcode.jar url=http://apk.android.reworldgame.com/apk/$JOB_NAME.apk image=$JOB_NAME.jpg save=/data/www/image  # 使用二维码生成jar 生成二维码
    
    • 1

    格式: java -jar 二维码生成jar路径 url=apk路径 image=xx.jpg save=二维码地址

    tips: 生成二维码的jar,在java 8平台编译,如果在java11 上不能运行。需要进行调整

    5. 集成360加固

    根据安全方面的考虑,对在国内应用市场上线的apk,上架app市场前,做加固处理。选择360加固,由于 360加固 助手提供命令行方式加固。

    #加固apk脚本 [参数1:加固apk 参数2:加固apk输出路径 参数3: 海外国内来区分使用的签名文件]

    if [ $jiagu = true ]; then
    dos2unix /data/360/360jg.sh  #忽略空格差异,造成无法执行脚本
    bash -ex  /data/360/360jg.sh ${WORKSPACE}/app/build/outputs/apk/${VARIABLE}/*.apk ${WORKSPACE}/app/build/outputs/apk/ china 
    
    完整shell脚本
    #!/bin/bash
    BASE=/data/360/jiagu/jiagu.jar
    BASE2=/data/360/jiagu/
    #360加固账号
    NAME=360账户
    PASSWORD=360密码
    APK=$1
    DEST=$2
    flavor=$3
    #chinaFlag="/apk/china/"
    #根据输出路径判断是国内分支还是海外分支
    #if[[$APK =~$chinaFlag]]
    #then
    #flavor="china"
    #else
    #flavor="overseas"
    #fi
    #签名文件根据输入flavor来区分
    echo "flavor = "$flavor
    if [ "$flavor" = "china" ];then
    KEY_PATH= #密钥路径
    KEY_PASSWORD= #密钥密码
    ALIAS=key0 #别名
    ALIAS_PASSWORD=#别名密码
    elif [ "$flavor" = "SouthEastAsia" ];then
    KEY_PATH=#密钥路径
    KEY_PASSWORD= #密钥密码
    ALIAS= #别名
    ALIAS_PASSWORD=密码 
    #别名密码
    else
    KEY_PATH=/data/360/sign/reworldoversea.jks #密钥路径
    KEY_PASSWORD=#密钥密码
    ALIAS=#别名
    ALIAS_PASSWORD= #别名密码
    fi
    echo "------ 打包签名详情! ------"
    echo "使用的签名文件路径 ="$KEY_PATH
    echo "Apk包路径 ="$APK
    echo "加固包输出路径 ="$DESTi
    echo "------ running! ------"
    cd $BASE2
    #java -jar ${BASE} -version
    java -jar ${BASE} -login ${NAME} ${PASSWORD}
    java -jar ${BASE} -importsign ${KEY_PATH} ${KEY_PASSWORD} ${ALIAS} ${ALIAS_PASSWORD}
    java -jar ${BASE} -showsign
    #java -jar ${BASE} -importmulpkg ${BASE2}/空渠道.txt #根据自身情况使用
    #java -jar ${BASE} -importmulpkg ${BASE2}/空渠道.txt #根据自身情况使用
    java -jar ${BASE} -showmulpkg
    java -jar ${BASE} -showconfig
    java -jar ${BASE} -jiagu ${APK} ${DEST} -autosign
    #java -jar ${BASE} -pkgparam ${BASE2}/哈哈.txt
    echo "--------finish------------"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    tips:
    ${WORKSPACE} 占位符方式,可以获取jenkins默认本地变量和通过参数化构建设置的自定义变量

    6. 集成蒲公英,fir平台插件

    发布到蒲公英和fir内测平台,通过以上两个平台提供的快速发布插件,可快速集成,这里提供一种回显蒲公英平台生成二维码到jenkins的方案
    发布到蒲公英平台之后,返回的json串格式,如下:

     {
        "code":0,
        "message":"",
        "data":{
            "appKey":"c2c6568526071a91d8ce0dfb596b894f",
            "userKey":"2b50d762a0957feaf481346938eba78e",
            "appType":"2",
            "appIsLastest":"1",
            "appFileSize":"259772621",
            "appName":"Reworld",
            "appVersion":"1.0.0",
            "appVersionNo":"1",
            "appBuildVersion":"1",
            "appIdentifier":"com.codereview.reworldsea",
            "appIcon":"5ff42e3dc70e4deffb8c0f48a3703dc2",
            "appDescription":"",
            "appUpdateDescription":"",
            "appScreenshots":"",
            "appShortcutUrl":"DrpS",
            "appCreated":"2021-11-25 14:29:00",
            "appUpdated":"2021-11-25 14:29:00",
            "appQRCodeURL":"https:\/\/www.pgyer.com\/app\/qrcodeHistory\/8273db84803bcb78f617c58c7d60f623ae20a25839d7efe9b90ea4788bba07f7"
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    shell脚本
    在将apk发布到蒲公英之后,对返回的结果json串中appQRCodeURL的值进行解析。

    # 脚本文件 pgyUpdate.sh
    #!/bin/bash
    
    #MAIN_MODULE AndroidStudio project directory under the main module
    MAIN_MODULE="."
    #The test address separately
    #MAIN_MODULE="./app" 
    # pgy  API account
    
    PGYER_USER_KEY="蒲公英userkey"
    
    PGYER_API_KEY="蒲公英api key"
    
    #APK path
    #APK_PATH="${MAIN_MODULE}/build/outputs/apk"
    #Receive the external transfer apk path
    
    APK_PATH=$1
    echo "=============================================="
    #echo "current path: `pwd`"
    echo "APK_PATH=${APK_PATH}"
    APK_LIST=`ls -t ${APK_PATH}`
    echo "${APK_LIST}"
    #ind the latest apk package
    for APK_FILE in ${APK_LIST}; do
        APK_NAME=${APK_FILE}
        echo "apk file name= $APK_NAME  File=$APK_FILE"
    done
    
    #-------------------------------------------------
    
    if [ -n "$APK_NAME" ]; then # Determine whether is empty
    
        echo "upload $APK_FILE pgy"
        #upload pgy updateDescription(version descript)
        RESULT=$(curl -F "file=@${APK_PATH}/${APK_NAME}" -F "uKey=${PGYER_USER_KEY}" -F "_api_key=${PGYER_API_KEY}" https://qiniu-storage.pgyer.com/apiv1/app/upload)
    
            echo  $RESULT > pgy.json
    #-------------------send mail-------------------------
       # echo "send mail to" test@qq.com
    
       # echo "${RESULT}" | mail -s "${APK_NAME} already unload pgy" test@qq.com
    
        # #http://www.pgyer.com/apiv1/app/upload
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    构建块中添加执行发布到分发平台的shell脚本即可
    #发布到蒲公英

    if [ $pgy = true ]; then
    
    cd /data/pgyupdate
    
    ./pgyUpdate.sh ${WORKSPACE}/app/build/outputs/apk/${VARIABLE}/
    
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    fir类似,不赘述

    7. 生成App Bundle

    AAB格式为上架google play需要,与生成apk区别点在于构建方式不同。构建之后的处理与apk类似。

    构建块中添加执行发布到分发平台的shell脚本即可

    if [ "bundle" = "$packageType" ];
    then
      cd /data/www/aab/
    #    typeset -l lowerBuildChannel=${Build_channel}
    #    typeset -l lowerBuildType=${Build_type}
        lowerBuildChannel=${Build_channel,}
        lowerBuildType=${Build_type,,}
        aabDir=${WORKSPACE}/app/build/outputs/bundle/${lowerBuildChannel}${Build_type}
        aabName=${aabDir}/app-${lowerBuildChannel}-${lowerBuildType,}.aab
        echo $aabName
        cp ${aabDir}/*.aab  /data/www/apk/$JOB_NAME.aab
        java -jar /data/service/tomcat/QRcode.jar url=http://apk.android.reworldgame.com/apk/$JOB_NAME.aab image=$JOB_NAME.jpg save=/data/www/image
            exit
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    8. jenkins动态化参数介绍

    参数构建是实现jenkins动态构建的基础。

    8.1 字符参数

    [图片]

    (图6)
    如上图,在需要用到的地方使用${App_VERSION_CODE},既可以取出来2406值来使用

    8.2选项参数

    [图片]

    (图7)

    8.3布尔参数

    [图片]

    (图8)

    8.4动态选择参数

    [图片]

    (图9)

    8.5 最终构建任务样式

    在这里插入图片描述

    1. 一键生成加固多渠道包脚本
      脚本逻辑介绍:
      对等待加固的apk,使用360加固包提供的脚本jar文件进行加固,然后针对生成的加固包执行wallet.jar 多渠道脚本,基于加固包生成多个渠道的apk文件,提供给对应渠道进行上架。
      @echo off
    
    
    echo ========== push apk to here ============
    ::需要加固的apk路径
    set/p APK= >nul
    set APK_VERSION=1
    set APK_FLAVOR=1
    
    
    set remain=%APK%
    set index=0
    :loop
    for /f "tokens=1* delims=_" %%a in ("%remain%") do (
        if %index%==1 (
            set APK_FLAVOR=%%a
        )
        if %index%==2 (
            set APK_VERSION=%%a
        )
        set /a index=index+1
        rem 将截取剩下的部分赋给变量remain,其实这里可以使用延迟变量开关
        set remain=%%b
    )
    ::如果还有剩余,则继续分割
    if defined remain goto :loop
    
    
    set APK_FLAVOR=%APK_FLAVOR:~0,7%
    echo %APK%
    echo APK_VERSION=%APK_VERSION%  APK_FLAVOR=%APK_FLAVOR%
    
    
    ::加固配置
    set SRT="C:\360\jiagu"
    set NAME=360账户
    set PASSWORD=360账户密码
    
    
    cd %SRT%
    echo current path ============== %cd%
    if %APK_FLAVOR%==oversea (
        echo =========== oversea =============
            set BASE=C:\360\haiwai\jiagu\jiagu.jar
        ::密钥路径
        set KEY_PATH=./jsk/reworldoversea.jks
        ::密钥
        set KEY_PASSWORD=密码
        ::别名
        set ALIAS=别名
        ::别名密码
        set ALIAS_PASSWORD=别名密码
        ::输出加固包路径
        set DEST=./海外/%APK_VERSION%
            echo 本次使用印度签名
    ) else if %APK_FLAVOR%==southEa (
        echo =========== SouthEastAsia =============
            set BASE=C:\360\southEastAsia\jiagu\jiagu.jar
        ::密钥路径
        set KEY_PATH=./jsk/xxx.jks
        ::密钥密码
        set KEY_PASSWORD=密码
        ::别名
        set ALIAS=别名
        ::别名密码
        set ALIAS_PASSWORD=别名密码
        ::输出加固包路径
             set DEST=./东南亚/%APK_VERSION%
             echo 本次使用东南亚签名
    ) else (
        echo =========== china =============
            set BASE=./jiagu.jar
        ::密钥路径
        set KEY_PATH=./jsk/test.jks
        ::密钥密码
        set KEY_PASSWORD=密码
        ::别名
        set ALIAS=别名
        ::别名密码
        set ALIAS_PASSWORD=别名密码
        ::输出加固包路径
        set DEST=./国内/%APK_VERSION%
            echo 本次使用china签名
    )
    echo  %BASE% jiagu apk output path ======: %DEST%
    md "%DEST%"
    
    
    echo "------ jaigu running! ------"
    
    
    java -jar %BASE% -version
    java -jar %BASE% -login %NAME% %PASSWORD%
    java -jar %BASE% -importsign %KEY_PATH% %KEY_PASSWORD% %ALIAS% %ALIAS_PASSWORD%
    java -jar %BASE% -showsign
    java -jar %BASE% -showmulpkg
    java -jar %BASE% -showconfig
    java -jar %BASE% -jiagu %APK% %DEST% -autosign
    
    
    echo "------ jaigu finished! ------"
    
    
    echo "------ start rename ------"
    cd %DEST%
    echo current path ============== %cd%
    for %%i in (./*.apk) do ( 
        echo %%i| findstr "jiagu" >nul && (
            echo find jiagu apk
            echo %%i| findstr "sign" >nul && (
                echo find signed apk
                copy "%%i" "reworld.apk"
                goto loop2
            )
        )
    )
    :loop2
    echo "------ end rename ------"
    
    
    echo "------ start walle ------"
    cd %SRT%
    echo current path ============== %cd%
    set CHANNEL_PATH=%DEST%/%date:~0,4%%date:~5,2%%date:~8,2%%time:~0,2%%time:~3,2%%time:~6,2%
    java -jar ./walle-cli-all.jar batch -f ./walle临时渠道.txt "%~f1" %DEST%/reworld.apk %CHANNEL_PATH%
    ::统计目录下文件个数
    cd %CHANNEL_PATH%
    echo current path ============== %cd%
    set count=0
    for %%i in (./*.apk) do set /a count+=1
    echo ------ channel file count:%count% ------
    echo "------ end walle ------"
    Pause
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133

    10. 校验apk签名脚本

    脚本介绍:
    针对加固之后apk签名与正确签名进行比对,避免海外,国内市场apk签名错用。

    @echo off
    
    
    echo ========== push apk to here ============
    ::需要加固的apk路径
    set/p APK= >nul
    echo ========== apk path is %APK%  ============
    echo ========== push flavor to here ============
    echo 1:china
    echo 2:oversea
    echo 3:southAsia
    set/p APK_FLAVOR_TYPE= >nul
    if %APK_FLAVOR_TYPE%==1 (
        set APK_FLAVOR=china
        set APK_DEFINE_SHA1=bd67d0933ec6a40fb
    )else if %APK_FLAVOR_TYPE%==2 (
        set APK_FLAVOR=oversea
        set APK_DEFINE_SHA1=5e33c207b8621a5a8bc458eb
    )else if %APK_FLAVOR_TYPE%==3 (
        set APK_FLAVOR=southAsia
        set APK_DEFINE_SHA1=478550704adff0a1a89
    )else (
        set APK_FLAVOR=unKnow
        set APK_DEFINE_SHA1=unSet
    )
    echo ============ choice flavor is %APK_FLAVOR% ============
    set SIGNER_INFO_PATH=temp_singer.txt
    set LINE_SHA1_FLAG=SHA-1
    java -jar .\apksigner.jar verify --print-certs %APK% > %SIGNER_INFO_PATH%
    call :read_apk_signer_sha1 %SIGNER_INFO_PATH%
    :read_apk_signer_sha1
      for /f "tokens=1,2 delims=:" %%a IN (%1)  do (
        echo %%a%%b
        echo %%a | findstr %LINE_SHA1_FLAG% >nul && set APK_SHA1=%%b
      )
    :del_left
    if "%APK_SHA1:~0,1%"==" " set APK_SHA1=%APK_SHA1:~1%&&goto del_left
    echo ============%APK_DEFINE_SHA1% ============
    echo ============%APK_SHA1% ============
    if %APK_SHA1% equ %APK_DEFINE_SHA1% (
        echo ============ SHA1 is right ============
    )else (
        echo ============ SHA1 is wrong ============
    )
    pause
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    11. 插件

    1.jenkins 下载地址
    2. 动态选择插件

  • 相关阅读:
    Flask 学习-44.Flask-RESTX 请求参数校验reqparse.RequestParser()
    华为设备链路聚合基础
    SQL Server 安装后,服务器再改名,造成名称不一致,查询并修改数据库服务器真实名称
    支持5G LAN的UPF转发模型
    Ubuntu系统初始设置
    (原创)【B4A】一步一步入门03:APP名称、图标等信息修改
    WinForm实现倒计时锁定程序完整源码附注释
    java学习第六步-常见类和api
    Instagram 早期技术架构
    死锁产生的条件及其预防
  • 原文地址:https://blog.csdn.net/o279642707/article/details/126878949