How does ivy:publish work?
Asked Answered
M

4

26

I'm completely at loss how the ant task ivy:publish is supposed to work.

I would expect that I do my normal build, which creates a bunch of jar files, then I would push those jars to the (local) repository.

How can I specify from where to retrieve the built jars, and how would those end up in the repository?

Update:

<target name="publish-local" description="--> Publish Local">
    <ivy:retrieve />
    <ivy:publish resolver="local" pubrevision="${release.version}" status="release" update="true" overwrite="true">
        <artifacts pattern="${dist.dir}/[organisation]-[module].[ext]" />
    </ivy:publish>
</target>

this actually works, I didn't include the retrieve before.

But I still have some problems, suppose I want to publish 3 jars, openscada-utils.jar, openscada-utils-sources.jar and openscada-utils-javadocs.jar as openscada-utils-0.9.2.jar, openscada-utils-0.9.2-sources.jar and openscada-utils-0.9.2-javadocs.jar

It isn't entirely clear to me, how the actual names are assembled, and where I can specify which names they should get. (Using the fragment above, the jars are always called only utils.jar).

Update 1:

I got it to work (a bit), but it still doesn't feel right. Somehow all tutorials focus on dependencies from 3rd party projects, but an equally important point for me is to handle project specific dependencies.

I have a bunch of sub projects which depend on each other in various ways. Considering ivy:publish it is not clear to me how to start.

  1. How do I handle the first version? I have a common version number for all sub projects to indicate that they belong together (lets say 0.9). Therefore the first revision should be 0.9.0, but so far nothing of my projects is in my repository. How do I get Ivy to assign this revision number.

  2. In the course of developing I want to publish the built files again, without changing the revision number so far.

  3. If I'm finished with my work I want to push it to a shared repository (and increase the revision number lets say from 0.9.0 to 0.9.1), what is the recommended approach to do so?

  4. For an actual release, I want to make distributions with dependencies and without, somehow I guess I can use different configurations for that. How can I use that to my advantage?

Marenmarena answered 9/12, 2008 at 16:18 Comment(1)
Just FYI, according to this deliver task is called by the publish task.Perla
R
10

You need to specify the "resolver". Something like:

<ivy:publish resolver="local" pubrevision="1.0"/>

It's controlled by the pattern. This page covers it pretty well. It looks like you want yours to be:

<artifacts pattern="${dist.dir}/[organisation]-[module]-[revision]-[type].[ext]" />

And you'll need to identify the three jars as artifacts in the ivy.xml file. Something like this:

<publications>
    <artifact name="utils"/>
    <artifact name="utils" type="source"/>
    <artifact name="utils" type="javadocs"/>
</publications>
Rewarding answered 9/12, 2008 at 16:30 Comment(0)
R
4

First you need an ivy.xml file.

<ivy-module version="2.0">
    <info organisation="com.example.code" module="MyProject"
         revision="${project.revision}"/>
    <configurations>
        <conf name="runtime" description="" />
        ... other config elements here...
    </configurations>

    <publications defaultconf="runtime">
        <artifact name="MyProject" type="jar" ext="jar" conf="runtime" />
    </publications>

    <dependencies>
        ...
    </dependencies>
</ivy-module>

The info element and publications elements in ivy.xml allow you to skip various attributes on the ivy elements in build.xml.

Note the ${project.revision} in ivy.xml. The property is given value in build.xml, but this seems to work nicely. The revision can then easily have whatever value is required (eg. nightly builds vs. local builds).

Here is a sample how you could set up your build.xml file

<property name="project.revision" value="1.0.0"/>

...

<target name="ivy">
    <ivy:resolve />

    <!-- Possible ivy:report, ivy:retrieve and other
    elements for managing your dependencies go here -->

    <ivy:deliver conf="*(public)"/> 
</target>

<target name="publish" depends="clean, ivy, jar">
    <ivy:publish resolver="local">
        <!-- possible artifacts elements if your artifacts
        are not in standard location -->
    </ivy:publish>
</target>

...
Retire answered 13/1, 2012 at 16:28 Comment(1)
Good reference draconianoverlord.com/2010/07/18/…Retire
V
3

You're suppose to run the <ivy:deliver/> task first. This creates an ivy.xml file that can be used by the Ivy repository.

When you use <ivy:publish> you specify which repository you want to publish to by specifying it in the resolver parameter. This needs to match the resolver name in your ivy.settings.xml file.

You don't really specify the artifacts, but a pattern where to find the artifacts to publish. You specify this via the <artifacts> subtask on the <ivy:publish> task. For example, if you build everything under the ${basedir}/target/archive directory like we do, you can specify it as this:

<ivy:publish resolver="public">
   <artifacts path="target/archive/[artifact].[ext]"/>
</ivy:publish>

If you want to change the revision number of your file, you can use the pubrevision parameter of the <ivy:publish> task. This doesn't update the ivy.xml, but will publish your jars/wars to the correct revision. I prefer to use the pubrevision parameter of the <ivy:deliver> task and let it create the correct ivy.xml file anyway. Then, <ivy:publish> will use the revision in my ivy.xml file.

You don't need to do <ivy:retrieve>. After all, you're running a build to create new jars, and they should be SOMEWHERE in your build. Otherwise, if you're not creating a jar or war what are you trying to publish into your Ivy repository? And, you certainly don't want to retrieve something already in your Ivy repository just to republish it.


My philosophy has always been that publishing is a CM task and shouldn't be done as part of the build procedure. Thus, we don't use <ivy:deliver> or <ivy:publish>.

We use Artifactory as our Ivy repository (and our Maven repository). We use Jenkins as our continuous build server.

What I do is have the developers make a pom.xml file out of their ivy.xml file via the <ivy:makepom> task. This and the build jars/wars are saved as archived artifacts in Jenkins.

When we are happy with a particular build and want it in our public repository, I use Jenkin's Promote Build task to promote a particular jar/war with its pom.xml to our Artifactory repository. We use the mvn deploy:deploy-file task to do that.

Valentinvalentina answered 28/8, 2012 at 18:7 Comment(0)
L
0

It's important to realize what ivy is doing here. It is NOT simply copying your artifact jars into the ivy repository - it is also generating the relevant ".ivy.xml" files that specify all the dependents of each of your artifacts.

Under the covers, the ivy:retrieve task is actually also triggering an ivy:resolve. When that ivy:resolve occurs, a file is written to your local ivy cache (in the .ivy folder in user.home) that specifies how the resolution happened (which revisions of which modules were required to complete the resolution.) When ivy:publish is encountered, that resolution record is retrieved from cache and used to generate the ivy.xml for your artifacts.

The largest pitfall I've found in doing this is the requirement that the ivy:resolve and ivy:publish tasks both be loaded by the same classloader when they are executed by ant. The easiest way to make sure this happens is to use the loaderRef on your taskdef tasks. For example (note the matching loaderRef tags):

<taskdef name="ivy-retrieve" 
     classname="org.apache.ivy.ant.IvyRetrieve" 
     classpathref="ivy.lib" 
     loaderRef="ivy.loader"/>
<taskdef name="ivy-publish" 
     classname="org.apache.ivy.ant.IvyPublish" 
     classpathref="ivy.lib" 
     loaderRef="ivy.loader"/>
Lewls answered 10/12, 2008 at 6:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.