Showing posts with label TFS. Show all posts
Showing posts with label TFS. Show all posts

Monday, June 20, 2016

Links for Powershell

Microsoft Team Foundation Server Client - Nuget package to integrate with TFS (version control, work item tracking, build, etc via REST APIs

Get Started with the REST APIs - shows the url format, usage, etc for TFS REST APIs.

TFS API Part 33 - Get Build Definitions and Build Details - example of how to get Build definition details.

Creating a Build Definition using the TFS 2013 API - actually in C#, but should work for Powershell also.

Pester - PowerShell testing. Support in VS2015 now.

NuGet Links

NuGet Package Restore - tells how to configure NuGet, TFS, etc to support different NuGet restore models.

Migrating MSBuild-Integrated solutions to use Automatic Package Restore

New-NuGetPackage Powershell script - create and publish NuGet packaes using a .nuspec or project file from Explorer or Powershell.

NuGet Package To Automatically Create Your NuGet Packages

TFS 2015 Build: NuGet restore from an internal repository

Friday, April 22, 2016

TFS 2015 Build Highlights

Goals of new system
  • Web based
  • Simple customization
  • Real-time output
  • Versioning of build definition
  • Build pools - share build agents across projects and collections
  • Cross-platform - even Mac and Linux
  • Full support for XAML-based builds
Build Overview
  • Templates
  • Web Applications
  • Unit Testing
  • Staging and drop locations
  • Azure Deployment
  • Powershell

Build Definitions
  • Web based
  • Several Templates 
  • No XAML templates, but still supports them
  • My Dev Machine produces the same outputs as TFS will
  • Task gallery
  • Auditing (changes are logged with notes if desired).
  • Web based diff tool.
Running a Build
  • Real-time log view
  • Project by project breakdown
  • Build Outputs
Build Customization
  • Settings
  • Variables
  • Triggers
  • Versioning of build
  • Draft (not published yet)
  • Templates - reuse
Hosted Agent
  • Visual Studio Online (not on premise)
  • One build at a time (No XAM L Builds)
  • < 1 hr
  • < 10 GB storage
  • No admin rights
  • Can't log on
  • Run on Visual Studio Online, not your agent
  • No interactive mode

Configuration
  • Options
  • Multi-configuration
  • Staging & build drop
  • Templates
Deployment
  • Deployment templates
  • Azure
  • PowerShell

Friday, April 1, 2016

Branching Strategy for Agile team desiring continuous integration that must work with a restriction of a slow release cycle

Solution Requirements:

  1. Continuous Integration - Frequent integration of code changes to limit big scary merges. Avoid long periods without merging back for others to see.
  2. Changes to UAT - Allows for a release to stabilize at a slow pace than development.
  3. What is approved in UAT is what gets released to production.
  4. Hot fixes to Production - Allow for emergency changes to a production release
  5. Parallel UAT and Development - Development should be considered working, but not ready for production. UAT would a candidate for release to production pending user approval.
  6. Code Reviews - each feature should be code reviewed. Ideally any merging that is done by everyone is be done at the feature level, but the developer making the changes can commit changes more often. Thus once the feature is done, it can be bundled up, code reviewed, and merged and ultimately released.
Goal: 
Deliver software with a high level of confidence. Confidence to be derived from unit tests, integration tests, BDD tests (End to End tests), and UAT user approval. This implies that what was approved in UAT is what should be moved to production.

A compromised Solution:
The solution we weretempted to implement is best described in the post A successful Git branching model by Vincent Driessen, but we are using TFS, not Git. It is basically says, each feature is done in a branch, though I would add that changes should be pulled from the develop branch DAILY. Ideally, we should be able to look at the develop branch and see features branches being merged in, not individual commits. The individual commits would have been done to the feature branch itself.This makes it easy to see what is in the develop branch and also when they are merged to the release branch and the main branch it is again at the feature level.

Once a feature passes all regression tests (unit tests, integration tests, BDD tests) and has been code reviewed it can then be merged into the develop branch. Ideally a feature branch would be only a few days. If it is longer than a few days the feature should be merged into the develop branch to avoid a big scary merge. If a feature is not finished by the end of a sprint and part of the feature has been merged to the develop branch, but part is unfinished a feature toggle (See Feature toggles note below on how these can be implemented) should be added so that it is not accessible to the user.

A feature should be merged into the release branch by the develop responsible for it once they are confident (passed unit tests, integration tests, BDD tests, and exploratory testing) it is ready for release (pending UAT approval). Unless a specific need comes up, we will only have one release branch and label each release in it when it is merged into master (main). A separate versioned release branch can be created if needed though.

If a change (bug fix, enhancement, etc) is need to the release branch because of something that needs to be changed in UAT the change should be made on the release branch and then merged to the develop branch. 

Similarly, if an emergency change (hotfix) is needed on the production code, the change should be made on the master (main) branch. It should then be merged into the develop branch and eventually to the release branch (as part of the usual merging into release branch process).

A label should be created automatically or explicitly when merging from development to release and then to master (main).

In the end this may not work so well when trying to continuously integration. It can work if the branches are short lived enough. The real issue is the unknown time it takes to integration when the effort for the integration of branches is large and the unknown time needed to stabilize after the integration and before release. This tends to be needed at least once before a release. Smaller more frequent integrations has proven to be a more stable amount of effort required and the code base tends to keep the code base stable when using feature toggles (feature hiding).

Refactoring is an exception to this strategy and the changes should be merged immediately to minimize difficult merges. This make this strategy not as useful unfortunately.

NOTE: This strategy could probably work by merging branches (both to and from the develop branch) at least once a day. The question is what is the benefit of doing a branch then? Branching is for isolation of development and successful continuous integration demands not being isolated. A compromise may work as well such that the branching on the develop branch is removed and instead everyone develops on the develop branch. A branch should not live more than 3 days to be considered short lived.


A Better Approach: 
Have one mainline (no other branches unless doing a bugfix for UAT or production). The key is that the mainline is ALWAYS deployable. Use feature toggles for every feature and enable or disable as needed to make current release stable or that what is enabled is deployable. Remove old feature toggles after not needed anymore. Use labels for each release or deployment. It has the advantage of always integrating, and only create a branch if needed in the case of an emergency hotfix or something. Alternatively, the mainline could be released for the hotfix if all previously unreleased feature toggles are still turned off, but that is a judgement call based on the situation. Note, the release label would be on the new branch in this case and then merged back into the mainline immediately. It is simple to manage and could work very well for open source or fast moving projects that can release as desired. It may be a bit difficult to use for processes where there is a lengthy UAT approval cycle by end users. This difficulty can be mitigated by making the change to the mainline, disabling the appropriate feature toggles and putting in UAT again. Could work well for a continuous deployment model too I would think. This entire model (as does any CI/CD model) relies on having automated regression tests.

Some guidelines:

  • Avoid branches - Branches should only rarely used. For example, only use branches for things like releases or spikes. In general things that will not be used again. 
  • No long-lived branches - Long-lived branches are opposed to successful continuous integration and should be avoided at all costs. This includes things like refactoring, long term development, etc. Instead use feature toggles (feature hiding).
  • Integration Daily - Get the latest from the mainline and Commit to the mainline at least once a day
  • Pass tests - all tests should still work BEFORE (and after) checking in your changes. This helps keep the mainline deployable.
  • Incremental changes - It may take a little longer to do a bigger change in smaller incremental changes, but the effort and time spent is worth the effort because the mainline is always deployable.
Optional:
  • Label or Branch for releases - A branch or label can be created just before a release. Once created testing and validation of the release is done from this branch. New development is performed on the mainline. i.e. Only critical bug fixes are done on the release branch and immediately merged back to mainline. Branches are always off the mainline, not existing release branches.
References:
A successful  Git branching model - what we are implementing here
Feature Toggles - enable / disable features using compile or runtime flags to make a feature visible to the end user. Pete Hodgson's perspective on how to implement / issues is here. Martin Fowler says this.
Branching and Merging: Ten Pretty-Good Practices
Continuous Delivery by Jez Humble and David Farley. See chapters on Chapter 13: Managing Components and Dependencies, and Chapter 14: Advanced Version Control.
Some different version control implementations - worth looking at since they are bit simpler than the successful git branching model.

Wednesday, March 23, 2016

Calling Powershell script in TFS 2013 Build Definition

Overview
The Build Definition Default template in TFS 2013 has added the ability to execute Powershell scripts before and after a build (Pre-build and Post-Build). This is different than the pre/post build scripts in Visual Studio. This is much easier than customizing the build template as was required in earlier version of TFS. TFS 2015 is different again, but I believe will still use Powershell scripts for extending its functionality.

Your Powershell Script
You will need to put the Powershell script in a file (a good thing) and reference it in the Pre-build script path or Post-build script path properties of the Process | Build | Advanced screen. There are corresponding Pre-build script agruments and Post-build script arguments properties as well that allow parameters to be passed to the Powershell scripts.

To avoid additional issues or configuration you may want to keep the file in the same path in TFS Source Control. If you don't want or need it to be under source control you can put it directly on the TFS Controller server and reference that path.This can be notably easier for experimenting, but you'll lose the benefits of source control unless manually keep changes in source control.

Logging 
Shows up under the Diagnostics tab (TFS web | your TFS project | Build tab | your build definition | Diagnostics tab)
Write-Host
Write-Output
Write-Warning
Write-Verbose

NOTE: If you want the Write-Verbose calls to show up you need to add [CmdletBinding()] attribute to the beginning of your .ps1 file AND add -verbose to the Pre-Build script agruments property in the build definition.

Environment Variables

  • $env.TF_BUILD_BUILDDEFINITIONNAME
  • $env.TF_BUILD_BUILDDIRECTORY
  • $env.TF_BUILD_BUILDNUMBER
  • $env.TF_BUILD_BUILDREASON
  • $env.TF_BUILD_BUILDURI
  • $env.TF_BUILD_DROPLOCATION
  • $env.TF_BUILD_SOURCEGETVERSION
  • $env.TF_BUILD_SOURCESDIRECTORY
  • $env.TF_BUILD_TESTRESULTSDIRECTORY
You can also put dir anywhere in the Powershell script to see all the environment varialbes.

NOTE: Much of this information is actually gathered from here.
Good information specific to TFS2013 can be found here.