How do I get my Windows service solution to produce an artifact with VSTS Build? - windows-services

I have a build definition in Visual Studio Team Services (a.k.a. Visual Studio Online? I'm not really sure the right name for it honestly) that is not producing an artifact, and I'm really not sure why. The main project in the solution file is a Windows service that is built using TopShelf. I suspect that maybe the MSBuild arguments in the Visual Studio Build task might be wrong. I copied them from a build definition for an MVC project that is working, but it occurs to me that they might not work for a Windows service.
Here they are:
/p:DeployOnBuild=true
/p:WebPublishMethod=Package
/p:PackageAsSingleFile=true
/p:SkipInvalidConfigurations=true
/p:PackageLocation="$(build.artifactstagingdirectory)\\"
I have a Copy Files task and a Publish Build Artifacts task later on in the process, but apparently the $(build.artifactstagingdirectory)\\ is empty. I get this warning:
##[warning]Directory 'd:\a\1\a' is empty. Nothing will be added to build artifact
Oddly enough, in another task in the process where I publish the symbols, everything appears to go off without a hitch.
One more bit: I'm using a hosted build agent. Not sure if that matters or not.
That's all of the pertinent information I can think to provide. Am I way off base here? I've used Octopus Deploy in the past and I know I had to install Octopack on my services. Do I need to do something similar here?

You don't need any of those MSbuild arguments; most of them apply to ASP .NET projects and will do nothing for a console application.
Replace them all with /p:OutDir=$(Build.ArtifactStagingDirectory). That will tell MSBuild to put the build outputs in the artifact staging directory.

Related

Azure DevOps PipeLine MSBuild does not produce web folder like local command

Fairly new to Azure DevOps and PipeLines, but we are stumped by the fact executing an MSBuild command locally or through publish in VS2019 gives us a complete ready to publish folder, while the same command in Azure DevOps pipeline seems to be doing nothing but build.
Local command:
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\msbuild" Webshop\Mvc.csproj /p:PublishUrl="c:\Publish\Mvc" /p:DeployOnBuild=true /p:Configuration=Release /p:WebPublishMethod=FileSystem /p:DeployTarget=WebPublish /p:AutoParameterizationWebConfigConnectionStrings=false /p:SolutionDir="." /p:PrecompileBeforePublish=true
MSBuild task:
steps:
- task: MSBuild#1
displayName: 'Build solution'
inputs:
solution: '$/MVC_Projects/<more here>/Webshop/Mvc.csproj'
msbuildVersion: 16.0
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
msbuildArguments: '/p:DeployOnBuild=true /p:DeployTarget=WebPublish /p:PublishUrl="$(build.artifactstagingdirectory)\publish" /p:WebPublishMethod=FileSystem /p:AutoParameterizationWebConfigConnectionStrings=false /p:PrecompileBeforePublish=true'
We tried playing with the parameters, but that does not seem to have much effect (or we don't know which parameters to tweek). The most we got was adding an /p:DeployTarget=Package and /p:OutDir="$(build.artifactstagingdirectory)\bin" would copy the bin folder. This was still without the .compiled files we were expecting though.
The project is an ASP.NET MVC Framework 4.8 application. The code does build properly and without errors. The logs do not hint with any warning or tasks not being able to be completed, so no clues there. We require the output folder for the full website and not just the DLL's to make our migration to DevOps easier. Having the folder allows other deployment processes to remain the same.
This might not be best practice, but it is practical for us at this moment in time.
Question 1. Why is MSBuild doing something else locally than in the DevOps Pipeline? Is it perhaps picking up configuration files we are unaware of ?
Question 2. What settings (or perhaps other task) would we need to set up to get the same local publish folder appear in the $(build.artifactstagingdirectory) folder in DevOps ?
Any insight, direction or solution is appreciated.
SOLUTION
After many checks and trials in the build parameters and pipeline setup, it was a DevOps server installation issue. The DevOps server had a full version of 2022 installed and only a partial version of 2019. Although the builds did not give any error or warning, the artifacts were not created without the 'ASP.NET and web components' for Visual Studio 2019 being installed. After that component was installed, the builds ran just fine and as expected.
Lesson learned is to double check local development installation with server installation with relation to installed (individual) components when results vary, even if there are no errors.

Build and Deploy a Web Application with TFS 2015 Build

We have just installed TFS 2015 (Update 1) on-premise and are trying to create a Continuous Integration/Build system using the new TFS Build system. The build works fine, and gives me a green light, but when I look at the default build it has only built the binaries from the bin directory, and there seems to be no easy way to deploy the app on-premise to a local server.
There are two deploy options for a filesystem copy, and a powershell script, and it would certainly be easy enough to use them to copy files to a new server, but since the build only built the binaries, I don't see a tool to gather up the Web artifacts (cshtml, images, scripts, css, etc..) for this.
After an exhaustive google search, I've only found one article which talks about this at:
http://www.deliveron.com/blog/building-websites-team-foundation-build-2015/
However, this uses WebDeploy and creates a rather messy deploy package.
How can I deploy the site (standard MVC web application, in fact my tests are using the default boilerplate site created by the create project wizard) complete with artifacts to a local server in the easiest possible way? I don't want to have to install WebDeploy on the servers, and would rather use PowerShell or something to deploy the final artifacts.
The build is just the standard Visual Studio build template, with 4 steps (Build, Test, Index & Publish, Publish Build Artifacts).
We use "Visual Studio Build" step and as Arguments for MSBuild we use following line:
/p:DeployOnBuild=True /p:PublishProfile=$(DeploymentConfiguration)
On Variables tab page DeploymentConfiguration has to be configured. It must be the Name of the publish Profile (filename of the pubxml file). If the file Name is Build.pubxml the publish profile is Build.
for example:
/p:DeployOnBuild=True /p:PublishProfile=Build
I wanted to add that Ben Day has an excellent write-up that helped us package quickly and then release to multiple environments through Release Manager.
His msbuild arguments look like this:
/p:DeployOnBuild=True /p:DeployDefaultTarget=WebPublish /p:WebPublishMethod=FileSystem /p:DeleteExistingFiles=True /p:publishUrl=$(build.artifactstagingdirectory)\for-deploy\website
The difference between this and the accepted answer is that this parameter set stages everything in an artifacts folder, and then saves it as part of the build. We can then deploy exactly the same code repeatedly.
We capture the web.env.config files alongside the for-deploy folder and then use xdt transforms in the release process to ensure everything gets updated for whichever environment we're deploying to. It works well for all our web projects.
We use WebDeploy/MSDeploy for 40+ applications and love it. We do install WebDeploy on all our servers so we can deploy more easily but you could also use the Web Deploy On Demand feature which doesn't require WebDeploy be pre-installed.

SSIS 2012 Continuous Integration with TFS 2013

I’ve been reading some articles (this one in particular: http://speaksql.wordpress.com/2013/06/07/a-journey-to-db-deployment-automaton-ssis-build-using-msbuild/) about using msbuild.exe to build and deploy an SSIS package (.ispac). I had no problem with that from my computer which has all the required assemblies, and only using the msbuild.exe command.
Once I tried to use the TFS Build Server I had some problems. First I realized that using a project with msbuild.exe (SSIS.MSBuild.proj) was not recommended with TFS 2013 since it was used with TFS 2008 and 2010. Anyway, I just wanted to make it work and it sounded plausible, but I had to use the TFSBuild.proj. That was not a problem, but my next problem was that the project I was being using (Microsoft SQL Server Community Samples: Integration Services) references a SQL Server assembly (Microsoft.SqlServer.ManagedDTS) which is not installed on my build server.
Then I realized that even if I managed to install that assembly on the gac, or referenced it on a relative path I would have a bigger problem next, I am using custom activities on my packages which I need to install using gacutil.exe on the host server, and I was wondering how to install, remotely, those dll.
That’s when I started to lose faith, and here I am, is there an “easy” way to implement continuous integration for SSIS packages without installing third party tools (http://remotegacutil.codeplex.com/ for example), and adding missing assemblies to the gac of a build server?
Did any of you have a similar issue? Did you solve it? How?
Thanks!
Use devenv.exe to build the ispac. Add an invoke process task and call out to devenv.
Add an Invoke Process to the Build Template, the one above shows a Sequence container, which assigns the path to the correct version of DeVenv to call, VS2010 /12 /13 etc. this is shown as hard coded but can be put into an argument, so it can be populated in individual build definitions. the one you can't see clearly is "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.com"
Next is the invoke Process, this call out to the specified devenv.exe and passes arguments used to build the ISPAC file.
The arguments are passed in localProject would get you the actual project you wanted to build in previous versions, you may have to do something different for 2013, due to the changes to the new templates.
this gives a TFS2012 way of doing it, as i say you may have to do something different to get the project that you want to build under 2013, but the build will run and an .ISPAC file will be generated.
at this point i would deploy the ISPAC using powershell, you may want to add additional scripts to the powershell calls to handle creating the SSIS Catalog and scheduling of the job.
deploying with Powershell can be found here Deploying ISPAC's with Powershell

Linked file in WCF RIA service does not build in TFS Build server

I've just setup a TFS (2012) server and now I'm trying to build the complete code (written in .NET 4.0 in VS 2010) via the TFS Build server. But in my solutions I have also a WCF RIA project which contains linked files because they are used somewhere else also and there is no possibility to add a reference to a general .NET binary in WCF/Silverlight.
Everything builds without any problem on my development machine but when I check it all in, create a standard build definition and run that build definition I get the following problem. The linked files have usings (UsingNamespace for example) to other projects that are also build by us and build before the WCF/Silverlight but the following error pops up while building through TFS Build server:
The type or namespace 'UsingNamespace' could not be found (are you
missing a using directive or an assembly reference?)'
Is there any solution for this problem that I looked over?
EDIT 1
Just tried to set the Copy to Output Directory propertie of the linked files to Copy Always but this still gives me the same error as I was expecting. The problem is that the linked file is placed somewhere that it can use the usings but the WCF RIA service cannot access/find that using.
EDIT 2
Just tried out my local test TFS where I can do what I want and there I made a build definition with just the solutions needed to make that the project with the linked files builds. This worked without any problem. Then I tried the same on our TFS server with a new build definition that has the same solutions as on my test TFS and here it did not work. The only difference that I know for sure is that my test TFS is TFS 2012 Update 1 and that my production TFS does not have the update 1 yet. I'll try to install it next week.
EDIT 3
I've just updated our production TFS to Update 1 but it is still not working with my temporary build definition which only contains the projects that are needed to build the silverlight application with the linked files. The 2 workspaces are the same on both server and the projects to build are also the same.
You need to specify the workspace information in the Build Definition for the build to use. The workspaces are what the build process copies from source control to the build server. If you don't have everything in the build server's workspace, it can't build properly.
The Source Control Folder in the workspace tab is the location of the files you need from TFS. The Build Agent Folder is a relative path from the build server's pre-defined base location. You'll usually use $(SourceDir)\Folder to specify the "Folder" that your build process needs.
This sounds like an $(Outdir) problem. A build definition in TFS automatically overrides the Bin folder. All Binaries are redirected to the bin folder upon compile. Sounds to me that you are using a mixture of project references and file references. The file references are probably what is causing your build failures.
Example if you compile in the same build the following solutions
Solution1.sln (TFS Build Pass)
project1.csproj
project2.csproj (references project 1)
Solution2.sln (TFS Build Failure)
project3.csproj (references binary output of project 1)
Expectations from TFS out of the box without customizing your workflow is that this simple build will fail. The reason is that in your development box all projects produce output to one destination while in a tfs build your projects will build to $(Outdir).
Some Things to try
Simple (best practice in my view)
Create 1 solution and use project references instead of file references.
Complex
Build using MSBuild project files
Modify your windows workflow to not override the $(Outdir)
Copy the binaries after a build is complete.
Best practice on Automating Builds
Build from command line
Build from cmd a NON vs2010 command line.
C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe FullpathtoSolutionFile.sln
Cheers!
Apparently there was just missing the WCF RIA services V1.0 SP2 on the TFS server. If that was installed the problem was solved.

Using Octopack on a TFS build with a website + windows service

I have a website, a windows service, and some shared class libraries in a single Visual Studio solution. I use Octopack on both the website and windows service, and on my machine these builds work as expected.
When using the TFS Build Server, the website nuget package is generated as expected, but the windows service nuget package contains all files from the website, as well as the service. E.g. it includes the _PublishedWebsites folder as well.
This is because TFS uses a single location to build projects.
What is the best way around this?
I know this question has since been closed, but I cam across this issue and solved it in a different way.
My solution is compromised of a number of websites and windows services and had the same issue of the OctoPack created nuget packages including all the solution assemblies from the 'pooled' output folder when building with Team Build. The reason the nuget packages get all the assemblies is OctoPack uses the outdir msbuild argument as the location to include assemblies from.
The way I got around it was to use the msbuild argument GenerateProjectSpecificOutputFolder=true. This instructs Team build to create a folder for each project in your output folder in the same way Visual Studio uses the bin folders under each project when building locally.
My build definition msbuild arguments looks like:
/p:GenerateProjectSpecificOutputFolder=true;RunOctoPack=true;OctoPackPublishPackageToFileShare=\\<NugetServer>
I currently just push the packages onto a shared folder but the OctoPackPublishPackageToHttp and OctoPackPublishApiKey parameters can also be used.
The benefit of this solution over the one above is you don't need to specify the files to include the nuget package.
Hope this helps someone.
I ended up using this nuget package to ensure the console app built to a seperate directory on the TFS server.
https://nuget.org/packages/PublishedApplications/2.1.0.0
I then had to specify in the nuspec file, which files should be included for the console app. e.g
This works and I can now deploy using Octopus deploy.
The downside of this apporach is that the PublishedApplications build only works on the TFS build server, so I can't build the project locally in release mode. Still looking on how to overcome this.

Resources