1. 程式人生 > >Ubuntu搭建Jenkins+Android自動化打包

Ubuntu搭建Jenkins+Android自動化打包

640?wx_fmt=png

今日科技快訊

11月18日,聯想因國內外打折促銷活動政策的不同,引發消費者爭論。聯想方面回覆北青報記者表示,一些誤解可能來源於把國內售價與海外不含稅且不含軟硬體的價格相對比,國內的商品一般提供預裝軟體和滑鼠等配件。同時,聯想在不同的國家(地區)獨立經營的,採取不同的產品規劃策略和銷售政策。

作者簡介

大家週一好,新的一週繼續努力加油!

本篇來自 Android_sheng 的投稿,分享了在Ubuntu系統下如何搭建Jenkins+Android自動化打包平臺相關的知識。一起來看看!希望大家喜歡。

Android_sheng 的部落格地址:

https://www.jianshu.com/u/43cf6103c128

前言

本文主要介紹如何在Ubuntu搭建Jenkins實現Android專案的自動化打包,一般部署在我們的伺服器,這裡我通過虛擬機器安裝Ubuntu來進行演示。

正文

環境配置

  • 下載並配置java環境

通過java官網下載對應jdk版本。開啟終端,輸入以下命令列進行解壓

tar -zxvf jdk-8u181-linux-x64.tar.gz

將解壓後的資料夾移動到/opt目錄下

sudo mv jdk1.8.0_181 /opt/

修改環境變數

sudo vi ~/.bashrc

在末尾新增如下配置

#set Java environment
export JAVA_HOME=/opt/jdk1.8.0_181
export JRE_HOME=${JAVA_HOME}
/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

儲存退出,使用source命令使其生效

source ~/.bashrc

驗證java環境是否配置成功

java -vsersion
  • Git安裝

sudo apt-get install git
  • 安裝配置nginx

為了使得外部能下載相關資源,安裝並配置本地目錄對映

sudo apt-get install nginx
sudo service nginx start
sudo vi /etc/nginx/nginx.conf

簡單修改配置檔案,新增如下內容

server {
        listen 81;
        server_name 192.168.80.140;
        client_max_body_size 4G;
        root /home/cc/pkg_bak;
        location / {
                autoindex on;
                autoindex_exact_size on;
                autoindex_localtime on;
        }
}

使配置生效

sudo service nginx reload 

Jenkins安裝

可以根據Jenkins官網文件進行安裝

wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins
  • 修改Jenkins配置

sudo vi /etc/default/jenkins

修改埠號

# 預設是8080埠
HTTP_PORT=8081
  • 啟動Jenkins

sudo service jenkins start

啟動完成,通過瀏覽器訪問 http://192.168.80.140:8081 即可看到啟動介面

640?wx_fmt=other

啟動jenkins.png

根據提示通過檢視 /var/lib/jenkins/secrets/initialAdminPassword 獲取到密碼即可。然後根據提示安裝需要的外掛,建立使用者,完成後出現下面的介面,Jenkins 搭建完成

640?wx_fmt=other

搭建完成.png

配置Android專案編譯環境

  • 安裝常用外掛

路徑:系統管理-外掛管理-可選外掛,在搜尋框輸入你需要安裝的外掛進行安裝即可

常用外掛有以下:

  • Git plugin

  • Git Parameter

  • GitLab Plugin

  • Gradle Plugin

  • Android Emulator Plugin

  • Android Lint Plugin

  • description setter plugin

  • Checkstyle Plug-in

  • FindBugs Plug-in

  • PMD Plug-in

  • SSH Agent

  • Role-based Authorization Strategy

  • OWASP Markup Formatter Plugin

  • 配置Git

路徑:系統管理-全域性工具配置-Git

因為Ubuntu已經安裝了Git,所以預設配置即可

640?wx_fmt=jpeg

配置Git.png

  • 配置JDK

路徑:系統管理-全域性工具配置-JDK

下載需要一個Oracle的帳號,新增完賬戶就可以了

640?wx_fmt=other

配置JDK.png

  • 配置Gradle

路徑:系統管理-全域性工具配置-Gradle

640?wx_fmt=other

配置Gradle.png

  • 配置Android SDK

路徑:系統管理-系統設定-Android

填寫SDK的存放路徑,同時勾選自動下載,警告可以忽略

640?wx_fmt=jpeg

配置AndroidSDK.png

這個時候有一個問題需要注意,必須在sdk的目錄下 新增license檔案,去你本地的sdk下拷貝一份進去

新建工程

640?wx_fmt=other

新建工程.png

  • 填寫General

一般會勾選丟棄舊的構建,防止伺服器累計過多次的編譯

640?wx_fmt=other

填寫General.png

  • 填寫原始碼管理

使用Git來拉取程式碼

640?wx_fmt=other

填寫原始碼管理.png

  • 構建配置

640?wx_fmt=other

配置構建介面.png

上內容述執行的是:

  1. 重置,清空專案內容

  2. 將存在伺服器的金鑰資訊、sdk目錄等資訊(local.properties),拷貝到專案中

  3. 使用工程下的gradlew來構建專案,保持gradle版本與本地一致,Tasks中輸入專案要編譯的任務

因為我的金鑰讀取是放到 local.properties 檔案中的,所以可以做到伺服器管控打包金鑰,local.properties 內容如下

KEY_STORE=金鑰路徑
KEY_STORE_PASSWORD=密碼
KEY_ALIAS=金鑰別名
KEY_ALIAS_PASSWORD=密碼
sdk.dir=sdk路徑
  • 構建後配置

需要收集相應的apk和mapping檔案

640?wx_fmt=jpeg

配置構建後介面.png

最後點選儲存,通過簡單配置,到此已經可以實現專案的構建了

更多定製化配置

  • 通過Git Parameter外掛實現分支選擇

640?wx_fmt=other

填寫GitParameter.png

  • 整合360加固

從360官方下載相關檔案,拷貝到/home/cc/backup/360jiagu目錄,使用命令列的方式進行加固,詳細可以檢視官方說明文件,這裡採用編寫指令碼檔案實現自動加固,檔案內容如下:

指令碼jiagu_360.sh存放路徑/home/cc/backup/360jiagu/jiagu

#!/bin/bash

BASE_JAR=/home/cc/backup/360jiagu/jiagu/jiagu.jar
JIA_GU_NAME=賬號
JIA_GU_PSD=密碼

echo "------ jiagu running! ------"
java -jar ${BASE_JAR} -version
java -jar ${BASE_JAR} -login ${JIA_GU_NAME} ${JIA_GU_PSD}

LOCAL_PATH=$1
echo "local.properties:${LOCAL_PATH}"

KEY_STORE=`cat ${LOCAL_PATH} |grep KEY_STORE= | awk -F= '{print $2}'`
KEY_STORE_PASSWORD=`cat ${LOCAL_PATH} |grep KEY_STORE_PASSWORD= | awk -F= '{print $2}'`
KEY_ALIAS=`cat ${LOCAL_PATH} |grep KEY_ALIAS= | awk -F= '{print $2}'`
KEY_ALIAS_PASSWORD=`cat ${LOCAL_PATH} |grep KEY_ALIAS_PASSWORD= | awk -F= '{print $2}'`

java -jar ${BASE_JAR} -importsign ${KEY_STORE} ${KEY_STORE_PASSWORD} ${KEY_ALIAS} ${KEY_ALIAS_PASSWORD}

java -jar ${BASE_JAR} -showsign

BuildApkLine=$2
Build_JiaGu_Dir=$3
echo "BuildApkLine:${BuildApkLine}, Build_JiaGu_Dir=${Build_JiaGu_Dir}"

java -jar ${BASE_JAR} -jiagu $BuildApkLine $Build_JiaGu_Dir -autosign   

echo "------ jiagu finished! ------"
  • 生成二維碼,在構建歷史展示更多資訊

安裝description setter plugin外掛

在Ubuntu上安裝qrencode, 用於生成二維碼圖片

sudo apt-get install qrencode

修改構建任務,在專案編譯完加固完成後執行下面命令

BuildApkLine=`find ./jiagu -name *_jiagu_sign.apk`

# 備份到檔案伺服器
PkgBakDir="/home/cc/pkg_bak/${JOB_NAME}"
if [ ! -d "$PkgBakDir" ]; then
mkdir $PkgBakDir
fi

BuildDir="$PkgBakDir/${BUILD_NUMBER}"
if [ ! -d "$BuildDir" ]; then
mkdir $BuildDir
fi

ApkName=${BuildApkLine##*/}

LastestApkName="dev_lastest.apk"

cp $BuildApkLine $BuildDir

if [ -f "$PkgBakDir/$LastestApkName" ]; then
rm $PkgBakDir/$LastestApkName
fi

ln -s "$BuildDir/$ApkName" "$PkgBakDir/$LastestApkName"

QrcodeValue="http://192.168.80.140:81/${JOB_NAME}/${BUILD_NUMBER}/$ApkName"
echo "QrcodeValue is $QrcodeValue" 

LastQrcodeValue="http://192.168.80.140:81/${JOB_NAME}/$LastestApkName"
echo "LastQrcodeValue is $LastQrcodeValue" 

# 將debug apk的下載地址 生成二維碼,以供下載
qrencode -o qrcode.png $QrcodeValue

# 將debug apk的下載地址 生成二維碼,以供下載
qrencode -o last_qrcode.png $LastQrcodeValue

# 輸出debug apk的下載地址,機械號,版本名稱
echo "BuildUrl: $QrcodeValue,$VersionCode,$VersionName,$dev_branch,$Tasks"

構建後操作,新增Set build description

640?wx_fmt=other

構建後操作.png

這裡解釋一下這兩個引數:

Regular expression:BuildUrl: (.),(.),(.),(.)

通過正則匹配獲取到上面BuildUrl的4個引數,分別為apk地址、機械號、版本名稱、分支名稱

Description

描述,這裡以html格式輸出其中 \1,\2..分別對應上面匹配的4個引數

完成後的結果如下:

640?wx_fmt=other

效果圖.png

  • 整合fir自動上傳

打包完成後實現自動上傳到fir,可參考 fir官方文件,這裡我們通過編寫Python指令碼實現自動上傳功能,指令碼程式碼如下:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import requests
import json
import sys

# 需要的引數
REQUEST_PARAM = {
    'api_token''這裡填寫自己的token資訊',
    'type''android',
    'applicationId''com.xxx.xxx',
    'appName''應用名稱',
    'versionName''1.0.1.0',
    'versionCode''10',
    'changelog_path''changelog檔案地址',
    'apk_path''apk地址'
}


# 初始化傳入的引數
def init_param():
    print('獲取到傳遞過來的引數:', str(sys.argv))
    REQUEST_PARAM['type'] = sys.argv[1]
    REQUEST_PARAM['applicationId'] = sys.argv[2]
    REQUEST_PARAM['appName'] = sys.argv[3]
    REQUEST_PARAM['versionName'] = sys.argv[4]
    REQUEST_PARAM['versionCode'] = sys.argv[5]
    REQUEST_PARAM['changelog_path'] = sys.argv[6]
    REQUEST_PARAM['apk_path'] = sys.argv[7]


# 獲取上傳憑證
def get_cert():
    print('發起獲取上傳憑證請求')
    param = {'type': REQUEST_PARAM['type'],
             'bundle_id': REQUEST_PARAM['applicationId'],
             'api_token': REQUEST_PARAM['api_token']}
    print('獲取上傳憑證請求引數:', param)
    req = requests.post(url='http://api.fir.im/apps', data=param)
    cert_response = req.content
    print('獲取上傳憑證響應:', str(cert_response))
    return cert_response


# 上傳到fir
def upload_fir(binary, apk_path):
    binary_key = binary['key']
    binary_token = binary['token']
    binary_upload_url = binary['upload_url']

    print('開始上傳Apk')
    changelog_str = open(REQUEST_PARAM['changelog_path']).read()
    file = {'file': open(apk_path, 'rb')}
    param = {
        "key": binary_key,
        "token": binary_token,
        "x:name": REQUEST_PARAM['appName'],
        'x:version': REQUEST_PARAM['versionName'],
        'x:build': REQUEST_PARAM['versionCode'],
        "x:changelog": changelog_str
    }
    req = requests.post(binary_upload_url, files=file, data=param)
    print('上傳結果:', req.content)


if __name__ == '__main__':
    init_param()
    response = get_cert()
    # 得到獲取上傳憑證回撥資訊
    cert_json = json.loads(response)
    cert_binary = cert_json['cert']['binary']
    # 上傳fir
    upload_fir(cert_binary, REQUEST_PARAM['apk_path'])

指令碼程式碼註釋也比較詳細,不再展開說明,最後通過在上面加固完成後的shell指令碼後面追加以下內容來實現自動上傳

# 編寫日誌內容
ChangeLog=changelog.txt
echo "Uploaded by fir cli" >> $ChangeLog
echo "構建編號:${BUILD_NUMBER}" >> $ChangeLog
echo "修改記錄:"  >> $ChangeLog
echo "${SCM_CHANGELOG}"  >> $ChangeLog

cat $ChangeLog

python /home/cc/backup/fir/uploadFir.py android $ApplicationId $AppName $VersionCode $VersionName $ChangeLog $BuildApkLine

常見問題

  • Jenkins啟動可能出現的問題

Job for jenkins.service failed because the control process exited with error code. See “systemctl status jenkins.service” and “journalctl -xe” for details.

根據提示輸入sudo systemctl status jenkins.service

● jenkins.service - LSB: Start Jenkins at boot time
   Loaded: loaded (/etc/init.d/jenkins; generated)
   Active: failed (Result: exit-code) since Thu 2018-10-18 11:19:37 CST; 21s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 3896 ExecStart=/etc/init.d/jenkins start (code=exited, status=1/FAILURE)

10月 18 11:19:37 cc-virtual-machine systemd[1]: Starting LSB: Start Jenkins at boot time...
10月 18 11:19:37 cc-virtual-machine jenkins[3896]: ERRORNo Java executable found in current PATH: /bin:/usr/bin:
10月 18 11:19:37 cc-virtual-machine jenkins[3896]: If you actually have java installed on the system make sure the
10月 18 11:19:37 cc-virtual-machine systemd[1]: jenkins.service: Control process exited, code=exited status=1
10月 18 11:19:37 cc-virtual-machine systemd[1]: jenkins.service: Failed with result 'exit-code'.
10月 18 11:19:3