鍍金池/ 教程/ Java/ 傳遞部署
集成自動化部署
架設(shè) CI 服務(wù)器
探索用戶資源
SSH agent 轉(zhuǎn)發(fā)
使用評論
身份認證基礎(chǔ)
管理部署密鑰
準備開始
傳遞部署
遍歷分頁
整合者的最佳做法
數(shù)據(jù)渲染成圖表

傳遞部署

Deployments API可以讓你托管在GitHub上的項目部署到你自己的服務(wù)器上。 結(jié)合 the Status API,你在提交代碼到 master 分支的同時可以調(diào)整部署。

本指南將為你演示一個你可以操作的步驟,在我們的腳本里,我們會:

  • Merge 一個 Pull Request
  • 當(dāng) CI 結(jié)束時,我們將相應(yīng)地設(shè)置 Pull Request 的狀態(tài)
  • 當(dāng) Pull Request 被 Merged,我們將運行部署到我們的服務(wù)器

我們的 CI 系統(tǒng)和主機服務(wù)器是我們憑空想象出來的,他們可以是 Heroku,Amazon 或其他一些實體。本指南的關(guān)鍵就是設(shè)置和配置服務(wù)端去管理通信。

如果你還沒有準備好,請確定你下載了ngrok,并且學(xué)會使用它。我們發(fā)現(xiàn)他是一個監(jiān)測本地連接非常好用的工具。

提示:你可以從 platform-samples repo 上下載這個項目完整的源碼。

編寫你的服務(wù)

我們將編寫一個輕便的 Sinatra 應(yīng)用程序來證明我們的本地連接正在工作。我們這樣開始:

    require 'sinatra'        
    require 'json'          

    post '/event_handler' do           
    payload = JSON.parse(params[:payload])          
      "Well, it workded!"         
    end         

(如果你不熟悉 Sinatra 如何工作, 我們推薦你閱讀 Sinatra指南)

啟動服務(wù)器。默認情況下,Sinatra 從 9393 端口啟動,所以你也會配置 ngrok 去監(jiān)聽這個端口。

為了讓這臺服務(wù)器的工作,我們需要創(chuàng)建一個帶有一個 webhook 的倉庫。無論一個 Pull Resuqest 是被 Merged 還是被創(chuàng)建,webhook 都應(yīng)該被配置為 fire。繼續(xù)并創(chuàng)建一個倉庫,染護沉浸其中。也許你可以參考 @octocat’s Spoon/Knife repository,之后,你會在你的倉庫里創(chuàng)建一個新的 webhook,并將 ngrok 提供你的 URL 填充上去:

http://wiki.jikexueyuan.com/project/github-developer-guides/images/webhook_sample_url.png" alt="image" />

點擊 Update webhook。你會看到消息響應(yīng)中顯示了 Well, it workded!,很好!點擊 Let me select individual events.,然后選擇下面的選項:

  • Deployment
  • Deployment status
  • Pull Request

無論發(fā)生了什么事件 Github 都會將這些事件發(fā)送到我們的服務(wù)器上。我們配置服務(wù)器只在 Pull Request 正被 merged 的時候處理。

post '/event_handler' do      
     @payload = JSON.parse(params[:payload])      

     case request.env['HTTP_X_GITHUB_EVENT']       
     when "pull_request"         
       if @payload["action"] == "closed" && @payload["pull_request"]["merged"]             
       puts "A pull request was merged! A deployment should start now..."              
     end             
  end             
end       

接下來做什么?每個 Github 發(fā)出的事件會附上一個 HTTP Header X-Github-Event。我們現(xiàn)在只需要關(guān)心 PR 事件。當(dāng) pull request 被 merged(它的狀態(tài)是 closed,并且 merged 的值為 true),我們將開始部署。

要測試這個 proof-of-concept,在你測試的庫的分支上做些修改,發(fā)起一個 pull request 并且 merge。你的服務(wù)器會作出相應(yīng)的響應(yīng)。

工作部署

我們的服務(wù)已經(jīng)到位,代碼經(jīng)過審查,同時我們的 pull request 被 merged,我們希望來部署我們的工程。

我們開始修改事件監(jiān)聽以在 pull requests 被 merged 時進行處理,然后開始關(guān)注下部署:

when "pull_request"        
     if @payload["action"] == "closed" && @payload["pull_request"]["merged"]        
     start_deployment(@payload["pull_request"])          
     end         
when "deployment"         
     process_deployment(@payload)              
when "deployment_status"          
     update_deployment_status          
end            

基于 pull request 里的信息,我們開始實現(xiàn) start_deployment 方法:

def start_deployment(pull_request)
  user = pull_request['user']['login']
  payload = JSON.generate(:environment => 'production', :deploy_user => user)
  @client.create_deployment(pull_request['head']['repo']['full_name'], pull_request['head']['sha'], {:payload => payload, :description => "Deploying my sweet branch"})
end,

部署可以附加一些元數(shù)據(jù),用一個 payload 和一個 description 的形式。盡管這些值是可選的,但是有助于我們 log 和展示信息。

當(dāng)一個新的部署被創(chuàng)建,一個單獨的事件就會觸發(fā)。這就是為什么我們在 depolyment 事件處理中有一個新的 switch case。當(dāng)一個部署已經(jīng)被觸發(fā)的時候,你可以使用這些信息來通知。

部署可能會持續(xù)很長時間,所以我們需要去監(jiān)聽各種事件,比如什么時候部署被創(chuàng)建,和當(dāng)前的狀態(tài)。

讓我們模擬一次做了某些工作的部署,并注意它的輸出。首先,讓我們完成 process_deployment 方法:

def process_deployment             
     payload = JSON.parse(@payload['payload'])             
     # you can send this information to your chat room, monitor, pager, e.t.c.              
     puts "Processing '#{@payload['description']}' for #{payload['deploy_user']} to #{payload['environment']}"          
     sleep 2 # simulate work            
     @client.create_deployment_status("repos/#{@payload['repository']['full_name']}/deployments/#{@payload['id']}", 'pending')              
     sleep 2 # simulate work              
     @client.create_deployment_status("repos/#{@payload['repository']['full_name']}/deployments/#{@payload['id']}", 'success')            
end           

最后,我們會模擬存儲狀態(tài)信息,控制臺輸出:

```, def update_deployment_status
puts "Deployment status for #{@payload['id']} is #{@payload['state']}"
end



我們梳理一下發(fā)生的事件。一個新的用來負責(zé)觸發(fā) deoloyment 事件的 deployment 被 `start_delopment` 方法創(chuàng)建,從那里,我們調(diào)用 `process_eloyment` 方法去模擬接下來的工作。在處理過程中,我們同樣調(diào)起 `create_deployment_status` 讓接收方知道接下來會發(fā)生什么,正如我們設(shè)定狀態(tài)為 `pending`。     

在 deployment 結(jié)束后,我們將狀態(tài)設(shè)定為`success`,你會發(fā)現(xiàn),這種模式和你的 CI 狀態(tài)是相同的。                 

## 結(jié)論         

在 Github 中,我們多年來一直使用 [Heaven](https://github.com/atmos/heaven) 的一個版本去管理 deployment,本質(zhì)上基本步驟和我們上面已經(jīng)建立的服務(wù)端極其相似。在 GitHub, 我們:          

- 在 CI 狀態(tài)下等待回應(yīng)               
- 如果代碼是綠色,我們 merge pull request          
- Heaven 持有這些 merge 后的代碼,并且部署到我們的臨時服務(wù)器和項目中       
- 同時,Heaven 還通知大家關(guān)于構(gòu)建的消息,通過 Hubot 進入我們的聊天室                          

這就是它了,你不需要自己建立一個 deployment 來使用這個例子,你可以始終依賴于[第三方服務(wù)](https://github.com/integrations)。