How to stop MSBuild _WPPCopyWebApplication target cleaning App_Data folder - deployment

I'm using the _WPPCopyWebApplication MSBuild target in a CruiseControl.net build-and-deploy script, but it appears that this target cleans files not part of the project before the deployment - specifically, App_Data files (which for this app, include uploaded images, etc).
From Microsoft.Web.Publishing.targets;
<OnBefore_WPPCopyWebApplication>
$(OnBefore_WPPCopyWebApplication);
CleanWebProjectOutputDir;
PipelineTransformPhase;
</OnBefore_WPPCopyWebApplication>
How can I stop it doing the CleanWebProjectOutputDir, given this target;
<Target Name="Deploy" DependsOnTargets="Tests">
<MSBuild Projects="$(TargetPath)Website.csproj" Properties="Configuration=Debug;WebProjectOutputDir=\\servername\share;Outdir=$(ProjectDir)bin\;" Targets="ResolveReferences;_WPPCopyWebApplication" />
</Target>
This is from a VS2010 solution, albeit built under CC.Net; I'm aware of MSDeploy, but haven't got my head around that fully yet, so would prefer to stick with MSBuild/_WPPCopyWebApplication for now.
EDIT:
I've further narrowed this to this part of the target;
<!-- In the case of the incremental Packaging/Publish, we need to find out the extra file and delee them-->
<ItemGroup>
<_AllExtraFilesUnderProjectOuputFolder Include="$(WebProjectOutputDir)\**" />
<_AllExtraFilesUnderProjectOuputFolder Remove="#(FilesForPackagingFromProject->'$(WebProjectOutputDir)\%(DestinationRelativePath)')" />
</ItemGroup>
<!--Remove all extra files in the temp folder that's not in the #(FilesForPackagingFromProject-->
<Delete Files="#(_AllExtraFilesUnderProjectOuputFolder)" />
So I guess the question becomes, how can I supress this specific Delete task, or at least add App_Data** to the _AllExtraFilesUnderProjectOuputFolder exclusions?

Add CleanWebProjectOutputDir=False to your properties:
<Target Name="Deploy" DependsOnTargets="Tests">
<MSBuild Projects="$(TargetPath)Website.csproj" Properties="Configuration=Debug;CleanWebProjectOutputDir=False;WebProjectOutputDir=\\servername\share;Outdir=$(ProjectDir)bin\;" Targets="ResolveReferences;_WPPCopyWebApplication" />
</Target>

Related

Phing update version number in XML manifest

I need to add the ability to a phing build to:
Parse an existing xml file within the project area to get an existing build number (in format 1.2.3)
Ask the user what type of 'change' this is (i.e. major, minor, fix)
Based on the response of the user at the time of run, upgrade the respective digit from the build number (if major increase 1 by 1; if minor increase 2 by 1; if fix increase 3 by 1)
Store the build number back into the original xml file
Have the new build number available for use when naming a zip file (later in the build).
Wondering if anyone already has a phing build file that does something like this or if you happen to know what phing tasks might help with these steps?
As a starting point you could do it without overhead using the version task (it uses a property file to store the version information) or with some more effort from a xml file.
The following example build script (documentation links can be found in the description attributes) contains both ways.
<?xml version="1.0" encoding="UTF-8" ?>
<project name="version test"
default="help"
phingVersion="3.0"
description="https://stackoverflow.com/questions/68584221/phing-update-version-number-in-xml-manifest"
>
<target name="help" description="usage help">
<echo>Usage:</echo>
<echo>bin/phing xml-file-based-workflow</echo>
<echo>bin/phing property-file-based-workflow</echo>
</target>
<target name="xml-file-based-workflow"
description="version handling with xml file"
depends="user-input,handle-xml-version,use-version"
/>
<target name="property-file-based-workflow"
description="version handling with property file"
depends="user-input,handle-property-version,use-version"
/>
<target name="user-input"
description="https://www.phing.info/guide/hlhtml/#InputTask"
hidden="true"
>
<input message="what is your release type?" propertyName="release.type" defaultValue="Bugfix"/>
</target>
<target name="handle-property-version"
description="https://www.phing.info/guide/hlhtml/#VersionTask"
hidden="true"
>
<version releasetype="${release.type}" file="VERSION.txt" property="version.number"/>
</target>
<target name="handle-xml-version"
description="
https://www.phing.info/guide/hlhtml/#XmlPropertyTask
https://www.phing.info/guide/hlhtml/#EchoPropertiesTask
https://www.phing.info/guide/hlhtml/#VersionTask
https://www.phing.info/guide/hlhtml/#DeleteTask
https://www.phing.info/guide/hlhtml/#EchoXMLTask
"
hidden="true"
>
<xmlproperty file="VERSION.xml" />
<echoproperties destfile="VERSION.txt" regex="/version\.number/"/>
<version releasetype="${release.type}" file="VERSION.txt" property="version.number"/>
<delete file="VERSION.txt"/>
<echoxml file="VERSION.xml">
<version>
<number>${version.number}</number>
</version>
</echoxml>
</target>
<target name="use-version"
description="https://www.phing.info/guide/hlhtml/#EchoTask"
hidden="true"
>
<echo message="${version.number}" />
</target>
</project>

Get the location of NuGet packages

In my company we have some home made tools that are used in the build process when building other projects.
I need to use these tools in VS2017 BeforeBuild and AfterBuild scripts and it must work in MS Build as well.
The tools are distributed as NuGet packages and most of our projects are ported to PackageReference instead of Packages.config
I know that the current installation of MyTool (version X.Y.Z) is at C:\Users\Me\.nuget\packages\MyTool\X.Y.Z, but how do I reference it in my project file, so it also works when the next version is released?
I think C:\Users\Me\.nuget\packages can be replaced with $(NuGetPackageRoot), but what to do to always reference the version installed in the project?
Some Nuget packages seem to put contributions into MyProject.csproj.nuget.g.props and MyProject.csproj.nuget.g.targets in the obj folder, but I can find very little useful information about these files.
Inside a target, you can use this to create a property based on an item:
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
</ItemGroup>
<Target Name="PrintStuff" AfterTargets="AfterBuild">
<PropertyGroup>
<NewtonsoftJsonVersion Condition="'%(PackageReference.Identity)' == 'Newtonsoft.Json'">%(PackageReference.Version)</NewtonsoftJsonVersion>
<NewtonsoftJsonPath>$(NuGetPackageRoot)newtonsoft.json\$(NewtonsoftJsonVersion)\</NewtonsoftJsonPath>
</PropertyGroup>
<Message Importance="high" Text="JSON.NET version: $(NewtonsoftJsonVersion)" />
<Message Importance="high" Text="JSON.NET path: $(NewtonsoftJsonPath)" />
<Exec Command="ls" WorkingDirectory="$(NewtonsoftJsonPath)" Condition="'$(OS)' != 'Windows_NT'" />
<Exec Command="dir" WorkingDirectory="$(NewtonsoftJsonPath)" Condition="'$(OS)' == 'Windows_NT'" />
</Target>

CruiseControl.net, send dynamic values to some files

I have been searching for a few days, I have also asked a question on the cc.net forum, but still don't have the answer.
My task is to fill Web.config with specific values during the building using cc.net. Here is the example:
I'm developing an ASP.NET website, I have a Web.config with some configuration, e.g. connection string:
<add name="ContextName" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=DatabaseName;User Id = UserName;Password=UserPassword;" providerName="System.Data.SqlClient" />
After the building I want to replace some values and make the config look like this:
<add name="ContextName" connectionString="Data Source=%SERVER%;Initial Catalog=%DATABASE%;User Id = %USER%;Password=%PASSWORD%;" providerName="System.Data.SqlClient" />
I tried this solution, but it didn't help me (or maybe I didn't understand how to use it properly).
Please help me to solve the task.
Thanks!
You can try to use this Config Transformation Tool which is XDT transformation command tool based on XDT (web.config) transform engine, which allows you to run XDT transformation on any XML files. You can use ccnet's task block to run it after your msbuild
<tasks>
<exec>
</exec>
</tasks>
More on ccnet executable task see here.
For more information on XDT transformation see this link in MSDN library
You can create a target on your build file to update the web.config and call that target after the build. I use something similar in my build files, here is an example:
<target name="update-config" >
<property name="export.config" value="" unless="${property::exists('export.config')}" />
<call target="${config-settings}" /> <!-- test or stage -->
<xmlpoke file="${export.config}" xpath="/configuration/appSettings/add[#key='ContextName']/#connectionString" value="${configValue.connectionString}" failonerror="true" />
</target>
<target name="test">
<property name="configValue.connectionString" value="test connection string here" />
</target>
<target name="stage">
<property name="configValue.connectionString" value="stage connection string here" />
</target>
After executing the target that compile your code and export you can run the target update-config, in this case I'm expecting a variable export.config with the path of the exported web.config then calling another target that sets the the value of the connectionstring variable (this can be target test or stage) and finally xmlpoke the web.config with the value.
Hope this helps!

TeamCity MSBuild, remap folders during deployment

We have a solution with a website project which is hosted on a load balanced environment. At the moment no CI is being used, and deployments are manual using zip-files >_< however I'm looking on setting it up, and have run into some difficulties.
The solution requires a App_Config folder containing all the configurations for the site in the root, however these configurations differ from each of the hostingserver, where one is the management server and another is the delivery server.
Each individual server configurations is stored in a separate folder at /Configs/servername/ containing a web.config file and the App_Config folder. These have been manually copied from this folder to the root to overwrite those that already existed.
Also deployment of the /Configs/ folder is not wanted.
Preferably no changes should have to be done to the Visual Studio solution.
Is it possible to automate this before deployment in TeamCity?
regards
You may want to set properties with different values based on the computer name.
That's one trick of the trade.
<Choose>
<When Condition=" '$(Computername)'=='MyManagementServer01' ">
<PropertyGroup>
<MyCustomProperty001>Red</MyCustomProperty001>
<MyCustomProperty002>Yellow</MyCustomProperty002>
</PropertyGroup>
</When>
<When Condition=" '$(Computername)'=='MyDeliveryServer01' ">
<PropertyGroup>
<MyCustomProperty001>Black</MyCustomProperty001>
<MyCustomProperty002>White</MyCustomProperty002>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<MyCustomProperty001>NoMatchMyCustomProperty001</MyCustomProperty001>
<MyCustomProperty002>NoMatchMyCustomProperty002</MyCustomProperty002>
</PropertyGroup>
</Otherwise>
</Choose>
You could setup a property called
<ConfigurationSourceFolder>/Configs/MyManagementServer01/</ConfigurationSourceFolder>
Or setup a "DeploymentType"
<DeploymentType>ManagementServerType</DeploymentType>
You can also put Conditions on "Targets" and even Tasks.
<MakeDir Directories="C:\MyCoolDirectory" Condition="('$(MyCustomProperty001)'!='')"/>
//////Preferably no changes should have to be done to the Visual Studio solution.//////
So here is an "in-general" tip.
Instead of putting alot of custom sometimes-hard-to-follow changes in the csproj files....use a basic .msbuild file.
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="AllTargetsWrapped">
<PropertyGroup>
<!-- Always declare some kind of "base directory" and then work off of that in the majority of cases -->
<WorkingCheckout>.</WorkingCheckout>
</PropertyGroup>
<Target Name="AllTargetsWrapped">
<CallTarget Targets="BuildItUp" />
</Target>
<Target Name="BuildItUp" >
<MSBuild Projects="$(WorkingCheckout)\MySolution.sln" Targets="Build" Properties="Configuration=$(Configuration)">
<Output TaskParameter="TargetOutputs" ItemName="TargetOutputsItemName"/>
</MSBuild>
<Message Text="BuildItUp completed" />
</Target>
</Project>

NAnt ignoring property in included build file

I'm trying to make my project build file include a local build file, to allow for some customization for each developer, without having to keep exclulding the build file from version control commits etc.
But NAnt keeps ignoring the properties in my included build file, and not overwriting the properties set in the global build file.
For demo purposes this short build file behaves the same:
<project name="FooProject" default="showme" basedir="." >
<description>Foo</description>
<!-- Overwrite this property in local.build -->
<property name="database.connectionstring" overwrite="true" readonly="false" value="foo" />
<include buildfile="local.build" failonerror="true" verbose="true" />
<target name="showme" description="Show connectionstring variable">
<echo message="Connectionstring: ${database.connectionstring}" />
</target>
</project>
-and my local.build file looks like this:
<property name="database.connectionstring" value="bar" />
The expected output when running NAnt with this build file is "Connectionstring: bar", but the resulit is "Connectionstring: foo", no matter which combination of readonly and overwrite I try.
It does fail if I rename the file to something else, so NAnt is aware of the included file.
NAnt is v0.91 alpha.
Am I overlooking something or is NAnt not supposed to work like I expect?
It seems you should still wrap the contents of the included build file inside a project-element. Like so:
<project>
<property name="database.connectionstring" value="bar" />
</project>
When I did that the connectionstring was "bar".
Granted: I use Nant 0.91 final.