Archive for the ‘deploy’ tag
Deploying a Maven artefact without a repository using Ant
You know the drill, you’re working on an open source project (or two), and users start demanding Maven support. Why you ask yourself? Why, would anyone want to use Maven. But then, they assure you that it’s not by choice. That yes, they know Maven sucks, that it makes the simple hard and moderate impossible. But they’ve been forced to use it, and they’d like help. Now you know Ant has problems, but Maven? Seriously?
Seriously. So you decide to add in Maven support. After all, you’re running the project for the people, and having Maven support would help adoption, so it’s all good (and you get to write lame blog posts too!).
Now here’s where the fun begins…
The problem is that you’re using a tool other than Maven to build the project(s), and you have no Maven repository into which to deploy your project artefacts. The example I’ll show is using Google Code, but this could be any Subversion service, the process should be similar - with the exception of the SVN commands - for exposing a repository over HTTP. I’m also using Ant as the build tool, again, this should be replicable in other tools.
To save you the hassle of find them yourself, here’s the two links you’ll need. Firstly, here’s the Guide to uploading artifacts to the Central Repository, and secondly, here’s the Maven Deploy Plugin Usage overview. Be warned though, like most things Maven, this documentation is pretty scarce, for example what URL schemes does the deploy-file plugin take? Will it accept svn://... URLs? Who knows, but this is what worked for me.
All in all, the process is fairly simple once you figure it all out. The thing we’ll be building is called a Maven Bundle, and is simply a jar (zip) file containing certain content. We’ll then “deploy” this into a local “repository”, creating the necessary directory structure.
- Ensure your project is creating three artefacts, a main jar, a sources jar, and a javadoc jar. The last two (source & javadoc) are optional, however they seem to be standard for most Maven bundles, and Maven aware tools (such as IntelliJ) will automatically link the source and javadoc jars to the main classes.
As detailed in the guide, they need to be named as follows:
${artifactId}-${version}.jar ${artifactId}-${version}-sources.jar ${artifactId}-${version}-javadoc.jarNote that if your project also contains Scala code, and Scaladoc (as Functional Java & Instinct do), I’ve not looked into how to get these hooked up into the Maven bundle. Lift is using Maven so I guess it’s possible…
-
Create a Maven POM file, the guide linked above shows you the minimum you’ll need to get started (there are rules in the guide, that tell you what you must and can’t have in a POM for deployment). Here’s Instinct’s POM:
<?xml version="1.0"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelversion>4.0.0</modelversion> <groupid>com.googlecode.instinct</groupid> <artifactid>instinct-core</artifactid> <packaging>jar</packaging> <name>Instinct Core</name> <description>Instinct Behaviour Driven Development (BDD) Framework</description> <version>0.1.9</version> <url>http://instinct.googlecode.com/</url> <licenses> <license> <name>The Apache Software License, Version 2.0</name> <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> <distribution>repo</distribution> </license> </licenses> <scm> <url>http://instinct.googlecode.com/svn/</url> </scm> <dependencies> ... </dependencies> </project> -
You’ll now need to build your bundle, the contents should look like this:
pom.xml ${artifactId}-${version}.jar ${artifactId}-${version}-sources.jar ${artifactId}-${version}-javadoc.jarHere’s some Ant XML showing how this can be done:
<property name="build.dir" value="build"/> <property name="release.dir" value="${build.dir}/release"/> <property name="maven-bundle.jar" value="instinct-0.1.9-bundle.jar"/> <target name="-maven-bundle" depends="-jar,-sources-jar,-javadoc"> <mkdir dir="${release.dir}"/> <jar destfile="${release.dir}/${maven-bundle.jar}"> <fileset dir="${basedir}" includes="pom.xml"/> <fileset dir="${build.dir}" includes="${project.jar}"/> <fileset dir="${build.dir}" includes="${sources.jar}"/> <fileset dir="${build.dir}" includes="${javadoc.jar}"/> </jar> </target>And here’s what it builds:
$ unzip -l build/release/instinct-0.1.9-bundle.jar Archive: build/release/instinct-0.1.9-bundle.jar Length Date Time Name -------- ---- ---- ---- 0 08-08-08 22:48 META-INF/ 98 08-08-08 22:48 META-INF/MANIFEST.MF 2136 08-08-08 12:36 pom.xml 378565 08-08-08 22:48 instinct-0.1.9.jar 315685 08-08-08 15:28 instinct-0.1.9-sources.jar 693521 08-08-08 22:48 instinct-0.1.9-javadoc.jar -------- ------- 1390005 6 files - Create a spot in your svn for the maven artefacts, this will become your “repository”. I added mine here:
http://instinct.googlecode.com/svn/artifacts/maven/. - Take a checkout of this directory, you’ll need to store it somewhere local to the project, you’ll need its path later. I checked mine out into a peer directory to my project, so from the project it’s accessed as “../artifacts/maven”. This will be a local version of your repository.
-
You’ll now need to “deploy” your classes jar into this local repository, as follows (documented in the deploy plugin usage):
$ mvn deploy:deploy-file -Durl=file://../artifacts/maven -DrepositoryId=local-svn-artifacts -Dfile=instinct-core-0.1.9.jar -DpomFile=pom.xml
I tried to get the
deploy-filegoal to deploy to a remove SVN directly with no luck, YMMV. Again, the documentation is lacking here.Note that the
deploy-filegoal does not accept bundles, it needs to be just your classes jar. If you want your sources and javadoc there as well, you’ll need to copy and hash them also (see Ant target below).Alternatively, you can have your build tool do this for you:
<property name="maven-bundle.jar" value="${project.shortname}-${project.version.full}-bundle.jar"/> <property name="maven-repo.dir" value="${basedir}/../artifacts/maven"/> <property name="maven-repo-release.dir" value="${maven-repo.dir}/com/googlecode/instinct/instinct-core/${project.version.full}"/> <exec dir="${basedir}" executable="mvn" failonerror="true" os="Mac OS X,Linux"> <arg value="deploy:deploy-file"/> <arg value="-Durl=file://${maven-repo.dir}"/> <arg value="-DrepositoryId=local-svn-artifacts"/> <arg value="-Dfile=${build.dir}/${project.jar}"/> <arg value="-DpomFile=${basedir}/pom.xml"/> </exec> <copy file="${release.dir}/${maven-bundle.jar}" todir="${maven-repo-release.dir}"/> <copy file="${build.dir}/${sources.jar}" todir="${maven-repo-release.dir}"/> <copy file="${build.dir}/${javadoc.jar}" todir="${maven-repo-release.dir}"/> <checksum file="${maven-repo-release.dir}/${sources.jar}" algorithm="MD5" forceOverwrite="yes" fileext=".md5"/> <checksum file="${maven-repo-release.dir}/${sources.jar}" algorithm="SHA" forceOverwrite="yes" fileext=".sha1"/> <checksum file="${maven-repo-release.dir}/${javadoc.jar}" algorithm="MD5" forceOverwrite="yes" fileext=".md5"/> <checksum file="${maven-repo-release.dir}/${javadoc.jar}" algorithm="SHA" forceOverwrite="yes" fileext=".sha1"/> -
Check the structure of the local repository, it should look something like this:
maven/com/googlecode/instinct/instinct-core/0.1.9/instinct-core-0.1.9.jar maven/com/googlecode/instinct/instinct-core/0.1.9/instinct-core-0.1.9-javadoc.jar.sha1 maven/com/googlecode/instinct/instinct-core/0.1.9/instinct-core-0.1.9-sources.jar maven/com/googlecode/instinct/instinct-core/0.1.9/instinct-core-0.1.9.jar.md5 maven/com/googlecode/instinct/instinct-core/0.1.9/instinct-core-0.1.9-javadoc.jar maven/com/googlecode/instinct/instinct-core/0.1.9/instinct-core-0.1.9-sources.jar.md5 maven/com/googlecode/instinct/instinct-core/0.1.9/instinct-core-0.1.9-bundle.jar maven/com/googlecode/instinct/instinct-core/0.1.9/instinct-core-0.1.9-javadoc.jar.md5 maven/com/googlecode/instinct/instinct-core/0.1.9/instinct-core-0.1.9.jar.sha1 maven/com/googlecode/instinct/instinct-core/0.1.9/instinct-core-0.1.9.pom maven/com/googlecode/instinct/instinct-core/0.1.9/instinct-core-0.1.9.pom.md5 maven/com/googlecode/instinct/instinct-core/0.1.9/instinct-core-0.1.9.pom.sha1 maven/com/googlecode/instinct/instinct-core/0.1.9/instinct-core-0.1.9-sources.jar.sha1 maven/com/googlecode/instinct/instinct-core/maven-metadata.xml maven/com/googlecode/instinct/instinct-core/maven-metadata.xml.md5 maven/com/googlecode/instinct/instinct-core/maven-metadata.xml.sha1
- If you’re happy with the local repository, commit it into your (svn) repository. Instinct’s 0.1.9 release was deployed into this URL:
http://instinct.googlecode.com/svn/artifacts/maven/com/googlecode/instinct/instinct-core/0.1.9/. - You’re now done with the technical side of building a bundle. You’ll then need to log a JIRA issue for the Maven developers to upload your bundle (following the instructions in the guide). Then wait, and hope… Here’s the Instinct 0.1.9 request.
There is another way that users can download your Maven artefacts without them needing to be deployed to the central Maven repository, it’s detailed in the introduction to Maven repositories. Basically client projects of your project need to add a repository to their POM as follows (substituting the ID and URL belong for that of your repository):
<project>
...
<repositories>
<repository>
<id>instinct-repository</id>
<url>http://instinct.googlecode.com/svn/artifacts/maven/</url>
</repository>
</repositories>
...
</project>
Note that the process I’ve described of uploading to the central repository process is a manual one. Looking at the Maven issues for bundle uploads, it appears that if you don’t provide rsync or ssh access to your repository, you need to make manual upload requests. Others who’ve followed a similar process to this one are asking whether the Maven sync can happen automatically, to which I’ve not seen an answer. The documentation isn’t overly clear on this last point. A friend of mine asked on the Maven IRC channel yesterday and was told syncing over HTTP “just works”, though this isn’t evident by the details in the guide, the issues being reported nor the list of automatically synced repositories.
For those interested, these instructions were gleaned from looking at other projects that deploy Maven artefacts, including GWT-Maven and the Struts 2 Maven Plugin repository.