Migrating from Maven Ant Tasks to Maven Artifact Resolver Ant Tasks: Signing - ant

Maven Ant Tasks has been retired in favor of Maven Artifact Resolver Ant Tasks. There is no official migration path and the documentation is, well, OK.
We used Maven Ant Tasks to stage our jars into Sonatype for publication in Maven Central. I've been able to almost completely replicate that behavior in Maven Artifact Resolver Ant Tasks, but I haven't been able to sign the jars.
Does anybody know how this should be performed? Previously, I'd add a
<arg value="org.apache.maven.plugins:maven-gpg-plugin:1.3:sign-and-deploy-file" />
in the <artifact:mvn> task. Now I have a <resolve:deploy> task
<resolver:deploy>
<pom file="pom.xml"/>
<remoterepo id="${maven-staging-repository-id}" url ="${maven-staging-repository-url}"/>
<artifact file="${maven-jar}" type="jar"/>
<artifact file="${maven-sources-jar}" type="jar" classifier="sources"/>
<artifact file="${maven-javadoc-jar}" type="jar" classifier="javadoc"/>
</resolver:deploy>
and it works perfectly, but no signing.

Related

How to retrieve artifacts with per specific patterns using ant ivy

I have a huge dependency which exports a number of dependencies. I wish to restrict my retriev to couple of them. The pattern is [artifact]-[revision].[ext].
How do i specify this in ivy:retrieve task call
Configurations in ivy is the mechanism for controlling groups of dependencies within ivy.
Once these configurations have been setup in your ivy file it becomes simple to retrieve them within your ANT build as follows:
<ivy:retrieve pattern="lib/[artifact].[ext]" conf="my_custom_conf"/>
Perhaps you could supply some more details of what you want to achieve and someone can demonstrate how to setup a configuration for this purpose. (I'd also recommend searching the Stackoverflow ivy tag, for other examples)
Update
If an ivy module publishes more than one artifact it's possible to restrict the dependency in your ivy file as follows:
ivy.xml
<configurations>
..
<conf name="archives" description="Configuration containing only archive files"/>
</configurations>
<dependencies>
..
<dependency org="acme" name="foo" rev="2.0" conf="archives->default">
<artifact name="a1" type="tar"/>
<artifact name="an" type="zip"/>
</dependency>
</dependencies>
Alternatively..
Look into the remote modules's ivy.xml. There may already be a configuration setup for these files, in which case it becomes a lot simpler (because it's been pre-setup)
<dependency org="acme" name="foo" rev="2.0" conf="archives->remotearchives"/>
The "conf" part of the dependency is mapping the remote configuration onto your local one.

Setting up Ant / Ivy

So, let's assume that I have an already installed SVN and installed ANT / Ivy locally.
I want to have the "shared" part of the ivy config point to some kind of share on a server. How would I need to set this up?
I know I have to dig through the ivy jar and pull out the ivysettings file and modify shared repositories.
So let's assume that I have a server on my intranet at MyServer.intranet.net and my team's folder was under /path/to/NetAdmin (thus the full path would be MyServer.intranet.net/path/to/NetAdmin ) How would I get this set up as a team repository for shared libraries? Would I just specify it and when I package the projects it writes the dependencies there?
Thanks
Here what I did:
I created a Subversion project called ivy.dir.
In this ivy.dir project, I have the latest ivy.jar.
In the ivy.dir, I have the ivysettings.xml setup for our environment. For example, we use a local Artifactory Maven repository for our own jars. The ivysettings.xml in the ivy.dir project points to that.
I created a file called ivy.tasks.xml. This is an Ant build file.
The ivy.tasks.xml looks like this:
<project name="Ivy.Tasks"
xmlns:ivy="http://ant.apache.org/ivy"
xmlns:jacoco="antlib:org.jacoco.ant">
<property environment="env"/>
<!-- Add Ivy Tasks -->
<taskdef uri="http://ant.apache.org/ivy"
resource="org/apache/ivy/ant/antlib.xml">
<classpath>
<fileset dir="${ivy.dir}">
<include name="ivy*.jar"/>
</fileset>
</classpath>
</taskdef>
<ivy:settings file="${ivy.dir}/ivysettings.xml"/>
</project>
Notice that I have my own Ivy settings, thank you. I didn't have to munge up the one in the ivy.jar (although I could have since everyone will use my ivy.jar file!). My ivysettings.xml looks like this:
<ivysettings>
<!-- I'll explain this part below -->
<property name="env.EXECUTOR_NUMBER" value="0" override="false"/>
<caches
defaultCacheDir="${ivy.default.ivy.user.dir}/cache-${env.EXECUTOR_NUMBER}"
resolutionCacheDir="${ivy.dir}/../target/ivy.cache"/>
<!-- Just the standard stuff you find in the `ivysettings.xml in the ivy.jar -->
<settings defaultResolver="default"/>
<include file="${ivy.dir}/ivysettings-public.xml"/> <!-- This one is different -->
<include url="${ivy.default.settings.dir}/ivysettings-shared.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-local.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-main-chain.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-default-chain.xml"/>
</ivysettings>
The big change is the ivysetting-public.xml file:
<ivysettings>
<resolvers>
<ibiblio name="public"
m2compatible="true"
checkmodified="true"
root="http://repos.vegicorp.com/artifactory/libs-release" />
</resolvers>
</ivysettings>
It's pointing to my local Maven repository -- my Artifactory server.
Now, for a developer to use Ivy, all they have to do is:
In the root of their project in Subversion, add a svn:external. This svn:external will be used to bring my ivy.dir project into their Subversion project.
In the build.xml
Add an Ivy namespace definition to their build.xml in the <project> definition.
Set the property ivy.dir to `${basedir}/ivy.dir.
Use the <import> task to import ${ivy.dir}/ivy.tasks.xml into their build.xml file.
Something like this:
<project name="post-a-matic" default="package" basedir="."
xmlns:ivy="http://ant.apache.org/ivy">
<property name="ivy.dir" value="${basedir}/ivy.dir"/>
<import file="${ivy.dir}/ivy.tasks.xml"/>
<!-- A whole bundle of properties are set -->
<target name="clean">
<delete dir="${target.dir}"/>
<ivy:cleancache/> <!-- Look: They have access to Ivy! -->
</target>
<target name="-resolve">
<ivy:resolve/>
</target>
<target name="compile"
depends="-resolve">
<ivy:cachpath
pathid="main.classpath"
conf="compile,provided"/>
<!-- Boy that's easy! -->
<javac srcdir="${main.srcdir}"
destdir="${main.destdir}"
classpathref="main.classpath"/>
</target>
<!-- On and on -->
This solves a lot of problems:
You can update the ivy.settings and everyone will have the updated settings. This ended up being very important to us because we use Jenkins and I wanted Jenkins to clean the ivy cache on each build. Whoops! That cleans out the ivy cache on builds that are being executed at the same time! I solved the problem by changing the ivysettings.xml file to define a different Ivy cache for each Jenkins build executor. One the Jenkins server, you have Ivy caches called $HOME/.ivy2/cache-0, $HOME/.ivy2/cache-1, etc. Each executor can delete it's own Ivy cache without affecting the others. Users, meanwhile will just have $HOME/.ivy2/cache-0.
You also can update Ivy when a new jar comes out. You update your Ivy jar file, and everyone gets the lated.
Big one of course is that Ivy installs itself when a project is checked out.
And an extra special bonus: You could use your ivy.dir and ivy.tasks.xml file to install other tasks. For example, each of our projects must run itself through Findbugs, PMD, CPD (part of the PMD project, Checkstyle, and use JaCoCo. for test coverage.
Each one of these projects consist of a jar file, and a <taskdef> to pull the task definitions into Ant. And, how do you use these tasks too? They're not defined in the standard Ant model. Developers don't know how to use them.
I've added these jars into my ivy.dir project, and installed all of those task definitions into my ivy.tasks.xml file. I also defined easy to use <macrodef> for most of these tasks, so it's easy for the developers to use them. In fact, I've even included the old Ant-Contrib tasks just for fun.
Now, once you add ivy.dir into your project, you have all of these extra tasks, and you have nothing to install on your machine.
You don't need to change the ivy jar. Just create a filesystem resolver in an ivysettings file and publish to this. Here's an example:
good ivy tutorial for local repository?
You'll find that ivy is very flexible and can support pretty much any mechanism for hosting files.
Personally, I'd consider installing a Maven repository manager like Nexus or Artifactory and use this to host both your builds dependencies and build outputs. In the long run it's a lot easier, especially if you're doing Java development.

How do you use nested artifact elements for the ivy publish ant task

Can anybody give me a hint on how to use nested artifact (and artifacts) elements for publishing modules use the ivy ant task. Unfortunately the official documentation does not specify how to use the attributes.
http://ant.apache.org/ivy/history/latest-milestone/use/publish.html
Maybe there is some documentation or some examples that I could not find?
I am aware of the artifact element in ivy.xml files. this is NOT what this question is about.
Does this answer to this question help?
Issues using ivy:publish task
The nested "artifact" elements in the publish task are used to identify the location(s) of the artifacts you've specified as to be published by your module.
So, for example, let's say your module publishes two files:
<ivy-module version="2.0">
<info organisation="someorganisation" module="myapp"/>
<publications>
<artifact name="myapp" type="jar"/>
<artifact name="license" type="txt"/>
</publications>
..
Your publish task might need to source these files from two different locations within the build workspace:
<ivy:publish resolver="${publish.resolver}" pubrevision="${publish.revision}" status="${publish.status}">
<artifacts pattern="${build.dir}/[artifact].[ext]"/>
<artifacts pattern="${src.dir}/licenses/[organisation]/[artifact].[ext]"/>
</ivy:publish>

how to publish 3rdparty artifacts with ivy and nexus

I'm busily getting my feet wet with ivy. I have an existing nexus repository running on my local PC, and an existing ant build script.
Both work fine.
Part of the build scripts have some files to retrieve our 3rdparty jar files (log4j, xmlbeans, junit, pdf, etc..) from a network share - which is klunky at best.
I want to use ivy's dependency mechanisms to retrieve these files from a nexus repository and use that in the build. Each 3rdparty lib has a name and an arbitrary set of files (jar, dll, license.dat, xml, etc).
Since we have a large number of these 3rdparty libs and each lib has multiple files - manual uploading to nexus is not an option -- i need something i can use to take a set of files, give them a lib name, a version number and upload the result to nexus. then I need to be able to retrieve this from ivy.
I managed to get the upload part to work, but the retreival process does not work. Using our xmlbeans lib as a starting point I created the following ivy.xml file
<ivy-module version="1.0">
<info organisation="thirdparty_tools" module="xmlbeans" status="integration">
<publications>
<artifact name="jsr173_api" type="jar" ext="jar"/>
<artifact name="saxon-dom" type="jar" ext="jar"/>
<artifact name="saxon-xpath" type="jar" ext="jar"/>
<artifact name="saxon" type="jar" ext="jar"/>
<artifact name="xbean" type="jar" ext="jar"/>
<artifact name="xbean_xpath" type="jar" ext="jar"/>
<artifact name="xmlpublic" type="jar" ext="jar"/>
</publications>
</ivy-module>
and then some ant script to publish it to nexus:
<ivy:resolve/>
<ivy:publish <ivy:publish resolver="thirdparty" forcedeliver="true" update="true" revision="${version}" overwrite="true">
<artifacts pattern="[artifact].[ext]"/>
<ivy:publish/>
And this all works fine. It publishes all the jar files to nexus in the expected directory.
The trouble comes when I try to use it in my build.
I created the following ivy.xml file for my build:
<ivy-module version="1.0">
<info organisation="myCompany" module="GLB_Data"/>
<dependencies>
<dependency org="thirdparty_tools" name="xmlbeans" rev="2.2.0"/>
</dependencies>
</ivy-module>
Then when I run my build - it fails to find anything:
::::::::::::::::::::::::::::::::::::::::::::::
:: UNRESOLVED DEPENDENCIES ::
::::::::::::::::::::::::::::::::::::::::::::::
:: thirdparty_tools#jsr173_api;2.2.0: not found
:: thirdparty_tools#saxon-dom;2.2.0: not found
:: thirdparty_tools#saxon-xpath;2.2.0: not found
:: thirdparty_tools#saxon;2.2.0: not found
:: thirdparty_tools#xbean;2.2.0: not found
:: thirdparty_tools#xbean_xpath;2.2.0: not found
:: thirdparty_tools#xmlpublic;2.2.0: not found
::::::::::::::::::::::::::::::::::::::::::::::
The problem seems to be with this pattern:
WARN: ==== public: tried
WARN: http //localhost:8081/nexus/content/groups/public/thirdparty_tools/jsr173_api/2.2.0/jsr173_api-2.2.0.pom
WARN: -- artifact thirdparty_tools#jsr173_api;2.2.0!jsr173_api.jar:
WARN: http //localhost:8081/nexus/content/groups/public/thirdparty_tools/jsr173_api/2.2.0/jsr173_api-2.2.0.jar
ivy seems to be looking for the jsr173_api artifact under its own name, rather than under the xmlbeans folder where it was published to:
[ivy:publish] published jsr173_api to http //localhost:8081/nexus/content/repositories/thirdparty/thirdparty_tools/xmlbeans/2.2.0/jsr173_api-2.2.0.jar
(urls obfuscated to prevent accidents).
so somehow I need to publish differently, or retrieve differently. Ideas and suggestions are much appreciated.
Nexus is primarily a Maven repository, this means one must adapt to the way Maven structures artifacts.
Since you're focused on bulk loading Nexus I suggest looking at the answer to the following question:
Upload artifacts to Nexus, without Maven
If you wish to stick with ivy read on.....
Background
Need a Maven POM
Your first issue is that your Maven module(s) will need a POM file. This file describes the maven module and can be easily generated from the contents of your ivy.xml file (See solution below).
Secondly, Maven assumes that there is one primary artifact being built. For example:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.myspotontheweb</groupId>
<artifactId>donaldduck</artifactId>
<version>1.0.1</version>
<packaging>txt</packaging>
</project>
A Maven client would translate this information into the following URL:
http://<host>/<repo>/com/myspotontheweb/donaldduck/1.0.1/donaldduck-1.0.1.txt
This demonstrates how Nexus can store any type of binary dependency. The packaging parameter defaults to "jar".
How maven handles additional module artifacts
While Maven focuses on a single build artifact, it is possible to add additional supplementary artifacts by posting them into the same directory (as you've done).
These are not listed in the Maven POM. Instead a Maven uses a special "classifier" attribute. The following is a possible dependency declaration.
<dependency>
<groupId>com.myspotontheweb</groupId>
<artifactId>donaldduck</artifactId>
<version>1.0.1</version>
<classifier>metadata</classifier>
<type>n3</type>
</dependency>
A Maven client would translate this into the following URL:
http://<host>/<repo>/com/myspotontheweb/donaldduck/1.0.1/donaldduck-1.0.1-metadata.n3
Open source projects typically release their source code in this manner.
Ivy Solution
So finally how does one publish files into Nexus using ivy?
First of all decide which artifact is the "main" build artifact and add an additional entry for your POM file:
<ivy-module version='2.0' xmlns:e="http://ant.apache.org/ivy/extra">
<info organisation="com.myspotonontheweb" module="donaldduck" revision="1.0.1"/>
<publications>
<artifact name="donaldduck" type="txt"/>
<artifact name="donaldduck" type="pom"/>
<artifact name="donaldduck" type="n3" e:classifier="metadata"/>
<artifact name="donaldduck" type="zip" e:classifier="disto"/>
</publications>
</ivy-module>
The other files can also be listed but each must have a unique classifier attribute..... Here you will be faced with one of the classic problems translating an ANT project into Maven.... Each jar file you publish, will probably need to have a separate POM. They not really "supplementary" artifacts.....
Pretending that you don't need to publish multiple modules.... Use the following build targets to publish your module:
<target name="prepare" description="Generate POM">
<!-- Optional: Intermediate file containing resolved version numbers -->
<ivy:deliver deliverpattern="${build.dir}/ivy.xml" pubrevision="${publish.revision}" status="release"/>
<!-- Generate the Maven POM -->
<ivy:makepom ivyfile="${build.dir}/ivy.xml" pomfile="${build.dir}/donaldduck.pom"/>
</target>
<target name="publish" depends="init,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>
Nexus credentials
And for completeness here's the ivysettings.xml file containing the Nexus repository location and credentials:
<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>
Update
Downloading artifacts
To retrieve all the published artifacts (not just the main one), you need to list them as follows:
<dependency org="com.myspotontheweb" name="donaldduck" rev="1.0.1">
<artifact name="donaldduck" type="txt"/>
<artifact name="donaldduck" type="n3" e:classifier="metadata"/>
<artifact name="donaldduck" type="zip" e:classifier="distro"/>
</dependency>
Functionally the same as the following Maven fragment:
<dependency>
<groupId>com.myspotontheweb</groupId>
<artifactId>donaldduck</artifactId>
<version>1.0.1</version>
<type>txt</type>
</dependency>
<dependency>
<groupId>com.myspotontheweb</groupId>
<artifactId>donaldduck</artifactId>
<version>1.0.1</version>
<classifier>metadata</classifier>
<type>n3</type>
</dependency>
<dependency>
<groupId>com.myspotontheweb</groupId>
<artifactId>donaldduck</artifactId>
<version>1.0.1</version>
<classifier>distro</classifier>
<type>zip</type>
</dependency>

How to build a Grails Plugin and deploy it to local Ivy repository?

Is there a way to build a Grails Plugin and deploy the artifacts to the local Ivy repository?
With Maven, I would do this:
mvn install
Use the ivy publish task
<ivy:publish resolver="local" pubrevision="1.0">
<artifacts pattern="build/[artifact].[ext]" />
</ivy:publish>
Note 1
Your ivy file must list the artifacts you plan to publish
<ivy-module version="2.0">
<info organisation="myorg" module="mymodule"/>
<publications>
<artifact name="mymodule" type="zip"/>
</publications>
</ivy-module>
Maven derives this information from the module declaration in the POM file. One of the advantages of using ivy is that you can publish more than one artifact.
Note 2
The ivy local repository is located in the following location by default:
${user.dir}/.ivy2/local
You can of course create your own custom repositories by declaring alternative resolvers in you settings file

Resources