set up build and release for two related packages in VSTS - azure-devops

Dears
Please help me with VSTS build configuration for linked packages
I have two projects in the solution, like Interfaces and Dto. Interfaces contains several interface definitions, Dto project implements interfaces and has reference to Interfaces. Each project has dedicated nuspec file and is available as dedicated package in the vsts package feed.
To achive this I created nuspec files that contains package dependencies according to project references defined. So Dto package depends from Interfaces like below:
<package >
<metadata>
<id>Dto</id>
<dependencies>
<dependency id="Interfaces" version="0.4.0" />
</dependencies>
Those projects are hosted in the same VSTS git source code repository (but different folders)
Right now I have simple build definition that is triggered by changes in master branch.
It builds solution, than packs and pushes all nuspec files from the solution folder.
How can I configure build definitions for two packages to build Interfaces project only if Interfaces folder content was changed? But to build Dto package if Interfaces or Dto folder content was changed?
I've thought that can create two build definition that triggers by different Path filters. However the problem is that i need to set correct dependency version reference from Dto nuspec file to Interfaces package.
To set package version I use global build definition variable $versionFromFile that contains minor and major part of version number, like 0.4 and vsts revision for third part of package version. It is parameterized in the build number format like:
$(versionFromFile).$(Rev:rr)
each package build automatically increment revision number like 0.4.1, 0.4.2. When I need to change major package version number I update build definition variable value and revision is starting to count from zero. To set package version I configured nuget pack task "Automatic package versioning" parameter to "use the build number" value.
So in case for two build definition I need to reference from Dto package to Interfaces package last version somehow. Unfortunately I have no idea how to reference from Dto package build definition to the latest Interfaces build definition version number. The only one idea that I found is to save Interfaces build version number to a file. Then read it from Dto build definition to the new variable and use it. However it looks a little bit ugly. Is there a better way to reference from one build definition to another build definition $(BUILD.BUILDNUMBER) value?
Thank you

The simple way is calling nuget update command through Command line task before build task, then pack the project through Nuget task with Include referenced projects option checked.

I've implemented solution that was suggested by #starianchen
To achieve this I had to
remove reference from dto project to interfaces and added interfaces as a package instead
create two build definitions, for interfaces and dto folders of the solution using Path filter on Triggers page
create interfaces.sln file because vsts fails to build interfaces.csproj. It needs sln file or output paths to be specified
change nuget pack to nuget custom command and write parameters manually for both interfaces and dto builds.
pack Interfaces\Interfaces.nuspec -version $(BUILD.BUILDNUMBER)
-properties "releaseNotes=$(releaseNotes)" -Verbosity Detailed -OutputDirectory $(build.artifactstagingdirectory)
and
pack Dro\Dto.csproj -version $(BUILD.BUILDNUMBER) -properties
"Configuration=Release;releaseNotes=$(releaseNotes)" -Verbosity
Detailed -OutputDirectory $(build.artifactstagingdirectory)
-IncludeReferencedProjects
Please note that i've used .csproj file that has corresponding .nuspec for Dto packing command.
- modify Dto.nuspec by removing Interfaces from dependency section and Dto.dll from Files (those elements are added by IncludeReferencedProjects option). However there are dto.xml and related assemblies
This allows me to update Interfaces package only when it changes. Dto project when packed takes dependency for the Interfaces package reference that was used when Dto project was built.

I would suggest using the BuildChain extension from the Marketplace. This extension allows you to easily chain builds and pass parameters from one build to the next.

Related

Azure Pipelines populate NuGet package fields

I have a Class Library project using .net Framework 4.6.1 and I am building a NuGet package using Azure Pipelines. I have got most of the fields in the NuGet package properties populated however I'm struggling with a few.
I'm using an extension to read the AssemblyVersion from AssemblyInfo.cs and use this for the versioning.
I can also see that it extracts the below fields form AssemblyInfo.cs
AssemblyInfo.cs Field
NuGet Package Property
AssemblyTitle
Title
AssemblyDescription
Description
AssemblyCompany
Authors
AssemblyProduct
ID
AssemblyCopyright
Copyright
The NuGet fields I'm trying to populate are Release Notes, Summary & Owners but I'm not sure where to start. I've look at what other fields I can use in AssemblyInfo and none of them sound like they would relate to the mentioned fields. I've also looked in the NuGet Pack task in Azure Pipelines but theres no mention of these fields either
When we pack the nuget package with .csproj file, nuget will get the package info from the AssemblyInfo.cs file in the project. (e.g: AssemblyVersion, AssemblyDescription,AssemblyCopyright etc).
We can see this information in the package overview page after it's published to a feed.
I'm trying to populate are Release Notes, Summary & Owners
Here is the direction for your reference. We can try to add this as a description for the NuGet package, we could add the description for assembly: AssemblyDescription in the AssemblyInfo.cs:
[assembly: AssemblyDescription("Release Notes, Summary & Owners here")]
However, we need to find a way to generate the required information (Release Notes, Summary, ect) and write it to the AssemblyInfo.cs file.
Another way is using the .nuspec file. We need to create this file on local machine with the command line nuget spec "..\*.csproj", then modify the <description>$description$</description> in the .nuspec, upload this file to the repos. Please see Create the .nuspec file for details.
After that, we can expand the "Advanced" option of the NuGet Pack task, then in the "Additional build properties" specify the value you want in this way:
Description="ReleaseNotesHere"
With this way, the specified value will replace description.
Specifies a list of token=value pairs, separated by semicolons, where
each occurrence of $token$ in the .nuspec file will be replaced with
the given value. Values can be strings in quotation marks.

Managing nuget versions from beta to release in VS2017 for .net core2.1 when building pipeline in Azure Devops

I need to create nuget package for a .net core 2.1 as part of build and release process in Azure Devops
What I would like to do
1) In the build section build the project and then add the compiled code to artifact
2) In Release definition will have 2 deployments one for Beta release where the version will be like 1.2.3-Beat.2 and push to azure artifact nuget and another deployment to release where the version will be like 1.2.3.2 and push to azure artifact nuget.
Currently I have only one build definition which will build (nuget package gets created during build process) and push to azure artifact nuget.
Pipeline I would like to create
Use the dotnet pack task with the --no-build option, and in your pre-release stage set the VersionSuffix value.
Note: My current team uses a set of Powershell scripts to append build number data to the Major.Minor data found in the .csproj (or AssemblyInfo.cs for netFramework), but that doesn't change the answer to your question. Once you figure out what the Major.Minor.Patch[.Build] data is going to be, you can use the VersionSuffix property in a dotnet pack task with --no-build to communicate quality of the package as it moves through your pipeline.
Given a .csproj file that looks like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageVersion>1.0.0.1</PackageVersion>
<AssemblyVersion>1.0.1812.201</AssemblyVersion>
<FileVersion>1.0.1812.201</FileVersion>
</PropertyGroup>
<ItemGroup>
<Content Include="Assemblies\*">
<Pack>true</Pack>
<PackagePath>lib\$(TargetFramework)</PackagePath>
</Content>
</ItemGroup>
</Project>
Again, if we ignore the versioning step that we use, the dotnet pack task in the pipeline image above will produce a package with the version 1.0.0.1-Beta.
Then in your stable release stage, don't set the suffix value and let the package get its version from the .csproj file like normal (eg. 1.0.0.1).
The elements and values in the sample .csproj file above can be written as direct edits to the .csproj or they can be set using the Properties >> Package tab.
If the values are not changed in the properties menu or added explicitly, the elements and values do not appear in the .csproj and are assumed by dotnet build|test|pack commands.
Finding the right combination of these properties and values can be daunting if you aren't familiar with how they're fitted together. I found this article useful when trying to decipher the version properties.
Also, you should understand 1.0.1-b2 < 1.0.1, so your pre-release version might be 1.2.3.2-beta1 and your stable version would be 1.2.3.2.
As the package version is included the moment you perform 'nuget pack', which you would generally perform during build, it might become a bit complicated to change that version afterwards.
What may be interesting in your case is using the concept of views in Azure Artifacts, this would allow you to promote a package to the release view at a later state without having to rebuild the package.
There is a nice extension on the marketplace that would allow you to do this from within a release: https://marketplace.visualstudio.com/items?itemName=rvo.vsts-promotepackage-task
using this flow you can have the packages in the pre-release view/feed as long as you like and make them available in the release view whenever you see fit.
downside of this is that the packages are not identified as pre-release packages by Nuget as you would not be packaging them with the proper semver for that

How do I build a VSTS project with an absolute-path reference folder?

I have two projects in TFS, WebSite and Reference, and they follow the structure:
$\
WebSite: Main project to be built
Reference: Repository with many referenceable dlls.
Website.dll uses dlls existing at Reference but, for several reasons, they are not contained in the same solution, and may be mapped to different folders that do not follow the VSTS structure.
So, in order to have the Website project compiling locally, the Reference's.dlls Hintpath at Website.csproj have been manually changed to a specific, absolute path, common to all developers' machine.
Now, we're experiencing with CI/CD, and we're thrilled with the hypothesis of having VSTS doing the dirty, tedious work of building/deploying. Thing is, since Reference.dll is not in the same project as Website, building ends up lacking essential libraries (the aforementioned Reference folder) and fails.
Is there a way of telling VSTS to GET Reference's dlls (which are compiled at this point), copy them to the directory Website.csproj is being built at and let them be used to build the main project?
What I've tried:
First:
Map Website and Reference in the Get Sources step
Using a Copy Files task, set Source FOlder as $\References and Target Folder as $(Agent.BuildDirectory)
Build
Now:
Added all the references in the main project.
In both cases, none of the references are found, and the
The type or namespace name '(namespacehere)' could not be found (are you missing a using directive or an assembly reference?)
errors are thrown.
I've been searching through the vsts help section, but can't seem to find any obvious solutions.
Any help is greatly appreciated.
It’s mainly caused by the Reference's dlls are not added in source control (TFVC repo).
First, please make sure you add the Reference's dlls into the website project. So the project file will contain the reference as below (ClassLibrary1.dll as the reference in below example):
<Reference Include="ClassLibrary1">
<HintPath>..\..\ClassLibrary1\ClassLibrary1\bin\Debug\netstandard2.0\ClassLibrary1.dll</HintPath>
</Reference>
Then you can use any of below options to make the referenced dlls work.
Option 1: add the referenced dlls into source control
If you have added .tfignore file into your TFVC repo, it will ignore files and folders under **\bin, so the reference dlls not checkin to TFVC repo by default. You can follow below options to checkin the reference dlls into TFVC repo:
Exclude the reference dlls in .tfignore
Exclude the dlls you want to refer in .tfignore. The format is:
!**\referencename.dll
Such as !**\ClassLibrary1.dll.
Add the reference dlls into source control
In VS -> Source Control Explorer -> Add items to folder -> selected the dlls.
Checkin and double check the dlls are added into TFVC repo
In VS pending changes window, there will show the dlls and the .tfignore file as Inculded changes, checkin the changes.
And double check the dlls are added into TFVC repo in VSTS web page.
Option 2: build the reference project before building website project
If you do not want to add the dlls into source control, you can also build the reference solution firstly so that the reference dlls will generate before build the website project. Details as below:
Edit build definition -> add VS Build task (specify reference solution) before building website project -> Save and queue the build.
Note: for option 2, the build configuration you specified in the relative path should be consistent with the build configuration in VSTS build definition.
Such as I specified Debug in the relative path ..\..\ClassLibrary1\ClassLibrary1\bin\Debug\netstandard2.0\ClassLibrary1.dll. So in my VSTS build definition, VS build task to build the reference project, the build configuration must be Debug.
Now, no matter which option you are using, VSTS build will not show the error message The type or namespace name '(namespacehere)' could not be found.
The correct way to approach this is to not store references in source control. Turn them into packages, store them in a package management feed, and restore them during build. Developers will automatically restore them on build.

Should I publish the nuspec file in a repository?

When creating an open source library on GitHub or another public website, should I publish the .nuspec file that describes the corresponding NuGet package?
I've done this a couple of times (since no API key or other sensitive information is included in the .nuspec file) in order to allow myself to easily publish subsequent versions without keeping private file, and to allow other people to fork it and add their own descriptions easily. However, the developers of many top packages don't seem to publish .nuspec files in their repositories (sometimes they publish NuGet.exe along with a .targets file, and so on), so I'm thinking that maybe I'm doing something wrong.
The package authoring should be considered part of the source code since it is a required asset to build the fully usable output.
Some projects use special msbuild-based tooling to create the nuspec file during the build so it seems like there is none in the repository. the new "SDK-based" projects (e.g. .NET Standard libraries) have integrated nuget tooling to be able to create a nupkg file from the csproj without the need to create a nuspec file. This tooling is also being adopted by some popular packages (e.g. Newtonsoft.Json).

Configuring Nuget pack for prerelease on VSTS

Note
If there is an easier way to create prerelease packages please let me know!
I am using Visual Studio Team Services and have setup a nuget pack and publish step.
I have a build variable called $(BuildSuffix) that allows me to tag build-specific variables onto the end of the build number format like so
$(Build.DefinitionName)_1.0.$(date:yyyy)$(date:MM)$(date:dd)$(rev:.r)$(BuildSuffix)
The idea then is that I can set $(BuildSuffix) to -beta so that my final build version might be Build_1.0.20170119.2-beta.
According to the nuget documentation here, appending -beta to a build number will create a prerelease package. The build in VSTS comes out with -beta appended but the nuget pack stage never seems to contain it. It always comes out as the exact version number but without the -beta tag.
My nuspec files look like this:
<package >
<metadata>
<id>MyCompany.Data</id>
<version>$version$</version>
My NuGet package step looks like this:
After some research and bashing my head against a brick wall I figured out how. You have to:
Configure a local Build Agent
Install Nuget CLI
On Nuget Packager Task set Path To NuGet.exe to the NuGet CLI
Set NuGet Arguments on the same screen to -suffix beta
With new NuGet task(version 2) you can specify Additional build properties and there you can pass your custom build number directly instead of using -suffix NuGet argument. Additional build properties are substituting $token$ with supplied value in nuspec and you are free to change whatever you want in there.
I also see it on your screenshot, but I never tried to use it like this with older NuGet tasks as those are deprecated now.
Maybe it will be helpful to try import NuGet Packaging Task Group definition I am using on my private projects. Check it out Here.