【发布时间】:2020-09-29 06:37:21
【问题描述】:
我是 Azure DevOps 和 Maven 的新手。
我们已经设置了一个 Azure 构建管道,以便它将为快照构建和发布部署工件。
我希望发布工件的部署是幂等的。 也就是说,如果工件已经部署,它不应该是一个错误。
问题是我收到了409 "resource conflict"
Q 有没有办法告诉 maven 仅在工件不存在时才部署 并且如果是这样也不是错误。
DevOps 有没有办法做到这一点?
为了我自己的教育,我也想知道如何为 maven(没有 Azure)做到这一点。这可以通过命令行开关、pom.xml 或 maven settings.xml
似乎暗示没有,如果是这样,这是一个令人惊讶的遗漏。我想了解其中的原理。
如果有办法检查部署的工件是否与管道刚刚构建的工件实际上相同,则可获得奖励积分。
相关管道sn-p为:
task: Maven@3
# condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
inputs:
mavenPomFile: 'pom.xml'
options: '-B -s $(mvnSettings.secureFilePath) -DWHERE="AzureDevops" clean deploy'
mavenAuthenticateFeed: true
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
作为背景,这是我对 Azure 和 Maven 的了解。如果我误解了任何东西,这可能是一个促成因素。
Maven 允许您部署两种工件:
快照
- 快照是软件包的开发版本。
- 快照具有后缀 -SNAPSHOT。例如。 1.2.0-快照
- SNAPSHOTS 是可变的。部署操作可以用新版本替换 SNAPSHOT(更新的开发版本可以替换开发版本)
发布
- 任何不以后缀 -SNAPSHOT 结尾的版本都被视为发布版本。
- 版本是不可变的。如果版本已部署到存储库,则部署操作将失败。
Azure 和 Maven 都认为已发布的工件是不可变的。 Azure 在充当 maven 存储库时理解 -SNAPSHOT 并允许覆盖开发版本。 这个想法是您不能(或至少不容易)替换其他可能依赖的已发布工件。
409 = 资源冲突
这可能意味着:
-
工件已发布,无法覆盖
-
由于类型错误,无法发布工件。 例如,将发布发布到仅接受快照的存储库或将快照发布到仅接受发布的存储库
如果工件已经存在,我不确定如何告诉 maven 部署失败是可以的。明显和错误的 hack(在 Linux 中)是:
mvn deploy || /bin/true
这很糟糕,因为如果由于其他原因而失败,它将报告部署步骤成功。
有一个 maven 插件 (https://github.com/chonton/exists-maven-plugin) 可以做到这一点。我不确定您将如何在 Azure 中使用它。 这个插件是事实上的标准吗?
另见:
- How to update a maven dependency with a same version number in Azure Artifacts
- Failed to deploy artifacts using maven, error code 409
2020 年 6 月 23 日更新
我快到了,但卡住了:
variables:
- name: artifactDoesNotExist
value: '0'
- name: mavenRepoURL
value: 'https://blahblah.visualstudio.com/_packaging/myazurefeedname/maven/v1/com/mycompany/myproject'
- task: Bash@3
displayName: 'Check if Maven artifact exists'
inputs:
targetType: inline
failOnStderr: false
script: |
#set variable iff artifact exists
VERSION=`cat VERSION.MVN`; mvn -X -B -s $(mvnSettings.secureFilePath) -DWHERE="AzureDevops" -DremoteRepositories=$(mavenRepoUrl) dependency:get -Dartifact=com.mycompany.project:artifiactId:"$VERSION"
echo "##vso[task.setvariable variable=artifactDoesNotExist]$?"
- task: Bash@3
condition: and(succeeded(), eq(variables['artifactDoesNotExist'], '0'))
inputs:
targetType: inline
script: |
echo artifactDoesNotExist == 0 -> true
- task: Bash@3
condition: and(succeeded(), eq(variables['artifactDoesNotExist'], '1'))
inputs:
targetType: inline
script: |
echo artifactDoesNotExist == 1 -> true
我怀疑dependency:get 命令行可能不太正确。
注意:在测试命令时,我必须记住从 ~/.m2/repository 中删除工件,因为它在本地文件中的样子。
另一件奇怪的事情正在发生。尽管我已经部署了新的工件测试版本,但它们并没有出现在相关的 Azure 提要中。然而,第一次尝试上传成功,而后续上传失败。 这些上传到哪里去了,为什么我在 Dev Ops 中看不到它们?
我发现此问题的版本仍作为 maven 工件“com.mycompany.myproject:artifactId”在提要中,并带有一个版本。
另见What are the equivalent maven commands and settings to upload and download azure artifacts?
【问题讨论】:
-
我还不明白:你为什么要再次尝试部署发布版本?我的意思是,如果您已经构建并部署了
4.0.9,为什么还要再次构建和部署4.0.9?为什么 Maven 如何处理这种情况很重要,为什么不干脆不做呢? -
当管道运行时,它会部署一个新版本。如果该版本不存在,则管道将失败。如果版本已经存在(理想情况下如果校验和匹配),那实际上应该是一个空操作。
-
但是当你构建一个发布版本时,你之后会增加版本号。管道如何构建与以前相同的版本?
-
管道可以由几个事情触发。例如,如果合并到主分支或手动运行。在一种情况下,它们是故意相同的,而在另一种情况下,它们可能不是。也许有人合并了文档更改。
-
我建议发布过程本身增加版本号(如在 Maven 发布插件中),或者如果它尝试构建的版本已经存在,则立即使管道失败。我没有看到将管道运行到最后然后发现您尝试构建的版本已经存在的好处。
标签: maven azure-devops