After downloading TFS 2015 RC, I wanted to create a simple build of my web app. The goal was to have a v.next build do the same thing as my xaml build. I wanted the build to get the latest code from source control, compile everything, run unit tests, then drop the build artifacts in a drop location along with a _PublishedWebsites folder with the web app all ready for an xcopy deploy. Here is a walkthrough of what I did. This walkthrough will show you how to create a v.next build, how to lay out the drop location the way you want it, and finally, this walkthrough will show you how to create a custom build step using PowerShell.
Inside of Team Explorer, click on Builds
Click on New Build Definition to create a new v.next build
This brings up the new build editor in the TFS 2015 RC web portal. An empty new build definition is shown. I want to use the Visual Studio build template (since I want to build a visual studio solution). So click on the green plus button
This brings up the pre-installed definition templates. Select the Visual Studio template and click the ok button
Now I see the visual studio build template along with two build steps. Visual Studio Build and Visual Studio Test. I’m going to go out on a limb and guess the the Visual Studio Build step will build whatever solution I pick and the Visual Studio Test step will run whatever test assemblies it finds. The first thing I want to do is configure the Visual Studio Build step to build my solution. So I select the Visual Studio Build step and click the ellipse button after the Solution parameter.
This brings up the Select Path dialog. I browse and select my solution and click ok.
Everything else looks good I think so I click on Visual Studio Test to configure the test step. If I’m reading this correctly, it looks like it’s going to run any dll’s that are in my build configuration folder that are name anything test anything except for anything in the obj directories. That looks good enough for me. Now I click on the Options section to see what options I can set.
This brings up the Options page. It looks like it’s going to build once for each platform and configuration and if one fails, it will continue with the build. It also looks like it will copy all the bin folders to a staging folder and will deploy it to the Server. For this demo, I want my build drop to be on a file share. So I click on the file share radio button and put in my drop location path.
I then click on Repository and it looks like I can select which Repository I want to pull from (I am using a git repo). I leave the defaults and click on Variables where build variables are defined. It looks like this build defaults to building both a debug and release configuration for any cpu. I’m fine with this so I leave everything as default. Triggers looks like I can set whether I want this to be a CI build or Scheduled. For this demo, I want to do manual builds so I’ll leave both checkboxes empty. Under the General section, it looks like I can set which build queue I want to send this build to. I can also give a description to this build, determine the build number format, the build timeout and if badges are enabled. I’m not sure how the build badges work so I’ll leave that alone for now. Finally, there’s a section for Demands where I can add tags that the build machines need in order to run my build. I leave everything as default and go on to Retention. Here I can set the retention rule for my build. I’ll leave this as default too. Finally, I go to the History tab where I can see the history for this particular build. And by history, I mean, who made what changes to this particular build. Yay! Versioning is now added to builds!!!!. I now click on the save button to save this build.
This brings up the Save dialog where I give my build a name and comments on what I did.
My DemoBuild now shows up in the tree on the left hand side. I want to queue a build and see what happens so I click the Queue build button.
This brings up the Queue Build for DemoBuild dialog. I select my Default Agent Pool (I will blog about creating build queue’s and adding build machines in a later blog) and just chose the defaults and click the OK button.
This kicks off my build and I watch while the build happen in real time. Looks like everything built. Hooray for that.
Now, let’s check the build drop… And this is what I see
Very interesting… It looks like the build just copied all the binary folders (per project) directly to where I said the drop folder is. It didn’t add a folder for the build name and then a folder for the build number like the xaml build does. Ok, no issues. I can probably set up the build to do that. Let’s take a look at our build again. I go and edit the build and go to the Options section.
I bet if I add the build name and build number to the path, it will do what I want. But how do I access the build name and build number? Here is a list of all the pre-defined build variables we can use. The build name is Build.DefinitionName, the build number is Build.BuildNumber. The folder structure that I want should be \\BlogVM\BuildDrop\$(Build.DefinitionName)\$(Build.DefinitionName)_$(Build.BuildNumber). I fill that in for the path and save the build.
This brings up the Save dialog where I enter a comment and click the OK button. Now let’s queue another build and see what happens. First, I clear out my drop location, then I fire up the build. When it completes, my drop location now looks like this:
Ok, cool. Looks like under my Build drop, I get the Build definition name. And under the build definition name I get the folder BuildName_BuildNumber. And under that, I have folders for all the projects, and under them I have the binaries. All that is fine. However I want my _Published website folder with the website ready for xcopy (like in a xaml build). So what I want is under the BuildName_BuildNumber folder, I want a folder called _PublishedWebsites and under there, I need a folder called the web app, project name, and under there, should be everything ready for xcopy. To do that, I’ll add a build step. What I want to do is copy the correct files and folders from the build sources folder over to the staging folder. The build sources folder is Build.SourcesDirectory (the environmental variable is BUILD_SOURCESDIRECTORY) and the staging folder is at Build.StagingDirectory (the environmental variable will be BUILD_STAGINGDIRECTORY). When I browse and look at the sources directory, it is just a get latest from the repository.
It should be relatively simple to create a powershell script that will copy everything under the WebApplication1 folder (that’s the folder with my web app) under the correct folder of the staging folder. And anything copied to the staging folder will be moved to the drop location. Here is my power shell script.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# Given the name of a web app project, this script packages up the web app during a build # gets it ready for an xcopy deploy and copies it to the staging folder under # _PublishedWebsites\$webApp #grab the web app name from the command line argument param( [string]$webApp ) Write-Host "web app: " $webApp #grab the staging and source folder from environmental variable $stagingFolder = $env:BUILD_STAGINGDIRECTORY $sourceFolder = $env:BUILD_SOURCESDIRECTORY Write-Host "staging folder: " $stagingFolder Write-Host "source folder: " $sourceFolder # copy all the files except for .cs, .csproj, .user and .gitignore and user folders files to the _PublishedWebsites\Website Name folder $source = $sourceFolder + "\" + $webApp $dest = $stagingFolder + "\_PublishedWebsites\" + $webApp Write-Host "copy source: " $source Write-Host "copy destination: " $dest $exclude = @('*.cs', '*.csproj', '*.user', '*.gitignore') Get-ChildItem $source -Recurse -Exclude $exclude | Copy-Item -Destination { Join-Path $dest $_.FullName.Substring($source.length) } # remove empty folders Get-ChildItem $dest -recurse | Where {$_.PSIsContainer -and ` @(Get-ChildItem -Lit $_.Fullname -r | Where {!$_.PSIsContainer}).Length -eq 0} | Remove-Item -recurse #remove unwanted folders obj $objFolder = $dest + "\" + "obj" Remove-Item $objFolder -Force -Recurse |
I save this file and name it PackageWebApp.ps1 and store it in my git repo under the folder BuildSteps. This way, my build can get and run this PowerShell script.
Now, go back to the web portal and edit the build. I need to add a build step so click the Add build step button
This brings up the Add Build Steps dialog. Click Utility and the add button next to Run a PowerShell script, the click the Close button
This adds a PowerShell build step as the last build step. I need to edit the values for this step so click on the PowerShell build step
This brings up the variables for the PowerShell build steps. I want to change the name so click the pencil button next to Powershell.
This brings up the Rename dialog. For Name, enter in Package Web Application1 and click the OK button
To chose which powershell script to run, click the ellipse button next to Script filename
This brings up the Select Path dialog. Browse to PackageWebApp.ps1 and select OK
Now I need to pass in the name of the web app I want to package as arguments. Type in –webApp WebApplication1 in the Arguments field and click Save
This brings up the save dailog. For comments, enter what changed and then click OK
After queuing a build, my drop folder now looks like this
Sweet! Looks like it worked. I now have my _PublishedWebsites folder under my drop, with the web site ready for xcopy! After playing around with the new build system, I really like it. It’s simple and straight forward. Much cleaner than the old xaml builds. Customizing your build with custom build steps using PowerShell is really simple. I know other people have already created a build steps which versions the build dll’s, but I think I want to create one from scratch just to do it. That will be next.
I have TFS 2015, build and controller installed on same server (Server 2012 R2 Standard)
Test Agent and Test controller are installed on windows 8.1.
I am trying to follow the same steps to create build, I go, edit the build and go to the Options section, not getting options “copy to staging folder” and “create build Drop”.
I am using TFS 2015 with update 1 and VS 2015 Enterprise.
Your help will be appreciated.