Skip to content

Instantly share code, notes, and snippets.

@legege
Created March 23, 2018 16:41
Show Gist options
  • Save legege/1f8e7b82675fc15beae4a6d9a8640d03 to your computer and use it in GitHub Desktop.
Save legege/1f8e7b82675fc15beae4a6d9a8640d03 to your computer and use it in GitHub Desktop.
Intelligently clean a Sonatype Nexus3 repository... keep the last X released versions of each "major.minor" artifact
import org.sonatype.nexus.repository.storage.Component
import org.sonatype.nexus.repository.storage.StorageFacet;
def retentionCount = 15
def repositoryName = 'releases'
def dryRun = true
log.info("Cleanup script started! Dry Run Mode: $dryRun");
def repo = repository.repositoryManager.get(repositoryName);
def tx = repo.facet(StorageFacet.class).txSupplier().get();
try {
tx.begin();
def components = tx.browseComponents(tx.findBucket(repo));
// Create an hashmap of components (key: groupId:artifactId, value: (key: major.minor, value: list of components))
def componentsByName = new TreeMap<String, Map<String, Component>>()
components.each { Component comp ->
def key = "${comp.group()}:${comp.name()}"
if (!componentsByName.containsKey(key)) {
componentsByName.put(key, new TreeMap<String, Component>())
}
def vComp = comp.version().split("\\.", 3)
def vMap = componentsByName.get(key)
try {
def vKey = "${vComp[0]}.${vComp[1]}"
if (vMap.containsKey(vKey)) {
vMap.get(vKey).add(comp)
} else {
def componentsForVersion = new LinkedList<Component>()
componentsForVersion.add(comp)
vMap.put(vKey, componentsForVersion)
}
} catch (Exception e){
log.info("Skipped ${comp.group()}:${comp.name()}:${comp.version()}")
}
}
componentsByName.each { componentName, Map<String, Component> vMap ->
vMap.each { version, List<Component> componentsForVersion ->
componentsForVersion.sort(true) { a, b ->
List verA = a.version().tokenize('.')
List verB = b.version().tokenize('.')
def commonIndices = Math.min(verA.size(), verB.size())
for (int i = 0; i < commonIndices; ++i) {
if (verA[i].isInteger() && verB[i].isInteger()) {
def numA = verA[i].toInteger()
def numB = verB[i].toInteger()
if (numA != numB) {
return numA <=> numB
}
} else {
return verA[i] <=> verB[i]
}
}
verA.size() <=> verB.size()
}
if (componentsForVersion.size() > retentionCount) {
log.info("There are ${componentsForVersion.size()} versions for ${componentName}... Repo contains ${componentsForVersion.collect { it.version() }.join(',')}")
def componentsToDelete = componentsForVersion.dropRight(retentionCount)
componentsToDelete.each { Component componentToDelete ->
log.info("... Deleting ${componentName}:${componentToDelete.version()}")
tx.deleteComponent(componentToDelete, true)
}
}
}
}
if (!dryRun) {
log.info("Committing transaction...")
tx.commit()
}
} catch (Exception e) {
log.info("Error: " + e)
} finally {
if (tx != null) tx.close()
}
@jackyjaijai
Copy link

componentsForVersion.size() always equal to 1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment