天天看點

Mac下搭建 Jenkins+Github+蒲公英/fir.im 持續內建環境(iOS自動打包)

看了幾篇關于使用jenkins持續內建的部落格,記錄一下自己搭建的過程,順便做一些更新

1. 安裝Jenkins直接下載下傳安裝包:http://jenkins-ci.org

或者使用指令行安裝

//安裝jenkins
$ brew install jenkins 
//啟動jenkins
$ jenkins
//解除安裝jenkins
$ brew uninstall jenkins
//brew無效? 哦 安裝homebrew 
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)”
           

2.啟動Jenkins後使用浏覽器通路:http://localhost:8080/

使用安裝包安裝後會自動打開,如果端口沖突那麼請修改端口

defaults write /Library/Preferences/org.jenkins-ci httpPort   
           

3.安裝插件:系統管理->插件管理 安裝Xcode integration;git plugin;PostBuildScript Plugin ; github plugin

點選左側工具欄“建立”,選擇第一項“建構一個自由風格的軟體項目”

Mac下搭建 Jenkins+Github+蒲公英/fir.im 持續內建環境(iOS自動打包)

5.配置

  • 源碼管理
    Mac下搭建 Jenkins+Github+蒲公英/fir.im 持續內建環境(iOS自動打包)

    Private項目需要配置ssh key多說幾句,本人比較笨踩了坑,寫一下jenkin配置ssh key的過程

    使用安裝包安裝,預設裝在Users/Shared/Jenkins 是以首先為jenkins使用者建立一個密碼

    $ sudo dscl . passwd /Users/jenkins **you pass**
    
    //切換到jenkins使用者 
    $ su jenkins
    //生成SSH KEY
    $ ssh-keygen -t rsa -b  -C "[email protected]"
    //打開id_rsa.pub 手動複制一下 添加到gitHub
    $ vi ~/.ssh/id_rsa.pub
    //測試一下
    $ ssh -T [email protected].com
    Hi ***! You've successfully authenticated, but GitHub does not provide shell access.
               
    SSH參考設定連結
  • 建構觸發器
    Mac下搭建 Jenkins+Github+蒲公英/fir.im 持續內建環境(iOS自動打包)
    這裡就是告訴jenkins什麼時候自動建構,如果開始安裝了github plugin插件的話就會有Build when a change is pushed to GitHub選項,這裡我同時設定了每周一到周五在每天的8點到9點之間執行一次
  • 建構

    增加建構步驟 -> Xcode

    Mac下搭建 Jenkins+Github+蒲公英/fir.im 持續內建環境(iOS自動打包)
    Mac下搭建 Jenkins+Github+蒲公英/fir.im 持續內建環境(iOS自動打包)

    關于證書

    如果在建構中出現了”Code Sign error: There are no valid certificate/private key pairs in the default keychain”這個錯誤,到你的鑰匙串串中,把有關iPhone開發的證書從“登入”便簽複制一份到“系統”标簽裡面。

    這個問題解決以後你會遇到下一個錯誤 “Code Sign error: Provisioning profile ‘xxxxx-xxxx-xxxx-xxxxx’ can’t be found”

    解決這個問題也很簡單,找到相應的.mobileprovision檔案,将其複制到/Users/Shared/Jenkins/Library/MobileDevice/Provisioning Profile就可以了

  • 建構後操作

    增加建構後操作步驟->Execute a set of scripts->Add build step->Execute shell

    Mac下搭建 Jenkins+Github+蒲公英/fir.im 持續內建環境(iOS自動打包)

    點選儲存,Job設定完成。

    Command裡腳本pugongying.py代碼如下,需要說明的是,這份代碼的原作者是@answer-huang 源碼在gitHub 本文的大部分内容參考answer_huang的《我是怎麼慢慢變懶的 : Jenkins + 蒲公英》

import time
import urllib2
import time
import json
import mimetypes
import os
import smtplib
from email.MIMEText import MIMEText
from email.MIMEMultipart import MIMEMultipart



#蒲公英應用上傳位址
url = 'http://www.pgyer.com/apiv1/app/upload'
#蒲公英提供的 使用者Key
uKey = '**********'
#上傳檔案的檔案名(這個可随便取,但一定要以 ipa 結尾)
file_name = 'test.ipa'
#蒲公英提供的 API Key
_api_key = '**********'
#安裝應用時需要輸入的密碼,這個可不填
installPassword = '111111'
# 運作時環境變量字典
environsDict = os.environ
#此次 jenkins 建構版本号
jenkins_build_number = environsDict['BUILD_NUMBER']

#項目名稱,用在 拼接 tomcat 檔案位址
project_name = '***'



#擷取 ipa 檔案路徑
def get_ipa_file_path():
    #工作目錄下面的 ipa 檔案
    ipa_file_workspace_path = '/Users/Shared/Jenkins/Home/workspace/' + project_name + '/build/'+file_name
    return ipa_file_workspace_path


# while get_ipa_file_path() is None:
#     time.sleep(5)

#ipa 檔案路徑
ipa_file_path = get_ipa_file_path()
print ipa_file_path

#請求字典編碼
def _encode_multipart(params_dict):

    boundary = '----------%s' % hex(int(time.time() * ))
    data = []
    for k, v in params_dict.items():
        data.append('--%s' % boundary)

        if hasattr(v, 'read'):
            filename = getattr(v, 'name', '')
            content = v.read()
            decoded_content = content.decode('ISO-8859-1')
            data.append('Content-Disposition: form-data; name="%s"; filename="kangda.ipa"' % k)
            data.append('Content-Type: application/octet-stream\r\n')
            data.append(decoded_content)
        else:
            data.append('Content-Disposition: form-data; name="%s"\r\n' % k)
            data.append(v if isinstance(v, str) else v.decode('utf-8'))
    data.append('--%s--\r\n' % boundary)
    return '\r\n'.join(data), boundary


#處理 蒲公英 上傳結果
def handle_resule(result):

    json_result = json.loads(result)


    print json_result


    if json_result['code'] is :
        send_Email(json_result)

#發送郵件
def send_Email(json_result):

    appName = json_result['data']['appName']
    appKey = json_result['data']['appKey']
    appVersion = json_result['data']['appVersion']
    appBuildVersion = json_result['data']['appBuildVersion']
    appShortcutUrl = json_result['data']['appShortcutUrl']
    #郵件接受者
    mail_receiver = ['***@***.com']
    #根據不同郵箱配置 host,user,和pwd
    mail_host = 'smtp.126.com'
    mail_user = '***@**.com'
    mail_pwd = '****'
    mail_to = ','.join(mail_receiver)
    mail_title = project_name + '最新打封包件' + '(' +jenkins_build_number + ')'
    msg = MIMEMultipart()

    environsString = '<h3>本次打包相關資訊</h3><p>'
    environsString += '<p>項目名稱 : '+ project_name + '<p>'
    environsString += '<p>建構ID:' + jenkins_build_number +'<p>'
    environsString += '<p>你也可從蒲公英網站線上安裝 : ' + 'http://www.pgyer.com/' + str(appShortcutUrl) + '   密碼 : ' + installPassword + '<p>'
    environsString += '<li><a href="itms-services://?action=download-manifest&url=https://ssl.pgyer.com/app/plist/' + str(appKey) + '">點我直接安裝</a></li>'
    message = environsString
    body = MIMEText(message, _subtype='html', _charset='utf-8')
    msg.attach(body)
    msg['To'] = mail_to
    msg['from'] = mail_user
    msg['subject'] =mail_title

    try:
        s = smtplib.SMTP()
        s.connect(mail_host)
        s.login(mail_user, mail_pwd)

        s.sendmail(mail_user, mail_receiver, msg.as_string())
        s.close()
        print 'success'
    except Exception, e:
        print e

#############################################################
#請求參數字典
params = {
    'uKey': uKey,
    '_api_key': _api_key,
    'file': open(ipa_file_path, 'rb'),
    'publishRange': '2',
    'password': installPassword

}

coded_params, boundary = _encode_multipart(params)
req = urllib2.Request(url, coded_params.encode('ISO-8859-1'))
req.add_header('Content-Type', 'multipart/form-data; boundary=%s' % boundary)
try:
    resp = urllib2.urlopen(req)
    body = resp.read().decode('utf-8')
    handle_resule(body)

except urllib2.HTTPError as e:
    print(e.fp.read())

           

OK 最後 點選 立即建構

稍等幾分鐘收到郵件

Mac下搭建 Jenkins+Github+蒲公英/fir.im 持續內建環境(iOS自動打包)
Mac下搭建 Jenkins+Github+蒲公英/fir.im 持續內建環境(iOS自動打包)

這種方法适合做日常測試,或者讓産品經理更好的了解進度。如果做上線測試建議使用iTunes Connect +Testflight, 保證送出稽核的版本跟測試最後看到的版本是同一個包!介紹的文章有很多了 随便 來一個吧 《如何使用TestFlight進行Beta測試》

Jenkins相關:《Jenkins+Github+Testflight在Mac下搭建持續內建環境》

《我是怎麼慢慢變懶的 : Jenkins + 蒲公英》

補充遇到的問題

1.建構失敗提示:–resource-rules has been deprecated in mac os x >= 10.10

解決:選擇 project > Targets > Select your target > Build Settings >

Code Signing Resource Rules Path 添加 $(SDKROOT)/ResourceRules.plist

2.建構失敗提示:

FATAL: Build directory does not exist at /Users/Shared/Jenkins/Home/**. Potential configuration issue.

Build step ‘Xcode’ marked build as failure

看了jenkins論壇,上面發了相識問題也沒有,仔細檢查一下發現 Advanced Xcode build options 少配置了一項,Build output directory設定為${WORKSPACE}/build/ OK解決!

Mac下搭建 Jenkins+Github+蒲公英/fir.im 持續內建環境(iOS自動打包)

3.注意:Schemes 勾選shared

4.在Xcode配置 Advanced Xcode build options -

Custom xcodebuild arguments 填寫:CODE_SIGN_RESOURCE_RULES_PATH=$(SDKROOT)/ResourceRules.plist