繁体   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