I am adding a publish-release target to my Ant build file. I would like to be able to run a build, and then optionally run the publish-release target to upload the files to my artifact server. So I tried the following:
<target name="publish-release">
<ivy:resolve conf="*" />
<ivy:publish resolver="releases">
<ivy:artifacts pattern="${out.dir}/[artifact]-[revision](-[classifier]).[ext]" />
</ivy:publish>
</target>
When I run this target the artifacts are uploaded properly, but the status in my Ivy descriptor file is integration. How can I change it to be release?
<!-- I would like the status here to be "release" -->
<info ... status="integration" publication="20141015084720"/>
I tried setting the ivy.status property to release but it didn't change anything.
My build was generating the Ivy descriptor with the integration status, and the publish step was just uploading that descriptor verbatim.
I added a deliver step to my publish-release task to regenerate the descriptor with the desired status:
<target name="publish-release">
<ivy:resolve conf="*" />
<ivy:deliver status="release" deliverpattern="${out.dir}/ivy-${project.version}.xml" />
<ivy:publish resolver="releases">
<ivy:artifacts pattern="${out.dir}/[artifact]-[revision](-[classifier]).[ext]" />
</ivy:publish>
</target>
Related
I've read all the tutorials and examples, and still cannot publish a set of custom jars in my local Ivy repository.
Edit: Basically I want the same behavior as maven-install-plugin.
Here's my setup. I have an Ant task which produces the jars in a given folder. The folder name is not fixed but rather passed as a property in file. I want to get all the jars in this folder and install them in my local Ivy repo so that I can use them on a next step.
Here is my Ant from where I call the ivy:publish:
<project name="Install Ivy Dependencies" xmlns:ivy="antlib:org.apache.ivy.ant" basedir="." default="publish">
<loadproperties srcFile="path_to_folder.properties"/>
<property name="file_pattern" value="${path_to_folder}/[artifact].[ext]" />
<property name="pub_revision" value="1.0.0" />
<target name="resolve">
<ivy:configure file="ivysettings.xml" />
<ivy:resolve file="ivy.xml" />
</target>
<target name="retrieve-all" depends="resolve">
<ivy:retrieve pattern="${file_pattern}" conf="*" />
</target>
<target name="publish" depends="retrieve-all">
<ivy:publish resolver="local" organisation="myOrg" update="true" overwrite="true" pubrevision="${pub_revision}">
<artifacts pattern="${file_pattern}"/>
</ivy:publish>
</target>
</project>
Here's my ivysettings.xml:
<ivysettings>
<resolvers>
<filesystem name="local" local="true"/>
</resolvers>
</ivysettings>
And the ivy.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="myOrg" module="myModule" revision="1.0.0"/>
<publications>
<artifact name="my-custom-jar" ext="jar" type="jar"/>
<artifact name="my-custom-jar-source" ext="jar" type="source"/>
</publications>
</ivy-module>
The error that I am getting when I call the ant task is:
impossible to publish artifacts for myOrg#myModule;1.0.0: java.lang.IllegalStateException: impossible to publish myOrg#myModule;1.0.0!my-custom-jar.jar using local: no artifact pattern defined
I've managed to run my scenario and to resolve my issues using this tutorial There were two major issues in my code/integration.
First one is that you cannot tell Ivy to publish the artifacts in its repository without providing a path to it. I did this with the filesystem resolver:
<filesystem name="local" local="true" transactional="local">
<ivy pattern="${ivy.default.ivy.user.dir}/local/[module]/ivy-[revision].xml" />
<artifact pattern="${ivy.default.ivy.user.dir}/local/[module]/[artifact]-[revision].[ext]" />
</filesystem>
The stupid think about it is this should be build in. If you copy it as is, then everything works. If the config is different, or pointing to a different location - nothing works and you are not told why. I read tons of docs about Apache Ivy and it was nowhere mentioned that these patterns should point to the local Ivy repository. I thought these were the paths from where the jars should be taken. I actually complained about this, but the Ivy documentation is very confusing. Also I think the examples there are wrong. Who would like to publish the artifacts in their ivy.settings.dir. In my case this directory was in my repository!
There was a second issue. It is a smaller one and again very hard to see and fix. There's something wrong the revision param and again the documentation is messed up. If you specify one and the same string for the revision and pub revision the artifacts aren't publish without any explanation why. I fixed it by removing the revision from ivy.xml file.
Last, but not least, I didn't manage to run successfully the "thing" as Ant task, but with java -jar $IVY_JAR ... Maybe the issue was because of the versions, but I was too tired to try it with the fix.
P.S.#cantSleepNow thanks for the help.
You need to add artifact pattern to resolver in ivysettings.xml, something like (example from ivy documentation):
<ivysettings>
<resolvers>
<filesystem name="local" local="true">
<ivy pattern="${ivy.settings.dir}/1/[organisation]/[module]/ivys/ivy-[revision].xml"/>
<artifact pattern="${ivy.settings.dir}/1/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
</filesystem>
</resolvers>
</ivysettings>
I am running build with next targets:
<Target Name="BeforeCompile">
<Message Text="Build no: $(BuildNumber)" />
</Target>
Then in between I run build (using nmake). After that I want to deploy firmware:
<Target Name="AfterCompile">
<MSBuild Projects="$(MSBuildProjectFile)" Targets="CustomDeployMagicFirmware" Properties="Id=1" />
</Target>
<Target Name="CustomDeployMagicFirmware">
<Message Text="...Deploying bootloader files to build machine - folder: $(BuildNumber)" />
<Exec Command='xcopy "$(SolutionRoot)\Repository\bootloader\*.axf" \\machine\bootloader\$(BuildNumber) /y /q'/>
<Exec Command='xcopy "$(SolutionRoot)\Repository\bootloader\*.hex" \\machine\bootloader\$(BuildNumber) /y /q'/ -->
</Target>
The problem is that in target "BeforeCompile" I get properly message output for $(BuildNumber). But later I have Message Test output like:
...Deploying bootloader files to build machine - folder:
There looks like variable $(BuildNumber) is not set anymore. Also command xcopy copies files to folder bootloader and not to folder bootloader\$(BuildNumber).
What do I do wrong? Which things can influence variable contents?
The error is in this line
<MSBuild Projects="$(MSBuildProjectFile)" Targets="CustomDeployMagicFirmware" Properties="Id=1" />
The MSBuild task spawns a new MSBuild.exe process and you are not passing the property $(BuildNumber) to the new process. Change it like below and this would work
<MSBuild Projects="$(MSBuildProjectFile)" Targets="CustomDeployMagicFirmware" Properties="Id=1;BuildNumber=$(BuildNumber)" />
Use <CallTarget> instead of <MSBuild> to invoke your CustomDeployMagicFirmware target.
I am trying to invoke MSbuild for a couple of projects twice. First time without any clean, but if this fails I will invoke a clean followed by a new build. (The reasoning is that I want my build to be fast but if that fails fall back to clean, restore nuget packages build etcetera). This works but the build will still fail if the first call failed (it has continueonerror set to true so I dont want it to fail...). Here are the relevant parts of the build file:
<ItemGroup>
<ProjectsToPublish Include="X.sln" />
</ItemGroup>
<Target Name="RestoreAllPackages">
<Message Text="#(ProjectsToPublish)" />
<Exec Command='"$(MSBuildProjectDirectory)\.nuget\nuget.exe" restore "$(MSBuildProjectDirectory)\%(ProjectsToPublish.Identity)"'
/>
</Target>
<Target Name="Build" >
<MSBuild Projects="#(ProjectsToPublish)" Properties="SkipRestore=True;RunCodeAnalysis=False;Retries=10;RetryDelayMilliseconds=50"
BuildInParallel="true" ContinueOnError="WarnAndContinue" />
<!-- MSBuildLastTaskResult outcome of previous task-->
<PropertyGroup>
<FastBuildFailed>false</FastBuildFailed>
<FastBuildFailed Condition="'$(MSBuildLastTaskResult)' == 'false'" >true</FastBuildFailed>
</PropertyGroup>
<Message Importance="high" Text="Initial build failed? $(FastBuildFailed)" />
<Message Importance="high" Text="Initial build failed will retry" Condition="'$(FastBuildFailed)'" />
<CallTarget Targets="FullBuild" Condition="'$(FastBuildFailed)'" />
</Target>
<Target Name="FullBuild" DependsOnTargets="RestoreAllPackages">
<!--Fake property below to reexecute build exact same properties prevents the build lform re-->
<MSBuild Projects="#(ProjectsToPublish)" Properties="SkipRestore=True;RunCodeAnalysis=False;FakeProperty=one" BuildInParallel="true" />
</Target>
<Target Name="RestoreAllPackages">
<Message Text="#(ProjectsToPublish)" />
<Exec Command='"$(MSBuildProjectDirectory)\.nuget\nuget.exe" restore "$(MSBuildProjectDirectory)\%(ProjectsToPublish.Identity)"'
/>
</Target>
For anyone with this rather exotic error. It seems that when a build is run inside of a TFS build server, the build server parses log output and will fail a build even with a ContinueOnError setting. My workaround ended up being <Exec Command="$(MSBuildBinPath)\msbuild.exe #(ProjectsToPublish) /noconlog " ContinueOnError="true" />
Basically spawning a new MSBuild using Exec and making sure that it did not output anything using /noconlog
Rather than using <OnError..., you can assign ContinueOnError the value 'WarnAndContinue', and then use a condition to check the $(MSBuildLastTaskResult) property.
Generic example:
<Error ContinueOnError="WarnAndContinue" />
<Message Importance="High" Text ="$(MSBuildLastTaskResult)" />
<!-- (Returns false) -->
(I believe both "WarnAndContinue" and $(MSBuildLastTaskResult) were introduced in MSBuild 4.0; they should be available on your TFS 2012 build server.)
I have just started getting Jenkins setup with Phing as the build tool. Although I have used Jenkins before, I'm new to Phing.
I have a project setup in Jenkins that has a Mercurial Repository setup and a Phing Build step.
The build.xml file simply archives the existing file, deletes them and copies the new files from the repository.
I have run phing from the terminal and everything works as planned. However, when running from within Jenkins, I'm getting the following in the Console Output:
[workspace] $ /usr/local/pear/bin/phing -buildfile /Users/Shared/Jenkins/Home/jobs/Project/workspace/build.xml "-Dwebroot=/Volumes/Websites/Project/ -Dcheckoutroot=/Users/Shared/Jenkins/Home/jobs/Project/workspace -Drevision=5" -logger phing.listener.DefaultLogger
/usr/local/pear/bin/phing: fork: Resource temporarily unavailable
Build step 'Invoke Phing targets' marked build as failure
My first thought was that it was permission related, but I've changed Jenkins to run as the same user that I ran Phing manually as and it still got the same issue.
Does anybody have any thoughts as to what might be causing the problem?
I can't find anything related to this error anywhere that isn't related to Cygwin...
The system is running on OS X 10.7.5 with Jenkins 1.518 and Phing 2.5.1
The build.xml file looks like:
<?xml version="1.0" encoding="UTF-8"?>
<project name="Project" default="dist">
<property name="revision" value="old" />
<property name="webroot" value="/Volumes/Websites/${phing.project.name}" />
<property name="checkoutroot" value="./" />
<target name="clean">
<echo msg="Backing up old site to ${phing.project.name}-${revision}..." />
<tar destfile="${webroot}/../${phing.project.name}-${revision}.tar.gz" basedir="${webroot}" compression="gzip" />
<echo msg="Deleting site from ${webroot}..." />
<delete>
<fileset dir="${webroot}" />
</delete>
</target>
<target name="dist" depends="clean">
<echo msg="Copying files to website at ${webroot}..." />
<copy todir="${webroot}">
<fileset dir="${checkoutroot}/Website">
<exclude name="**/.hg/**" />
</fileset>
</copy>
</target>
</project>
I've managed to resolve this issue by removing all of the path details in the Phing configuration section within Jenkins.
This makes absolutely no sense to me as to why it's working without these details as I definitely only have one Phing install, so it's not as if it was picking up the wrong one or something.
However, by not specifying anything in the Phing section of the Jenkins project config so it picks up the default path, default build target etc. and this is working flawlessly now!
I am using Ivy to publish a snapshot of a built Jar to a locally hosted Nexus repository using the following Ant target.
<target name="publish">
<ivy:publish resolver="nexus_snapshot" pubrevision="SNAPSHOT" overwrite="true">
<artifacts pattern="${dist.dir}/[artifact].[ext]" />
</ivy:publish>
</target>
This appears to work fine, resulting in the Jar and its associated ivy.xml being present in the repository (with filenames mymodule-SNAPSHOT.jar and ivy-SNAPSHOT.jar).
Later, in another build script, I wish to retrieve the Jar and its associated dependencies (i.e. as specified in its ivy.xml) into a directory.
This is the Ant target I'm using.
<target name="deploy">
<delete dir="deploy" />
<mkdir dir="deploy" />
<ivy:settings file="${ivy.dir}/ivy_deploy_settings.xml" />
<ivy:retrieve organisation="myorg" module="mymodule"
inline="true" revision="SNAPSHOT" pattern="deploy/[artifact].[ext]"/>
</target>
This retrieves the Jar to the directory, but not its dependencies. Also, if I add
conf="impl"
to the retrieve, it fails as the configuration is not found.
As such, it seems that the retrieve is simply not referencing the ivy.xml and hence not resolving the dependencies.
Should this work or am I misunderstanding something?
I have now resolved this problem. I believe the issue is simply that Nexus works using POM files rather than Ivy files (by default at least - I can't see any relevant configuration options).
The solution is therefore to generate a suitable POM and publish this along with the Jar.
<target name="publish">
<property name="generated.ivy.file" value="${dist.dir}/ivy.xml" />
<ivy:deliver deliverpattern="${generated.ivy.file}"
organisation="${ivy.organisation}"
module="${ivy.module}" status="integration"
revision="${ivy.revision}"
pubrevision="SNAPSHOT"
conf="impl" />
<ivy:makepom ivyfile="${generated.ivy.file}"
pomfile="${dist.dir}/${ivy.module}.pom"/>
<ivy:publish resolver="nexus_snapshot" pubrevision="SNAPSHOT"
publishivy="false" status="integration" overwrite="true">
<artifacts pattern="${dist.dir}/[artifact].[ext]" />
<artifact name="${ivy.module}" type="pom" ext="pom"/>
</ivy:publish>
</target>
Note that I first generate an Ivy file for the current module (and my desired configuration) to create the POM from.