一、背景
由于公司的jenkins運(yùn)行在k8s集群中,在jenkins打包時調(diào)用jenkins-slave 來工作,所以需先構(gòu)建android-jenkins-slave鏡像。
jenkins-slave 在打包過程中會用到gradle和sdk,那么就牽涉到gradle插件和sdk持久化。
Android打包對資源要求較高,也可以單獨(dú)建立jenkins工作節(jié)點(diǎn),將Android打包調(diào)度到物理機(jī)節(jié)點(diǎn)進(jìn)行。
二、NFS存儲
//安裝NFS服務(wù)端[root@nfs-server ~]# yum install -y nfs-utils[root@nfs-server ~]# mkdir -p /data/android[root@nfs-server ~]# mkdir -p /data/gradle[root@nfs-server ~]# vi /etc/exports/data/android 192.168.10.0/24(rw,no_root_squash)/data/gradle 192.168.10.0/24(rw,no_root_squash)[root@nfs-server ~]# systemctl enable rpcbind.service[root@nfs-server ~]# systemctl enable nfs-server.service[root@nfs-server ~]# systemctl start rpcbind.service[root@nfs-server ~]# systemctl start nfs-server.service[root@nfs-server ~]# exportfs -r//可能存在NFS無法訪問,需提高權(quán)限[root@nfs-server ~]# chmod -R 777 /data/android /data/gradle
三、android-jenkins-slave鏡像的Dockerfile
[root@mayi-ops jenkins-slave-android]# vim DockerfileFROM centos:7LABEL maintainer dengyouchengCOPY jdk-8u261-linux-x64.rpm /optCOPY gradle-6.7.1-all.zip /optCOPY sdk-tools-linux-3859397.zip /opt COPY slave.jar /usr/share/jenkins/slave.jarCOPY jenkins-slave /usr/bin/jenkins-slave#initRUN yum -y install wget && mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bak && wget -O /etc/yum.repos.d/CentOS-Base.repo && yum makecache && yum -y install epel-release && yum -y install gcc gcc-c++ jq net-tools git unzip && yum clean all && rm -rf /var/cache/yum/* && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && mkdir -p /opt/android/sdk && mkdir -p /usr/share/jenkins && chmod +x /usr/bin/jenkins-slave#install javaRUN yum -y install /opt/jdk-8u261-linux-x64.rpmENV JAVA_HOME /usr/java/jdk1.8.0_261-amd64ENV JRE_HOME ${JAVA_HOME}/jreENV CLASSPATH .$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jarENV PATH $PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin#install sdk#./sdkmanager –list查看有哪些版本RUN unzip /opt/sdk-tools-linux-3859397.zip -d /opt/android/sdk && mkdir /root/.android/ && touch /root/.android/repositories.cfg && cd /opt/android/sdk/tools/bin && ./sdkmanager –listENV ANDROID_HOME /root/.androidENV PATH $PATH:$ANDROID_HOME:$ANDROID_HOME/emulator:$ANDROID_HOME/platform-toolsENV ANDROID_ROOT /opt/android/sdk ENV PATH $PATH:$ANDROID_ROOT/tools:$ANDROID_ROOT/tools/bin# sdkmanagerSDK指定目錄,可以持久化存儲# yes | ./sdkmanager –licenses && # yes | ./sdkmanager “build-tools;33.0.0” “platforms;android-33” “build-tools;30.0.2” “platforms;android-30” “platform-tools” –sdk_root=/root/.android#install gradleRUN cd /opt/ && unzip gradle-6.7.1-all.zip && mv gradle-6.7.1 gradleENV PATH $PATH:/opt/gradle/binWORKDIR /optENTRYPOINT [“jenkins-slave”]
三、pipeline 腳本(測試腳本)
//*************************************************// Author : mayi-ops// Last modified: 2021-01-06// wechat: a403182580// Description : 安卓打包腳本//*************************************************//定義java-slave的yamldef podTemplate = “””kind: Podmetadata: name: android-slavespec: containers: – name: jnlp image: “${registry}/library/jenkins-slave-android:1.3” imagePullPolicy: Always volumeMounts: – name: docker-cmd mountPath: /usr/bin/docker – name: docker-sock mountPath: /var/run/docker.sock – name: gradlecache mountPath: /root/.gradle – name: androidcache mountPath: /root/.android volumes: – name: docker-cmd hostPath: path: /usr/bin/docker – name: docker-sock hostPath: path: /var/run/docker.sock – name: gradlecache nfs: server: ${nfsip} path: ${gradle_cache} – name: androidcache nfs: server: ${nfsip} path: ${android_cache}”””//pipeline構(gòu)建過程pipeline { agent { //根據(jù)yaml創(chuàng)建salve kubernetes { label “android-slave” yaml podTemplate } } //變量 environment { DingTalkHook = “” } stages { //如果是非admin、打包、打包部署,才會打包 stage(‘拉取代碼’) { steps{ script { /* 獲取git地址 */ if ( env.GitAddress ){ if ( env.GitAddress == ” ) { echo “請輸入git分支!” } }else{ echo “請輸入gitlab項(xiàng)目地址。” exit 0 } /* 代碼分支 */ //輸入分支:參數(shù)化構(gòu)建過程->字符參數(shù)->名稱:codeBranch->默認(rèn)值:fat if ( env.codeBranch ){ if ( env.codeBranch == ” ){ echo “請輸入git分支!” } }else{ echo “沒輸入分支,默認(rèn)使用master” env.codeBranch = “master” } echo “git:”+env.GitAddress echo “Branch:”+env.codeBranch //拉取業(yè)務(wù)代碼 checkout([ $class: ‘GitSCM’, branches: [[name: “${codeBranch}”]], doGenerateSubmoduleConfigurations: false, extensions: [[$class: ‘RelativeTargetDirectory’, relativeTargetDir: ‘code’]], submoduleCfg: [], userRemoteConfigs: [[credentialsId: “build_auth”, url: “${GitAddress}”]] ]) } } } stage(‘android打包’){ steps{ script { dir(“code”){ /* 打包腳本 */ sh “java -version” sh “adb version” sh “gradle -v” echo “=================gradle打包中===============================” sh “gradle assembleRelease” echo “=================gradle打包完成=============================” sh “cp app/build/outputs/apk/*/*.apk /root/ttt.apk” echo “=================gradle clean==============================” //sh “gradle clean” } } } } stage(‘push APK’){ steps{ script { env.Apkurl = sh returnStdout: true, script: “””curl -F “file=@/root/ttt.apk” -F “uKey=${env.USER_KEY}” -F “_api_key=${env.API_KEY}” appQRCodeURL|awk -F'”‘ ‘{print $4}'””” echo “蒲公英二維碼地址: “+env.Apkurl } } } } //使用post 插件必須使用pipeline,不能使用podTemplate插件 post { //安裝插件 HTTP Request Plugin和 Post build task success{ script { //打包成功 def ReqBody = “””{ “msgtype”: “markdown”, “markdown”: { “title”: “APK打包信息”, “text”: “## 【${env.objectname}】打包成功 n>- **打包分支:${env.codeBranch}**n>- **掃描二維碼下載APK:**n>- ![screenshot](${env.Apkurl}) n>- 構(gòu)建日志: [點(diǎn)擊查看詳情](${env.BUILD_URL}console)” }, “at”: { “isAtAll”: true } }””” httpRequest acceptType: ‘APPLICATION_JSON_UTF8’, consoleLogResponseBody: false, contentType: ‘APPLICATION_JSON_UTF8’, httpMode: ‘POST’, ignoreSslErrors: true, requestBody: ReqBody, responseHandle: ‘NONE’, url: “${env.DingTalkHook}”, quiet: true } } failure{ script { //打包失敗 def ReqBody = “””{ “msgtype”: “markdown”, “markdown”: { “title”: “APK打包信息”, “text”: “## 【${env.objectname}】打包失敗 n>- **打包分支:${env.codeBranch}**n>- 構(gòu)建日志: [點(diǎn)擊查看詳情](${env.BUILD_URL}console)” }, “at”: { “isAtAll”: true } }””” httpRequest acceptType: ‘APPLICATION_JSON_UTF8’, consoleLogResponseBody: false, contentType: ‘APPLICATION_JSON_UTF8’, httpMode: ‘POST’, ignoreSslErrors: true, requestBody: ReqBody, responseHandle: ‘NONE’, url: “${env.DingTalkHook}”, quiet: true } } }}