Packing and publishing NuGet packages with .NET CLI in TeamCity - .net-core

I am trying to create Team City build template which requires minimum customisation, and I want it to play nicely with legacy projects and projects developed with .NET Core/Standard and .NET CLI.
I am stuck with NuGet as there were some considerable changes in how things work.
Earlier we had to create nuspec file to pack project as a NuGet package. At least in that file we could define various package-related properties.
New csproj file format allows us to define all package properties inside itself. That's fine, but how then do we know which projects should be packaged and which should not?
So far our TeamCity's build step Pack NuGet just contained **.nuspec for Specification files: field. The very fact of nuspec file presence served like a flag pack & publish this project.
However, for dotnet pack we need to specify the project. There is no simple way to distinguish 'main' projects from 'auxiliary' ones on which mains depend. (Let us ignore that project-to-project references are currently not supported.)
We either could pack all projects specifying **.*proj (yet in that case we are to know which packages to publish) or we might specify projects explicitly in a build configuration, but I don't like this approach because you must edit build configuration each time new project is added to the solution.
I also considered the option Generate package on build and omit dot net pack step as package is created on build. The only thing left is publishing the packages with dotnet nuget push specifying **/%BuildConfiguration%/*.nupkg.
Unfortunately when starting build against solution without projects with enabled Generate package on build makes TC fail complaining that
Target files not found for pattern "**/Release/*.nupkg"
Hence, I either need another recipe for achieving the required result or an advice how to make TC consider empty result just as a NOP and mark build as successful.
Yet another option is to use nuspec even for new csproj...

Since TeamCity 2017.2 will be available option to associate build configuration with multiple templates. So you will be able to create different templates to create packages for old projects and new .NET CLI projects.
To specify paths for target .NET projects, which should be packaged, you could use build configuration parameters.
To set such parameters during the build you could send in the preceding build step service message. The value of this parameter could be set to the list of target project files which could be selected via script like that: https://stackoverflow.com/a/8153857/305875

Related

How to pack a referenced project into a nuget package?

I have a C# solution which contains 3 projects; Application.Server, Application.Client, and Application.Common. Both server and client have a project reference to common.
I want to pack server and client up so that they can be used by other teams in my organisation. I have some automated build pipeline set up that do so, and they publish the nuget packages for server and client. They do not package or publish common. When I inspect the nuget packages, I can see that they reference the common package.
Is there a way that I can get them to build that project into them self? Ideally I don't want to publish the common package as it's pretty specific to my application, and it doesn't really make sense that it's something that's independently consumable by other departments. I also don't want to have to worry about wrangling extra nuget packages if I can help it (as in reality, Common is actually several projects).
If your projects are "old style"/non-SDK/traditional csproj, AND if any project uses a NuGet package, if all those NuGet references are defined using packages.config, then use you can use nuget.exe pack -IncludeReferencedProjects. However, if any of your projects use PackageReference to define their package references (new, SDK-style projects can only use PackageReference), then nuget.exe pack will not correctly create NuGet dependencies for those packages. For SDK style multi-targeting projects, nuget pack will probably completely fail.
The only supported way to pack projects that use PackageReference, or any SDK style project, is to use NuGet's MSBuild pack target (either dotnet pack or msbuild -t:pack). However, this does not have an equivalent to nuget.exe's IncludeReferencedProjects.
If your projects are SDK style, it really shouldn't be any more difficult to create and publish one package or many packages. Simply run dotnet pack on your solution, and every packable project gets packed (remember to mark any class library project you don't want to become a package as not packable). Then use your favourite scripting language to find and publish all nupkg files. For example (Get-ChildItem -Recurse -Filter *.nupkg $SLN_DIR | ForEach-Object { & dotnet nuget push $_ }, or copy/move all nupkgs to a single place (or use the appropriate setting to make NuGet create the packages there in the first place) and use dotnet nuget push *.nupkg.
The NuGet team recommends one package per assembly, and the tooling automatically creates NuGet dependencies for project references, so it all "just works" out of the box. To create a package with all the assemblies included, instead of NuGet dependencies, requires you to do a bunch of work.

How to deploy solution with multiple web projects with VSTS?

I have a solution with multiple web-projects and many class libraries.
I want to deploy web-projects to my own VM with installed deployment agents.
Should I create for every web-project separate its own Build and Release Definitions, right?
Obviously, creating separate Build and Release definition for each web project works. But if you want to use one build & release definition, it also can be achieved, and there are many ways.
For example, if you want to use each project artifact, you could use individual project files in the solution to build in Build definition. Or you could copy the file you need for one project in Release definition, etc. In a word, it depends on how do you want to achieve your requirement.

.NET MVC 3 Deployment package missing references

In an ASP.NET MVC3 project I have a structure like this:
Core.csproj
-> 3rdparty1.dll
-> 3rdpartyreference.dll
-> 3rdparty2.dll
Web.csproj
-> core.dll
I'm using the Build Deployment Package feature in VS2010. When I build, there are some references missing in the final bin directory. It only contains the web.dll, core.dll, 3rdparty1.dll and 3rdparty2.dll but is missing the 3rdpartyreference.dll.
How can I force the Deployment functionality to copy all the necessary references? (without manually creating a specific "copy something.dll" instruction in the afterbuild in the csproj)
The MSBuild tasks involved in the deployment package and publish features of VS 2010 fail to pickup indirect references by where your app depends on an assembly that depends on another. Either you can copy the files manually (not recommended), or you can add an unused reference variable to your core project that points to some class in the thirdpartyreference.dll. This reference variable, even if unused, will cause VS 2010 to think you have an explicit dependency on that third party dll and copy it to the bin directory as expected.
The feature you're looking for is called "Bin deployment". In this article there's a step-by-step solution. Basically, you need to add deployable assemblies to your project - specific folder will show up in your project structure where you can add necessary dll files.

TeamCity working directory of dependency?

If you have a project that builds one project before building the next, but the next needs to know the 'path' of the first build, is it possible to get this?
For example:
Project A has Build Configuration A and Build Configuration B.
Build Configuration B has a dependency on Build Configuration A. From without the Build Configuration B it will need access to the path of Build Configuration A. Is there are a way to obtain this?
Most simple approach would be to define a custom checkout directory in the A and use the same hard-coded value in B.
If you use TeamCity snapshot or artifact dependencies, you can use %dep.btXXX.teamcity.build.checkoutDir% to get checkout directory of the dependency build. However, this will not work in 6.5.0-6.5.5 TeamCity versions, see details and workaround in the issue TW-18715.
However, you should really avoid accessing checkout directory of one build from another. If you need sources of A, you can checkout them in B; if you output of the A's build, then publishing the output as build's artifacts and then using TeamCity artifact dependencies is the way to go. In both cases additionally using TeamCity snapshot dependencies will ensure both builds use the same sources snapshot which is probably what you need.
If you have one agent, and only ever one agent then you could try and use the path from a previous build.
I wouldn't recommend doing this however because if you had two agents, or scaled up in the future to two agents, then it is possible your projects will be built on different agents; this would mean your dependency working directory won't be on the same machine, or it will be outdated as the latest was built elsewhere.
I assume you're after the path of the first build to get its output?
If so, the method we use to share dependencies between projects is to checkin the output from each project into our source control, then every project that requires the output simply has to check them out.

Automatic BizTalk Versioning in My Build Process

In all of my other .net apps my build process (a mixture of nant and custom tasks) automatically updates the [AssemblyVersionAttribute] AssemblyInfo.cs with the current build number before the call to msbuild, stamping in the build number in the version number.
I'm now working on my first BizTalk project and I'd like to do the same thing with the version numbers of the BizTalk assemblies, but I've run into trouble!
First of all the aseembly version numbers are stored in the btproj files, so I did some googling and found www.codeplex.com/biztalk which looked like the answer to my problem, but there is a deeper problem!
I have a project for my schemas and another for my pipelines, the pipelines project references my schemas project as I have a flat file dis/assemblers. The problem comes when I update the version numbers, as updating them even from within visual studio does not update the pipeline components references to the schemas.
So if I update all the version numbers manually in the VS IDE from 1.0.0.0 to 1.1.0.0, the build fails as the pipeline components flat file dis/assemblers still reference the old 1.0.0.0 version of the schemas! They don't automatically update!
Is this really a manual process of updating the version numbers of the BizTalk projects in the property pages, then building the projects and manually updating the references to them in the properties of all the pipeline components that reference them?
This means that I can't have my build process control the build number part of my version numbers!
Or is there a better method of managing the version numbers of the BizTalk assemblies?
I'm sorry to disappoint you but I've been down the exact some road I had to give up. I guess it could be possible to achieve it but it would require a lot of changes to both the binding files and other XML files (as you mentioned and even more if you have published services etc).
Maybe it could be possible to wrap all these necessary changes in a build step (a MSBuild step or similar in other build frameworks) - that would be useful!
Developer- :)
We had the similar problem and we ended up developing a small utility which would change the version number in all the projects i.e. *.csproj (asssemblyinfo.cs), *.btproj accordingly. Apart from this it would open and modify the *.btp files with the new version of schemas. In nutshell, what all you have to do is to configure this utility in your VS.net tools menu and execute it.
I guess its not very difficult to develop such utility in any .net lanagauge.
Caveat: Do not forget to save the files after updates with the same encoding as they were originally.
Cheers!
Gutted, thought that might be the case. Maybe BizTalk 2009 projects will play more nicely when updating references when changing version numbers.
I started to go through and automate it manually, and when I realised what needed to be done, I took a biiig step back when I realised just how many places I'd have to modify to get it working. Thank god for Undo Checkout.
I do have a standard C# class library included in my project (various helper functions), which i am able to update the version number of during my build process, so I'm basically using that one assembly to version the whole application. If anyone wants to know what version is in any environment, check out the version number of that one assembly.
Not ideal, but it's working.
We've done this successfully on our project - I'll see if I can get the developer of the tool to post details...
This problem arises when you perform an integration build to the latest versions of your dependent components as file references (aka schemas here).
Keep in mind that upgrading the assemblyversion must always performed manually, that way you are always in charge of changes to assemblyversions.
A possible solution to solve the buildbreaks issue is to file reference to a specific version of a dependent component build and not to the latest version and use a subst drive and a copy script to get the latest component builds.
For example:
SchemaA, assembly version 1.0.0.0
PipelineA (with pipelinecomponent XMLValidator for example), assembly version 1.0.0.0
PipelineA has a file reference to a subst drive(say R drive, which maps to a workspace D:\MyComponents) and version 1.0.0.0 of SchemaA as follows:
R:\SchemaA\1.0.0.0\SchemaA.dll.
The copy-script copies the buildoutput of SchemaA locally to your R drive.
When schema A updates to version 1.1.0.0 you don't have any issues because you still use version 1.0.0.0 and YOU have the choice to use the 1.1.0.0 version of your schema. When you want to upgrade, you have to alter your copy-script and replace the file reference to R:\SchemaA\1.1.0.0\SchemaA.dll.

Resources