Pretty Build Summary on TFS 2012
Behold the new summary page when you run your builds in TFS 2012:
The output you see above is included by default without any code needed on your part. You can however write your own messages into these sections using the new Write-BuildSummaryMessage cmdlet. This cmdlet only works on TFS 2012. When you specify the “name” parameter of the cmdlet, pass the name of a delivery pipeline code block (“Init”, “Commit”, or “Deploy” for example) to have your message show up in that section.
Delivery Module API
This is a feature I’ve been wanting to add for a while now. One of the nice things about powerdelivery is that instead of having to learn all the moving parts in Windows Workflow foundation, you just have a PowerShell script and CSV files. However, there are some things you might do over and over again in your script that you want to drive with configuration to eliminate having to place code in your script for them. Examples are deploying databases, websites, etc. There are already cmdlets in powerdelivery to do this, but I’ve introduced a new Delivery Module API that can be used to create even more powerful reusable modules for delivering different types of assets.
To create a delivery module, you need to create a regular simple PowerShell module following any of the instructions you’ll find on the web and make sure it’s available to your script (putting the folder that contains it in your PSMODULEPATH system environment variable is easiest). Pick a name that’s unique and from then on you may use that module in your scripts by using the new Import-DeliveryModule cmdlet. If you call this cmdlet by passing “MSBuild” for example, powerdelivery will try and invoke functions that match this name following the convention below:
Where “ModuleName” might be “MSBuild” and “Stage” might be “PreCompile” (for example, Invoke-MSBuildDeliveryModulePreCompile). You can name the functions in your module starting with “Pre” or “Post” to have them run before or after the actual “Compile” function in the build script that imports the module.
If this function is found it is invoked before or after the pipeline stage specified, and you can do anything you want in this function. A common use would be to look for CSV files with values you can pass to existing functions. I’ve included an initial MSBuild delivery module as an example of how to do this. It looks for a file named “MSBuild.csv” and if it finds it, will build any projects using the settings in that file.
I’m still working on this API so any feedback is appreciated.
Build Asset Cmdlets
A common operation in your build script is copying files from the current “working” directory of your build on the TFS build agent server out to the “drop location” which is typically a UNC path. To make this easier I’ve added the Publish-Assets and Get-Assets cmdlets which are quite simple and take a source and destination path. These cmdlets will push and pull between our local working directory and the drop location without having to specify a full path and should simplify your script. The build summary page on TFS will display any assets you publish.
The next two things I will be completing is the integrated help for all included cmdlets (so you can get syntax help in PowerShell instead of on the wiki), and updating the existing templates other than the Blank one to match the new syntax in the 2.0 release. I’ll then be working on getting more templates and delivery modules put together to help you hit the ground running with your delivery automation.
There’s never been a better time to get started looking at continuous delivery with PowerShell and TFS than today. Over the weekend I redesigned powerdelivery to have a cleaner syntax, and allow for quicker installation using chocolatey (a system-wide package manager for Windows based on nuget). This topic describes the redesign as well as how to upgrade older (version 1.0) powerdelivery projects.
The section below describes what’s been changed in powerdelivery 2.
Cleaner build script format
Powerdelivery 1.0 required declaring of script parameters, declaring an app name and version as variables, and adding functions for the stages of your deployment pipeline you want to support. Version 2.0 refines this dramatically by allowing you to invoke the Pipeline function at the top of your script to set the name and version, and then declare code blocks into which the code that executes in each stage goes.
Take a look at the default build template on github for an example of a the new blank script format.
Install with chocolatey
Install chocolatey following the instructions in the website, and then open an administrative command prompt. To install powerdelivery enter the following:
As new releases come out, you now only need to re-run this command to get the latest package setup and configured for use by your build server (or locally, for local builds). Note that this method of installation also has the benefit of providing intellisense in the PowerShell ISE or PowerGUI for all of the included powerdelivery cmdlets.
Environment targets secured by TFS
When you use the Add-Pipeline cmdlet to add powerdelivery to your TFS project, a security group is created that users must be placed in to trigger/queue non-commit builds. This allows IT to control who is allowed to promote builds to the test and production environment and will fail the build with an appropriate error message if you try and circumvent this.
Target TFS version auto-detected
With powerdelivery 1.0 you had to tell the Add-Pipeline cmdlet whether the target TFS server was running version 2010 or 2012. Version 2 detects this automatically and will configure the server appropriately without requiring you to specify anything.
Pipeline promotion order enforced
In powerdelivery 1.0 it was possible (though frowned upon!) to promote a commit build to production, or a test build to commit. This certainly was not intended though the limited audience using it was able to control this.
Version 2 enforces the pipeline promotion order as follows:
- Test, UAT, and CapacityTest environment builds must be promoted from a Commit build
- Production environment builds must be promoted from a Test build
Upgrading to Version 2
Upgrading to version 2 of powerdelivery is fairly straightforward.
- Follow the instructions on the website for installing powerdelivery using chocolatey on your build server.
- Refactor your build script to follow the new format. This should be self explanatory looking at the blank template. A key change is to try and use script instead of global scoped variables in your Init block.
- Locate the directory powerdelivery is installed into (for example, C:\Chocolatey\lib\powerdelivery.XXX). Find the files in the “BuildProcessTemplates” directory and upload these to your TFS project. These are the updated build process templates needed by version 2. We’re working on adding a switch to the Add-Pipeline cmdlet to allow you to do this automatically in the future.
- Remove the PowerShellModules subdirectory of your TFS project. This is no longer necessary as powerdelivery is now loaded as a module via chocolatey. If you had any other modules you were using other than powerdelivery in this directory, either install them as system-wide modules or add the following line to the top of your script:
$env:PSModulePath += “;.\PowerShellModules”
IMPORTANT: Remember to delete the “Powerdelivery” subdirectory of PowerShellModules if you choose to keep this directory.
- You may need to have your TFS administrator add users that were able to queue test and production builds to the security groups controlling who can build to each environment. If you don’t have appropriate permissions to build to an environment you will get an error message during the build that should be self explanatory for helping you figure out which group to add the user to.
The open source powerdelivery project I’ve been blogging about using to enable continuous delivery automation for your software projects has now been updated to support TFS 2012.
Creating new projects using TFS 2012 powerdelivery
To add powerdelivery to a TFS 2012 project, just pass the –tfsVersion parameter to the AddPipeline utility specifying 2012. For instance:
.\AddPipeline.ps1 (other parameters) –tfsVersion 2012
If you are using Visual Studio 2012 as well for your developers, you will probably also want to pass the –vsVersion parameter and specify 11.0 (10.0 is the default, which is Visual Studio 2010).
Upgrading existing projects to TFS 2012 powerdelivery
If you were using TFS 2010 and want to upgrade your server to 2012, to upgrade your powerdelivery-enabled projects to use the 2012 configuration, grab the latest zip from master and add the following files to source control from the source:
Lastly, you will need to edit the Build Process Template for your “Commit” build and set it to use the PowerDeliveryTemplate11.xaml file (instead of PowerDeliveryTemplate.xaml) and edit the rest of your builds (Test, CapacityTest, Production) to set them to use PowerDeliveryChangeSetTemplate11.xaml.
Happy continuously delivering!
I’ll discuss continuously delivering web and mobile applications in a later post, but since I just recently worked on one I’d like to start with guidance for using powerdelivery to deliver a Business Intelligence (BI) solution. This solution might deliver databases, cubes, packages, reports, or SharePoint dashboards like PerformancePoint.
I’ll assume at this point you have a backlog of user stories that describe business capabilities that are desired. You’ve also had your sprint planning meeting and come up with acceptance criteria for what you’re going to build in your first sprint. You desire to iteratively release pieces of acceptance tested BI functionality. You want to reduce your cycle time, and thus the time it takes to go from an idea for BI functionality, until it is delivered to users.
In a nutshell you want to release to users as quickly as possible after an idea is conceived!
Perform the following steps initially by only deploying to your “Commit” (development) build environment. Once you have it working there, you should immediately escalate it to test, and then to production to get your initial release in place even if it has no functionality yet!
Step 1: Create build account
Have your IT administrator create a user account for builds to run under. Configure Team Foundation Server to build using this account (see the TFS agent service on your TFS agent computers).
Step 2: Procure and secure environment
Identify the environments that will be used to deliver your solution. Determine the desired production environment’s physical and virtual nodes (servers or VMs), and procure a development and test environment with at least one node for each scaled point of the production environment. For example, if you have a load balancer with 5 nodes in production, have a load balancer but with just one node in development and test environments. Ideally, you should setup these computers from scratch with identical OS and middleware (SQL server for example) and lock them down only be accessed by the Active Directory build account. All future configuration changes will be made via your build.
Step 3: Open ports
Have your IT administrator open ports for the TFS agent to perform automation activities. Ports 5985 and 5986 must be open on each computer to be automated (development, test, and production database and SharePoint server computers or VMs for example). You also need to open any ports needed to perform other automation activities and send data between computers. Examples are port 1433 for SQL server, or port 2383 and 2384 for SSAS (multidimensional and tabular defaults, respectively). You may also need to open port 137 to allow UNC paths to be accessed.
Step 4: Create delivery pipeline
Next, use the AddPipeline utility to create builds for your deliverable. You want to create a build for each capability you need to independently deploy. If you have databases, SSIS packages, and cubes that all work together to provide one data mart, web site, or BI capability, you may want to keep these in a single build for simplicity of maintenance.
Step 5: Create UNC shares on environment nodes
Create a UNC share on each of your computers that will have SSIS packages, SSAS models, databases, or other assets deployed to them as files. Give write permission to the Active Directory account your build runs under to these shares.
Step 6: Record your environment configuration
Edit the .csv files for your powerdelivery build’s environment configuration and add name/value pairs for each setting that is environment specific. Include settings for things such as:
- Database servers
- Database names
- Computer names
- UNC paths
- Tabular server instances
- Connection strings
Tip: If you have multiple nodes in production and only one in development and test but need to automate configuration, use a PowerShell array as the value in the .csv file and loop over it in your script for each node. For example in production:
Step 7: Identify subsets of data for automated testing
As you identify source data over sprints, create views (if they don’t already exist) to abstract the data and use a database migration technology such as RoundhousE or Visual Studio Database Projects to deploy them with your build. If an existing system that one of your components is sourcing data from has millions of rows, you want to have development versions of these views that only pull a subset of your data suitable for testing. The views in your UAT and production environment will pull the entire data set.
The reason for this is to speed up builds and processing in your commit (development) environment so that automated tests can run and provide feedback faster than what would be necessary when processing the entire set of data. You will need to lean heavily on experts of the data, and business analysts to either identify a subset of data that exists, or script creation in an empty database perhaps of new data suitable for running your tests.
Step 8: Load your environment configuration
Modify your build script to create global variables for all the environment configuration settings you filled out in step 6 in the Init function of the build.
Step 9: Copy assets to the drop location
Modify your build script further by editing the Compile function. Use this function to copy any files you will need during deployment from your current directory (where TFS grabbed a copy of the source code) to the drop location. These files include dlls, SSIS packages, .asdatabase files, .sql scripts, powershell scripts, or any other files that will be deployed to the environment computers.
Step 10: Script environment modifications
If the latest version of your code requires a dependency of a configuration change, use this function to do so.
Examples of things to do here are:
- Set environment variables. Your SSIS packages or other deliverables will pick up the correct settings for each environment.
- Use the Azure PowerShell cmdlets to procure an Azure node or database
- Give security permission to users on SQL databases
- Run NuGet to install .NET dependencies (log4net, Entity Framework etc.)
- Apply OS or middleware patches
- Change security settings of services or file system
Step 11: Script deployment activities
In the Deploy function of your script, you will perform the steps to actually deploy the solution assets. You can only use files in the build’s drop location, so a common problem here will be to try and run something that’s in source control but you didn’t copy in the Compile function. If this happens, go back to step 9.
Examples of things to do here are:
- Run SQL scripts
- Deploy and/or run SSIS packages
- Create and/or run SQL jobs
- Deploy and/or process SSAS cubes (BISM Multidimensional or Tabular)
- Start/stop SQL jobs
Tip: Your script is running on your TFS build agent computer. But many of the deployment utilities used for automation, such as dtexec.exe (to run SSIS packages), or Microsoft.AnalysisServices.Deployment.exe (to deploy cubes) will run on the database or other servers. Because of this, you will often need to copy files that are input for these commands to one of the UNC shares you setup in step 5.
Step 12: Script unit tests
In the TestUnits function of your script, you can run tests that make sure that individual units of your solution work independently. You might use MSTest.exe to run Visual Studio database unit tests written in T-SQL.
Step 13: Script acceptance tests
If you automate one kind of test, at least do the acceptance ones. These are what you described to the business during the sprint planning meeting that you’d show. Read my prior post on defining acceptance if you are new to it.
Because most BI solutions use scheduled batch jobs to do processing, you will need to cause jobs or any other sort of processing to run in the Deploy function in step 11 if you want them available to be tested here.
Since powerdelivery is a synchronous script, you have two options for doing acceptance testing:
Inline publishing of tests
With this approach, your script should run the SSIS packages or SQL scripts that a job normally invokes on a schedule and and wait for them to finish. You can then run your tests immediately after and automate publishing their results if you want business users that access the TFS portal to see the results of your testing.
Late publishing of tests
With this approach, you can let the build finish and wait for scheduled SQL jobs or processing to finish by monitoring the process. When it completes, run your tests using Visual Studio manually and publish them to the build they were run against.
Step 14: Automate restoring test databases from production
To make sure that any database alterations made in production are tested exactly as they will work in production, add a step to the Deploy function to take a production backup and restore it over your test databases prior to running these alterations. Only run this step while doing a test environment build. You can check for this using the powerdelivery Get-BuildEnvironment helper cmdlet.
Promoting your releases
At this point, you should get your build to succeed in the Commit (development) environment and then immediately promote it to Test, and then Production. As you plan sprints, use the knowledge you gained setting up the script to help team members estimate the work it will take to make modifications to the build to deploy and change the environment needed by their features. Include this in your estimate for user stories you deliver in the future.
When one or more team members has their feature passing acceptance tests in the Commit environment, promote that build to your Test environment and have it inspected by QA. If it is of sufficient quality, hold the sprint review meeting. If the business decides to release to production, queue a Production build and release it to your users.
The open source powerdelivery project for doing continuous delivery I’ve blogged about does a lot of things in a small package, so it’s natural to want to understand why you would bother to use it if perhaps you like the concepts of continuous delivery but you’ve been using off the shelf Microsoft Team Foundation Server (TFS) builds and figure they are good enough. Here’s just a few reasons to consider it for streamlining your releases.
You can build locally
TFS lets you create custom builds, but you can’t run them locally. Since powerdelivery is a PowerShell script, as long as you fill out values for your “Local” environment configuration file you can build on your own computer. This is great for single computer deployments, demoing or working offline.
You can prevent untested changes from being deployed
You have to use the build number of a successful commit build as input to a test build, and the same goes for moving builds from test to production. This prevents deployment of the latest changes to test or production with an unintended change since the last time you tested and when you actually deploy to production.
You can add custom build tasks without compiling
To customize vanilla TFS builds, you need to use Windows Workflow Foundation (WWF *snicker*) and MSBuild. If you want to do anything in these builds that isn’t part of one of the built in WWF activities or MSBuild tasks, your stuck writing custom .dlls that must be compiled, checked back into TFS, and referenced by your build each time they change. Since powerdelivery just uses a script, just edit the script and check it in, and your Commit build starts automatically.
You only need one build script for all your environments
You can use the vanilla technologies mentioned above to create builds targeting multiple environments, but you will have to create a custom solution. Powerdelivery does this for you out of the box.
You can reduce your deployment time by compiling only in commit (development)
The Commit function is only called in Local and Commit builds, so you can perform long-running compilation activities only once and benefit from speedy deployments to your test and production environment.
Today I’m beginning a series of posts on Continuous Delivery with Team Foundation Server and Windows PowerShell based on my open source project powerdelivery. The project is already in use at a business intelligence solution for a large healthcare provider.
In 2011 I was working at a large client who had a hard time releasing software. People would forget to make environment changes (like server patches, environment variables, and settings) when doing a production deployment that were in development, and vice versa. The production system would go down and everyone would stress out, and releases happened very infrequently because things were uncoordinated and fragile.
Around that time, I read the book on Continuous Delivery from Jez Humble and found within it a solution. It talks about using a Delivery Pipeline to promote builds through the environments your code runs in so that changes don’t get out of synch with each other. There’s many benefits and techniques to Continuous Delivery other than that, and many of them rely on having a team that follows SCRUM to release in sprints, defining their work with easily demonstrated acceptance criteria, and using automating tests that repeatably do so.
I loved the concepts in the book and wanted to start using them on my own projects. I work for Catapult Systems, a Microsoft Gold Partner as a consultant and our primary platform for builds is Team Foundation Server. Unfortunately TFS gives you an easy way to compile a project with test gates to one environment, but doesn’t give you much for coordinating the promotion of builds from one environment to the next like you’d need for a Delivery Pipeline. So I built one on top of it.
- A framework for writing a single PowerShell script that deploys your software into multiple environments.
- Templates with included build scripts that you can use as a starting point for your builds.
- A mechanism for storing environment configuration settings in .csv files. For instance, your local computer, development, test, and production environment probably use a different database.
- PowerShell cmdlets that help with writing builds.
- Build process templates for Microsoft Team Foundation Server that trigger your script.
- An Add Pipeline utility that will add powerdelivery to your Microsoft Team Foundation Server project.
Where do I get it?
Read the wiki and grab a copy (from source) off of github. You don’t have to compile anything to use it, but you’ll want to read the requirements in the documentation for getting TFS and PowerShell setup.
What’s the delivery workflow?
If you want to release software faster, it’s a given that you need automated deployment capabilities, and an incremental product change process like SCRUM – but you also need confidence in the code base. This confidence comes from having agreement on what the application currently does, and being able to verify quickly at any time that it still works as users expect.
Acceptance defines how you demonstrate it is working
Even in an agile development process such as SCRUM it is of the utmost importance that you define acceptance criteria that can be quickly verified. When the business and the team agree to implement something in a sprint, coding shouldn’t be started until a description exists in English of how to demonstrate that it works properly. This description provides both a script for the developer to demo the functionality to the business, and a set of steps to guide the developer or a QA resource to implement an automated test that verifies it works correctly without requiring manual testing.
It is important that the acceptance criteria leave as little room for interpretation or the need to get more info from the author of the criteria as possible.
Bad acceptance criteria
Go to the products page. Click on a product and enter in purchase details on the next page. Submit the order and make sure there aren’t any errors.
Good acceptance criteria
- Go to http://mydevserver/somepage
- Click the product “My Test Product”
- In the page that appears, enter the following values:
- Name: Test
- Quantity: 6
- Click the “Submit” button
- On the page that appears, the message “Product ‘test’ was added to your cart’ must appear on the page.
- An email must have been sent that includes the subject ‘About your order from XYZ corporation’. The body should contain the message in the attachment to this user story where ‘Product name’ in the attachment is replaced with ‘Test product’ and ‘User’ is replaced with the account you were signed in as when you made the purchase.
Quality products are not an accident
When you haven’t defined acceptance criteria that is either written up or contained in an existing automated test that is self documenting, there is functionality in your application that is subject to change at any time. It can change in that if refactoring is done, the existing functionality can break without catching it with a manual test – but even worse, there is nowhere the team can go to understand its original intent and the reason for its existence in the first place. This leads to incorrect assumptions when enhancements to it are made, disagreement between team members in communicating its operation and intent, and a deceptive view on its completeness.
In a green field project, it’s easier to enforce automated acceptance testing being done as you can hold back kicking off the next sprint until all acceptance tests can demonstrate passing and the features are demoed and accepted by the business. The business and the team get used to the velocity needed to do so, and the rate at which new features are available.
In a brown field (existing) project, chances are there will be significant functionality that already exists for which no automated tests exist, verifying it must be done through manual testing, and in a worse scenario; it may not be tested regularly at all and the business has lost clarity on its behavior and operation. To automate verification of it working properly will cause the velocity of the team to slow down.
When this happens, a team gets into what I like to call “quality debt”. The more features that exist in the application that are unverified, or the longer it takes to verify those features, the more investment it takes to ensure quality of the application – and in turn the slower you can release. This situation is in direct opposition to continuous delivery, and to get your product ready for quicker cycle times a strategy for paying down this debt is crucial. The higher up this scale you are, the lower your debt.
Evaluating acceptance readiness for continuous delivery in existing functionality
If you are on a brown field project and want to set a goal to reduce your release cycle time, the team needs to evaluate each function of the software to determine how far along this progression of acceptance readiness it is.
- Implemented – the software does something in the code, and it was demonstrated at some point. No tests or documents exist that describe it however.
- Partially verifiable – a document or test exists somewhere that describes how the function should work, but it has grown out of sync with changes over time of the feature, or is incomplete and does not cover all cases.
- Acceptance testable – a document exists somewhere that describes how the function should work, but it takes manual effort to verify it each time a release grows near.
- Automated acceptance – Acceptance tests exist that can be run automatically on demand and report their success or failure. They cover all implemented aspects of the feature as of the current sprint.
Pay off existing debt
If your project’s features are not at phase 4 (Automated acceptance), you will need to schedule time in coming sprints to help them get there. I would caution against jumping from implementation to automated acceptance without establishing the acceptance criteria again. If there is no document or test that says what a feature should do, automating it without making sure it meets the needs of the business (and that what it does is understood) is dangerous because your are investing in automating something that is more likely to change. Revisit each existing feature with the business and come up with acceptance criteria first, then automate.
Don’t add new debt
In addition to scheduling a portion of the workload of the sprint to pay down the existing debt, avoid adding to it by defining better acceptance criteria in user stories scheduled for completion that relate to new work. Also require that automated acceptance tests be built before the conclusion of the sprint that prove proper operation of those stories. You will find that you can get less done in the sprint, but at each one’s conclusion you have features that can be released to users with confidence as they can be verified automatically at any time.
The pain only lasts as long as you want it to
The harsh truth is that the more your existing application does that is not automated for acceptance, the more painful it is to get out of debt. An organization can continue to go about business as usual without addressing it, but doing so leaves them at a competitive disadvantage as they take longer to get to market with new functionality. Organizations with better discipline around managing their workload and establishing automatable acceptance processes will respond more quickly to changes in the market, deliver features that meet the needs of their customers faster, and deliver them with more consistent quality.
Wow, never saw this coming. Fantastic move Microsoft! Not much to add to Glenn Block’s post on Codebetter.com so get all the details there. Happy node-ing!
The always divisive David provides an entertaining look at why people are averse to loss as they progress in their careers. He also talks about the illusionary ceilings for education and questions us to think about why we continue to cling to our existing body of knowledge around software, or any topic that is accumulated through years of experience.
I encounter this often, whether talking about continuous delivery, agile development processes, minimalism in tooling, Microsoft’s shift to open technologies on the client, or open source technology use in enterprises. He starts off with some mention of technologies specific to rails, but bear with it as he then leads into the meat of the conversation which is applicable to anyone, and the real gem in the keynote. I’d recommend anyone watch this, especially folks who have decided that certain technologies are not useful – you are the subject of the conversation and may learn some things from it.