簡體   English   中英

如何防止覆蓋 hudson 上的 Maven 存儲庫中已發布的工件(非快照版本)

[英]How to prevent overwriting of released artifacts (non snapshot versions) in maven repository on hudson

問題描述

考慮在 hudson 上使用 maven 的情況。

現在有人簽出一個項目,修改了一些文件,但不小心使用了相同的工件 ID 和版本號(非快照)。

然后他/她在 hudson 上構建這個項目並安裝了 maven。修改后的工件現在在 hudson .m2 中。 任何其他依賴於它的項目都將使用修改后的工件構建。 如果編譯沒有失敗,沒有人會發現這一點。 即使正確的工件駐留在中央存儲庫中,它也從未使用過,因為在 hudson 開始構建時從 .m2 中提取了修改過的工件。

所以我正在尋找一種方法來防止這種意外的人為錯誤。

  1. 無論如何要撤銷 hudson 上非快照版本(已發布的工件)上的 maven 安裝權限?
  2. 有什么方法可以比較 hudson 和遠程中央存儲庫中 .m2 的校驗和,以便校驗和失敗可以生成警告或構建失敗?

我已經檢查過沒有辦法從中央存儲庫強制更新非快照版本,因為它們是不可變的。

清除中央存儲庫或為 hudson 上的每個作業使用單獨的存儲庫將分別導致構建時間和磁盤空間使用量增加。

任何幫助,將不勝感激。

沒有直接的方法可以解決這個問題,但我們通過編寫一個每五分鍾運行一次的 cron-job 並在 Hundson 的本地存儲庫中將所有非快照的 jar 標記為只讀來解決這個問題。 這樣,當 Hudson 中的某個項目試圖覆蓋它時,我的 mvn install 或 mvn deploy 它無法覆蓋工件,因為它們是只讀的。

可以輕松編寫要釋放的任何新工件。 一旦在接下來的五分鍾內寫入,腳本會將它們標記為只讀。

這是unix腳本permission-handler.sh的代碼

#!/bin/bash
cd ~/.m2
date 2>&1>> permission-handler.out
find . -name '*jar' -type f | grep -v 'SNAPSHOT' | xargs chmod -vc 444 2>&1>> permission-handler.out
chmod 777 permission-handler.out

還處理日志以查看哪些所有工件已標記為僅發布。

我認為您不會找到一種方法來阻止安裝覆蓋工件。 存儲庫服務器應該有一個設置來防止部署更新的發布工件。 例如,請參閱 Nexus 的“如何禁用工件重新部署”

以下是我們在項目中管理版本的方式:

我們正在開發SNAPSHOT版本。 在 Jenkins 上,我們有一個快速構建作業來構建和測試此應用程序,但如果版本不是SNAPSHOT則失敗。 這是由自定義執行器完成的(這與require 發布版本執行器相反)。

當我們想要發布時,我們會使用 Jenkins 作業。 使用參數化的 buildMaven release plugin ,負責做發布的人只會指出發布的版本(穩定版本),下一個SNAPSHOT版本,以及 SCM 標簽的名稱。 因此,只有 Jenkins 會定義一個穩定版本,開發人員將始終使用SNAPSHOT代碼。

但是當然,這並不妨礙開發人員在他的本地機器上制作他想要的東西。 但我們總是考慮一個值得信賴的地方:Jenkins 服務器。 它在我的機器上工作從來都不是問題的好答案;o)

這是通過配置您的 Maven 存儲庫(例如 Nexus、Artifactory)不允許覆蓋發布存儲庫來解決的。 在 Nexus 中,我們有一個用於 SNAPSHOT 的倉庫和一個用於發布的倉庫。 SNAPSHOT 存儲庫允許覆蓋。 但是發布回購不允許覆蓋。 這只是 Nexus 中該存儲庫的一個簡單復選框功能。 一旦將發布版本放入存儲庫,就無法覆蓋它。 效果很好。

我有同樣的要求。 可以使用來自 gradle 任務的 REST 請求來檢查工件。

publish.dependsOn lookForArtifacts

task lookForArtifacts {
    group "upload"
    doLast {

        def pomFileName = "${ARTIFACT_ID}-${ARTIFACT_VERSION}.pom"
        def artifactPath = "${ARTIFACT_GROUP.replace(".", "/")}/${ARTIFACT_ID}/${ARTIFACT_VERSION}/${pomFileName}"
        def repositoryUrl = "$MAVEN_SERVER/${artifactPath}"

        println("# searching for existing artifact wit id ${ARTIFACT_VERSION}")
        println("")

        if (urlExists(repositoryUrl)) {
            println("# Existing artifact found")
            println("")
            throw new RuntimeException("Artifact with version $ARTIFACT_VERSION already exist - increase the verion to publish")
        } else {
            println("# No existing artifact found. Preceding to publish")
            println("")
        }
    }
}

def urlExists(String repositoryUrl) {

    try {
        def connection = (HttpURLConnection) new URL(repositoryUrl).openConnection()

        connection.setRequestProperty("Authorization", "Basic " + getBase64EncodedCredentials())
        connection.setConnectTimeout(10000)
        connection.setReadTimeout(10000)
        connection.setRequestMethod("HEAD")

        def responseCode = connection.getResponseCode()

        if (responseCode == 401) {
            throw new RuntimeException("Unauthorized MavenUser user. Please provide valid username and password.")
        }

        return (200 == responseCode)

    } catch (IOException ignored) {
        println(ignored)
        return false
    }
}

def getBase64EncodedCredentials() {
    def s = "$MAVEN_USERNAME" + ":" + "$MAVEN_PASSWORD"
    return s.bytes.encodeBase64().toString()
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM