Pass parameters with msbuild task - jenkins

I am trying to create a build script, to migrate our build process from Cruise Control to jenkins, and I can't see how to get access to all the normal command line parameters when I call the MSBuild task.
For instance I would like to run the equivalent of
msbuild common.sln /p:Platform="$(MsBuildPlatformAnyCpu)" /p:Configuration=$(MsBuildConfiguration) /v:$(MsBuildVerbosity) /p:WarningLevel=$(MsBuildWarningLevel);OutputPath="$(ProjectBinariesFolder)" /fileLogger /flp1:logfile=$(ProjectBuildLogsFolder)\$(ProjectFile)_BuildErrors.txt;errorsonly /flp2:logfile=$(ProjectBuildLogsFolder)\$(ProjectFile)_BuildWarnings.txt;warningsonly /flp3:LogFile=$(ProjectBuildLogsFolder)\$(ProjectFile)_Build.txt;Verbosity=diagnostic
This is my msbuild file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build">
<PropertyGroup>
<JenkinsBuildFolder>C:\Program Files (x86)\Jenkins\jobs\build2\workspace</JenkinsBuildFolder>
<ProjectSourcesFolder>$(JenkinsBuildFolder)\Sources</ProjectSourcesFolder>
<ProjectBinariesFolder>$(JenkinsBuildFolder)\Binaries</ProjectBinariesFolder>
<ProjectBuildLogsFolder>$(JenkinsBuildFolder)\BuildLogs</ProjectBuildLogsFolder>
<ProjectTestLogsFolder>$(JenkinsBuildFolder)\TestLogs</ProjectTestLogsFolder>
<ProjectGuid>{F8A25B4A-589A-4D3D-A568-4700FD776250}</ProjectGuid>
</PropertyGroup>
<ItemGroup>
<ProjectToBuild Include="Common.sln">
<Properties>OutputPath=$(ProjectBinariesFolder);Configuration=Build</Properties>
</ProjectToBuild>
</ItemGroup>
<Target Name="Build">
<MSBuild Projects="#(ProjectToBuild)" />
</Target>
</Project>
However I have no idea how to get the task equivalent properties of the command line switches /v /filelogger etc

You can't.
/p is used to inject properties into the build from the command line. The other command line options like /v are specific to the build process and you cannot move them to the proj file.
Note that there was probably good reason why your Cruise Control setup specified those /p params. I suspect it is because the values for those params are defined in Cruise Control and it is a way to parametrize the build - so one could kick off a build and say $(MsBuildConfiguration) = "Debug". You may want to do the same with Jenkins and not hardcore the values.
As for the /p params, Jenkins allows you pass parameters to msbuild - see Default parameters below.

Related

How can I pass a default value via command line when running ant?

<target name="clone-repo" description="Pull code from SCM repository" depends="resolve">
<taskdef resource="org/eclipse/jgit/ant/ant-tasks.properties" classpathref="build.path"/>
<delete dir="${basedir}/omoc_build"/>
<git-clone uri="https://user:******#github.com/sirect/omoc.git" dest="${basedir}/omoc_build" branch="${branch}" />
<zip destfile="${basedir}/devtoolkit/devtoolkit_docker/config.zip" basedir="${basedir}/omoc_build/config" />
I want to run ant command where by default it should clone from main branch
Few things!
To answer your question, you can set the branch property in a properties file, which would be overwritten if you specify on commandline. Include the property file above your target:
<property file="defaults.properties" description="default configuration."/>
in defaults.properties you'll set branch to main and you could overide it with -Dbranch=non-main-branch
That allows you to set a default.
Now for the advice you didn't ask for:
Don't want ant cloning your source. You should have your build system checkout the source and then ant should build the source. You're creating a chicken and egg problem here... build.xml is in source control, and it's checking out source? That's fishy.

Can't access ArtifactStagingDirectory variable in MSBuild

During my build process I'm trying to copy a folder to the artifacts folder (\myserver\d$\TFBuild-Agent01\66\a).
So I put this in the .csproj file:
<Target Name="BeforeBuild">
<Exec
Command="xcopy.exe Databases "$(Build.ArtifactStagingDirectory)\Databases" /i /e /y /d" />
</Target>
This gets me
Error MSB4184: The expression """.ArtifactStagingDirectory" cannot be evaluated. Method 'System.String.ArtifactStagingDirectory' not found*
Everything I can find online says that $(Build.ArtifactStagingDirectory) is the way to do it. But it doesn't work.
Building with Visual Studio 2015 on TFS 2015
This doesn't work either:
<Exec
Command="xcopy.exe Databases "$($Env:BUILD_ARTIFACTSTAGINGDIRECTORY)\Databases" /i /e /y /d" />
The expression "$Env:BUILD_ARTIFACTSTAGINGDIRECTORY" cannot be evaluated.*
This doesn't error, but it looks like %BUILD_ARTIFACTSTAGINGDIRECTORY% gets replaced as an empty string:
<Exec Command="xcopy.exe Databases "%BUILD_ARTIFACTSTAGINGDIRECTORY%\Databases" /i /e /y /d" />
You have been mixing ways to access the build variables that the agent allows you. The syntax using $(some.variable) is interpreted by the agent itself. MSBuild has a similar looking syntax - $(PropertyName) - which does something different - it gives access to msbuild properties and does not allow for dots (.) in it's name, since you can use the dot to call functions on the value (e.g. $(OutputPath.Substring(3))).
When you want to reference build variables from MSBuild, you need to reference the environment variable that the agent sets. This is possible because MSBuild makes all environment variables accessible as global properties using its property syntax. The environment variable for Build.ArtifactStagingDirectory is BUILD_ARTIFACTSTAGINGDIRECTORY so you can use it in MSBuild using $(BUILD_ARTIFACTSTAGINGDIRECTORY).
I have been using it successfully in this script to default a property when run as part of a TFS/VSTS build (PublishBaseDir is a custom property used later):
<PropertyGroup>
<!-- Default artifact staging directory when built via VSTS / TFS agent -->
<PublishBaseDir Condition="'$(PublishBaseDir)' == '' and '$(BUILD_ARTIFACTSTAGINGDIRECTORY)' != '' ">$(BUILD_ARTIFACTSTAGINGDIRECTORY)</PublishBaseDir>
<!-- If not built on a known agent, use a "publish" subdir next to this file -->
<PublishBaseDir Condition="'$(PublishBaseDir)' == ''">$(MSBuildThisFileDirectory)publish\</PublishBaseDir>
<!-- Normalize directory if set manually or through ENV var -->
<PublishBaseDir Condition="!HasTrailingSlash('$(PublishBaseDir)')">$(PublishBaseDir)\</PublishBaseDir>
</PropertyGroup>
OK, I guess that because I'm using Visual Studio to build my solution, I can't access $(Build.StagingDirectory) from the .csproj. However, it's being passed on the command line to the "Visual Studio Build" build step as a property:
/p:OutDir="$(Build.StagingDirectory)"
So that can be accessed by doing
<Exec Command="xcopy.exe Databases "$(OutDir)\Databases" /i /e /y /d" />

Configure Jenkins to deploy PHP project that passed PHPUNit

I have PHP Project, that is hosted on GitHub.
Now, I'd like to configure Jenkins to run unit tests so that:
Whenever developer push/commits code to specific branch, it triggers corresponding PHPUnit build job.
If commit passes the unit tests, the source code is deployed (assuming I already have the required script to deploy).
The question is how to trigger the deployment script when source code passes the unit test (i.e. PHPUnit tests succeed)?
Please suggest to me the way to do that, which plugin I should try to achieve the result?
Thanks!
This is going to be a long post, as there's a lot involved, but it works a treat:
You will need:
Ant
Git Publisher plugin
Ant and phpunit will need to be on your PATH
Step 1: Configure your project
In your Jenkins, configure your project to 'Poll SCM' under the Git option. Leave the 'Schedule' as blank. Under 'branches to build' set that as the branch you want to build your release package from.
Reference:
Step 2: Run ant for every build
Add a build step to 'Invoke Ant'
If you don't use Ant already, create a build.xml file in your project root, add it to Git and have the following contents:
<?xml version="1.0" encoding="UTF-8"?>
<project default="full-build">
<property name="phpunit" value="phpunit"/>
<target name="full-build"
depends="phpunit-unittests,-check-failure"
description="runs the tests"/>
<target name="phpunit-unittests"
unless="phpunit-unittests.done"
description="Run unit tests with PHPUnit">
<exec executable="cmd" failonerror="true" resultproperty="result.phpunit" taskname="phpunit-unittests">
<arg value="/c"/>
<arg value="${phpunit}"/>
<arg value="--configuration"/>
<arg path="${basedir}/phpunit.xml"/>
<arg value="--testsuite=Unit"/>
</exec>
<property name="phpunit-unittests.done" value="true"/>
</target>
<target name="-check-failure">
<fail message="PHPUnit did not finish successfully">
<condition>
<not>
<equals arg1="${result.phpunit}" arg2="0"/>
</not>
</condition>
</fail>
</target>
</project>
That will run all unit tests whenever the Ant task is invoked, which is now set for every time the project is built.
Then, install the Git Publisher tool. Configure as follows:
This creates a new release tag upon a successful build. You will use this later to publish the release to the final location. Note: There are different variables that Git Publisher provides for use, commit hash, user etc so use what you want. I stick to an incremental tag of v1.1.BUILD as that's a bit more standard.
Lastly, you will need to add a Git hook which will trigger a build upon a commit/push from any location.
Navigate to your repository folder and within that the 'hooks' directory.
Create a new file named 'post-receive' (you will see examples in there; overwrite this one). Place the following content in:
#!/bin/bash
while read oldrev newrev refname
do
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
if [ "master" == "$branch" ]; then
curl http://YOUR_JENKINS_URL:8080/git/notifyCommit?url=YOUR_GIT_REPOSITORY_URL
fi
done
That should do the job nicely. I have left out implementation details of how you actually release your project as everyone does this differently. There are options to FTP files to a location, and all sorts. Personally I go into the folder where the application resides and do a checkout of the newly created tag - a one line command. Whatever suits your environment.
Other stuff I've ommitted but you will find useful - the Ant build task can do literally anything - In mine, I run composer to install dependences, run bower, run grunt, do syntax checking, coding standard checking, fire up selenium and run web tests, and a load of other stuff. It's a perfect combination of tools to automate the whole project deployment.

MSbuild error while chekout : exited with code 9009

I am try to chekout my file from TFS using MSBuild script. But I am getting "exited with code 9009"
My code is bellow :
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<TfCommand>
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\tf.exe"
</TfCommand>
</PropertyGroup>
<Target Name="Build">
<Exec Command="$(TfCommand) checkout "$/ApplicationSharedServices/release/dev_branch/renderer/bin/MIME.dll""/>
</Target>
</Project>
As per Just TFS's answer, you need to be in the folder that is in your workspace before you run TF. it might work fine with VS but with MSBuild pure you need to be in the folder. Now you technically don't need to put the full path when doing the get then. just MIME.dll.
Just out of curiosity, why are you running an MSBuild TF get command? is this in you automated build? You should start using PowerShell and run a pre-build script to get the info you need. You could also use Nuget with package restore to get any DLLs needed for compilation.
Cheers,
ET

How to determine Jenkins build directory from Ant?

I am trying to migrate an Ant script I wrote to build and deploy projects from within the Jenkins framework (instead of triggered from an SVN post-commit hook, which was the expedient way we initially approached things). Everything is great, except I need to stage files for the deploy step and I want to stuff them into the 'build' directory Jenkins creates for the job (and since my build.xml lives in a non-project-specific location, ${basedir} and ${user.dir} do not point to the desired location).
within the Jenkins configuration, I've setup the following:
[Jenkins]
Build Record Root Directory: E:/builds/${ITEM_FULLNAME}
[Job-Specific]
Build File: C:\vc-tools\shadow\build.xml
when running a build, the script is appropriately launched and a job-specific build directory is created, e.g.
E:\builds\Test\2012-08-07_12-51-21
I want to get at this directory from within the build script, but cannot figure out how. some of the things I've tried:
[echo] ${basedir}: C:\vc-tools\shadow
[echo] ${user.dir}: C:\vc-tools
[echo] ${env.workspace}: C:\Program Files (x86)\Jenkins\workspace\Test
[echo] ${env.build_id}: 2012-08-07_12-51-21
[echo] ${jenkins_home}: C:\Program Files (x86)\Jenkins
[echo] ${BuildDir}: E:/builds/${ITEM_FULLNAME}
note: for that last one, I tried passing in:
BuildDir=E:/builds/${ITEM_FULLNAME}
as a property configured from the job within Jenkins (clearly ${} expansion doesn't take place in this context).
according to the documentation, there are no specific environment variables that are set to the full build directory path -- I can fudge it by hardcoding the E:\builds root and tacking on ${env.build_id}, but was hoping there would be an easier way to access the complete path from something Jenkins exposes (either an Ant property and an environment variable) in order to make the script more flexible.
I am using Jenkins version 1.476.
thanks
It's always a good idea for your project to have a copy of it's build logic included alongside the source code. It makes your build more portable across machines.
Having said that it's also quite common to setup build files containing common shared build logic. ANT defines the following tasks to support such activity:
include
import
So a possible solution is to store a simple build.xml file, in the root of your project directory:
<project name="my project" default="build">
<include file="C:\vc-tools\shadow\common-build-1.0.xml" as="common"/>
<target name="build" depends="common.build"/>
</project>
Notes:
It's a good idea to use a revision number in the common build file name. This assists in preserving backward compatibility with other builds using the older logic.
Update
When Jenkins runs a job is sets a number of environment variables.
The following ANT logic will print the location of the Jenkins workspace directory:
<property environment="env"/>
<target name="run">
<echo message="Jenkins workspace: ${env.WORKSPACE}"/>
<echo message="Job directory: ${env.WORKSPACE}../../jobs/${env.JOB_NAME}"/>
<echo message="Build data: ${env.WORKSPACE}../../jobs/${env.JOB_NAME}/build/${env.BUILD_ID}"/>
</target>
These days (Jenkins v. 1.484) 'run' target from answer above should look like this:
<target name="run">
<echo message="Jenkins workspace: ${env.WORKSPACE}"/>
<echo message="Job directory: ${env.WORKSPACE}/../../${env.JOB_NAME}"/>
<echo message="Build data: ${env.WORKSPACE}/../../${env.JOB_NAME}/builds/${env.BUILD_ID}"/>
</target>

Resources