安卓Jenkins持續(xù)化集成

安裝篇

1.打開(kāi)你的瀏覽器郁惜,輸入www.baidu.com
2.搜索jenkins點(diǎn)開(kāi)第一個(gè)骑晶,然后等待加載轉(zhuǎn)圈圈https://www.jenkins.io/zh/

官網(wǎng).png

3.下載左邊的蛾坯,穩(wěn)定版,不下每周更新版
下載.png

4.MAC Linux Windows都下載自己的版本
5.安裝后打開(kāi),各種默認(rèn)化配置狂男,有下一步點(diǎn)擊下一步
image.png

6.等待插件下載完,部分下載失敗也沒(méi)事品腹,不用管岖食,能進(jìn)入主頁(yè)直接進(jìn)入主頁(yè)
image.png

7.看到這個(gè),恭喜舞吭,你安裝并且登錄成功了
image.png

使用篇 以u(píng)bantu為例

問(wèn)題1:jenkins配置局域網(wǎng)其他電腦可訪問(wèn)(自己百度找泡垃,就是把127.0.0.1改成0.0.0.0)
https://blog.csdn.net/weixin_33860147/article/details/89752482
問(wèn)題2:jenkins配置環(huán)境變量
Manage Jenkins ->Configure System->Environment variables 配置一些你的環(huán)境變量
系統(tǒng)默認(rèn)的path可用,可以輸出path以示例镣典。
問(wèn)題3:開(kāi)啟用戶認(rèn)證兔毙,或者說(shuō)多用戶體系
默認(rèn)只有單用戶唾琼,在Manage Jenkins ->Configure Global Security->勾選允許用戶注冊(cè)兄春,勾選項(xiàng)目矩陣授權(quán)策略,效果如下锡溯,給對(duì)應(yīng)的用戶赶舆,對(duì)應(yīng)的權(quán)限,允許用戶注冊(cè)祭饭,由管理員管理

image.png

問(wèn)題4芜茵,插件安裝
Manage Jenkins ->Manage Plugins->點(diǎn)擊可選插件->在搜索欄輸入對(duì)應(yīng)關(guān)鍵字,示例如下
image.png

已安裝倡蝙,或者已更新里面都可以找找九串,高級(jí)里面有安裝本地插件的選項(xiàng)。
問(wèn)題5.安裝gradle版本(你得先安裝gradle插件寺鸥,默認(rèn)推薦已經(jīng)安裝了)
Manage Jenkins ->Global Tool Configuration->找到gradle安裝->新增gradle->選個(gè)版本填個(gè)名字保存
image.png

準(zhǔn)備工作基本完畢猪钮,然后就是創(chuàng)建項(xiàng)目

1.回到j(luò)enkins首頁(yè),點(diǎn)擊新建item胆建。輸入個(gè)名字烤低,選擇freestyle project完成(其他類型的,有興趣自己搞笆载,我沒(méi)用到)


image.png

2.step1


image.png

3.step2
image.png

4.step3
這里就是一些鉤子扑馁,中文描述已經(jīng)很清楚,你不想點(diǎn)擊可以選擇其中一種凉驻,輪詢scm腻要,可以設(shè)置定時(shí)檢查,這個(gè)不用鉤子涝登,根據(jù)規(guī)則寫(xiě)一句話就好了


image.png

5.step4
構(gòu)建步驟雄家,與構(gòu)建后操作,只要你想要缀拭,自己添加咳短,構(gòu)建操作可以執(zhí)行python填帽,sh,windows command等咙好,習(xí)慣哪個(gè)用哪個(gè)篡腌。個(gè)人喜歡用sh調(diào)用本地python腳本,方便調(diào)試跟腳本管理勾效。也可以選擇這里上傳pgy等(要安裝個(gè)pgy插件嘹悼,按提示操作就好)
image.png

然后你就可以愉快的使用jenkins了。层宫。

目前我用的解決方案

1.使用jenkins進(jìn)行項(xiàng)目構(gòu)建杨伙,
2.構(gòu)建完成后,調(diào)用預(yù)寫(xiě)好的python腳本萌腿,做一系列操作
3.自己打包個(gè)qrcode.jar限匣。生成二維碼用
4.下載360加固的jiagu.jar。加固包使用
5.下載walle的jar包毁菱。打渠道包用
6.下載tomcat米死,起服務(wù)器用
7.python腳本具體流程實(shí)現(xiàn)為,保存mapping(解混淆使用)贮庞,執(zhí)行加固峦筒,加固完成后,移動(dòng)到備份的文件夾窗慎,執(zhí)行walle打渠道包物喷,打完后,將至復(fù)制到tomcat的webapp下遮斥,然后根據(jù)所在路徑生成二維碼峦失,然后從git中,取出一些信息伏伐,比如多少條提交日志宠进,所在分支,或者構(gòu)建參數(shù)等藐翎,組成推送文案材蹬,調(diào)用企業(yè)微信機(jī)器人的發(fā)消息方法通知到測(cè)試群,測(cè)試或者開(kāi)發(fā)同學(xué)自行掃碼下載即可

附其中部分python腳本方法吝镣。

import base64
import hashlib
import json
import os
import shutil
import socket
import time
import urllib.request
import urllib.error

import requests

# 新建任務(wù)需要執(zhí)行的腳本需要修改的地方
# 渠道名字堤器,復(fù)制粘貼的時(shí)候記得改
channel = "demo 名字自己設(shè)置"
# 這里對(duì)應(yīng)jenkins任務(wù)目錄,復(fù)制粘貼的時(shí)候記得改
rootPath = "/var/lib/jenkins/workspace/demo jenkins項(xiàng)目地址"
# 對(duì)應(yīng)渠道的keystore名字
key_store_name = "keystore.jks的名字"
# keystore的賬號(hào)密碼末贾,空格不可刪除
key_store_pass = ' 密碼 別名 別名密碼'

# 以下不需要改動(dòng)
# 加固寶的位置
jiaguPath = "/var/lib/jenkins/workspace/task/360jiagubao_linux_64/jiagu""#你放哪闸溃,就填哪里
# apk的位置
apkRootPath = rootPath + "/app/build/outputs"
# 歸檔文件夾的主目錄
copyfilePath = "/home/haha/NewDisk/歸檔"
# 歸檔文件夾的子目錄
outPutFolder = int(round(time.time() * 1000)).__str__()
# 管理員密碼
sudoPassword = "1"#ubantu 的管理員密碼,有些操作需要管理員權(quán)限
# tomecat服務(wù)器目錄
tomcatPath = "/home/haha/studio/tomcat/webapps/examples"
# 二維碼生成jar包的路徑
qrcodeJarPath = "/var/lib/jenkins/workspace/task/myqrcode.jar"


def getNewestMessage():
    result2 = os.popen("git name-rev --name-only HEAD")
    outPut = result2.buffer.read().decode('utf-8')
    return outPut


def getCommitMsg():
    outPut = os.popen("git log --pretty=format:\"%H\" | head -10")
    idArray = outPut.buffer.read().decode('utf-8').split('\n')
    for i in range(0, len(idArray)):
        result2 = os.popen("git log --pretty=format:\"%s\" " + idArray[i] + " -1")
        outPut = result2.buffer.read().decode('utf-8')
        if "Merge branch" in outPut:
            continue
        else:
            return outPut
    return "無(wú)額外提交信息"


# 獲取apk路徑
def apkPath(file_dir):
    list = []
    for root, dirs, files in os.walk(file_dir):
        if len(files) > 0:
            for file in files:
                if file.endswith(".apk"):
                    list.append(root + "/" + file + '')
    return list


# 獲取apk版本號(hào)
def file_name():
    for root, dirs, files in os.walk(apkRootPath):
        if len(files) > 0:
            for file in files:
                if file.endswith(".apk"):
                    a = file.split("_")
                    return a[len(a) - 2]


# 創(chuàng)建文件夾
def create_folder(check_path):
    if not os.path.exists(check_path):
        os.makedirs(check_path)


# 拷貝目錄到子文件
def copyfile():
    # 創(chuàng)建歸檔目錄
    out_path = os.path.join(copyfilePath, channel, file_name(), outPutFolder)
    create_folder(out_path)
    # 獲取需要拷貝的apk列表
    list = apkPath(apkRootPath)
    if len(list) > 0:
        for path in list:
            shutil.copy(path, out_path)


def copyMapping():
    # 創(chuàng)建歸檔目錄
    os.chdir(copyfilePath)
    # create_folder(os.path.join(file_name(), outPutFolder))

    folder1 = os.path.join(apkRootPath, "mapping")
    folder2 = os.path.join(copyfilePath, channel, file_name(), outPutFolder, "mapping")
    shutil.copytree(folder1, folder2, ignore=shutil.ignore_patterns("output.json"))


def exec_360_jiagu(path):
    output_path = os.path.join(copyfilePath, file_name(), outPutFolder)
    if not os.path.exists(output_path):
        os.mkdir(output_path)
    jiagu_cmd = 'java -jar jiagu.jar -jiagu ' + path + ' ' + output_path + ' -autosign'
    result = os.system('echo %s|sudo -S %s' % (sudoPassword, jiagu_cmd))
    if not result:
        print("========" + str(result) + "  加固成功")
    else:
        print("加固失敗")


def jiagu():
    # 檢查輸出路徑是否存在
    folder0 = os.path.join(copyfilePath, file_name(), outPutFolder)
    create_folder(folder0)

    # 登陸加固程序
    os.chdir(jiaguPath)
    command = 'java -jar jiagu.jar -login 18268065891 ff623893'
    os.system('echo %s|sudo -S %s' % (sudoPassword, command))

    folder1 = os.path.join(rootPath, "app", key_store_name)
    command = 'java -jar jiagu.jar -importsign ' + folder1 + key_store_pass
    os.system('echo %s|sudo -S %s' % (sudoPassword, command))
    # 獲取需要加固的APK列表
    list = apkPath(apkRootPath)
    if len(list) > 0:
        for path in list:
            # 開(kāi)始加固
            exec_360_jiagu(path)


def notifyQyWx(downloadPath):
    url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=f38fa1f7-8193-4e28-bfff-d6fbd5680770'

    os.chdir(rootPath)

    con = {"msgtype": "text",
           "text": {"content": "打包成功了:下載鏈接 \n" + downloadPath + "\n打包分支:" + getNewestMessage()}, }

    jd = json.dumps(con).encode('utf-8')

    req = urllib.request.Request(url, jd)

    req.add_header('Content-Type', 'application/json')

    response = urllib.request.urlopen(req)


def notifyQyWxText():
    url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=aaaa'

    os.chdir(rootPath)

    result2 = os.popen("echo $message")
    back_message = result2.buffer.read().decode('utf-8')

    con = {"msgtype": "text",
           "text": {"content": "打包成功了\n版本號(hào):" + file_name() + "\n提交日志:" + getCommitMsg()+"\n所在分支:" + getNewestMessage()+"\n備注信息:"+back_message}, }

    jd = json.dumps(con).encode('utf-8')

    req = urllib.request.Request(url, jd)

    req.add_header('Content-Type', 'application/json')

    response = urllib.request.urlopen(req)




def wx_image(image):
    with open(image, 'rb') as file:  # 轉(zhuǎn)換圖片成base64格式
        data = file.read()
        encodestr = base64.b64encode(data)
        image_data = str(encodestr, 'utf-8')

    with open(image, 'rb') as file:  # 圖片的MD5值
        md = hashlib.md5()
        md.update(file.read())
        image_md5 = md.hexdigest()

    url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=aaaa"  # 填上機(jī)器人Webhook地址
    headers = {"Content-Type": "application/json"}
    data = {
        "msgtype": "image",
        "image": {
            "base64": image_data,
            "md5": image_md5
        }
    }
    result = requests.post(url, headers=headers, json=data)
    return result


def generateQrcode():
    # 加固的輸出目錄
    input_path = os.path.join(copyfilePath, channel, file_name(), outPutFolder)
    # list = apkPath(input_path)
    # if len(list) > 0:
    #     for path in list:
    #         # 開(kāi)始加固
    #         exec_360_jiagu(path)
    output_path = os.path.join(tomcatPath, "apk", channel, file_name())
    if os.path.exists(output_path):
        shutil.rmtree(output_path)
    shutil.copytree(input_path, output_path, ignore=shutil.ignore_patterns("mapping"))
    server_path = "http://" + get_host_ip() + ":8088"
    list = apkPath(output_path)
    downloadpaths = ""
    if len(list) > 0:
        notifyQyWxText()
        for path in list:
            qrcode_content = server_path + path.replace("/home/haha/studio/tomcat/webapps", "")
            pic_path = tomcatPath + "/img/" + channel + "/" + file_name() + ".png"
            command = "java -jar " + qrcodeJarPath + " src=" + qrcode_content + " path=" + pic_path
            os.system('echo %s|sudo -S %s' % (sudoPassword, command))
            wx_image(pic_path)
            downloadpaths = downloadpaths \
                .__add__(qrcode_content) \
                .__add__("\n")
    # 通知到企業(yè)微信(暫時(shí)不用)
    # notifyQyWx(downloadpaths)
    # 復(fù)制文件到tomcat


def get_host_ip():
    """
    查詢本機(jī)ip地址
    :return:
    """
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8', 80))
        ip = s.getsockname()[0]
    finally:
        s.close()
    return ip


if __name__ == '__main__':
    # 初始化存儲(chǔ)目錄
    # copyMapping() 測(cè)試不需要拷貝mapping
    # jiagu() 測(cè)試包不需要加固

    copyfile()
    generateQrcode()

附二維碼生成qrcode.jar
使用方法 java -jar myqrcode.jar src=aa path=D:/aaa.png //這里反斜桿不要輸入錯(cuò)
鏈接:https://pan.baidu.com/s/1sOOihVTCXGGzU62CzoXWpw
提取碼:8pzb

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乓旗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子屿愚,更是在濱河造成了極大的恐慌,老刑警劉巖妆距,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異娱据,居然都是意外死亡蚪黑,警方通過(guò)查閱死者的電腦和手機(jī)吸耿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門酷窥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)咽安,“玉大人,你說(shuō)我怎么就攤上這事蓬推∽卑簦” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵沸伏,是天一觀的道長(zhǎng)糕珊。 經(jīng)常有香客問(wèn)我,道長(zhǎng)毅糟,這世上最難降的妖魔是什么红选? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮姆另,結(jié)果婚禮上喇肋,老公的妹妹穿的比我還像新娘。我一直安慰自己迹辐,他們只是感情好蝶防,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著明吩,像睡著了一般间学。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,792評(píng)論 1 290
  • 那天低葫,我揣著相機(jī)與錄音详羡,去河邊找鬼。 笑死嘿悬,一個(gè)胖子當(dāng)著我的面吹牛殷绍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鹊漠,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼主到,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了躯概?” 一聲冷哼從身側(cè)響起登钥,我...
    開(kāi)封第一講書(shū)人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎娶靡,沒(méi)想到半個(gè)月后牧牢,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡姿锭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年塔鳍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呻此。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡轮纫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出焚鲜,到底是詐尸還是另有隱情,我是刑警寧澤忿磅,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布葱她,位于F島的核電站,受9級(jí)特大地震影響搓谆,放射性物質(zhì)發(fā)生泄漏锤灿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一螃诅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧倘是,春花似錦袭艺、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至获茬,卻和暖如春倔既,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背渤涌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工歼捏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瞳秽。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓练俐,卻偏偏與公主長(zhǎng)得像腺晾,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子悯蝉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348