while resolving my ivy.xml, I get a long list of errors, all stating "unknown resolver XYZ". I know the resolver, it is used in the same project but different task.
As far as I understand, the resolver used to create the cache entry is stored and than cannot be determined by the follow-up resolver.
Question is: how can I avoid this? Seeams like this is not really an error, more like a warning since I am able to resolve all dependencies and continue compiling.
Within the same project, the build resolver will not change because it's defined in your ivysettings.xml file.
This is more likely to be a problem with a stale ivy cache. I'd suggest adding an extra target that purges your cache. Useful when encountering this type of problem:
<target name="clean-all" depends="clean" description="Purge ivy cache">
<ivy:cleancache/>
</target>
Run your ant build with the verbose flag (-v). This will give you clear insight into which settings files are being used throughout the resolve process. My wager is you will find your problem fairly easily and it will be along the lines of the settings file you thought you were using is actually not being used.
In my projects, I find this type of thing often happens when a post-resolve task (such as retrieve) triggers a resolve "automatically" and uses the default ivy settings instead of the one I want it to use at the moment. Chances are, your default settings file does not contain the resolvers you're expecting.
To solve these issues, I make a ivysettings-common.xml containing only resolvers. Then, in each of my settings files, I import the common settings and reference the resolvers in the main chain. That looks like:
<ivysettings>
<settings defaultResolver="all-repositories" />
<include file="ivysettings-common.xml" />
<resolvers>
<chain name="all-repositories" returnFirst="true" >
<resolver ref="project" />
<resolver ref="local" />
<resolver ref="hibernate" />
<resolver ref="ibibilo" />
</chain>
</resolvers>
</ivysettings>
From there, I make the common file my default settings, just "in case of emergency" I know all my resolvers can be found (by adding the following to ivy.properties):
ivy.settings.file = ${basedir}/path/to/ivysettings-common.xml
but I explicitly point all my ivy calls to the appropriate settings file, trying to never rely on the default because the whole reason I use ivy+ant is that I prefer precise control over my build process:
I hope all that helps you or someone else.
~gMale
Related
To eliminate redundancy in my ant build.xml files, I decided out-factor the repeated targets into mytargets.xml file, publish it to to the artifact repository, and then import it in the following way:
<import>
<url url="http://mycompany.com/artifacts/mycompany.com/mytargets/1.2.3/mytargets-1.2.3.xml"/>
</import>
There are two things I don't like about this approach:
mytargets-1.2.3.xml never appears anywhere on the disk where I can easily look at it.
I absolutely need access to http://mycompany.com/artifacts in order to do anything in the project---it completely undermines offline work.
So, I tried creating a setup target to fetch a local copy of mytargets.xml and adjusted my <import> to use this local copy.
<import file="${basedir}/antlib/mytargets/mytargets.xml"/>
However, as you have probably guessed, I cannot even execute my setup my target after adjusting my <import> in this way because the file does not yet exist:
Buildfile: /home/me/myproject/build.xml
BUILD FAILED
/home/me/myproject/build.xml:265: Cannot find /home/me/myproject/antlib/mytargets/mytargets.xml imported from /home/me/myproject/build.xml
Adding optional="true" to the <import> only defers the problem to the first target that depends upon mytargets.xml.
I looked at https://ant.apache.org/manual/Types/antlib.html, but this approach does not appears to permit you to define a <target>.
So, how does someone share bits of ant XML across multiple projects? Am I already doing it the 'one true way'? Or, is there a better way?
If you're mainly just trying to avoid download the remote copy when you have a local copy already available, you can try something like this:
<condition property="mytargets.xml.available">
<available file="${basedir}/antlib/mytargets/mytargets.xml" />
</condition>
<target name="setup" unless="mytargets.xml.available">
<get
src="http://mycompany.com/artifacts/mycompany.com/mytargets/1.2.3/mytargets-1.2.3.xml"
dest="${basedir}/antlib/mytargets"
/>
</target>
<target name="main" depends="setup">
<import file="${basedir}/antlib/mytargets/mytargets.xml" />
...
</target>
So, it seems to me that <target> is inherently local and not intended for reuse. On the other hand, <macrodef> appears intended for reuse.
Here is the 'library', mymacros.xml:
<?xml version="1.0"?>
<antlib>
<macrodef name="mymacro">
...
</macrodef>
</antlib>
Here is the client, myproject/build.xml:
<?xml version="1.0"?>
<project name="myproject">
<target name="mytarget">
<mymacro/>
</target>
<taskdef file="mymacros.xml"/>
</project>
Unlike <import> and <include>, <taskdef> will not cause the build to fail immediately if mymacros.xml is missing, which gives you the opportunity to download it.
I am trying to tackle some technical debt in our Ant/Ivy system and one of my current tasks is to address some post-retrieve behaviors we currently have. By default, our build system retrieves Ivy dependencies and then extracts compressed artifacts (tar, tar.bz2, gzip, zip only) to a dependency folder, so that our projects have a consistent dependency location:
(project.root)/dependency/.archive <- the compressed dependency location
(project.root)/dependency/extracted-foo` <- the uncompressed dependency
The extraction occurs in a post-retrieve-artifact trigger so that we get the benefit of some of the metadata (paths, names, types, etc., all prefixed with 'dep'.
We currently have one property that can be set to turn off this default behavior for all the dependencies specified in an ivy.xml file. Thus, we are left with an all-or-nothing situation. If we want something in-between, we currently have to use our build.xml file and write some custom code. This is painful because the metadata is not readily available.
I would like to retain the use of the all-or-nothing flag but allow projects to selectively extract items - we have several projects whose build.xml files would be greatly simplified if we could knock the extraction process down to an attribute on the artifact itself.
Thus, my thinking is to use an extra attribute on the artifact tag to "inject" this information and override the ivy.retrieve.pattern to search for this attribute.
Ivy.xml
<ivy-module version="2.0" xmlns:e="http://ant.apache.org/ivy/extra">
<dependencies>
<dependency org="my.org" name="foo" rev="${foo.version}" conf="${conf.archive}->*" transitive="false">
<artifact name="megapin" type="war" e:expand="expand"/>
</dependency>
</dependencies>
</ivy-module>
Build.xml
This is where I think I'm having trouble getting the expand extra attribute to show up.
Question 1: This does add the "extract" attribute to the artifact name at retrieve time. I can use the contains clause to check if that is there in the dep.to Is there a way to retrieve the extra attributes (e.g., ${dep.extra.expand} ?
<property name="ivy.retrieve.pattern" value="${dependency.dir}/[conf]/[artifact]-[rev])(-[expand]).[ext]"/>
</property>
<target name="ivy-post-retrieve-trigger">
<local name="doexpand"/>
<condition property="doexpand">
<contains string="${dep.to}" substring="expand" casesensitive="false"/>
</condition>
<!-- this step works if the flag is set properly, so I'm leaving out these non-relevant steps-->
<...extract if:isset="doexpand"... />
ivysettings.xml
This file basically has the trigger and other resolver settings.
<triggers>
<ant-call target="ivy-post-retrieve-trigger" prefix="dep" event="post-retrieve-artifact"/>
</triggers>
Question 2: Any suggestions on a "noexpand" name? My concern with the <contains> clause is that the "expand" is going to get hit all the time.
I think I am close to getting this working - but the only information I get is: Property "doexpand" has not been set and thus it is skipping the extraction step. Q3 Any tips/advice/examples on how to use the extra attribute on a trigger with Ant/Ivy?
I ended up adding some additional debugging statements to Ivy (as compiled from source). In the ant-ivy/src/java/org/apache/ivy/ant/AntCallTrigger.java I added the following line:
Message.verbose("\tp.name=" + p.getName() + " | p.value=" + p.getValue() );
If I modified my dependency in my Ivy.xml file to be:
<dependency org="my.org" name="foo" rev="${foo.version}" conf="${conf.archive}->*" transitive="false">
<artifact name="megapin" type="war" e:expand="true"/>
</dependency>
This showed
[ivy:retrieve] p.name=dep.expand | p.value=true
At which point I could do something like
<isset property="dep.expand"/>
or
<istrue value=${dep.expand}/>
This answers my Q1. Additionally, I don't need to add this to the Ivy retrieve pattern (thus changing the filename after retrieve), can use a "true" or "false" value as desired (Q2), and this general guidance answers Q3.
I have an MVC application with a Dev, Staging, and Production environment. Dev and Staging are essentially the same thing (same VM, IIS, DB etc.); however, Production is hosted on 4 VMs behind a load balancer. Each VM has it's own DB. For example, the instance deployed to VM1 communicates with the PROD1 DB, VM2->PROD2, etc.
For deployment to Dev and Staging, I do a simple File System deployment from VS2013 to the VM using Debug/Release web.config transforms. For Production deployments, a SysAdmin will copy the bits deployed and tested in Staging to each Production VM. This is to ensure that what was tested and verified by QA in Staging is what we promote to Production -- I don't want to do another build between Staging and Production. Because of this, our SysAdmin is responsible for (with DevOps guidance) editing each web.config between Staging and Production. This basically consists of changing connectionString values from "Data Source=STAGINGDB" to "Data Source=PROD1" (and PROD2, PROD3, PROD4).
What I ultimately want is when I publish to Staging, I want to deploy my web.config using standard Release web.config transform; however, alongside this file I want to also create and drop 4 additional files (web.config.PROD1, .PROD2, etc.). This will allow us to create scripts which ignore the existing web.config (with Staging settings) and copy/rename the appropriate .PROD config.
I am able to (sort of) achieve this with MSBuild:
<Project ToolsVersion="12.0" DefaultTargets="Build">
...
<Target Name="Build">
<TransformXml Source="Web.config" Transform="Web.PROD1.config" Destination="Web.config.PROD1" />
<TransformXml Source="Web.config" Transform="Web.PROD2.config" Destination="Web.config.PROD2" />
...
</Target>
</Project>
My main issue with this approach is that I have to create 4 essentially redundant solution configurations to wire up to the Transform. Every setting is the same except the DB connectionString. Seems like there should be a more efficient way.
Can I execute individual transforms without solution configurations by simply calling the appropriate transform via MSBuild, like:
<add name="connectionString" connectionString="PROD1" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
Should I be using another process altogether? I'd rather not use a 3rd party nuget solution if I can stay way from it. Should I be using a .wpp.targets file? XmlPoke?
My desired workflow
Right-click my MVC app and choose "Publish" (File System)
Let the Release transforms do their thing and generate the web.config. I have basic configurations. Debug = Dev, Release = Staging.
Add a custom step that generates 4 additional web.config files
Package everything up, and publish to the Staging server, so I see this on the VM:
Everything I've read leads me to believe that I should be writing custom MSBuild steps, but I don't know what I should be doing (or how). Here's some pseudo-code:
<Project ToolsVersion="12.0" DefaultTargets="Build">
...
<Target Name="Build">
<TransformXml Source="Web.config" Transform="[Do-Basic-Transform-On-Conection-String]" Destination="Web.config.PROD1" />
<TransformXml Source="Web.config" Transform="[Do-Basic-Transform-On-Conection-String]" Destination="Web.config.PROD2" />
<IncludeFilesInPublish>
<FileToInclude>Web.config.PROD1</FileToInclude>
<FileToInclude>Web.config.PROD2</FileToInclude>
</IncludeFilesInPublish>
</Target>
</Project>
Can I [Do-Basic-Transform-On-Connection-String] inline here without a solution configuration? I'll only be changing 2 connectionString values. If I need to create a solution config, that's fine... I just don't think it's totally necessary especially if I can do it inline. Maybe I'm wrong?
How do I accomplish the <IncludeFilesInPublish> bit so that whatever I do get's packaged up during the Publish, so my Staging deployment has my release candidate code and web.configs ready for promotions.
I think your question is twofold: 1) how do I pass environment variables or parameters (i.e. PROD1) into my xdt transformation file so I only have to use one transformation file? and 2) how do I get MSBuild to iterate over a set of known named items to produce outputs distinguished by each item in this set?
For the first part, the only reason why I assert you might be asking this is because you said "I have to create 4 essentially redundant solution configurations to wire up to the Transform", so if your transform took "PROD1" as a parameter you could ideally just use one transform. But I'm not sure that you can do this without creating your own XmlTransform task. The xdt transformation tooling is really limited. But the nice thing about MSBuild is that it's flexible enough that you could theoretically come up with your own transformation task that extends/subclasses or behaves like the one out of the box.
using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.Web.Publishing.Tasks;
namespace Thanks.IllWriteMyOwnTasks
{
public class MyCustomTransformXml : TransformXml // no idea if you can do this
{
public override bool Execute()
{
// do stuff here,
// maybe declare parameters that you can pass down to base.Execute()
return true;
}
}
}
..
<!--<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.Tasks.dll" />-->
<UsingTask TaskName="MyCustomTransformXml" AssemblyFile="Thanks.IllWriteMyOwnTasks.dll" />
For the second part, I think you can use ItemGroup.
<ItemGroup>
<MyEnvironments Include="PROD1" />
<MyEnvironments Include="PROD2" />
<MyEnvironments Include="PROD3" />
<MyEnvironments Include="PROD4" />
</ItemGroup>
<Target Name="BeforeBuild">
<TransformXml Source="Web.config"
Transform="Web.%(MyEnvironments.Identity).config"
Destination="Web.config.%(MyEnvironments.Identity)" />
</Target>
I haven't tested this, but I think based on what I see over here it will automatically repeat the same task as it iterates over MyEnvironments in this example.
You can add the extra transform files to your solution without adding a new solution configuration, and run the transform as in your own example (except for the target. 'Build' didn't work for me):
<Project ToolsVersion="12.0" DefaultTargets="Build">
...
<Target Name="BeforeBuild">
<TransformXml Source="Web.config" Transform="Web.PROD1.config" Destination="Web.config.PROD1" />
<TransformXml Source="Web.config" Transform="Web.PROD2.config" Destination="Web.config.PROD2" />
...
</Target>
</Project>
If you are only changing a connectionstring, your transform file will be pretty minimal:
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=PROD1SQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
</configuration>
After adding the above, and compiling, you will need to add the newly generated Web.config.PRODX files to your solution. After adding them, you simply open properties for each file and ensure that their compile action is set to 'Content'. This will mean that they are included in your deployments.
As the web.PRODX.config transform files are not part of a solution configuration, you could stick them in a folder to reduce clutter.
.
Hello, everyone
I'm studying IzPack as a tool to be used in a future project and I'm really enjoying it. It's as flexible as I need and makes the process much more easy. I have even submmited a silly pull request at github with a modification I needed to my purposes. Who knows?
Although I don't find it particularly complicated, I've been stuck trying to use a resource for some days. I need that certain Ant Tasks to be executed in certain points of the installation process (right before everything is unpacked is the really one that matters) and that is not working, besides all the efford. :(
My current state, that seems right looking at examples, is the following:
[ My current use of this is based on an example I found here (the docs don't clear too much when It cames to these kind of Actions.]
In my definitions xml file, I included some things:
First, the AntActionsSpect.xml and the .jars, followed by the listeners:
<resources>
...
<res id="AntActionsSpec.xml" src="specs/AntActionsSpec.xml" />
...
</resources>
<jar src="libs/ant/ant.jar" stage="both" />
<jar src="libs/ant/ant-launcher.jar" stage="both" />
<listeners>
<listener classname="AntActionInstallerListener" stage="install" />
<listener classname="AntActionUninstallerListener" stage="uninstall" />
</listeners>
<pack name="test_app" required="yes" installGroups="Application Core">
...
In the specs/AntActionsSpec.xml file, I have the following:
<pack name="test_app">
<antcall order="beforepacks" quiet="no" verbose="yes" buildfile="$INSTALL_PATH/ant-tasks.xml">
<property name="INSTALL_PATH" value="$INSTALL_PATH" />
<target name="touch_beforepacks" />
</antcall>
</pack>
And the ant-tasks.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<target name="touch_beforepacks">
<touch file="$INSTALL_PATH/beforepacks.txt"/>
</target>
</project>
Nothing special here, just creating a dumb file.
The ant-tasks.xml is unpacked right before anyone else. Everything builds with no error, even if I create one "mistake" at AntActionsSpec or ant-tasks.xml, what suggests me that they aren't even been loaded, though if I mess with the path where the definitions file has them, the build will fail.
I would like some help addressing that. I'm probably making some stupid little error and just can't see it by myself. If any of you could provide an example of a running build, that would be sweet.
If I can give any more information, please, let me known so I can update the question.
Thank you very much.
Just found it using a forum on a Google Groups discussion: [izpack-user] Quick question on variable substitution.
Unfortunattly the I will conclude that the docs are misleading. The docs in
"AntActionInstallerListener and AntActionUninstallerListener" until this date are stating that I should use this listener configuration:
<listeners>
<listener classname="AntActionInstallerListener" stage="install" />
<listener classname="AntActionUninstallerListener" stage="uninstall" />
</listeners>
That is what is up there, in the question. Comparing my XML code with the one in the Google Groups discussion, I found a different use of it:
<listeners>
<listener installer="AntActionInstallerListener"
uninstaller="AntActionUninstallerListener" />
</listeners>
In fact, that is the instruction given in the other wiki: Ant Actions (InstallerListener and UninstallerListener), what points out that I something can be wrong under the hood, but that is a story to another episode.
That just works. The Ant tasks are executed properly. :)
I just could not find where freaking Codehaus will allow me to grab a login and edit the docs wiki. >:( . If someone could endorse-me with some testing and then adjust the wiki for future happiness or just give a link to this tired programmer, I'd be happy.
I have a set of build files, some of them calling others -- importing them first. End of line builds may have or may not have a specific target (e.g. "copyother"). I want to call it from my main build file if that target is defined within the end-of-line build script. How can I do it?
Part of the calling script:
<!-- Import project-specific libraries and classpath -->
<property name="build.dir" value="${projectDir}/build"/>
<import file="${build.dir}/build_libs.xml"/>
...
<!-- "copyother" is a foreign target, imported in build_libs.xml per project -->
<target name="pre-package" depends=" clean,
init,
compile-src,
copy-src-resources,
copy-app-resources,
copyother,
compile-tests,
run-junit-tests"/>
I do not want every project to define "copyother" target. How can I do a conditional ant call?
I'm guessing you aren't importing the "other" build scripts into your main build.xml. (Because that wouldn't work. Ant treats imports as local.)
At the same time, you are using depends and not ant/ant call so maybe you are importing them, but one at a time.
You can't do what you want in native Ant. As you noted testing for a file is easy but a target is not. Especially if that other project isn't loaded yet. You definitely have to write a custom Ant task to accomplish what you want. Two avenues:
1) Call project.getTargets() and see if your target is there. This involves refactoring your script to use ant/antcall instead of pure depends, but doesn't feel like a hack. Writing a custom Java condition isn't hard and there is an example in the Ant manual.
2) Add a target to the current project if not already there. The new target would be a no-op. [not sure if this approach works]
For the same of completeness. Another approach is to have some target for checking the target.
The approach is discussed here: http://ant.1045680.n5.nabble.com/Checking-if-a-Target-Exists-td4960861.html (vimil's post). Check is done using scriptdef. So it is not that different from other answer(Jeanne Boyarsky), but script is easy to add.
<scriptdef name="hastarget" language="javascript">
<attribute name="targetname"/>
<attribute name="property"/>
<![CDATA[
var targetname = attributes.get("property");
if(project.getTargets().containsKey(targetname)) {
project.setProperty(attributes.get("property"), "true");
}
]]>
</scriptdef>
<target name="check-and-call-exports">
<hastarget targetname="exports" property="is-export-defined"/>
<if>
<isset property="is-export-defined"/>
<then>
<antcall target="exports" if="is-export-defined"/>
</then>
</if>
</target>
<target name="target-that-may-run-exports-if-available" depends="check-and-call-exports">
You should explore use of the typefound condition, added to ANT in 1.7. You can use it, for example, with the if task from antcontrib like this, but you have to check for a macrodef and not a taskdef due to how it works:
<if>
<typefound name="some-macrodef"/>
<then>
<some-macrodef/>
</then>
</if>
With this, ant files that have a macrodef named "some-macro-or-taskdef" will get it invoked and other ant files without it will not get an error.