Tag Archives: maven

Bintray – Deployment via Maven


Flattr this

Motivation

Da beim Deployment auf bintray doch immer ein bisl Handarbeit notwendig ist und ich mich jedesmal ein wenig um das Deployment drücken möchte weil ich denke es wird Stunden dauern hier nun einfach eine Gedankenstütze was alles zu tun ist.

Den Quellkode finalisieren

Zunächst muss mal das Projekt rund geschliffen werden. Also der maven Build funktioniert, das CI System meldet grün und das Codecoverage System liegt auch bei über 90%.

Die groupId des Projektes sollte so gewählt werden, das auch alle zukünftigen Projekte diese nutzen können, denn ein Nutzer kann unter bintray nur mit einer groupId arbeiten. (Das sollte unbedingt beachtet werden, da es auf bintray manuelle Schritte gitbt, welche erst nach Antrag vom Support durchgeführt werden (Wenn es also das erste Projekt ist, dann take it easy, es wird morgen nicht live sein aber stelle sicher,  dass Du es zukünftig leichter hast).

In der pom.xml werden die Deployment Repositories von jfrog eingetragen. Bitte auch in der settings.xml die verschlüsselten Zugangsinfos hinterlegen. (Die settings.xml im Homeverzeichnis sollte geschützt sein). Hier ein Beispiel für die pom.xml Einträge:

<distributionManagement>
<snapshotRepository>
<id>bintray-funthomas424242-snapshots</id>
<name>oss-jfrog-artifactory-snapshots</name>
<url>https://oss.jfrog.org/artifactory/oss-snapshot-local</url&gt;
</snapshotRepository>
<repository>
<id>bintray-funthomas424242-releases</id>
<name>oss-jfrog-artifactory-releases</name>
<url>https://oss.jfrog.org/artifactory/oss-release-local</url&gt;
</repository>
</distributionManagement>

Dann sind die Projektinformationen fertig zu stellen. Die README muss vorhanden sein und ist auf den aktuellen Stand zu bringen. Bei der Gelegenheit bauen wir gleich ein Template für den späteren Download Button (im Markdown Format) ein:

[ ![Download](https://api.bintray.com/packages/bintray-nutzer-name/bintray-repo-name/bintray-package-name/images/download.svg) ](https://bintray.com/bintray-nutzer-name/bintray-repo-name/bintray-package-name/_latestVersion)

(Die fett geschriebenen Bezeichner kennzeichnen die variablen Teile welche konkret von Nutzer und Projekt abhängen)

Die Changelog muss vorhanden sein und ist so zu aktualisieren, dass das das gleich zu bauende Release darin beschrieben ist. 

Ein File LICENSE befindet sich auch im Projektverzeichnis und enthält den aktuellen Lizenztext unter dem das Projekt entwickelt wird.

Bintray vorbereiten

Jetzt loggen wir uns auf bintray ein und navigieren in das Zielrepository. Falls wir noch keines angelegt haben jetzt wäre der ideale Zeitpunkt dafür 🙂 . Wenn der Quellkode auf github gehostet ist, können wir jetzt das Projekt importieren und dabei ein Package vom Wizard anlegen lassen. 

Ein Release bauen und hochladen

Jetzt wäre der richtige Zeitpunkt mvn -B -Dtag=0.0.0-RELEASE release:prepare lokal auszuführen. Falls alles klappt gleich mvn release:perform hinterher. Mit git checkout tags/0.0.0-RELEASE -b release-0.0.0 den Release Tag als neuen Branch auschecken. Anschließend alles schön pushen und schauen ob es im scm sichtbar ist, z.B. mit git push xxxx.  

Da wir uns auf dem Release Tag Stand befinden, sollte jetzt in der pom.xml auch eine Release Version (also ohne -SNAPSHOT) stehen. Auf diesem Stand versuchen wir  ein Deployment mit mvn deploy, welches unter jfrog im oss-release-local Repository landen sollte. 

(Möglicherweise benötigt man hierzu gesonderte Berechtigungen und muss erst die Aufnahme des auf Bintray angelegten Packages ins JCenter beantragen – wobei man hier den Haken für staging von snapshots setzen muss.)

Das Release veröffentlichen

Auf jfrog schauen wir unter oss-release-local und stellen sicher, dass unsere Dateien angekommen sind. Sollten sie unter oss-snapshots-local gelandet sein, dann korrigieren bis es geht. Snapshots können nicht auf bintray veröffentlicht werden!

Auf jforg im Release setzen wir auf dem Versionsorner unseres Releases nun folgende Properties:

Property

Description
bintray.package
A target package name under the repository.

Please note that you must first create the package in Bintray if it does not exist.

bintray.path

A target path in the repository under which to save the file.

The path is considered optional as Artifactory will use the same path the file is stored in the repository.

bintray.repo
A target repository in Bintray, in the format of {username}/{repository}
bintray.version
A target version under the package.If the version does not yet exist in Bintray, it is created automatically.

 

Fazit

Es ist ganz schön viel Handarbeit und für die Zukunft wäre  es schön für den ganzen Overhead ein maven Plugin zu besitzen – aktuell ist mir aber keines bekannt. 

 

Advertisements

Maven Download from SF.net


Flattr this

Motivation

Die OpenSource Entwickler welche ein Maven Plugin Projekt auf Sourceforge.net hosten und es ihren Nutzern maven like zum Download anbieten möchten, haben damit seit der Geburt von maven ein Problem. Sie müssen ihre Artifakte im File Release System (FRS) des Sourceforge Portals hosten. Ein Hosting im Bereich der Projekt Homepage auf Sourceforge ist nicht gestattet.

Hintergrund dieser Regelungen scheint die Lastverteilung beim Download zu sein. Das FRS von Sourceforge ist optimiert auf eine schnelle Verbreitung der Artifakte über diverse in der Welt verteilte Proxies. Bei der Web Area in welcher die Hompages der Projekte gehostet werden, scheinen andere Mechanismen im Einsatz zu sein als im FRS.

Aber auch der automatische Upload der Artifakte per Maven ist nicht trivial, da Sourceforge bestimmte Sicherheitsrichtlinien aufgesetzt hat, welche den Projekten eine entsprechende Sicherheit garantieren sollen.

Lösung für den Download

Nachdem ich eine Weile nach Lösungen gesucht hatte fand ich von Brian Matthews das Projekt wagon-sf auf sourceforge. Allerdings hatte Brian seinen Schwerpunkt wohl auf andere Projekte verlagert, denn es waren keine Artifakte zum Download verfügbar. Durch das Projekt auf die richtige Spur gebracht schrieb ich mir daraufhin einen eigenen Maven Wagon. Dieser ist als Unterprojekt wagon-http-sourceforge unter meiner Maven Plugin Sammlung zu finden.

Lösung für den Upload

Hierbei konnte ich auf Maven Boardmittel zurück greifen. Es ist lediglich die pom.xml um folgende, angepasste Einträge zu erweitern:

<distributionManagement>
<!– use the following if you’re not using a snapshot version. –>
<repository>
<id>sourceforge-sf-mvn-plugins</id>
<name>FRS Area</name>
<uniqueVersion>false</uniqueVersion>
<url>sftp://web.sourceforge.net/home/frs/project/s/sf/<your_project>/<your_folder></url>
</repository>
<site>
<id>sourceforge-sf-mvn-plugins</id>
<name>Web Area</name>
<url>
sftp://web.sourceforge.net/home/project-web/s/sf/sf-mvn-plugins/htdocs/${artifactId}
</url>
</site>
</distributionManagement>

<build>

<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>1.0-beta-6</version>
</extension>
</extensions>

</build>

Um die Zugangsdaten an den Upload Wagon zu übermitteln, kann man in der lokalen settings.xml folgende Einträge vornehmen (die settings.xml muss vor lesenden Zugriffen anderer Nutzer geschützt werden!):

<servers>
<server>
<id>sourceforge-sf-mvn-plugins</id>
<username>loginname,projectname</username>
<password>your-password</password>
</server>
</servers>

Die fett geschriebene ID ist natürlich beliebig wählbar, sie muss nur an allen Stellen gleich sein – sonst funktioniert es nicht. Das Komma zwischen dem LoginNamen und dem Projektnamen bei der Angabe des username ist ebenfalls wichtig.

Maven: Abhängigkeiten verwalten


Flattr this
Endlich habe ich beim Schmökern einen Artikel über das Dependency Management von Maven gefunden. Die Quellenbeschreibung habe ich abgelegt unter:

http://www.bibsonomy.org/bibtex/2ef10bb1bc1be7806bc3fba53417bbd5f/funthomas424242

Abhängigkeiten werden in Maven bekanntlich in der pom.xml im <dependencies/> Block, ähnlich dem folgenden Beispiel definiert:

<dependencies>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.1</version>
    </dependency>
</dependencies>

Hierbei bedeutet der obige Kodeausschnitt eine Abhängigkeit zur commons-logging Bibliothek von Apache in der Version 1.1.  Die Angabe im Version Tag stellt allerdings nur eine Empfehlung an Maven dar. Falls diese Version also nicht verfügbar ist oder mit einer anderen Version kollidiert kann Maven durchaus selbst entscheiden welche Version benutzt wird.

Warum ist das überhaupt entscheidend? Ganz einfach! Wenn unser Programm von mehreren Bibliotheken abhängig ist. Wenn dabei mindestens 2 Bibliotheken von einer commons-logging Implementierung abhängig sind. Dann wäre es verdammt gut wenn die beiden Bibliotheken von der selben Version der commons-logging Implementierung abhängen. Falls das nicht so ist, müssten wir mehrere Versionen der commons-logging Bibliothek mit unserem Programm ausliefern. Damit ist aber nicht gesagt, dass dies dann auch läuft. Letztlich wird die Bibliothek angezogen welche zuerst im Klassenpfad liegt. Nicht gefundene Methoden und andere Fehler können die Folge sein.

Hier setzt das Dependency Management von Maven an. Maven prüft die Abhängigkeiten auf genau solche Konflikte und löst diese dann nach vorgegebenen Regeln auf. Beim Berechnen der zu benutzenden Versionen spielen mindestens folgende Dinge eine Rolle:

  • Angabe der Version im Version Tag:
    • <version>[1.1] </version>exakte Versionsangabe
      -> nur diese darf verwendet werden.
    • <version>1.1</version> empfohlene Versionsangabe
      -> Maven sollte diese benutzen, muss es aber nicht.
  • Scope der Abhängigkeit
    (compile, provided, test, runtime, system, import)
  • Angaben im Dependency Management des Haupt- oder des Eltern- Projektes.
  • Entfernung der Abhängigkeit (Dependency mediation)
    Wenn Projekt A abhängt von B und C und weiterhin B abhängt von D sowie D abhängt von E in Version 2 und C abhängt von E in Version 1 dann wird Version 1 von E benutzt. Weil die Entfernung in der transitiven Hülle von E (Version 1) über C zum Main Projekt A kürzer ist als die Entfernung von E (Version 2) über D und B zu A.
  • Scope der transitiven Abhängigkeit  (Dependency scope)
    Der Scope der transitiven Abhängigkeiten wird von Maven für die Berechnung nach definierten Regeln modifiziert (siehe Tabelle 1).

Wer wissen möchte welche Abhängigkeiten bestehen, kann sich den Graphen per Shell Kommando erzeugen lassen:

mvn dependency:tree

Die Ausgabe des Baumes auf der Console sieht beispielsweise für das jar-install-plugin wie folgt aus:

[INFO]
[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ jar-install-plugin ---
[INFO] net.sf.maven.plugins:jar-install-plugin:maven-plugin:0.1-SNAPSHOT
[INFO] +- junit:junit:jar:4.4:test (scope not updated to compile)
[INFO] +- commons-io:commons-io:jar:1.4:compile
[INFO] +- org.apache.maven:maven-plugin-api:jar:2.0.9:compile
[INFO] +- org.apache.maven:maven-artifact:jar:2.0.9:compile
[INFO] |  \- org.codehaus.plexus:plexus-utils:jar:1.5.1:compile
[INFO] +- org.apache.maven:maven-project:jar:2.0.9:compile
[INFO] |  +- org.apache.maven:maven-settings:jar:2.0.9:compile
[INFO] |  +- org.apache.maven:maven-profile:jar:2.0.9:compile
[INFO] |  +- org.apache.maven:maven-artifact-manager:jar:2.0.9:compile
[INFO] |  |  +- org.apache.maven:maven-repository-metadata:jar:2.0.9:compile
[INFO] |  |  \- org.apache.maven.wagon:wagon-provider-api:jar:1.0-beta-2:compile
[INFO] |  +- org.apache.maven:maven-plugin-registry:jar:2.0.9:compile
[INFO] |  \- org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9-stable-1:compile
[INFO] |     \- classworlds:classworlds:jar:1.1-alpha-2:compile
[INFO] \- org.apache.maven:maven-model:jar:2.0.9:compile

Um die verwendeten Versionen über die gesamte transitive Hülle der Abhängigkeiten steuern zu können, sollte hierzu die Beschreibung über die Tags <dependencyManagement/> erfolgen. Die zwischen den Tag’s definierten Versionen der Bibliotheken und Projekte werden dann von Maven auch bei der Auflösung von Konflikten in 3th Party Bibliotheken benutzt. Dazu folgendes Kodebeispiel:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.1</version>
    </dependency>
  </dependencies>
</dependencyManagement>
<dependencyManagement> <dependencies> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1</version> </dependency> </dependencies> </dependencyManagement>

Durch diese Deklaration wird Maven angehalten alle Abhängigkeiten so zu wählen, dass die commons-logging Bibliothek in der Version 1.1 benutzt werden kann. Wie bereits erwähnt es ist eine Empfehlung an Maven die nicht eingehalten werden muss. Daher macht es immer Sinn abschließend die tatsächlich benutzten Versionen über mvn dependency:tree zu prüfen.

Tabelle 1

Einbindung der Wirt-Lib im
aktuellen Projekt POM mit Scope
Scope in der
eingebundenen Lib
Geänderter Scope
compile compile compile
compile runtime runtime
provided compile, runtime provided
test compile, runtime test
runtime compile, runtime runtime
system * – (entfernt)
import n/a n/a
* test – (entfernt)
* provided – (entfernt)
* system – (entfernt)

(Wenn jemand zu dieser Tabelle eine bessere Erläuterung als oben oder im nachfolgende Link hat, bitte als Kommentar an diesen Artikel anfügen – vielen Dank)

Weiterführende Links:

Einführung in Maven


Maven Einsteiger Workshop