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 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) } } }