简体   繁体   English

Azure DevOps 管道 - Maven 仅在不存在时部署发布

[英]Azure DevOps Pipeline - Maven deploy release only if it does not exist

I am new to both Azure DevOps and Maven.我是 Azure DevOps 和 Maven 的新手。

We have set up an Azure build pipeline such that it will deploy artifacts for snapshot builds and also for releases.我们已经建立了一个 Azure 构建管道,这样它将为快照构建和发布部署工件。

I want deployment of release artifacts to be idempotent.我希望发布工件的部署是幂等的。 That is if the artifact has already been deployed it should not be an error.也就是说,如果工件已经部署,它不应该是一个错误。

The problem is I get a 409 "resource conflict"问题是我收到409“资源冲突”

Q Is there a way to tell maven to deploy only if the artifact does not exist and that it is not an error if it does. Q 有没有办法告诉 maven 仅在工件不存在时才部署,并且如果存在则不是错误。

Is there anyway to do this from DevOps? DevOps 有没有办法做到这一点?

For my own education, I would also like to know how to do this for maven (without Azure).对于我自己的教育,我也想知道如何为 maven(没有 Azure)执行此操作。 This could be via either a command line switch, the pom.xml or the maven settings.xml这可以通过命令行开关 pom.xml 或 maven settings.xml

It seems to be implied that there is not, if so it is a surprising omission.似乎暗示没有,如果是这样,这是一个令人惊讶的遗漏。 I would like to understand the rationale.我想了解其中的原理。

Bonus points if there is a way to check that the artifact deployed is actually the same as the one just built by the pipeline.如果有一种方法可以检查所部署的工件实际上与管道刚刚构建的工件是否相同,则可以加分。

The relevant pipeline snippet is:相关的管道片段是:

   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'

For background this is what I know about Azure and Maven.作为背景,这就是我对 Azure 和 Maven 的了解。 If I have misunderstood anything it may be a contributing factor.如果我误解了任何事情,这可能是一个促成因素。

Maven allow you to deploy two kinds of artifact: Maven 允许您部署两种工件:

SNAPSHOTS快照

  • A snapshot is a development version of a package.快照是 package 的开发版本。
  • Snapshots have the suffix -SNAPSHOT.快照具有后缀 -SNAPSHOT。 Eg 1.2.0-SNAPSHOT例如 1.2.0-SNAPSHOT
  • SNAPSHOTS are mutable.快照是可变的。 A deploy operation can replace a SNAPSHOT with a new version (more recent development versions can replace development versions)部署操作可以用新版本替换 SNAPSHOT(更新的开发版本可以替换开发版本)

RELEASES发布

  • Any version not ending in the suffix -SNAPSHOT is considered a release version.任何不以后缀 -SNAPSHOT 结尾的版本都被视为发布版本。
  • Releases are immutable.发布是不可变的。 A deploy operation will fail if the release has already been deployed to the repository.如果版本已部署到存储库,则部署操作将失败。

Both Azure and Maven considered published artifacts as immutable. Azure 和 Maven 都认为已发布的工件是不可变的。 Azure understands -SNAPSHOT when acting as a maven repository and allow development versions to be overwritten. Azure 在充当 maven 存储库时理解 -SNAPSHOT 并允许覆盖开发版本。 The idea is that you cannot (or at least not easily) replace a published artifact that something else might depend upon.这个想法是您不能(或至少不容易)替换其他可能依赖的已发布工件。

409 = Resource Conflict 409 = 资源冲突

This can mean:这可能意味着:

  • The artifact has already been published and cannot be overwritten工件已发布,无法覆盖

  • The artifact could not be published because it was the wrong type.该工件无法发布,因为它是错误的类型。 For example publishing a release to a repository that only accepts snapshots or publishing a snapshot to a repository that only accepts releases例如,将发布发布到仅接受快照的存储库或将快照发布到仅接受发布的存储库

I am not sure how to tell maven that its okay for the deployment to fail if the artifact already exists.我不确定如何告诉 maven 如果工件已经存在,部署失败是可以的。 The obvious and wrong hack (in Linux) is:明显和错误的 hack(在 Linux 中)是:

mvn deploy || /bin/true

This is bad because it will report the deployment step as successful if it has failed for another reason.这很糟糕,因为如果由于其他原因而失败,它将报告部署步骤成功。

There is a maven plugin ( https://github.com/chonton/exists-maven-plugin ) for doing this.有一个 maven 插件( https://github.com/chonton/exists-maven-plugin )可以做到这一点。 I am not sure how you would use this in Azure.我不确定您将如何在 Azure 中使用它。 Is this plugin a defacto standard?这个插件是事实上的标准吗?

See also:也可以看看:


Update 23/06/2020 2020 年 6 月 23 日更新

I am nearly there with this but stuck:我快到了,但卡住了:

    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

I suspect the dependency:get command line may not be quite right.我怀疑 dependency:get 命令行可能不太正确。

Note: when testing the command I have to remember to delete the artifact from ~/.m2/repository as it look in the local one.注意:在测试命令时,我必须记住从 ~/.m2/repository 中删除工件,因为它在本地文件中看起来。

Another strange thing is occurring.另一件奇怪的事情正在发生。 Although I have deployed new test versions of the artifact they do not appear in the relevant Azure feed.尽管我已经部署了工件的新测试版本,但它们并未出现在相关的 Azure 提要中。 And yet the first attempted upload succeeds while subsequent uploads fail.然而,第一次尝试上传成功,而后续上传失败。 Where are these uploads going and why can't I see them in Dev Ops?这些上传到哪里去了,为什么我在 Dev Ops 中看不到它们?

The version for which I discovered this issue is still in the feed as a maven artifact 'com.mycompany.myproject:artifactId' with a version.我发现此问题的版本仍作为 maven 工件“com.mycompany.myproject:artifactId”在提要中,并带有一个版本。

See also What are the equivalent maven commands and settings to upload and download azure artifacts?另请参阅上传和下载 azure 工件的等效 maven 命令和设置是什么?

This should more related to Maven, there is nothing specific to configure in Azure DevOps side.这应该与 Maven 更相关,在 Azure DevOps 端没有具体配置。

You could try to use a command line task in your build pipeline to check first if that release version exists:您可以尝试在构建管道中使用命令行任务首先检查该发行版本是否存在:

mvn dependency:get -Dartifact=g:a:v -o -DrepoUrl=file://path/to/your/repo

More details take a look at this How to determine if a Maven artifact is in my repo from command line?更多详细信息请查看如何从命令行确定 Maven 工件是否在我的仓库中?

If that gave (group-artifact-version) does exists, then you don't proceed with the rest of the build.如果给定的 (group-artifact-version) 确实存在,那么您不要继续构建 rest。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM