How can I find corrupted artifacts using AQL and delete them?

You may have corrupted artifacts (e.g. an artifact with a wrong content as a result of a DNS error) that got cached into Artifactory.

By default, Artifactory keeps your repositories healthy by refusing POMs with incorrect coordinates (path).

If the groupId:artifactId:version information inside the POM does not match the deployed path, Artifactory rejects the deployment with a “409 Conflict” error.

You can disable this behavior by setting the Suppress POM Consistency checkbox.

Below is a sample Artifactory Query Language (AQL) query to help identify files that are possibly corrupted.

  

items.find(
{"$or":[
{
"$and":[
{"type":"file"},
{"size":{"$lte":"1364"}},
{"repo":"remote-cache"},
{"name":{"$ne":"maven-metadata.xml"}},
{"name":{"$nmatch":"*.pom"}},
{"name":{"$nmatch":"*.asc"}}
]
},
{
"$and":[
{"type":"file"},
{"size":"0"},
{"repo":"remote-cache"}
]
},
{
"$and":[
{"type":"file"},
{"archive.entry.name":{"$eq":null}},
{"name":{"$match":"*.jar"}},
{"repo":"remote-cache"}
]
}
]
}
)
.sort({"$desc":["name"]})

  

The AQL example above will search for any files that are in remote-cache (cache of “remote” repository) that meet ANY of the following condition

  1. files with a file size that are less than or equal to 1364 bytes, except maven-metadata.xml, *.pom, *.asc
  2. files that has 0 file size
  3. *.jar (archive) files contain null

You may save the JSON file above as a file (e.g. cleanaql) then use it for the command below.

 

curl -L  -X POST -H"Content-type:text/plain" -uadmin:password --data-binary @cleanaql  https://my-artifactory/artifactory/api/search/aql >aql-result.json

 

After examining the output (aql-result.json), you may use below groovy script to delete the artifacts found by the AQL above.

    

import groovy.json.JsonSlurper
import org.jfrog.artifactory.client.Artifactory
import org.jfrog.artifactory.client.ArtifactoryClient

/**
* Created by eli@jfrog on 03/03/2016.
*/
class DeleteFiles {
final static String ARTIFACTORY_URL = 'https://my_artifactory/artifactory'
static String adminUser = '*'
static String adminPassword = '*'
static Artifactory artifactoryClient = ArtifactoryClient.create(ARTIFACTORY_URL, adminUser, adminPassword)
public static void main(String[] args) {
def json = new JsonSlurper().parse(new File('/PATH-TO-FILE/aql-result.json'))
json.results.each{it->
String path = "${it.path}/${it.name}"
println "deleteing path $path"
artifactoryClient.repositories().repository("remote-cache").delete(path)
}
}
}