Hur man låter Gradle kolla om man har de senaste versionerna av sina tredjepartsbibliotek

Inledning

Nu för tiden använder nog de flesta Javaprojekt någon sorts dependencyhanterare i sina byggen.

Den tid då man checkade in sina tredjepartsbibliotek i versionshanteringen är förbi. Nu låter man Maven (eller Ivy eller Gradle) läsa en incheckad förteckning, hämta hem jarfilerna ifrån de centrala förråd som finns därute och sätta upp class path.

En sak som dessa verktyg dock inte hjälper till med är att hålla koll på att man inte ligger kvar på gamla versioner. Att köra på gamla versioner kan ses som en sorts teknisk skuld, eftersom det blir värre och värre att uppgradera ju fler versioner man har missat.

Det är dock ett mödosamt och tråkigt manuellt arbete att kolla hur bra man ligger till.

Jag har därför utvecklat en Gradle-task som automatiserar detta!

(Se där, ännu en anledning att byta till Gradle!)

Jag har skrivit tasken i min build.gradle för Varmfront.nu, men med Gradle är det ju lätt att bryta ut kod för återanvändning. (Hur man gör detta kanske blir ämne för ett annat blogginlägg.)

Gradlekoden

Så utan vidare krussiduller, här kommer koden:

task findUpgradableDependencies {
    description "Find dependencies which have newer versions in Maven central."
    group "Help"

    doLast {
        def checked = [:]
        allprojects {
            configurations.each { configuration ->
                configuration.allDependencies.each { dependency ->
                    if (dependency instanceof ExternalDependency && !checked[dependency]) {
                        def url = """http://search.maven.org/solrsearch/select?q=g:"$dependency.group"+AND+a:"$dependency.name"&rows=1&wt=xml"""
                        try {
                            def response = new XmlSlurper().parseText(url.toURL().text)
                            def latest = response.result.doc.str.grep { it.@name == "latestVersion"}.join()
                            if (dependency.version != latest && latest && !latest.matches('20030203\\.000[0-9]{3}')) {
                                // commons-lang and commons-io have peculiar metadata in Maven Central
                                println "$dependency.group:$dependency.name:$dependency.version -> $latest"
                            }
                        } catch(FileNotFoundException e) {
                            logger.debug "Unable to download $url: " + e.message
                        } catch(org.xml.sax.SAXParseException e) {
                            logger.debug "Unable to parse $url: " + e.message
                        }
                        checked[dependency] = true
                    }
                }
            }
        }
    }
}

Exempel på en körning

Så här kan en körning se ut:

olle@olles-laptop2:~/workspace/git/varmfront$ gradle findUpgradableDependencies
:findUpgradableDependencies
org.springframework.data:spring-data-commons:1.5.1.RELEASE -> 1.5.2.RELEASE
org.springframework.data:spring-data-mongodb:1.2.1.RELEASE -> 1.2.3.RELEASE
org.projectlombok:lombok:0.11.8 -> 0.12.0
org.codehaus.groovy:groovy-all:2.1.5 -> 2.2.0-beta-1
de.flapdoodle.embed:de.flapdoodle.embed.mongo:1.33 -> 1.34
org.apache.tomcat.embed:tomcat-embed-core:7.0.41 -> 7.0.42
org.apache.tomcat.embed:tomcat-embed-logging-juli:7.0.41 -> 7.0.42
org.apache.tomcat.embed:tomcat-embed-jasper:7.0.41 -> 7.0.42

BUILD SUCCESSFUL

Total time: 14.648 secs
olle@olles-laptop2:~/workspace/git/varmfront$

Diskussion

Nu är det ju naturligtvis inte så att man ska uppgradera omedelbart så fort det kommer en ny version. Det kan finnas många legitima skäl till att ligga kvar på gamla versioner.

Men med detta verktyg får man ju lätt fatt på informationen om hur illa man ligger till och kan lättare ta med det i planeringen.

Begränsningar och möjliga förbättringar

Min kod hanterar bara Maven Central via dess REST-gränsnitt.

Man skulle också kunna tänka sig att lägga in en undantagslista, så att man i byggscriptet kan dokumentera beslut om att ligga kvar på vissa gamla versioner.

4 responses on “Hur man låter Gradle kolla om man har de senaste versionerna av sina tredjepartsbibliotek

  1. Med Maven måste man använda en plugin för att komma åt interna API:er (som t.ex. dependency-maskineriet). Saknas lämpligt plugin är det en väldigt hög tröskel att klättra över.

    Med Gradle kan man använda någon existerande plugin eller helt enkelt hacka till funktionaliteten själv (som jag visade i mitt exempel ovan). Gradle är ju implementerat i Groovy, och du har således direkt tillgång till alla interna API:er.

    Detta är i mina ögon en enorm fördel!

    PS. Jag har en gång skrivit en Maven-mojo som tog reda på vilket Perforce changeliste-nummer som man hade synkat sin workspace till. En ansenlig mängd accidental complexity, eftersom det gick ut på att slå kommandot p4 changes -m1 ...#have och parsa ut ett heltal i första raden i svaret.

    Med Gradle blev samma sak en Groovy-funktion på c:a 5 rader, direkt i build.gradle. Funktionen är så trivial att det inte är värt att paketera den. Jag copy-pastear när jag behöver den igen i ett annat projekt. DS.

    PPS, Ibland tar det längre tid att leta upp en lämplig plugin som fungerar, än att hacka till funktionen själv. DS.

Leave a Reply to Per Lundholm Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.