How to reproduce old/previous builds in TFS Build? - tfs

Environment:
TFS 2018 with source code in TFS Git
developers are using gitflow-like workflow (main, develop and short-lived feature branches)
there is a build definition used for CI (off of develop branch)
... and another one for releases (off of main branch)
as project evolves build definitions get updated (new steps, etc)
What is the best approach that allows reproduction of previous builds (or, at minimum, release builds)? (in case if previously made build was lost in boating accident)
Ideally I need to be able to plug in version (e.g. 8.5.12345.1) somewhere, press OK and eventually receive data identical to that produced by corresponding build in the past.

Your best approach is to switch to YAML builds and releases. That way your pipeline is versioned together with the code.
If you don't do that, you may need to clone your build and releases every time you make breaking changes.
Alternatively, use the version diff view in your pipeline to go back to an older version or use the json to create a new definition using the API.
Upgrading to Azure DevOps Servers 2020 will give you more advanced YAML features not yet available in Team Foundation Server 2018.
Note: for truly reproducible builds, you'll need to also find a way to lock the build tasks themselves, TFS and Azure DevOps will automatically roll forward to the latest minor version of a given build task. While task authors should try to prevent any breaking changes in those minor upgrades there are no guarantees. You can also never rely on any tool installers that use a v2.x notation or a task that relies on latest. Azure DevOps isn't ideally suited for full reproducible builds.
You can pin task versions in YAML now, if I remember correctly, this was added in Azure DevOps 2020.
You can set which minor version gets used by specifying the full version number of a task after the # sign (example: GoTool#0.3.1). You can only use task versions that exist for your organization.
See: https://learn.microsoft.com/en-us/azure/devops/pipelines/process/tasks?view=azure-devops&tabs=yaml#task-versions
The Tasks docs offer special scripts to pin the versions of out-of-the-box tasks as well.

Related

Upgrade from TFS 2017 to Azure DevOps - build/release pipeline

My company is considering upgrading our on prem TFS 2017 update 3 to the latest Azure DevOps Server (notably, the on prem variety).
During discussions about that possibility, one key stakeholder claimed that if you upgrade, all of your build and release pipelines would have to be rebuilt from scratch. We have a healthy number of build and release definitions in TFS 2017.
I have looked for the answer in the Microsoft documentation about what exactly gets upgraded, but unfortunately I can't get the level of granularity which would prove or disprove the above claim. On the surface it would seem like a horrible upgrade story if it were true. But I also understand that designs and architectures change and upgrades aren't always possible.
Could somebody let me know whether the build and release pipelines can survive the upgrade more or less unscathed? Knowing this would be a valuable data point as we work toward a decision.
Thanks in advance!
The vNext build definitions and the release pipeline I would expect would be pretty lift and shift. Depending on the tasks that you have defined, they might no longer be supported or there might be new versions. The UI will let you know that new versions are available.
A lot of the new focus is building out the features for the YAML build definitions. If you want to leverage those, you'd have to do a lot more rework of converting those vNext tasks into YAML. But converting is not really a hard requirement.
You mentioned that you aren't using the XAML build definitions, but if you happened to be using them, I would image that is where a lot of the rework comes in. Having done that in the past, I can say it is a pain if you have to do it.
all of your build and release pipelines would have to be rebuilt from scratch.
I've tested it and it won't lose any data after upgrading. We should use scheduled backups to ensure that we always have backups in place in case something goes wrong.
we can use that new hardware to do a dry run first, and then we will wipe everything clean and use it again for the production upgrade.
For our dry run, the steps for our upgrade will be:
Copy recent database backups to our new SQL instance.
Install TFS 2015 on our new application tier.
Use scheduled backups to restore the database backups.
Run through the upgrade wizard, being sure to use a service account which does not have any permissions in our production environment. See Protecting production in the dry run in pre-production document for more information.
Optionally configure new features which require changes to our existing projects.
The production upgrade steps will be quite similar. There the steps will be:
Take the production server offline using TFSServiceControl's quiesce command. The goal here is to ensure that the backups we use to move to our new hardware are complete and we don't lose any user data.
Take new backups of each database.
Copy the backups to our new SQL instance.
Install TFS 2015 on our new application tier.
Use the scheduled backups wizard to restore the database backups.
Run through the upgrade wizard, using our desired production service account.
Optionally configure new features which require changes to our existing projects.
You can refer to this doc for more details.

TFS 2017 Build Numbering

We have upgraded from TFS 2013 to TFS 2017, One feature we are trying to implement that we had in 2013 was the ability to have a custom build number. the previous method we had a file called BuildVersion.XML which during the first build step would read the major,minor, and revision and name the build with that build number + 1 on the revision. It would then change then checkout and update the revison number and check in the new version. I know that there are steps where people update the AssemblyInfo. The issue is that not all our code is .net apps. we also now have SSIS Packages, Cordova iOS/android apps, angular sites, aws Lambda functions with node.js which do not have the concept of AssemblyInfo. is there an easy way to implement this?
You can do exactly the same thing in Team Build in TFS 2017.
You can update the build number from any task by calling:
Write-Verbose -Verbose "##vso[build.updatebuildnumber]1.2.3.4"
Add a PowerShell task and add an inline script to read from your file and update the build number with the above.
You can then have additional scripts that use the build number any way you need to version your application.
You can see the full list of logging commands here
https://github.com/Microsoft/vso-agent-tasks/blob/master/docs/authoring/commands.md
You can use my VSTS TFVC tasks to interact with source control, though I do not recommend it. I built these tasks for clients of mine who were doing exactly what you are doing.
Instead of relying on a file in source control it would be a much better solution to pass the BuildNumber from the Build Definition along to the build, have one of your first steps update the files on disk with the correct version number then run your build.
If you manipulate files during the build and check them in you run the risk of inconsistent numbering when you scale up to multiple build agents, it's hard to use in combination with parallel builds and build variable multiplexing and it becomes notoriously hard to do Gated Checkins and Shelveset builds. Plus, it limits your options to move to Git in the future.

TFS Build Definitions and release management best practice with mutliple branches and solutions

I'm currently using Team Foundation Server 2015 (Update 2) and wanting to use the new build definitions and release management and wondering what the best practice is around creating build definitions when using multiple branches.
We have multiple branches and there will also be multiple solutions in each branch (for this example i'll call them WinApp.sln, WebApp.sln & MobileApp.sln).
Our project branches are something like the following...
Project
Dev
Main *** This is our development branch for new features
Updates
1.2 *** This branch is used for any bug fixes for version 1.2
Main
Releases
1.1
1.2 *** Current release branch that will be deployed to customers
Using the new build definitions in TFS 2015 is it best to create a new build definition for each of the branches or each of the applications in each branch.
For example I create the following build definitions:
AppName.Dev.WinApp
AppName.Dev.WebApp
AppName.Dev.MobileApp
AppName.Updates.1.2.WinApp
AppName.Updates.1.2.WebApp
AppName.Updates.1.2.MobileApp
AppName.Release.1.2.WinApp
AppName.Release.1.2.WebApp
AppName.Release.1.2.MobileApp
And then that would flow through to the release management by having release definitions like the following:
AppName.Dev
AppName.Updates.1.2
AppName.Release.1.2
Each release definition will have artifacts added for each of the 3 solution builds.
Or would it be better to just have 1 build definition for each branch?
Would be interesting to know what other people are doing in similar situations.
Previously with the xaml based builds, we had multiple build deifnitions because whenever we released a new build template, we did not want the older release build definitions impacted, hence we maintained multiple build definitions. We also maintained that for the sake of the version the build gets.
But, with the new vNext builds in place there is no way we can have a previous version of a task available to use once we enhance a task and upload it to the TFS all build definitions start using the latest task and there is no way(other than renaming a task) by which we can select a task of older version. So, I think it would be of no use to maintain multiple build definitions, as the build definitions are going to get updated if a task is updated.
There is a case where we require to maintain a version for a specific release and if the number depends on the builds triggered, in that case we'll have maitain different build definitions becuase our patches cannot have the latest version number.
One more reason to maintain different build definition is to escape from the headache of remembering what tasks were used in a specific release previously.
So all in all I'll go with different build definitions to avoid versioning chaos and to maitain integrity of a release build definition.
When it comes to release,we bind a build definition to a release definition. So, again to have a smooth bug fix and update, different release definition for each build definition has to be present.

TFS 2012: Correllating binaries to builds and source code

I'm starting to dive into TFS 2012 and I have a basic understanding of the tiers and how build servers, controllers and agents work and how different build scripts can have different configurations and projects.
However, one of the things I'm struggling with is a requirement for our source control solution that says that I need to be able to prove a particular changeset or shelfset produced a particular build. That is, given a particular binary, I can point to a release changeset that generated that binary. I should also be able to point to the test changeset that was merged into the release branch. The idea here is not just a separation of duty, but validating that because the release and test changesets are identical, no code was injected into a project by a code reviewer.
I've read one blog post that talks about "Binary promotions" -- would that concept be useful in my situation? I'm having a hard time finding how this binary promotion is set up in TFS.
Deployment
Out of the box TFS doesn't really support deployments, it can deploy to 1 location on build which often is a test server (think lab management). TFS 2012 has built in support for Azure deployments, but they still happen at the end of a build and the build artifacts cannot be automatically deployed to a new location.
You could modify the build template to allow to release to different locations, but that would still be a fresh build for every environment and not true binary promotions.
TFS does, however, have a concept of build quality and actually fires off events when this quality is changed. TFS Deployer is a 3rd party tool that hooks into the quality change event and can execute powershell scripts. This means with a simple change of a dropdown value you can automatically kickoff a script that releases to any environment you want. You can customize the build quality list (per team collection) to be a list of environments (dev, uat, staging, production etc) which the script then figures out where to release the specific build to.
VS2012 also has some nice improvements to web deploy which means deployment configurations are stored in source control with the project, which in theory means they'll be available in the drop folder for TFS Deployer to make use of.
I don't believe TFS keeps a history of build qualities, which means you can't really use the build quality history to maintain a list of what is deployed to which environment. You could fairly easily record this information as part of the deployment script though. Or at the very least add a custom summary node to the build with information about the release.
TFS2012 does have the ability to mark a build as deployed as part of the Azure deployment functionality, you mark tfs deployer builds as deployed using a script but it doesn't feel very useful.
Octopus Deploy is another project that's worth checking out, and could be used instead of TFS Deployer if your build template creates NuGet packages. It requires a bit more control over the production hardware as you need to install agents on each environment to handle releases, but it solves a lot of other issues with deployment.
Versioning
Once you have a nice consistent way of automatically releasing that people don't bypass, you can look at enhancing the build template to inject the build version, or changeset number as the assembly version for anything built as part of that automated build. There's a number of different ways to do it and plenty of blog posts and tools to help you achieve that.
Alternatively you could just use automatic assembly versioning ([assembly: AssemblyVersion("1.0.*")]) to give you the date/time the build occurred, which ends up like 1.0.1234.123 where 1234 is something like the days since jan 1st 2000, and 123 is the minutes since midnight (my specifics may be wrong here).
If you're deploying websites, then I highly recommend injecting the current build version into the html somewhere. This way you can check what version a website is running without needing access to the bin directory. It can also be appended as a querystring to css/js file imports to ensure no browser caching occurs between versions.
Thoughts
Personally I'm hoping Microsoft realise that the xaml build workflows are trying to do too much and that they split the different concerns (build, test, deployment...) into different scriptable parts. Of course that would not be until the next major release of TFS which is years away. Although with Team Foundation Service they are trying to iterate a lot quicker, so they may actually extend the Azure deployment stuff into something more useful in the nearer future.

Build Pipelines in TFS

In 2009, there was a SO question on the same topic.
I'm wondering if later versions of Team Foundation Server are better at longer build pipelines. Refer features of Jenkins, TeamCity, ThoughtWorks' Go (my employer).
The visualizations of the build pipelines are important to me, as well as the notification about individual stages passing or failing. That and the eminent clone-ability of say a 'trunk' pipeline into one for a release branch as that branch leaps into being.
Secondly, a personal holy-grail is the CI server storing its config in the SCM that's holding the buildable thing itself, and even picking up on the creation of branches silently to provision new pipelines; Can TFS be configured to store the CI definitions/scripts in its SCM side rather than its accompanying SqlServer?
TFS build consists of three components:
The build definition - stored on the SQL server data tier.
The build workflow - a XAML file stored in the source control.
The supporting MSBuild scripts - usually contains user defined actions, also stored in the source control.
As the build progresses, you can see visualization of the build steps and you also get a different log for the main build and the MSBuild output.
The build definition in TFS is merely a collection of build settings, similar to CC.Net's config file and TeamCity's build configuration tab which both stored on the file system as well. Assuming there's a backup plan on the database you don't really need to store the build defintions on the source control, but if you must it's possible by exporting the tbl_BuildDefinition table.
The TFS Power Tools adds cloning functionality for build definitions.
There's no OOTB support for provisioning build definitions from a new branch though it's fairly feasible using the TFS-API.
Bit late to the party, but just don't bother with TFS if you want advanced build pipeline automation. It simply doesn't cut it.
I have used Jenkins and TFS both extensively. Tfs is just. pure. crap. Here's why.
No down/up stream build.
No piepline/orchestraion build. (like jenkins)
Obscure ways of adding build steps and falls back to using MsBuild.
Slow and still polls the source control.
Ties you to MsTest.
And please don't point me to "Oh look you can do everything if you write a custom activity". I'm not wasting time doing development for a closed source, sub-par platform. If I am going to contribute something, it's to a FREE. OPEN SOURCE platform.

Resources