How to publish a test source folder using ivy? - ivy

In my project I have two separate source folders - /src where the code is and /test for mock and test objects.
On top of the standard jar (from /src) that ivy successfully publishes for my project I would like to publish another artifact through ivy that only includes the objects in the /test folder in order to be able to share these mock objects with other projects.
Can someone please provide an ivy configuration to support this?

1- You need to build a test-jar from the test-folder, lets call it project-test.jar
<javac destdir="build/test" srcdir="test/">
<classpath refid="test.classpath" />
</javac>
<jar destfile="dist/project-test.jar"
basedir="build/test"/>
2- Define an artifact in your ivy.xml
<publications>
<artifact name="project" type="jar" conf="default" ext="jar"/>
<artifact name="project-test" type="jar" conf="test ext="jar"/>
</publications>
3- Publish
<ivy:resolve
revision="${project.version}"
conf="compile,test"
/>
<!-- Alle Artifacts für compile mit dem jars resolver publishen -->
<ivy:publish
revision="${project.version}">
<artifacts pattern="dist/[artifact]-[revision].[type]" />
</ivy:publish>

Related

IVY resolve to latest.release resolves to wrong artifact

I have an ivy xml file contains dependencies declarations, but uses the rev="latest.release" settings rather than specifying a hard wired revision.
<dependency org="<organisation name>" name="<module>" rev="latest.release"/>
The reason I am using latest.release is that every Sunday our build process runs and generates 'release' artifacts for ALL modules in our project. These artifacts are named WKXX-YYYY so for example, the most recent was WK05-2017
The problem is, when I do a resolve IVY is resolving the artifacts to version WK50-2016 and I do not understand why. The published ivy.xml that resides with the artifact on our central ivy repo seems correct and the info section states the correct status eg release and the publication date is also correct.
eg
WK50-2016
<info organisation="<org name>" module="<module name>" revision="WK50-2016" status="release" publication="20161218140515"/>
WK05-2017
<info organisation="<org name>" module="<module name>" revision="WK05-2017" status="release" publication="20170205140555"/>
As you can see from the above, the publication date is more recent in the WK05-2017 artifact.
I have also included the ivysettings.xml that is also used as part of the IVY configuration.
ivysettings.xml
<ivysettings>
<settings defaultResolver="chained"/>
<resolvers>
<!-- Remote IVY Repo -->
<filesystem name="remote" changingPattern=".*-SNAPSHOT.*" changingMatcher="regexp" checkmodified="true">
<ivy pattern="${ivy.repo.dir}/[organisation]/[module]/[revision]/ivy.xml"/>
<artifact pattern="${ivy.repo.dir}/[organisation]/[module]/[revision]/[artifact].[ext]"/>
</filesystem>
<!-- Local IVY Repo -->
<filesystem name="local" changingPattern=".*-SNAPSHOT.*" changingMatcher="regexp" checkmodified="true">
<ivy pattern="${ivy.local.repo.dir}/[organisation]/[module]/[revision]/ivy.xml"/>
<artifact pattern="${ivy.local.repo.dir}/[organisation]/[module]/[revision]/[artifact].[ext]"/>
</filesystem>
<!-- Use both the local and remote repos -->
<chain name="chained" changingPattern=".*-SNAPSHOT.*" changingMatcher="regexp" checkmodified="true">
<resolver ref="local" />
<resolver ref="remote"/>
</chain>
</resolvers>
<caches defaultCacheDir="${ivy.cache.dir}" ivyPattern="${ivy.cache.ivy.pattern}" artifactPattern="${ivy.cache.artifact.pattern}"/>
</ivysettings>
Just for reference.
changingPattern=".*-SNAPSHOT.*" changingMatcher="regexp" checkmodified="true"
are used as we also use SNAPSHOT integration artefacts that are built and published when commits are made to trunk. I found that without these attributes ivy would use the local SNAPSHOT even if the version on the remote repo was more recent.
Thanks in advance.

Error when trying to use optional token in artifacts pattern

Up until now, I was only generating a dist/imasUtils.jar file in the build (using Ant), and publiching it with the following Ant code:
<ivy:resolve/>
<ivy:publish resolver="imas-ssh" overwrite="true" publishivy="true">
<artifacts pattern="dist/[artifact].[ext]"/>
</ivy:publish>
So far, this worked, but now I want to publish also the source, so I am also generating dist/imasUtils_src.zip. According to my understanding of the ivy manual, I could do this:
<ivy:resolve/>
<ivy:publish resolver="imas-ssh" overwrite="true" publishivy="true">
<artifacts pattern="dist/[artifact](_[type]).[ext]"/>
</ivy:publish>
and that would recognize both of my files dist/imasUtils.jar and dist/imasUtils_src.zip, the only difference is that when I published them the type attribute would be null for the jar file.
Instead, I am getting the following error message:
/[myDirectory]/build.xml:119: impossible to publish artifacts for net.conselldemallorca.imas#imasUtils;1.2.0:
java.io.IOException: missing artifact net.conselldemallorca.imas#imasUtils;1.2.0!imasUtils.jar
at org.apache.ivy.core.publish.PublishEngine.publish(PublishEngine.java:225)
at org.apache.ivy.core.publish.PublishEngine.publish(PublishEngine.java:172)
at org.apache.ivy.Ivy.publish(Ivy.java:621)
at org.apache.ivy.ant.IvyPublish.doExecute(IvyPublish.java:311)
at org.apache.ivy.ant.IvyTask.execute(IvyTask.java:271)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
...
My ivy.xml file:
<ivy-module version="2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
<info organisation="net.conselldemallorca.imas"
module="imasUtils" revision="${ivy.revision}"/>
<publications>
<artifact />
</publications>
</ivy-module>
and my organization ivy-settings.xml file:
<ivysettings>
<property name="ivy.pattern" value="artifacts/[organisation]/[module]/r[revision]/ivy-[revision].xml" override="false"/>
<property name="artifact.pattern" value="artifacts/[organisation]/[module]/r[revision]/[artifact].[ext]" override="false"/>
<settings defaultResolver="shared"/>
<resolvers>
<ssh name="imas-ssh" host="MYHOST" publishPermissions="0770">
<ivy pattern="/var/www/html/Ivy/${ivy.pattern}"/>
<artifact pattern="/var/www/html/Ivy/${artifact.pattern}"/>
</ssh>
<chain name="shared">
<url name="imas">
<ivy pattern="http://ivy.proves.imasmallorca.net/Ivy/${ivy.pattern}"/>
<artifact pattern="http://ivy.proves.imasmallorca.net/Ivy/${artifact.pattern}"/>
</url>
<ibiblio name="public" m2compatible="true"/>
</chain>
</resolvers>
</ivysettings>
I am using Apache Ant 1.9.3 and Ivy 2.4.0
I suspect the problem might be the way you've defined the "type" in the pattern. You also need to declare more than one file in your ivy file's publications section.
I suggest the following change to your ivy file:
<ivy-module version="2.0" xmlns:e="http://ant.apache.org/ivy/extra">
<publications>
<artifact name="imasUtils" type="jar"/>
<artifact name="imasUtils" type="zip" e:classifier="src"/>
</publications>
And corresponding change in the publish task's pattern:
<ivy:publish .. >
<artifacts pattern="dist/[artifact](_[classifier]).[ext]"/>
</ivy:publish>
The "classifier" is an example of a custom extra attribute.
Example:
Convert ivy.xml to pom.xml
The following link provides more explanation on how ivy interacts with Maven repos which has a fixed understanding of a "sources" attribute.
how to publish 3rdparty artifacts with ivy and nexus

How to copy runtime libraries without the provided ones in IVY

I thought I wouldn't need to ask this but I am not having any progress.
The solution to this question:
How are maven scopes mapped to ivy configurations by ivy actually addresses question but in its theoretical part.
I have this configuration:
<conf name="compile" description="???" />
<conf name="runtime" description="???" extends="compile" />
<conf name="test" description="???" extends="runtime" />
<conf name="provided" description="???" />
Assume I have this dependency:
<dependency org="org.apache.tomcat" name="servlet-api" rev="6.0.16" transitive="false" />
What I want is: when I invoke the ivy:retrieve to copy the libraries to the .war lib directory before bundling it, I want only to copy all runtime (and compile implicitly) but no servlet-api.
so how to use ivy:retrieve then?
<ivy:retrieve conf="WHAT_TO_PUT_HERE" />
and how to configure the dependency:
<dependency conf="WHAT_IS_THE_CONF_MAPPING" org="org.apache.tomcat" name="servlet-api" rev="6.0.16" transitive="false" />
I'm plateauing here, so please any help would be appreciated.
Knowing that the ivy.xml for servlet-api defines the artifact with
conf="master"
So I think the question is how to 'really' map Provided scope of maven to the provided configuration of IVY.
This is how you map a dependency onto the local "provided" configuration:
<dependency org="org.apache.tomcat" name="servlet-api" rev="6.0.16" conf="provided->master"/>
The configuration mapping works as follows:
provided->master
^ ^
| |
Local Remote
config config
As explained in the answer the special "master" configuration contains only the artifact published by this module itself, with no transitive dependencies:
How are maven scopes mapped to ivy configurations by ivy
This means the "transitive=false" attribute is not required.
Update
How you use the configuration is up to you. The first option is simpler, but I prefer the second approach because my configuration reports match my classpath contents
Option 1
You can create a single classpath as follows:
<ivy:cachepath pathid="compile.path" conf="compile,provided"/>
This can then be used in the javac task as follows:
<javac ... classpathref="compile.path">
..
Option 2
Or I prefer to have a one-2-one mapping between configurations and classpaths:
<ivy:cachepath pathid="compile.path" conf="compile"/>
<ivy:cachepath pathid="provide.path" conf="provided"/>
The problem with the latter approach is that the javac task need to have the classpath usage explicitly stated as follows:
<javac ...
<classpath>
<path refid="compile.path"/>
<path refid="provided.path"/>
</classpath>
I think this explicitly explains how you use this special provided scope, but it's really up to you.

How do I use a local folder as an ivy repository?

What if I have already jars in my project lib folder and I want to use that folder as my repository instead of downloading and install it into my iv2/local folder.
Right now its first downloading jars from maven to my local repository. Some jars are not found in the repository, but I have them in a lib folder and would lie to retrieve them from there.
You need to create an ivysettings.xml where you define two resolvers in a chain:
FileSystemResolver
Maven Repository Resolver
This could look like this (Example from the chain resolver:
<ivysettings>
<resolvers>
<chain name="test">
<filesystem name="1">
<ivy pattern="${ivy.settings.dir}/lib/[organisation]/[module]/ivys/ivy-[revision].xml"/>
<artifact pattern="${ivy.settings.dir}/lib/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
</filesystem>
<ibiblio name="maven2" m2compatible="true"/>
</chain>
</resolvers>
</ivysettings>
${ivy.settings.dir} is the folder, where your ivysettings.xml is located.
To include / set an ivysettings.xml in your build.xml you need to use the settings task:
<ivy:settings />
or
<ivy:settings file="path_to_file/ivysettings.xml" />

Issues using ivy

I am new bie to ivy.
I am using packager resolver and that packager resolver resolves the zip file, unzip it, extracts the jar file from it in temp build file, but it stays temporarily and only the jar file which i specified as a module name gets copied to destination rest of all are ignored. Is there a way i can get all the jar files? I use preseverBuildDirectories but is there a better way to do it?
Also is it possible for me to publish an artifact to svn using normal ivy? I got error while i was trying to use ivy 2.1.0 on XP using ant 1.8.0 java.illegalArguementException saying authorization failed. Is there a way i can work through ivy:publish?
Is there a way i can use ivy variable in packager.xml?
Thanks in advance,
Almas
1) Packager resolver
You need to include an ivy file for the repackaged module listing all the artifacts.
Here's my example that downloads the files associated with the Solr distribution
ivysettings.xml
<ivysettings>
<settings defaultResolver="maven2"/>
<caches defaultCacheDir="${user.home}/.ivy2/cache"/>
<resolvers>
<ibiblio name="maven2" m2compatible="true"/>
<packager name="repackage" buildRoot="${user.home}/.ivy2/packager/build" resourceCache="${user.home}/.ivy2/packager/cache" preserveBuildDirectories="false">
<ivy pattern="file:///${ivy.settings.dir}/packager/[organisation]/[module]/ivy-[revision].xml"/>
<artifact pattern="file:///${ivy.settings.dir}/packager/[organisation]/[module]/packager-[revision].xml"/>
</packager>
</resolvers>
<modules>
<module organisation="org.apache.solr" name="solr" resolver="repackage"/>
</modules>
</ivysettings>
Note how the packager resolver specifies a path to both an ivy and packager file.
The ivy file specifies the artifacts that are part of the package in the publications section.
packager/org.apache.solr/solr/ivy-1.4.0.xml
<ivy-module version="2.0">
<info organisation="org.apache.solr" module="solr" revision="1.4.0"/>
<configurations>
<conf name="jars" description="Jars released with SOLR distribution"/>
<conf name="webapps" description="Web applications"/>
</configurations>
<publications>
<!-- jars -->
<artifact name="solr-cell" conf="jars"/>
<artifact name="solr-clustering" conf="jars"/>
<artifact name="solr-core" conf="jars"/>
<artifact name="solr-dataimporthandler" conf="jars"/>
<artifact name="solr-dataimporthandler-extras" conf="jars"/>
<!-- webapps -->
<artifact name="solr" type="war" conf="webapps"/>
</publications>
</ivy-module>
The packager file contains the logic that copies out each artifact listed in the ivy file for the solr module.
packager/org.apache.solr/solr/packager-1.4.0.xml
<packager-module version="1.0">
<property name="name" value="${ivy.packager.module}"/>
<property name="version" value="${ivy.packager.revision}"/>
<resource dest="archive" url="http://ftp.heanet.ie/mirrors/www.apache.org/dist/lucene/solr/1.4.0/apache-solr-1.4.0.tgz" sha1="521d4d7ce536dd16c424a11ae8837b65e6b7bd2d">
<url href="http://www.apache.org/dist/lucene/solr/1.4.0/apache-solr-1.4.0.tgz"/>
</resource>
<build>
<!-- Jar artifacts -->
<move file="archive/apache-${name}-${version}/dist/apache-${name}-cell-${version}.jar" tofile="artifacts/jars/${name}-cell.jar"/>
<move file="archive/apache-${name}-${version}/dist/apache-${name}-clustering-${version}.jar" tofile="artifacts/jars/${name}-clustering.jar"/>
<move file="archive/apache-${name}-${version}/dist/apache-${name}-core-${version}.jar" tofile="artifacts/jars/${name}-core.jar"/>
<move file="archive/apache-${name}-${version}/dist/apache-${name}-dataimporthandler-${version}.jar" tofile="artifacts/jars/${name}-dataimporthandler.jar"/>
<move file="archive/apache-${name}-${version}/dist/apache-${name}-dataimporthandler-extras-${version}.jar" tofile="artifacts/jars/${name}-dataimporthandler-extras.jar"/>
<!-- War artifacts -->
<move file="archive/apache-${name}-${version}/dist/apache-${name}-${version}.war" tofile="artifacts/wars/${name}.war"/>
</build>
</packager-module>
2) Publish to subversion
I've never used it myself but I think you need to configure the subversion resolver and use this to publish your artifacts
3) Using ivy variable in packager file
The packager file listed above uses two ivy variables. Not sure what your question is.
Update: Supporting 3rd party jars
The publications section of the ivy file include the version number in the name of the 3rd party jar:
ivy file
..
<publications>
<artifact name="abc-1.0" conf="jars"/>
<artifact name="pqr-2.0" conf="jars"/>
</publications>
..
packager file
..
<build>
<move file="archive/apache-${name}-${version}/dist/abc-1.0.jar" tofile="artifacts/jars/abc-1.0.jar"/>
<move file="archive/apache-${name}-${version}/dist/pqr-2.0.jar" tofile="artifacts/jars/pqr-2.0.jar"/>
</build>
..