azureartifactory

How can I download the MD5 files from JFrog Artifactory within an Azure Pipeline


I'm using Azure pipelines to connect to our JFrog Artifactory server to download some files. Artifactory stores the checkums (e.g. MD5) for each file explicitly.

I am able to download the MD5-file of a .txt-file, e.g. by using

curl -u user:token -O $artifactory_server/filename.txt.md5

So adding the extension "md5" will automatically download the corresponding MD5-file of that specific file. It works when using it inside a .sh-script. Interestingly it does not work when pasting the address directly into the browser: Here the file is downloaded with its original name "filename.txt" but the file contains the MD5-checksum. I don't know why the file does not have the extension ".md5".

Inside our Azure pipeline I'm using a generic JFrog task to download, using "fileSpec":

task: JFrogGenericArtifacts@1
displayName: 'Download MD5 from Artifactory'
inputs:
  command: 'Download'
  connection: 'JFrog Artifactory'
  specSource: 'taskConfiguration'
  fileSpec: |
    {
      "files": [
        {
          "pattern": "${{ variables.jFrogRepository }}/${{ variables.jFrogFolder }}/version.txt.md5",
          "target": "${{ variables.workspace }}/"
        }
      ]
    }
  failNoOp: true

However, this does not return the MD5-file but gives an error:

{
 11:36:21 [Error] No errors, but also no files affected (fail-no-op flag).
 "status": "failure",
 "totals": {
   "success": 0,
   "failure": 0
 }
}

What would be the correct way to use a JFrog Artifactory service connection / task inside an Azure pipeline to retrieve the checksum-files? Unfortunately I couldn't find any answer yet, specifically for using pipeline tasks.


Solution

  • [Error] No errors, but also no files affected (fail-no-op flag).

    The reason you're encountering this issue is because .md5 files in Artifactory are not actual files saved in the repository—they’re created on the fly when requested through a URL. The JFrogGenericArtifacts@1 task uses the JFrog CLI, which only downloads real, stored files. Since the .md5 file doesn’t actually exist, nothing gets downloaded, leading to the fail-no-op error.

    Since JFrog Artifactory serves .md5 via a simple HTTP request, use a script step in your pipeline instead of the JFrogGenericArtifacts@1 task.

    The credentials from the connection: 'JFrog Artifactory' can’t be used directly in script steps. So it's best to save your Artifactory username and token as secret variables in the pipeline and use them securely in the script.

    Sample bash script:

    - script: |
        curl -u $(artifactoryUser):$(artifactoryToken) -O "$(artifactoryUrl)/$(jFrogRepository)/$(jFrogFolder)/version.txt.md5"
      displayName: 'Download MD5 using curl'
      env:
        artifactoryUser: $(artifactoryUser)
        artifactoryToken: $(artifactoryToken)
        artifactoryUrl: https://your-artifactory.example.com/artifactory
    

    Make sure to define artifactoryUser and artifactoryToken as secrets in Azure DevOps. This ensures credentials are kept confidential and are not exposed in logs.

    For additional security, you can also use a .netrc file to avoid passing credentials directly in the curl command.

    - script: |
        echo "machine your-artifactory.example.com login $(artifactoryUser) password $(artifactoryToken)" > ~/.netrc
        curl -n -O "$(artifactoryUrl)/$(jFrogRepository)/$(jFrogFolder)/version.txt.md5"