VSTS Visual Studio Build task is not incremental; keeps rebuilding - azure-devops

The VSTS msbuild task seems to keep executing CoreCompile, despite the Clean option being disabled and the source files untouched (nothing changed in the source fetch).
Yet locally when I run msbuild locally or directly on the build machine, it behaves as expected - all unmodified projects are not rebuilt; CoreCompile does not run csc.exe.

I found that this was because the "TargetFrameworkMoniker" file that MSBuild generates and injects into the compile silently is written to the temporary directory, i.e. what you get when you run System.IO.Path.GetTempPath().
The VSTS agents however, specify their own temporary directory (_temp) and seem to clear it after every build. This seems like good behaviour - it's MSBuild that should fix it (IMO).
A quick and dirty fix, that may not work if your projects use mixed frameworks, is to add this MSBuild option:
/p:TargetFrameworkMonikerAssemblyAttributesPath=$(Build.Repository.LocalPath)\temp.moniker.cs
Alternatively, you can disable the file generation with:
/p:GenerateTargetFrameworkAttribute=False

Related

TFS 2015 Build step Nuget Publisher "Ambiguous option 's'"

OK, so we're stuck on on-site TFS2015 at the moment. My Nuget Publisher build step is failing with:
##[error]Ambiguous option 's'. Possible values: Source SymbolSource SymbolApiKey.
It appears inside the build step they have put -s instead of -source, and in later versions they've added more commands starting with s. So what are my options?
Write my own in Powershell (Can do, but TFS Build is very clunky for this)
Find wherever this is defined in TFS (hopefully a template .ps file) and fix it there (Anyone know where this is kept?)
Upgrade to a later version of TFS (a fairly large, but perhaps inevitable undertaking)
Somehow override the -s command another way?
????????
Invoke NuGet.exe however you'd like via the Command Line task
If you did #3 (upgrade TFS), you'd find that the PowerShell build task can run an in-line PowerShell script, making it significantly less clunky.
You may be able to extract and modify the task with the tfx command line utility, but I can almost guarantee this will have nasty ramifications when you do eventually upgrade.
I'm adding my answer for details about step 5 maybe it will help team that are still using TFS 2015.
Nuget Publisher seems to use old version, which means "-s" option will not work.
To bypass this situation you can setup your build as follow:
1- Add Nuget Packager Step and specify the the Package Folder value:
2- Add a new step which would copy your artifacts(Note that contents that should be copied must end with nupkg):
3- And Finaly you can just run a command line that will perform the publish operation. In my case we are pushing the whole repository using init command(PackageRepository is the path to our internal feed that we set in we've set in Variables section):

How to activate "treat warning as error" for specific build definitions?

I would like to make my main branch TFS build definitions to treat warnings as errors so that the build fails when the projects are not error free. Since I do not want to activate "treat error as warning" in all project as a default, my first idea was to add a powershell script to my main build definition that substitues false with true in the line <TreatWarningsAsErrors>...</TreatWarningsAsErrors> in all csproj files it finds (something along the line of this). Is there any better/straighter way via some option as part of the build definition settings?
In the build definition specify /p:TreatWarningsAsErrors=True in the MSBuild argument field.
This will override any setting from the csproj files.
Unfortunately, there is no this kind of settings as part of the build definition.
However, you could be able to return warnings and errors from your powershell script using logging commands. With using task.logissue type=error you could fail the build task and then fail the build.
More details you could take a look at this similar question: Is it possible to raise and display build warnings from build steps using TFS 2015

How to differentiate TFS Builds and manual builds using macros in Post build event

In TFS post build script of a .proj file I want to find whether the project build is happening through TFS triggered build or manually triggered build.
Can someone suggest me how to do this using macros in Post Build event.
Short answer: you can make use of the IsDesktopBuild MSBUILD property within your csproj file to differentiate between TFS and local build.
Long Answer:
Developer or Team Build?
To differentiate the build environments we have to implement a mechanism that detects in which environment the build is being executed. In other words, we need to know if we running a local build that is executed by the developer or a team build running on the build server.
In fact, there are 3 different build environments we need to consider:
· Visual Studio Build – a build executed by a developer, on their own development machine inside the Visual Studio IDE
· Team Build – a build executed by TFS (manually or scheduled), on the build.
· Desktop Build – a build explicitly executed manually, on the development workstation using the command 'msbuild.exe tfsbuild.proj'.
A ‘DesktopBuild’ and a ‘TeamBuild’ are very similar in nature except that ‘DesktopBuild’ does not perform a ‘GetLatest’ function from source repository, will not ‘Label’ the source tree and will not determine the change set.
When using MSBUILD tasks (as we will use primarily in following sections), one common way to achieve this is to use the ‘IsDesktopBuild’ and ‘BuildingSolutionFile’ properties as conditions to test in the tasks.The ‘IsDesktopBuild’ property is declared in the ‘Microsoft.TeamFoundationBuild.targets’. The ‘BuildingSolutionFile’ property is declared and assigned automatically by MSBUILD.
The following table lists the values of each of these properties in each of the build environments.
Environment IsDesktopBuild BuildingSolutionFile
Visual Studio Build (empty) (empty)
Desktop Build true true
Team Build false true
One caveat with using the ‘IsDesktopBuild’ property is that it is not defined in many target files by default. This property will have an ‘empty’ value in a Visual Studio build, so we initialize it to a value of ‘true’ as the default value. Therefore we need to be explicitly define it in all MSBUILD target files where it will be tested.
We simply add the following element to all target files where we need to differentiate between a build on the development machine and a build on the build server (within the first section).
<IsDesktopBuild Condition="'$(IsDesktopBuild)' == ''">true</IsDesktopBuild>
Update: thank you #dbardakov. Starting VS 2012 we can use the property to find if the build is happening within Visual Studio:
BuildingInsideVisualStudio
MSDN SOURCE - for BuildingInsideVisualStudio
MSDN SOURCE

Invalid file names when trying to deploy SSDT project with TeamCity 8

I am trying to deploy Visual Studio 2012 SSDT project to Sql Server using TeamCity 8 and MSBuild Publish task but the deployment fails.
When I look at TeamCity logs and use /v:diag switch in my build configuration I see that for unknown reason MSBuild searches for MyProject.sqlproj.publish.sql and for MyProject.sqlproj.dacpac files.
The exact error:
[SqlPublishTask] C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets(1233, 5): File "C:\Program Files\TeamCity\buildAgent\work\abf8bc05a2cfe7f\*MyProject*\bin\Debug\*MyProject*.sqlproj.dacpac" does not exist.
The correct .sql and .dacpac files get generated (without the .sqlproj in the middel) in buildAgent/work/identificator/*MySolution*/MyProject/bin/Debug folder.
My TeamCity build step is configured as follows:
Runner type: MSbuild
Build file path: MyProject/*MyProject*.sqlproj
MSBuild version: 4.5
MsBuild ToolsVersion: 4.0
Run platform: 4.0
Targets: Publish
Command line parameters: /p:SqlPublishProfilePath="Debug.publish.xml" /p:Configuration=Debug
If I execute this from commandline I get no errors.
Any ideas on how can I configure TeamCity to search for correct files or configure my project to generate the files that TeamCity is searching for.
Or is my plan to use MSBuild's Publish task futile and I should utilise sqlpackage.exe instead?
UPDATE
After spending almost three days trying to figure this out I gave up and used sqlpackage.exe which works like a charm.
But I would still be interested in an answer though, passing paths to executables in build servers seems a bit crude way to accomplish things.
I had a similar issue and came to the conclusion that the way TeamCity produces "pseudo-project" files with *.teamcity suffixes is confusing something in the MSBuild/SSDT target chain.
I simply replaced the MSBuild runner build step with a pure Command Line step and the problem went away.
We lose the user friendliness of the TeamCity MSBuild runner configuration, but if it works, it's a compromise I'm willing to make.
Note - we are running TeamCity 7 - I am not sure if this has been addressed in later versions.
I found out you can set a System Property named "system.SqlTargetName" on the build configuration to override the default value.
Setting this to your project name without the ".sqlproj" makes the error go away.

Automatic installer deploy to remote server using TeamCity and MSBuild

I'm having a .net WPF project that compiles to a bunch of dlls. I also have another project that compiles all the dlls and creates an installator exe.
I am also using TeamCity to automatically do those tasks for me with a press of a button.
The problem is that I want to have a separate TeamCity build configuration intended to automatically copy the result installator exe to a number of remote machines, each having specific credentials. But, unfortunately, I don't get how do I do this.
I have found some articles on automatic deploying (like this http://www.troyhunt.com/2010/11/you-deploying-it-wrong-teamcity.html), but, obviously, they are very specific for web projects.
So, how should I correctly deploy my installator on build?
Your best bet is to research NAnt and make a simple task that will copy the TeamCity artifact (installer) out to the specified location.
All you would need to do is have TeamCity execute the specified NAnt task after the installer has been built.
http://nant.sourceforge.net/release/0.85/help/tasks/copy.html
Update
Also, check out this question for solutions on specifying the credentials for the copy task.
OK, I've found out that it's pretty easy to do this using the FtpUpload MSBuild community task. There, one can set up the credentials and all other stuff needed for uploading a file (or a set of files) via ftp.