How does ivy:publish work?

烈酒焚心 提交于 2019-12-02 18:05:31

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>

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>

...

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.

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"/>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!