Publish on TFS does not find the pubxml file for Node.js test project - node.js

I created a Node.js project for an protractor test environment using the Node.js Tools to test a web application on a team foundation server. The test project and the web application are in one solution file. However, if i want to deploy the Node.js project on the tfs, it is not able to find the pubxml file located in the web application project.
Error log:
12>CoreCompile:
Creating directory "bin".
Copying file from "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Node.js Tools\Microsoft.NodejsTools.WebRole.dll" to "bin\Microsoft.NodejsTools.WebRole.dll".
ValidatePublishProfileSettings:
Validating PublishProfile(TestProfile) settings.
12>C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.targets(4364,5): error : The value for PublishProfile is set to 'TestProfile', expected to find the file at '<PATH>\TestProject.Web.Protractor.Tests\__profiles\TestProfile.pubxml' but it could not be found. [<PATH>\TestProject.Web.Protractor.Tests.njsproj]
12>C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.targets(4371,4): error : PublishProfile(TestProfile) is set. But the $(WebPublishMethod) does not have a valid value. Current Value is "". [<PATH>\TestProject.Web.Protractor.Tests.njsproj]
12>Done Building Project "<PATH>\TestProject.Web.Protractor.Tests.njsproj" (default targets) -- FAILED.

After analyzing the Microsoft.Web.Publishing.targets i found the PublishProfileRootFolder variable to change the search path for the pubxml file.
First i tried to place the variable inside the MSBuild arguments. However, this raised problems with other test projects and i was not able to use variables like the $(SolutionDir).
I ended trying to use the PublishProfileRootFolder variable inside the project file and this works now:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
...
<PublishProfileRootFolder>$(SolutionDir)PathToWebApplication\Properties\PublishProfiles</PublishProfileRootFolder>
</PropertyGroup>
...
PS: Additionally you need a Web.config file, placed in the project root of the test project:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<customErrors mode="on"/>
<compilation debug="true"/>
</system.web>
</configuration>

Related

${currentdir} target is not generating file anymore

I have recently upgraded my asp.net core project to .net core 2.2 and at same time updated NLog.Web.AspNetCore.
After I did this (maybe coincidence?) I noticed that log files are not being generated.
In my config this is my target:
<target xsi:type="File" name="allfile" fileName="${currentdir}/Logs/nlog-all-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />
After some debugging I realised that if I specified the path explicitly then it would generate log file:
<target xsi:type="File" name="allfile" fileName="E:\Project\Logs\nlog-all-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />
I have throwExceptions="true" set in config but when a file is not generated no exception is thrown, it just silently doesn't create the file.
To further debug this I created a console project and added nuget NLog.Web.AspNetCore and copied my config. Now in the console project it works fine and is creating log files in the debug output directory.
Is there any way to debug why the log file isn't being generated with this target in my main project?
Instead of using ${currentdir} then consider using ${aspnet-appbasepath} (Or ${basedir} if not in-process-hosting)
NLog InternalLogger usually gives very good hints when something is not working as expected.
Please avoid using throwExceptions="true" as it is for unit-testing, and not for production environments.

How to share parameters configuration between VS publish profile and MSDeploy SetParameters.xml?

I have a web application in Visual Studio 2012. I publish this website to IIS using publish profiles (.pubxml).
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>MSDeploy</WebPublishMethod>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<ExcludeApp_Data>False</ExcludeApp_Data>
<MSDeployServiceURL>server</MSDeployServiceURL>
<DeployIisAppPath>site</DeployIisAppPath>
<RemoteSitePhysicalPath />
<SkipExtraFilesOnServer>False</SkipExtraFilesOnServer>
<MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
<EnableMSDeployBackup>True</EnableMSDeployBackup>
<UserName>domain\username</UserName>
</PropertyGroup>
<ItemGroup>
<MSDeployParameterValue Include="MyParam">
<ParameterValue>MyValue</ParameterValue>
</MSDeployParameterValue>
...
</ItemGroup>
</Project>
Beside I setup a CI to build a package with msbuild and then use it to publish to the different environnement using msdeploy. Both in 2 separates steps, so I can reuse the same package multiple times.
To do this I need to use a SetParameters.xml with a different syntax than the publish profil used by VS.
<?xml version="1.0" encoding="utf-8"?>
<parameters>
<setParameter name="IIS Web Application Name" value="site" />
<setParameter name="MyParam" value="MyValue" />
...
</parameters>
Is there a way to share the parameters configuration in a single file so I can maintain only one file ?
I see this answers from 2014 but I can't managed to make it works.
I've researched this and can't find a way to override the SetParameters file when publish via VisualStudio. It doesn't look like the MSBuild tasks support this.
The best alternative I can offer is to use the commandline instead of right click publish. You can create the MSDeploy package by calling the Package target:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild /t:Package /p:PublishProfile=<profile-name>
And then deploy using MSDeploy.exe:
"C:\Program Files (x86)\IIS\Microsoft Web Deploy V3\msdeploy.exe" -verb:sync -source:package=WebApplication7.zip -dest:manifest=WebApplication7.DestManifest.xml -setParamFile:SetParameters.custom.xml
The following blog posts has more details:
https://dotnetcatch.com/2016/02/25/the-anatomy-of-a-webdeploy-package/

Include files in MSBuild that are not part of project

I'm trying to create an automated build for my web application project.
We use a standard CMS project and have tweaked some parts of it. Only the tweaked files are part of our project, but I want to include the full CMS in the deployment package.
So I've created a custom .targets file to define a task to include the CMS files during the build:
<Target Name="GetCMSFiles">
<ItemGroup>
<!-- Include the CMS files into the package -->
<_CMSFiles Include="..\packages\CMSFiles\**\*" />
<FilesForPackagingFromProject Include="%(_CMSFiles.Identity)">
<DestinationRelativePath>
%(RecursiveDir)%(Filename)%(Extension)
</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<!-- VS2010 -->
<CopyAllFilesToSingleFolderForPackageDependsOn>
GetCMSFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
<!-- VS2012 -->
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
GetCMSFiles;
$(CopyAllFilesToSingleFolderForMsdeployDependsOn);
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
</PropertyGroup>
This works fine, but the problem is that the files from our project do not get copied to the deployment folder. So in other words, it does not overwrite the files that already exist after I copied them with the GetCMSFiles task.
The way I see it there are two options:
Force the CopyAllFilesToSingleFolder to overwrite any existing files in the deployment folder.
Have a condition in the GetCMSFiles task to only include files that don't already exist in the project.
But I'm not sure whether this is possible and how to achieve this. Any ideas?

MSBuild & SQL Server Database Project: bind the deploy and publish desination to the build configuration

Visual Studio 2012. SQL Server Database Project.
Four build configurations were created in solution: Debug, DevDb, TestDb, LocalDb.
Three publish profiles were created in project: DevDb.publish.xml, TestDb.publish.xml, LocalDb.publish.xml
Pushing F5 button (!) I want to:
deploy project with connection string from project properties if
build configuration is Debug.
publish project with connection string
from the corresponding publish profiles if build configuration is
DevDb, TestDb or LocalDb.
To do this I edit project (.sqlproj) xml, trying to catch a call of the Deploy target and replace the standart Deploy target with a custom behavior:
<Target Name="Deploy">
<!-- The first statment is for Debug configuration -->
<MSBuild Condition=" '$(Configuration)' == 'Debug' "
Targets="Deploy"
Projects="$(MSBuildProjectFile)"
Properties="Configuration=$(Configuration);"
/>
<!-- The second statement is for DevDb, TestDb, LocalDb configurations -->
<MSBuild Condition=" '$(Configuration)' != 'Debug' "
Targets="SqlPublish"
Projects="$(MSBuildProjectFile)"
Properties="SqlPublishProfilePath=$(Configuration).publish.xml;
Configuration=$(Configuration);"
/>
</Target>
The second statement works fine and I get deployment to the right destination.
The problem is with the first statement - it produces a circular dependency.
error MSB4006: There is a circular dependency in the target dependency graph involving target "Deploy".
My question is: how to intersect (catch and replace) the standart target and if it's required to invoke the standart target again?
Or am I trying to reinvent the wheel and there is another way to do what I want?
(What I want is described above under words "Pushing F5 button" :)
I think I've got the solution.
So if we put such a PropertyGroup with Condition and a custom Target to the end of database project xml file:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
----------- Skip -----------
<PropertyGroup Condition=" '$(Configuration)' != 'Debug' and Exists('$(Configuration).publish.xml')">
<DeployDependsOn>
PublishDatabase
</DeployDependsOn>
</PropertyGroup>
<Target Name="PublishDatabase"> <!-- Custom Target -->
<Message
Text="Deploy is replaced with SqlPublish for configuration = $(Configuration)"
Importance="high" />
<MSBuild
Targets="SqlPublish"
Projects="$(MSBuildProjectFile)"
Properties="SqlPublishProfilePath=$(Configuration).publish.xml;
Configuration=$(Configuration);" />
</Target>
</Project>
we will get the following behaviour:
If the solution build configuration is differ from Debug and the publish profile *.publish.xml exists, then the Deploy target and
operation will be replaced with SqlPublish target and this publish
operation will get the required configuration such as connection
string from the corresponding publish profile.
If the solution build configuration is Debug, then we preserve the standart Visual Studio behaviour when it take th connection string from the project properties.

Transform external config in a web role

Can slowcheetah transform an external config file in an azure web role? e.g. I have logging info in log4net.config. But the transformed version does not get created when packaged.
I did not manage to get slowCheetah working in my Azure solution.
One alternative you can use is to create complete config files for each environment - e.g. :
log4net.debug.config
log4net.release.config
and copy the contents of these into the log4net.config at buildtime depending on the build configuration chosen.
This is done by adding a build target to your csproj file like so:
<Target Name="BeforeBuild">
<Delete Files="$(ProjectDir)log4net.config" />
<Copy SourceFiles="$(ProjectDir)log4net.$(Configuration).config"
DestinationFiles="$(ProjectDir)log4net.config" />
</Target>
(you may have to modify the paths in the script depending on where in the solution your config files are)
You can find more information on MSBuild and manipulating your .csproj file here and here

Resources