Publish SNAPSHOT artifacts to Maven using IVY - what's the magic?
Asked Answered
D

2

5

We have a slight convoluted situation...

For the most part we've been using IVY and ANT to manage our builds and dependencies. Now the company is moving towards using Maven. We have a set of projects called common libraries which are used by several of the core products.

Common libraries use IVY and are published to an IVY repository. We also need to make common libraries available for our new Maven projects. So when common libraries get built and published, I've modified the script to publish to Maven (Artifactory) as well IVY. Here are the two targets that now get called when publishing the built IVY projects:

<target name="publish-ivyrepo" depends="load-ivysettings">
    <ivy:resolve file="ivy.xml"  /> 
    <ivy:publish 
        module="${ant.project.name}"
        artifactspattern="${dist.dir}/[artifact].[ext]" 
        resolver="integration" 
        pubrevision="${build.version}" 
        status="integration"    
        overwrite="true"
        update="true"/>
</target>

<target name="publish-artifactory" depends="load-ivysettings">
    <ivy:resolve file="ivy.xml"  /> 
    <ivy:publish 
        module="${ant.project.name}"
        artifactspattern="${dist.dir}/[artifact].[ext]" 
        resolver="artifactory" 
        pubrevision="${build.version}-SNAPSHOT" 
        status="integration"    
        overwrite="true"
        update="true"/>
</target>

And here is the IVY settings detailing the resolvers:

<sftp name="integration" checkmodified="true" changingPattern=".*" host="host" user="ivy" userPassword="abc">
  <ivy pattern="${ivy.integration.default.root}/${ivy.public.default.ivy.pattern}"/>
  <artifact pattern="${ivy.integration.default.root}/${ivy.public.default.artifact.pattern}"/>
</sftp>
<url name="artifactory" checkmodified="false" changingPattern=".*" m2compatible="true">
  <ivy pattern="http://server/artifactory/libs-snapshot-local/${maven.default.ivy.pattern}"/>
  <artifact pattern="http://server/artifactory/libs-snapshot-local/${maven.default.artifact.pattern}"/>
</url>

This kind of works in that I now see the common library jars within Artifactory, with SNAPSHOT substituted for the unique timestamp. However, the source jar and the IVY xml file doesn't have SNAPSHOT substituted. Also, no POM file is being generated (though I dont know if this is necessary.

So this appears to be okay, though there are questions around the need for the POM file and the version naming of the IVY xml and the source jar. However, when I now proceed to specify a dependency from one of the Maven projects to one of the SNAPSHOT versions of the common library projects, it complains that it cannot resolve the dependency:

Missing artifact com.smartstream.common_library:common_library_dao:jar:4.0.0.5-4-SNAPSHOT:compile

I've tried specifying the repositories to Artifactory via the POM file and via the Maven settings file will little success:

<repository>
    <id>test</id>
    <name>simple test</name>
    <url>http://server/artifactory/libs-snapshot</url>
    <releases>
        <enabled>false</enabled>
    </releases>
    <snapshots>
        <enabled>true</enabled>
    </snapshots>
</repository>

What is strange is if I get IVY to publish a release as opposed to a SNAPSHOT into the libs-release-local repository of Artifactory, all resolves as you'd expect. Also, if I specify the unique timestamp as part of the dependency version (the substiute of SNAPSHOT), it also resolves it. So this shows that the Maven projects are able to resolve against Artifactory, just that something is going amiss with SNAPSHOT versions.

I've dug around high and low with little hope on this issue. If you can provide any insight, that'll be highly appreciated.

Disconnection answered 14/12, 2011 at 13:12 Comment(0)
G
7

Publishing to a Nexus repository from ivy has been answered here:

how to publish 3rdparty artifacts with ivy and nexus

That answer is possibly too comprehensive. The relevent section is titled "Ivy Solution". I'll summarise it here:

Example

ivy.xml

You'll need a publications section stating that you're publishing a jar and it's associated POM:

<ivy-module version='2.0'>
    <info organisation="com.myspotonontheweb" module="donaldduck"/>

    <publications>
        <artifact name="donaldduck" type="jar"/>
        <artifact name="donaldduck" type="pom"/>
    </publications>

    ..
    ..

</ivy-module>

Notes:

  • The other example is more complicated, demonstrating how addtional artifacts can be added to the Maven module.

ivysettings.xml

I'm using ibiblio resolvers, with Maven 2 compatibility switched on. In my experience this is the best way to configure a Maven repository in ivy.

<ivysettings>
    <settings defaultResolver="nexus-central"/>
    <credentials host="somehost" realm="Sonatype Nexus Repository Manager" username="????" passwd="????"/>
    <resolvers>
        <ibiblio name="nexus-central" root="http://somehost/nexus/content/repositories/central/" m2compatible="true"/>
        <ibiblio name="nexus-deploy" root="http://somehost/nexus/content/repositories/repo" m2compatible="true"/>
    </resolvers>
</ivysettings>

Notes:

  • For artifactory the credentials realm parameter would be "Artifactory Realm".

build.xml

Finally the build logic itself.

<target name="prepare" description="Generate POM">
    <ivy:deliver deliverpattern="${build.dir}/ivy.xml" pubrevision="${publish.revision}" status="release"/>
    <ivy:makepom ivyfile="${build.dir}/ivy.xml" pomfile="${build.dir}/donaldduck.pom"/>
</target>

<target name="publish" depends="init,build,prepare" description="Upload to Nexus">
    <ivy:publish resolver="nexus-deploy" pubrevision="${publish.revision}" overwrite="true" publishivy="false" >
        <artifacts pattern="${build.dir}/[artifact](-[classifier]).[ext]"/>
    </ivy:publish>
</target>

Notes:

  • The prepare target generates the POM using the makepom task.
  • The ivy deliver task is optional, but recommended in case you have any dynamic revisions (latest.integration, latest.release) in your ivy file.
  • The publish target publishes to the nexus-deploy resolver defined in your settings file.
  • The ${publish.revision} property is set elsewhere in the build. I'd recommend reading about ivy's buildnumber task

Note on artifactory

Artifactory appears to have some built-in support for ivy

Goody answered 15/12, 2011 at 21:48 Comment(2)
Well explained, helped a lot. However, this solution still failed to upload the pom.xml. In order to achieve this, I had to add <artifact name="donaldduck" ext="pom" type="pom" /> to the inner elements of the <ivy:publish> target. It is described here: [theholyjava.wordpress.com/2011/01/26/using-ivy-with-pom-xml/] , but I honestly do not understand how this works (curiously, I generate the pom into a subfolder, but do not have to state this subfolder in the <artifact> element)Mechanic
Sorry, wrongly formatted, the closing square bracket is should not be part of the URL: theholyjava.wordpress.com/2011/01/26/using-ivy-with-pom-xmlMechanic
G
0

If you are already going to migrate to Maven I would suggest to check out the Aether Ant Tasks, which are the replacement for the old (and now pretty much deprecated) Maven Ant Tasks. Using that will be exposing all the needed Maven dependency handling features you need for your task..

Gebhardt answered 14/12, 2011 at 20:15 Comment(2)
Disappointingly, the Aether ANT tasks are still not formally released, not available in Maven Central, seems the only way to obtain them is compile the github source. The older Maven ANT tasks only support Maven 2..... So that means, currently, ivy is the best non-Maven way to interact with a Maven repository :-)Copartner
Fair enough. I have created an issue on github with the project requesting a release.Gebhardt

© 2022 - 2024 — McMap. All rights reserved.