Meer met Maven – Reproducible builds

In elke editie zal Robert Scholte een probleem voorleggen en deze oplossen met behulp van Apache Maven om meer inzicht te geven in Maven zelf en de vele beschikbare plugins.

“Reproducible builds are a set of software development practices that create an independently-verifiable path from source to binary code.” Met deze zin opent de website reproducible-builds.org en klinkt als een goede best practice, ook voor Maven-projecten.

Er is een nuanceverschil tussen rebuildable en reproducible. Het overgrote deel van de projecten, dat ooit met Maven gebouwd is, kan nu nog steeds gebouwd worden. Echter bij reproducible builds moet het resultaat bit voor bit hetzelfde zijn, zodat er steeds dezelfde hash uit kan komen. Om dit voor elkaar te krijgen is er een aantal hindernissen die overwonnen moet worden.

Het meest voor de hand liggende probleem is dat we nergens meer een tijdstip genereren voor wanneer een bestand is aangemaakt. Dat betekent dus, dat we geen gebruik meer kunnen maken van de java.util.Properties.store-methodes, omdat deze altijd een regel met de huidige datum+tijd toevoegt. Daarnaast is de volgorde van de properties onvoorspelbaar, dus nog een reden om een eigen PropertiesWriter te schrijven.

Bijna alle problemen hebben te maken met volgorde en tijdstippen, zo ook voor alle entries in een artifact (jar, war, etc). In de meeste gevallen zijn de entries van oorsprong een File, maar wie de documentatie van java.io.File.list() leest, moet het volgende opvallen: “There is no guarantee that the name strings in the resulting array will appear in any specific order; they are not, in particular, guaranteed to appear in alphabetical order.” Vandaar dat we zelf een algoritme geschreven hebben voor een voorspelbare volgorde van de entries.

Voor de tijdstippen is een aparte property in het leven geroepen: project.build.outputTimestamp. Deze bevat een constante waarde, die gebruikt wordt als tijdstip voor elke entry. Deze zal door de maven-release-plugin automatisch bijgewerkt worden.

Een ander probleem is de username, die in sommige bestanden terug komt. Voorheen werd de username als creator toegevoegd aan de MANIFEST. MF, maar omwille van reproducibility is deze verwijderd. Daarmee zijn de belangrijkste source-gerelateerde problemen opgelost. Dan zijn er nog drie belangrijke factoren: het besturingssysteem, de Java-versie en de Maven-versie. Het besturingssysteem blijkt bijna geen effect te hebben op de gegenereerde bestanden. Het belangrijkste verschil zit in de line endings, maar dit blijkt eenvoudig op te lossen door een system property mee te geven via de commandline, bijvoorbeeld met -Dline.separator=’\n’

De Java versie heeft veel impact, omdat de compiler soms efficiëntere classes genereert met een nieuwere JDK versie. Het is dus van belang om te weten wat de oorspronkelijke versie was om de reproducible artifact te valideren. Voor Maven geldt, dat met name de plugins reproducilibity moeten ondersteunen. De versie van Maven 3 heeft zelden invloed erop.

Daarmee is het ondertussen mogelijk om ook met Maven reproducible builds te maken.

 

Klik hier voor meer informatie