Only build the project that has changed - azure-devops

I have a single .NET solution with multiple class library projects, each one is published as a nuget feed using azure-devops.
Then I have an azure-devops build pipeline, with steps to Restore, Build, Publish, Pack and Push.
The first 4 steps are setup for **/.csproj and the last is a $(Build.ArtifactStagingDirectory)/.nupkg with the target feed.
I have everything set up and working, except if you make a change to just one project, it builds ALL projects because of the **/*.csproj.
This is no good for nuget packages, as it increments every project's version number and they all appear as having an update available in the nuget package manager.
My Question: Is there a way to do this so that only the project(s) with changes go through the process?

Is there a way to do this so that only the project(s) with changes go through the process?
The answer is yes.
The solution is use the private agent to build your solution instead of the hosted agent.
That because every time the hosted agent assigned to us is a clean machine, VS/MSbuild will build all the projects for the setting **/* csproj. So, to resolve this issue, we must save the results of the last build to achieve incremental builds.
So, to resolve this issue, we need to set up a private agent to build those projects and do not clean the working directory of your private agent before the build is run:
Set the Clean option to false on the Get sources:
Note: Since you also set the **/*.csproj for the task nuget push, if the project not modified, this command will push the same version to the feed, it will throw the conflict error, you need enable Allow duplicates to be skipped on the nuget push task:
Hope this helps.

Related

Dependencies between BuildConfigurations in TeamCity when deploying

I'm having a hard time figuring out how to correctly deploy to different environments with TeamCity (in terms of cross BuildConfiguration dependencies) and hope to get some input as to how to configure my SubProjects/BuildConfigurations properly. Lets start based on a concrete example: I made this test "TeamcityConfigurationTests" to better learn how TeamCity handled dependencies, and the current state shows the result i am looking for:
I have 3 subProjects, Dev, Test and Prod - and all associated tasks for those "environments" as seperate build configurations within that subProject. This is to more clearly visualize what is going on, and if anything breaks, to be able to see immediately what is broken (separate Build, UnitTest and DeployToDev BuildConfigurations, rather than 3 different steps in one single Build Configuration).
Ideally, i only want to build my application once in the Dev.Build step, and let the Dev.UnitTest and Dev.DeployToDev steps grab that artifact and run tests and deploy. That i got going for me, by having snapshot and artifact dependencies. But i am having trouble getting the correct artifact when i want to deploy from Dev -> Test or Test -> Prod.
My issue is to correctly reference the latest successfully DEV deployed artifact when running Test.DeployToTest - and the same for getting the latest successfully TEST deployed artifact when running Prod.DeployToProd. (Essentially i want to promote the artifact to the next environment).
Now, my issue is, if I in the Test.DeployToTest have a SnapshotDependency to Dev.DeployToDev and an artifact dependency to Dev.Build, and the VCS source has changed since Deploy to Dev has run, it triggeres running all the DEV steps again. This is not the worst part, the same happens when i run Prod.DeployToProd if the VCS source changed since the initial build on dev (because of all the snapshot dependencies). Meaning, that rather than promoting Test -> Prod, I Build and deploy whatever is currently on VCS to Dev, Test AND Prod.
How am i supposed to set this up correctly?
The only other option i am aware of, is letting Dev.DeployToDev also publish the same artifact, and only have an (LatestSuccessful) ArtifactDependency in Test.DeployToTest. I would also have to publish the artifact again in Test.DeployToTest, for letting Prod.DeployToProd only have a (LatestSuccessfull) artifact dependency to Test.DeployToTest. (This would be to get rid of the SnapshotDependencies causing previous environments to run build/deploy again in case of VCS changes). But then i am publishing the artifact 3 times, rather than just the one time when the application is originally built in DEV - which i would like to avoid. Also, i have cases where no artifact is needed for deploying to Test and Prod, so there is no artifact to depend on (essentially i only need the BuildNumber from the "Dependent" environment i want to promote from).
I hope for some input. Thank you
Regards
Frederik
For anyone wondering, i made a JetBrains support ticket, and got the following response:
Basically, there are options to resolve your case:
Option 1: use "Promote" action form the build's Actions top-right menu
(or change the type of the Deploy* configurations to deployment and
use the action from the block on the build results. This is the
preferred way: before deploying you select the build to deploy and
"promote" it to the next environment. There is also an experimental
hidden feature to hide the "Run" button: add
"teamcity.ui.runButton.caption" configuration parameter in the build
configurations to empty value.
Option 2: do not use snapshot dependency, use only artifact dependency
on the latest successful build. However, when you run the build you
cannot be sure that the last successful build you see will be
deployed: while the build is standing int he queue, another
Dev.DeployToDev can finish and then be deployed as the last
successful.
We went with option 1

Deploying from Appveyor to Nuget only on changes in a particular folder

I have a .NET Core project that is auto-built in Appveyor and deployed to Nuget. By default, every successful build causes a new Nuget release.
However, there are many cases when a new release is meaningless because the library's actual code has not changed:
Readme updated
Unit tests added
Appveyor configuration changed
Other cases
It is possible to configure the build so that Nuget publishing only runs if there are changes in the actual code (for example, in folder X)?
There are a few options.
Commit filtering. Note that with it the whole build, not just deployment will be skipped if nothing in folder x changed. You may need a build without deployment at least when unit tests added. As a workaround consider adding separate AppVeyor project which will build and deploy only if folder x changed and keep current project to build every time, but not deploy
Inspect changed files with script. Please check this sample on how to check those files if you use GitHub. So if you see that files in folder x changed, you can set some custom environment variable (lets say you call it deploy_nuget) to true, and use it with a conditional deployment.

CICD using VSTS

With CICD done, On every commit VSTS creates the build and deploys it to the target environment successfully.
I want to understand how the build is done, is it incremental OR full build every time I commit the change in the .net project.
If anytime I want to rollback, to the previous working build does VSTS does it or I need to configure or follow some procedures to do it hassle free ?
If you are using Hosted agent, it is full build every time. (Need to download source, build whole projects)
If you are using private build agent and do not clear anything (e.g. In Get sources, clean is false; Visual Studio Build task, clean option unchecked), part of build will be up to date if source not be changed. (can just download the updated files and skip some build targets if build results are up to date)
The VSTS can’t rollback the build, you can roll back changes, then rebuild and redeploy. There is a blog about rollback: Implement Rollback with Release Management.

Where is the nuget packages folder located on a hosted build server using TFS?

I need to execute a command line utility from a package that is downloaded as part of nuget package restore in the TFS build process.
On my local computer that is stored in c:\users\me.nuget*
I've tried every permutation of that on TFS without success. I've also tried \mydir\packages with no success as well.
The biggest problem is that I have to run the package restore step before being able to see any sort of feedback from the log. That's some slow debugging.
Any ideas? Thanks ahead.
With the latest nuget/msbuild the packages folder is held under the active user's profile directory, so an appropriate Powershell command is
Get-ChildItem $(UserProfile)\.nuget\packages
This currently evaluates on the VSTS 2017 Hosted build agent to C:\Users\VssAdministrator\.nuget\packages but by using the variable you are insulated from any changes made.
Just an addition to #Paul Hatcher's answer:
I also faced the same problem in Azure DevOps build pipeline where a specific package and nuget packages directory could not be found.
It is a Xamarin.Forms app based on a .net standard library where no packages folder exists. I later noticed in build logs that the packages are restored to nuget folder under user's profile. However this particular case is not documented on https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=vsts#agent-variables.
That means #Paul Hatcher's answer is also valid if you try to reference nuget package folder directly from your build pipeline. This ($(UserProfile).nuget\packages) should actually be a (standard) predefined build variable.
The Nuget package cache folder is in C:\Users\buildguest.nuget\packages, but it will be cleaned after build if you are using Hosted build server.
The simple way to verify:
Add NuGet restore or .Net Core Restore build step to restore packages
Add PowerShell build step to list files in C:\Users\buildguest.nuget\packages
Code:
Get-ChildItem -Path C:\Users\buildguest\.nuget\packages
Queue build and check the PowerShell step log (the packages’ will be listed in the log)
Remove/disable NuGet restore or .Net Core Restore build step > Save build definition
Queue build
The build will be failed, because the path does not exist.
So, the packages need to be restored before build solution/project if aren’t existing. You can add packages to source control and map to build agent to deal with the issue of too long time takes to restore packages.

How to remove the [warning]To connect to NuGet feeds when restoring NuGet packages

I've got a build running in VSTS which is restoring NuGet packages from both nuget.org and a custom feed in VSTS. The custom feed is in the solutions NuGet.config as a <packageSource>, along with the user name and password in <packageSourceCredentials>
The build, including the restore, is working Ok, but there is a warning ...
2016-10-12T16:18:57.6589001Z ##[warning]To connect to NuGet feeds
hosted in your Team Services account/TFS project collection with
NuGet 3.1 or below, edit your build definition to specify a path
to a NuGet.config containing the package sources you wish to use.
How can I remove this?
Based on my test, that warning remains even through using higher version of nugget (e.g. 3.3) or do not restore package from VSTS feed. (Hosted build agent has the same result).
You can’t remove it unless you custom a build task to restore package through command line.
I submit a issue here.
Update:
The issue has been updated.
I see the issue in the code coming from our transition from depending
on assets coming with the agent to being deployed with the task. You
can get around this for now until we get an official change out by
either (1) choosing to use the Nuget 3.5 version radio button in the
task config or (2) supplying a path to your nuget.config.
So, you can use Nuget 3.5 version or specify nuget.config file.