2016-02-26 22 views
3

我正在測試Jenkins的使用Github pull request builder plugin我已經成功地在Github上設置了一個玩具項目,並且開發了Jenkins的安裝程序,以便提高PR或將更改推送到PR分支會觸發構建。大多數情況下,這是按照要求工作的 - 有些東西與首選工作流程不匹配,但是自由編寫和維護我們自己的插件是一件大事。如何跨多個合併請求並行運行持續集成?

我有一個潛在的showstopper。該插件將所有推送到所有PR中的所有推送排隊,並且似乎一次只運行一項作業,即使有可用的備用執行程序。在現實世界的項目中,我們可能會有10個活躍的PR,每個可能會在一天內得到一些推動的更新以迴應QC評論,並且完整的CI運行需要> 30分鐘。但是,我們確實有足夠的構建執行程序供應,可以同時運行多個作業。

我看不到任何方式來配置PR請求生成器來同時在同一個觸發器上處理多個作業,但我可能會在Jenkins的其他地方丟失一些基本的東西。有沒有辦法做到這一點,而無需自定義插件?

我已經安裝了Jenkins ver。 1.649在一個新的Ubuntu 14.04服務器上(在一個VirtualBox客戶端上),並遵循ghprb plugin(當前版本爲1.30.5)的README,包括在Github上設置一個jenkins「bot」賬戶作爲協作者,以運行所有集成API調用Github上。

我想知道如果我克隆作業(創建新項目和「複製現有項目」)會有什麼樣的行爲,並且可能會嘗試下一步,但我預計這會導致作業同時運行多個作業沒有任何好處,而不是與其他工作輪詢同一個PR池的智能交互。

回答

4

我已經找到配置設置,同時探索更多的問題。

當你知道它是哪個配置項時,真的很容易,但Jenkins有很多配置可以解決,尤其是當你在探索插件時。

關鍵是,並行服務排隊作業的選項(可用的執行程序允許)是核心Jenkins配置,而不是Github PR構建器的一部分。

所以,只需檢查選項如有必要,執行併發構建。這個選項應該在配置的第一個未命名部分的底部找到。這是一個非常基本的詹金斯選擇,像我這樣的新手因爲其他選擇的高峯而錯過了。

+1

謝謝!我也忽略了這個複選框! _「jenkins並行作業」_的90%命中_告訴我使用Build Flow插件或其他插件。你可能是世界上唯一一個發現這個複選框的人。 –

+0

我不知道它是如何工作的,因爲每個工作只有一個工作空間。如果檢查出沒有涉及git倉庫,這些工作可以並行運行。不過,在這種情況下,git倉庫被檢出到工作區中。 如果有多個PR和2個作業並行運行,最後檢出的PR是有效代碼,但測試將對最後一個PR並行運行。 – puneeth

+0

@ user2283864:當作業同時運行時,Jenkins會自動創建多個工作區(附加例如'@ 2'這個名稱)。 –

1

可能回答這個問題爲時已晚,但經過幾天的研究,我找到了一種方法在github中爲每個PR創建多個作業。 我在這裏展示的代碼適用於github企業版,但它對於一般github(bitbucket)以及url和git命令中的一些調整已經足夠好了。

針對其永久居民的創建需要有一個文件的主線庫,我把它叫做PRJob.groovy幷包含

import groovy.json.JsonSlurper 


gitUrl = GIT_URL 

repoRestUrl = "${GITHUB_WEB_URL}/repos/${project}/${repo}" 

def getJSON(url) { 
    def conn = (HttpURLConnection) new URL(url).openConnection() 
    conn.setRequestProperty("Authorization", "token ${OAUTH_TOKEN}"); 
    return new JsonSlurper().parse(new InputStreamReader(conn.getInputStream())) 
} 


def createPipeline(name, description, branch, prId) { 

    return pipelineJob(name) { 
     delegate.description description 
     if (ENABLE_TRIGGERS == 'true') { 
     triggers { 
      cron 'H H/8 * * *' 
      scm 'H/5 * * * *' 
     } 
     } 
     quietPeriod(60) 
     environmentVariables { 
     env 'BRANCH_NAME', branch 
     env 'PULL_REQUEST', prId 
     env 'GITHUB_WEB_URL', GITHUB_WEB_URL 
     env 'OAUTH_TOKEN', OAUTH_TOKEN 
     env 'PROJECT', project 
     env 'REPO', repo 
     } 
     definition { 
     cpsScm { 
      scriptPath "Jenkinsfile" 
      scm { 
      git { 
       remote { 
       credentials "jenkins-ssh-key" 
       delegate.url gitUrl 
       if (prId != "") { 
        refspec "+refs/pull/${prId}/*:refs/remotes/origin/pr/${prId}/*" 
       } 
       } 
       delegate.branch branch 
      } 
      } 
     } 
     } 
    } 
} 




def createPRJobs() { 

    def prs = getJSON("${repoRestUrl}/pulls?state=open") 

    if (prs.size() == 0) { 

    def mergedPrs = getJSON("${repoRestUrl}/pulls?state=closed") 
    if (mergedPrs.size() == 0) { 
     throw new RuntimeException("No pull-requests found; auth token has likely expired") 
    } 
    } 

    prs.each { pr -> 
    def id = pr.get("number") 
    def title = pr.get("title") 
    def fromRef = pr.get("head") 
    def fromBranchName = fromRef.get("ref") 
    def prRepo = fromRef.get("repo") 
    def repoName = prRepo.get("name") 
    def prHref = pr.get("url") 

    createPipeline("${repo}-PR-${id}-${fromBranchName}", 
     "${prHref} Pull Request ${id}: ${title}", "origin/pr/${id}/head", id) 
    } 

} 

createPRJobs() 

這就造成每個PR 1個詹金斯工作。 這依賴於項目有Jenkinsfile可以拿起來運行peipeline工作。示例Jenkinsfile將如下所示:

//Jenkinsfile for building and creating jobs 
commitId = null 
repoRestUrl = "${GITHUB_WEB_URL}/repos/${PROJECT}/${REPO}" 

try{ 
    stage('Install and Tests') { 
     runTest("Hello") 
    } 
    notify_github 'success' 
}catch (Exception e) { 
    notify_github 'failure' 
    print e 
    throw e 
} 

def runTest(String someDummyVariable) { 
    node { 
    checkout scm 
    sh 'git clean -qdf' 
    if (env.PULL_REQUEST == ""){ 
     sh 'git rev-parse --verify HEAD > commit.txt' 
    } else { 
     // We check out PR after it is merged with master, but we need to report the result against the commit before merge 
     sh "git rev-parse refs/remotes/origin/pr/${env.PULL_REQUEST}/head^{commit} > commit.txt" 

    } 
    commitId = readFile 'commit.txt' 
    echo commitId 
    sh 'rm -f commit.txt' 

    //Here goes your code for doing anything 
    sh 'echo "Hello World!!!!!"' 


    } 
} 


def http_post(url, rawJson) { 
    def conn = (HttpURLConnection) new URL(url).openConnection() 
    conn.setRequestProperty("Authorization", "token ${OAUTH_TOKEN}"); 
    conn.doOutput = true 
    conn.requestMethod = "POST" 
    conn.setRequestProperty("Content-Type", "application/json") 
    def wr = new OutputStreamWriter(conn.getOutputStream()); 
    wr.write(rawJson); 
    wr.close() 

    def code = conn.getResponseCode() 
    if (code < 200 || code >= 300){ 
    println 'Failed to post to ' + url 
    def es = conn.getErrorStream(); 
    if (es != null) { 
     println es.getText() 
    } 
    } 
} 


def notify_github(state) { 

    http_post(
    "${repoRestUrl}/statuses/${commitId}", 
    """ 
     { "state": "${state}", 
     "target_url": "${env.BUILD_URL}", 
     "description": "Build Pipeline", 
     "context": "Build Pipeline" 
     } 
    """ 
) 
} 

希望這可以幫助某人。

相關問題