APK automatic compilation Platform construction (GitLab + Jenkins + SVN + Dingding)

Build an automatic compilation platform on Jenkins, release APK to SVN, and push the compilation result to Dingding.

Install Jenkins

It’s worth mentioning that you can also install it via Docker. Docker can be understood as building a virtual machine and running Jenkins in the virtual machine.

Jenkins compiles APK

  1. There is also a lot of documentation to refer to, but note the addition of the ANDROID_HOME environment variable in the Jenkins configuration menu
  2. Note the Gradle configuration. Use./sdkmanager –list and then install any NDKS you need

The next step is to successfully compile and generate the correct APK in the workspace.

Gitlab triggers Jenkins to compile automatically

The two platforms need to be connected to enable specific branches of GitLab to actively trigger compilation after receiving a push or commit merge.

  1. Jenkins installs Gitlab Hook Plugin and Gitlab Plugin.

  2. The Jenkins task configuration screen is displayed

    Filter Branches by name Fill in the branches you are interested in.

    Click the Generate button to Generate a Secret token.

    Save.

  3. Fill 👆URL and Secret Token into the integration options of GitLab project, Trigger only check Push Events, which will also be triggered after merge. Select Enable SSL verification and Add Webhook. After you add the Test button, select Push Events. If Jenkins builds properly, it’s OK.

The APK is advertised to the SVN

Due to historical reasons, our APK under test is stored on the SVN. When the SVN submits a COMMIT, it needs to bring the version number, gitSha and COMMIT of the application to facilitate tracing problems.

Commit (SCM_CHANGELOG) commit (SCM_CHANGELOG) The script can read it later.

Second, the version number and gitSha can be compiled to generate the APK format app_1.0.2_sdJFhga.apk and then parsed. The specific compilation and generation methods are as follows:

//build.gradle (app)
// My versionCode versionName is automatically incremented with the commit. For example, the current versionCode is 100 and the versionName is 1.1.100
// When you commit a commit, the versionCode of the generated APK automatically changes to 101 and its versionName is 1.1.101
// Can be used on demand.
def getSelfDefinedVersion(type) {Git environment variables need to be configured to compile
    Process process = "git rev-list --count HEAD".execute()/ / git commits
    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
	}
	// Specify the name of the generated APK file
    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"}}}}Copy the code

When the submission content is ready, go to Jenkins’ directory on the server and create the script directory. Next, write the script SVN_PUSH_apk.sh pushed by the SVN.

#! /bin/bash -ilex
#Jenkins Work Catalog
WORKSPACE=$1
#The location of the compiled generated Apk. Such as the app/build/outputs/apk/release / *. Apk
RELEASE_APK_REG=$2
#Location for storing APK on the SVN. Such as the app/JenkinsTest/app. Apk 
SVN_APK_PATH=$3
#git commit
SCM_CHANGELOG=$4

#Directory for storing the SVNCOMMONAPK_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 more than 300 indicates that there are too many commits at one time. I don't think it's normal.if [ ${#SCM_CHANGELOG} -gt 300 ]; then echo "git commit too long"#GitSha, like last time, does not commit.
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
Copy the code

Back to the Jenkins project configuration interface, add two parameters first, which will be useful later. Add post-build operations. The two contents are pushing to SVN and sending related results to Dingding.

Push to the SVN. BUILD SUCCESSFUL indicates that the following script needs to be executed only after the compilation is SUCCESSFUL.

#WORKSPACE 2-releaseApk location 3- APK location on the SVN 4- Commitlogif [ "$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" fiCopy the code

Results are sent to the nail

  1. Add “robot” to Dingding’s “Intelligent Swarm Assistant” and select “Custom” (access custom service through Webhook). Security Settings Select user-defined keywords and fill in “Click view” for keywords.

  2. After adding the robot, there is a WebHook address, copy it. You can then send messages to the group from this address.

  3. Back to Jenkins add post-build operations. Log text says Build because whatever the result of the Build is, it’s going to be notified and sent to the peggroup. Script:

    cd $WORKSPACE/.. /script /bin/bash jenkins_to_dingding.sh "$JOB_NAME" "$BUILD_NUMBER" "$SCM_CHANGELOG" "$push_to_svn"Copy the code
  4. Go to the script directory Jenkins created on the server and edit jenkins_to_dingding.sh

    #! /bin/bash -ilex
    ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    #Pin the message variable definition
    ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #JOB_NAME=$1 BUILD_NUMBER=$2 SCM_CHANGELOG=$3 PUSH_TO_SVN=$4 BUILD_STATUS="<font color='#ff0000'> failed </font>#This is my Jenkins server address, including some of the server addresses below, please change them if you use them.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 = # 00 ff00 '> success < / font >" the else BUILD_RESULT = $(echo $LAST_BUILD_BUILD_XML | grep "<result>FAILURE</result>") if [ "${BUILD_RESULT}" ]; Then BUILD_STATUS="<font color='#ff0000'> failed </font>" else BUILD_STATUS="<font color='#ff0000'> Failed </font JENKINS_JOB_BUILD_LOG_URL = "HTTP: / / 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_CONSOLEif [ "$push_to_svn" = "true" ]; Then SVN_BUILD_STATUS = "< font color = # ff0000" > failure < / font > "SVN_BUILD_RESULT = $(echo $JENKINS_LAST_BUILD_CONSOLE | grep "Committed revision") if [ "${SVN_BUILD_RESULT}" ]; Then SVN_BUILD_STATUS = "< font color = # 00 ff00 '> success < / font >" the 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}" ]; <font color='#ff0000'> then SVN_BUILD_STATUS="<font color='#ff0000'> </font>" elif [ "${SVN_BUILD_RESULT}" ]; Then SVN_BUILD_STATUS="<font color='#ff0000'> Same as last gitSHA submission </font>" else SVN_BUILD_STATUS="<font color='#ff0000'> failed </font>" fi fi else SVN_BUILD_STATUS="<font Color ='#a9a9a9'> skip </font>" fi
    #Robot Webhook address (add the webhook address copied at the end of the nail robot above)
    DINGTALK_WEBHOOK_URL='https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxx'
    #News headlines# it doesn't actually work, but it can't be small, otherwise it will fail to sendDINGTALK_TITLE=" New build for Jenkins platform"#The message body
    #Jenkins Job Build log addressDINGTALK_TEXT = "# # # ${JOB_NAME} there is a new build \ n \ n > \ * * [build ID] : ${BUILD_NUMBER} \ n \ n > \ * * * * [compilation state 】 : ${BUILD_STATUS} \ n \ n > \ * * * *" SVN status ": ${SVN_BUILD_STATUS} \ n \ n > \ * * * * "commit" : * * ${SCM_CHANGELOG} \ n \ n > \ * * [Jenkins 】 : [Click to see more](${JENKINS_JOB_BUILD_LOG_URL})**\n"#  
    #Sends a pin message notification function
    ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    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 a pin message
    ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    SEND_MESSAGE_TO_DINGTALK "${DINGTALK_WEBHOOK_URL}" "${DINGTALK_TITLE}" "${DINGTALK_TEXT}"
    Copy the code
  5. The final effect is as follows:

conclusion

  1. Try not to use SVN if you can use Git. Some plugins don’t work well or don’t meet requirements. You have to write it yourself.
  2. In fact, the above script may not be able to meet your needs, the best way is to change according to the needs of their own customization. The reason why I wrote these two scripts was also because Jenkins version was relatively low, plug-ins could not meet the requirements, and I was worried about the upgrade problems, so I had to write them by myself or take the online template for modification.
  3. After the whole process is done, it is quite cool. Before, you need to submit the merge code first, then use Android Studio to compile and generate APK, and then manually submit to SVN. The whole process is cumbersome and prone to errors caused by non-compliance. For example, if the code is not compliant, the SVN is directly submitted first. Once that’s done, all you need to do is validate the submit merge. Jenkins compiled and submitted on your behalf. GitLab Quick Merge Request is a very useful plugin for Android Studio. You can use shortcuts to submit a Request in Android Studio. Detailed usage methods can be found in my previous article.