Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am new to both Azure DevOps and Maven.

We have set up an Azure build pipeline such that it will deploy artifacts for snapshot builds and also for releases.

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"

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.

Is there anyway to do this from DevOps?

For my own education, I would also like to know how to do this for maven (without Azure). This could be via either a command line switch, the pom.xml or the 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. If I have misunderstood anything it may be a contributing factor.

Maven allow you to deploy two kinds of artifact:

SNAPSHOTS

  • A snapshot is a development version of a package.
  • Snapshots have the suffix -SNAPSHOT. E.g. 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)

RELEASES

  • Any version not ending in the suffix -SNAPSHOT is considered a release version.
  • 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 understands -SNAPSHOT when acting as a maven repository and allow development versions to be overwritten. The idea is that you cannot (or at least not easily) replace a published artifact that something else might depend upon.

409 = Resource Conflict

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. The obvious and wrong hack (in Linux) is:

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. I am not sure how you would use this in Azure. Is this plugin a defacto standard?

See also:

  • How to update a maven dependency with a same version number in Azure Artifacts
  • Failed to deploy artifacts using maven, error code 409

Update 23/06/2020

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.

Note: when testing the command I have to remember to delete the artifact from ~/.m2/repository as it look in the local one.

Another strange thing is occurring. Although I have deployed new test versions of the artifact they do not appear in the relevant Azure feed. 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?

The version for which I discovered this issue is still in the feed as a maven artifact 'com.mycompany.myproject:artifactId' with a version.

See also What are the equivalent maven commands and settings to upload and download azure artifacts?

like image 301
Bruce Adams Avatar asked Jun 09 '20 23:06

Bruce Adams


People also ask

How do I deploy a previous release in Azure DevOps?

Open Project>Pipeline>Release>Select you CD pipeline and select last successful build and you can file redeploy option their.

Can a release pipeline publish artifact?

Publishing pipeline artifacts is not supported in release pipelines. The publish keyword is a shortcut for the Publish Pipeline Artifact task . targetPath: the path to the folder or file you want to publish. artifactName: the name of the artifact that you want to create.

Are Azure DevOps release pipelines deprecated?

Draft releases are deprecated in Azure Pipelines because you can change variables while you're creating the release. Creating a draft release allows you to edit some settings for the release and tasks, depending on your role permissions before you start the deployment.

Does Azure DevOps pipeline use Maven?

Azure DevOps Pipeline - Maven deploy release only if it does not exist - Stack Overflow I am new to both Azure DevOps and Maven. We have set up an Azure build pipeline such that it will deploy artifacts for snapshot builds and also for releases.

Should deployment of release artifacts be idempotent in azure build pipeline?

I am new to both Azure DevOps and Maven. We have set up an Azure build pipeline such that it will deploy artifacts for snapshot builds and also for releases. I want deployment of release artifacts to be idempotent. That is if the artifact has already been deployed it should not be an error.

Can Maven release plugin use in Jenkins pipeline 0?

Maven Release Plugin use in Jenkins Pipeline 0 Azure DevOps: Error importing Maven artifact from Azure Artifacts into Release 0 How to check availability of Published Pipeline Artifacts in azure pipeline release 0 Azure Release Pipeline - Release to Universal Artifact

Why does a deploy operation fail in azure?

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 understands -SNAPSHOT when acting as a maven repository and allow development versions to be overwritten.


1 Answers

This should more related to Maven , there is nothing specific to configure in Azure DevOps side.

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?

If that gave (group-artifact-version) does exists, then you don't proceed with the rest of the build.

like image 150
PatrickLu-MSFT Avatar answered Oct 14 '22 14:10

PatrickLu-MSFT