Can't deploy from VS2013 (or TeamCity) after TypeScript 1.6 upgrade - msbuild

Today I updated to TypeScript 1.6, and now the CopyPipelineFiles task is failing when trying to deploy web applications.
I redirect TypeScript's compiled JavaScript output directory to scripts\compiled\ in the Web project's settings (via TypeScriptOutDir entry in the csproj file) and this has always worked fine up until now. Typescript files are being compiled correctly, and to the correct directory (ie scripts\compiled\ under the web project directory).
However, the CopyPipelineFiles task seems to be getting confused about the root directory of TypeScript files, and now always assumes that it is the root directory of the web project. As a result, it's adding folders to the path that don't exist, for example, after compiling scripts\foo.ts, instead of grabbing scripts\compiled\foo.js MSBuild is looking for \scripts\compiled\scripts\foo.js. I have tried using $(ProjectDir) in the output directory, and I've also tried setting the TypeScriptRootDir to the appropriate root directory (e.g. scripts\) but the problem persists.
The only way I've been able to remedy the situation is to remove the output directory and allow the compiled JavaScript files to be output to the same locations at their TypeScript counterparts.
The following is an example of a real error I've received, where the path of the TypeScript file would be scripts\account\app.ts:
Copying file scripts\compiled\scripts\account\app.js to obj\Release\AspnetCompileMerge\Source\scripts\compiled\scripts\account\app.js failed. Could not find a part of the path 'scripts\compiled\scripts\account\app.js'
This happens on all local machines with Typescript 1.6 installed, as well as our TeamCity build server with 1.6 installed.

Filed a bug report with the TypeScript team and they've confirmed it. Seems to be an issue with how the compiler is computing absolute paths. The workaround right now is to explicitly set relative paths for both the outDir and the rootDir, so something along the lines of this:
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<TypeScriptOutDir>Scripts\compiled</TypeScriptOutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<TypeScriptOutDir>Scripts\compiled</TypeScriptOutDir>
</PropertyGroup>
<PropertyGroup>
<TypeScriptRootDir>Scripts\typescript</TypeScriptRootDir>
</PropertyGroup>
In my case I've just moved both the outDir and rootDir to the property group with no condition since I don't need to switch the outputDir between builds, something like so:
<PropertyGroup>
<TypeScriptRootDir>Scripts\typescript</TypeScriptRootDir>
<TypeScriptOutDir>Scripts\compiled</TypeScriptOutDir>
</PropertyGroup>

Related

Get solution directory in VS publish profile file

I have a solution composed with different projects from different path. We use foundation projects from a vanilla folder and then project specific projects from specific directory. Example:
specific project directory: c:\proj\specific
vanilla project directory: c:\proj\vanilla
vanilla project x path: c:\proj\vanilla\repo\src\project\x\code\
In each vanilla project we have a publish profile that points to the root directory and includes a publishsettings.targets file that has the actual target where the project should be published. By using this structure we can have a lot of projects and publish them using a single target so we don't need to change that target in all projects.
We discovered now that we have a problem when using these vanilla projects as the path used in publish profile is relative to vanilla directory and actually we need it to be relative to the specific project directory (solution directory).
In our publish profile we have:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\..\..\publishsettings.targets" />
<PropertyGroup>
...
</PropertyGroup>
</Project>
So we need a way to specify the actual sln directory to this path so we can include the correct target so when we do the publish from visual studio it will publish to the specific project and not vanilla one.
I tried finding a "MSBuildSolutionDirectory" but it only seems to be a "MSBuildProjectDirectory" variable that can be used.
Does anyone knows a way I could get the path
Project="c:\proj\vanilla\publishsettings.targets"
to actually be
Project="c:\proj\specific\publishsettings.targets"
by using some msbuild or custom variable and not hardcoding it?
I need it to work both with vanilla (as I have a vanilla.sln) and also with specific project (as I have a X.sln).
Here is a way to make your own version of the MSBuildSolutionDirectory you were hoping to see built in:
<PropertyGroup>
<SolutionDirectory>$([MSBuild]::GetDirectoryNameOfFileAbove(`$(MSBuildProjectDirectory)`, `YOUR_SOLUTION_NAME.sln`))\</SolutionDirectory>
</PropertyGroup>
Notes on the GetDirectoryNameOfFileAbove MSBuild property function:
From http://blogs.msdn.com/b/visualstudio/archive/2010/04/02/msbuild-property-functions.aspx:
$([MSBuild]::GetDirectoryNameOfFileAbove(directory, filename) Looks
in the designated directory, then progressively in the parent
directories until it finds the file provided or hits the root. Then it
returns the path to that root.
From my own testing:
The returned path does not include a trailing backslash.
If the filename is not found, an empty string is returned.

Include additional files in build using MSBuild

In the past we have used a combination of TeamCity and MsDeploy to deploy our projects. We've recently moved into using Octopus deploy, and TeamCity purely for the Build. This meant changing the build process in TeamCity and removing any references to MsDeploy.
In the past we've used confiiguration such as the below in our project file which included additional files and directories:
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
<Target Name="CustomCollectFiles" BeforeTargets="BeforeBuild">
<ItemGroup>
<UCommerceAssemblies Include="$(MSBuildThisFileDirectory)..\..\Resources\UCommerce\ucommerce\*" />
<FilesForPackagingFromProject Include="%(UCommerceAssemblies.Identity)">
<DestinationRelativePath>bin\uCommerce\%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
However this now doesnt seem to get invoked whatsoever. It appears (to me anyhow) that these pipelines were created for use with Publishing from Visual Studio, or using MSDeploy, however we need to just include these files in the directory either before or after the build has taken place. There seems to be tons of references across the web about doing this, however they all refer to using MSDeploy.
Can anyone shed any light on how I can include additional files/directories in the build without using MSDeploy?
Thanks for your time in advance
dotdev
As you are using Octopus for deployment you only need to include additional files (reference assemblies, etc.) into code package sent to Octopus.
To do this one needs to use OctoPack for project packaging. Then add .nuspec file into the project, for example this line in .nuspec will add all files from some different location into the .nupkg package under "bin\additional" and will be deployed correctly by octopus.
 
Nuspec docs
Similar solution is discuses here.

setting external library /bin folder in cmake in windows

My question is related to PCL installation and here it goes:
I compiled PCL using MSVC2013 and I updated manually my PCLConfig.cmake to point to all its dependences (3rdParty libs). The problem is that I want also to set its binaries /bin folders in the same cmake file (instead of adding /bin to environment variables). Is there a way to do that ?
What makes this question pertinent is that I'am testing different versions of PCL (1.6, 1.7, 1.8...), so won't adding the /bin folders to path of all these versions will create some kind of confict between them afterwards (in the retreive step) ?
*To be clear, what i succeded to do is that, using cmake, I can choose the PCLConfig of the PCL version I want, but when running my program (succefully compiled), it throws a missing pcl_****.dll missing, which is logic because the PCL/bin folder is not added to the system environement. so, my question is "can I add the PCL/bin floder to the project environment using the CMakeLists of my project? (instead of adding it to system environment)"
Thanks in advance.
A temporary fix i found is generating my project with the specified PCL version wanted and then Adding the bin folders manually in MSVC 2013 :
Debugging->Environment << PATH=path_to_lib\lib;%PATH%
Tsyvarev, I'm looking for your proposition and I'll let you know if it worked. Looks like a cleaner way...
Cheers,
That PATH information for debugging is stored in the "user" project file. I've written a CMake function to generate such a file automatically. This worked for VC10. I assume it'll still work, or it may need some modification. The principal is to keep an empty user project file as a template, and CONFIGURE_FILE the contents to set whatever you want. I've set mine up so that you first do: SET(USERFILE_ENVIRONMENT "PATH=${directory}") then call the macro CREATE_USER_FILE with the name of the CMake project.
CreateUserFile.cmake:
get_filename_component(MY_DIRECTORY ${CMAKE_CURRENT_LIST_FILE} PATH)
SET(USERFILE_TEMPLATE ${MY_DIRECTORY}/msdev.vcxprojuser.template CACHE STRING "" FORCE)
MACRO(CREATE_USER_FILE _projectName)
# Find user and system name
SET(SYSTEM_NAME $ENV{USERDOMAIN} CACHE STRING SystemName)
SET(USER_NAME $ENV{USERNAME} CACHE STRING UserName)
IF (${CMAKE_SIZEOF_VOID_P} MATCHES 4)
SET(USERFILE_ARCH Win32)
ELSE()
SET(USERFILE_ARCH x64)
ENDIF()
SET(USER_FILE ${_projectName}.vcxproj.user)
SET(USERFILE_TEMPLATE ${USERFILE_TEMPLATE})
SET(OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${USER_FILE})
# Configure the template file
CONFIGURE_FILE(${USERFILE_TEMPLATE} ${USER_FILE} #ONLY)
ENDMACRO(CREATE_USER_FILE)
And here's the template file.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|#USERFILE_ARCH#'">
<LocalDebuggerEnvironment>#USERFILE_ENVIRONMENT#</LocalDebuggerEnvironment>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|#USERFILE_ARCH#'">
<LocalDebuggerEnvironment>#USERFILE_ENVIRONMENT#</LocalDebuggerEnvironment>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|#USERFILE_ARCH#'">
<LocalDebuggerEnvironment>#USERFILE_ENVIRONMENT#</LocalDebuggerEnvironment>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|#USERFILE_ARCH#'">
<LocalDebuggerEnvironment>#USERFILE_ENVIRONMENT#</LocalDebuggerEnvironment>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>
ProTip: do something similar to generate a .bat file to launch your program after setting the PATH that CMake computes, so you can run it from outside Visual Studio.

Web Deploy - Using Relative Paths for local file system deployment

I am wanting to use Web Deploy to run a custom deployment setup.
As I am wanting to have this work fine when running on many different environments (team members local machines, 4 different builds servers) I want to deploy to a local path that is relative.
What I am wanting to do is:
Deploy to a local relative path
Have the after build step do magical things...
However when i enter the local file path to deploy to as: "..\Deploy_Production"
web deploy complains with this:
2>Connecting to ..\Deploy_Live...
2>Unable to create the Web site '../Deploy_Live'. The URL http://:0 is invalid.
Its as if Web deploy thinks that the relative file path is a website URL. Using "..\" instead doesn't help my cause.
How do you get WebDeploy to deploy to a local relative path?
Edit 1:
I have tried to use a ConvertToAbsolutePath task before build, to no avail:
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<SiteUrlToLaunchAfterPublish>http://mywebsite.com</SiteUrlToLaunchAfterPublish>
<publishUrl>..\Deploy_Production</publishUrl>
<DeleteExistingFiles>False</DeleteExistingFiles>
</PropertyGroup>
<Target Name="BeforeBuild">
<ConvertToAbsolutePath Paths="$(publishUrl)">
<Output TaskParameter="AbsolutePaths" PropertyName="publishUrl" />
</ConvertToAbsolutePath>
</Target>
Edit 2:
The above works, but only when running commandline builds against the Solution file not a project file
We have a bug here, when publishing using File system you have to provide a full path. We actually found this bug earlier this week. It will be fixed in our next update. In this case when the relative path is passed it incorrectly thinks that its an IIS path.
As a workaround you can edit the .pubxml to make the publishUrl a fullpath. Fortunately you can use an MSBuild property so that this works in team scenarios. Here is what you should do, edit your .pubxml file and update the value of publishUrl to be the following.
<publishUrl>$(MSBuildThisFileDirectory)..\..\..\Deploy_Production</publishUrl>
This path will be relative to the .pubxml file itself. I've verified that this works from both the command line as well as the publish dialog. If you have any issues with this let me know, but the fix should hopefully be released in a few months [no guarantees of course :) ].

MSBuild - Determine a solution's _PublishedWebsites

I am writing a web development targets file and would like to programmatically determine the name of the directory that appears beneath "_PublishedWebsites".
I currently have to use this:
$(BinariesRoot)\%(ConfigurationToBuild.FlavorToBuild)\_PublishedWebsites\ MyWebApplication
Any ideas?
(I am not using this for solutions with more than one website to publish)
The new Web Publishing Pipeline (WPP) in .NET 4.0 has a method for controlling the output location.
First, you need to opt-in to WPP during the execution of the CopyWebApplication target. Set the following MSBuild properties, either at command line or in the MSBuild project file:
<PropertyGroup>
<UseWPP_CopyWebApplication>True</UseWPP_CopyWebApplication>
<PipelineDependsOnBuild>False</PipelineDependsOnBuild>
</PropertyGroup>
The command line-variant is:
/p:UseWPP_CopyWebApplication=True /p:PipelineDependsOnBuild=False
Next, create a new MSBuild targets file in the same directory as your project and name it "ProjectName.wpp.targets" where "ProjectName" is the filename of your project, minus the extension. In other words, if you have "MyWebsite.csproj" you need to create "MyWebsite.wpp.targets". I find it helps to add the targets file to the project as well. It's not required, but it makes it easier to edit.
In the new targets file, you will need to override the WebProjectOutputDir property. Only do this when CopyWebApplication will be called - in other words, when the "OutDir" is redirected away from the "OutputPath":
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebProjectOutputDir Condition="'$(OutDir)' != '$(OutputPath)'">$(OutDir)Websites\MyCustomFolderName</WebProjectOutputDir>
</PropertyGroup>
</Project>
That's it - you should be good to go. You can test it locally by setting the OutDir property. Don't forget the trailing backslash:
msbuild MyWebsite.csproj /p:OutDir=C:\Development\WebOutputTest\