--- Sjoerd Hooft's InFormation Technology ---

User Tools

Site Tools



Recently Changed Pages:

View All Pages

View All Tags

WIKI Disclaimer: As with most other things on the Internet, the content on this wiki is not supported. It was contributed by me and is published “as is”. It has worked for me, and might work for you.
Also note that any view or statement expressed anywhere on this site are strictly mine and not the opinions or views of my employer.

Pages with comments

2019/11/18 13:52 1 Comment

View All Comments


Creating a Build and Release Pipeline in TFS 2018

After installing all requirements we can now create a build and release it to the deployment group.

Create Code


When you created the project, somewhere in the project was a change to initialize the repostory and add some code to the project. Make sure you have a folder in your code with a recognizable name like “code” and make sure you have an index.html file in there so you actually have something to deploy. Because we need a html file that we can modify with data that is collected with PowerShell you could use this html/bootstrap template:

<!DOCTYPE html>
<html lang="en">
  <title>SHIFT Portal</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="">
  <script src=""></script>
  <script src=""></script>
  <script src=""></script>
<div class="jumbotron text-center" style="margin-bottom:0">
  <h1>SHIFT Portal</h1>
<div class="container-fluid" style="margin-top:30px">
  <div class="row">
    <div class="col-sm-12">
      <h2>VM environment</h2>
      <h5>Refreshed on: __SHIFT-DEVELOPMENT-REFRESHEDDATE__ </h5>
      <h5>Number of VMs: __SHIFT-DEVELOPMENT-NUMBEROFVMS__ </h5>
      <h5>In use for: </h5>
      <p>Note: Notes for this environment</p>
      <a href="" role="button" class="btn btn-danger">Go</a>
<div id="contact" class="jumbotron text-center" style="margin-bottom:0">
  <p>Contact information</p>
Note that there is already an environment with variables that will be replaced in the process.


We will also need a powershell script to provide the information to replace the variables in the html code. Create a folder in the code repository called powershell and add a script called for example vminfo.ps1:

# mgtpass is now a string so must be converted
$mgtpasssec = ConvertTo-SecureString -String $mgtpass -AsPlainText -Force
#Testing with variable secrets - Note that the $mgtpass appears in the logfile as ***** and the $mgtpasssec as "System.Security.SecureString"
Write-Host "Read user $mgtuser"
Write-Host "Read pass $mgtpass en $mgtpasssec"
# Connect to scvmm 
$vmmserver = "vmm.shift.local"
$mgtcreds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $mgtuser,$mgtpasssec
Get-SCVMMServer $vmmserver -Credential $mgtcreds
# Collect all clouds
$clouds = Get-SCCloud
# Get vmcount and fill array
ForEach ($cloud in $clouds){
	#Create temporary object to store information
	#$temp = "" | Select DTAPName,VMCount,Created
	$cloudname = $
	$vmcount = (Get-SCVirtualMachine -cloud $cloud).count
	### Get creationtime of oldest VM
	$oldestvm = Get-SCVirtualMachine -cloud $cloud | sort {(get-date $_.creationtime)} | select -First 1
	$oldestvmdate = $oldestvm.creationtime
	### Use write-host to store found information as system environments for TFS
	write-host "Cloud $cloudname has $vmcount VMs and was probably created on $oldestvmdate"
	Write-Host "##vso[task.setvariable variable=$cloudname-NumberOfVMs]$vmcount"
    Write-Host "##vso[task.setvariable variable=$cloudname-RefreshedDate]$oldestvmdate"
Notice it would even be nicer to also have the vmm server provided in the same way as the user and the password.

Also notice that the build agent as installed here needs to have the proper PowerShell modules installed. You can install the SCVMM console on the server which will also install the required powershell modules.

Create Build

Follow these steps to create a build:

  • In your project, go to Build and Release and select the Builds tab.
  • Click +New, and unless you know what you're doing select to start with an empty process
  • Provide a name, and in the agent queue make sure to select the pool you created earlier
  • Click Save & Queue and select save to only save the build definition.

You have now created an empty build definition.

Add Tasks

We will now add a couple of tasks to the build definition to make sure we get the correct files.

PowerShell: Get VM Variables

We need to run the script so follow these steps to add a taks:

  • Click + Add Task to add a taks to the build definition and select PowerShell (you can drag the task to change the order of tasks)
    • Version: 1.*
    • Display Name: Get VM Variables
    • Type: File Path
    • Script Path: powershell/vminfo.ps1 (you can click the three dots on the right to browse to the script)
    • Arguments: -mgtuser "$(automationaccount)" -mgtpass "$(automationaccountpass)"

PowerShell: Get System Variables

The variables set with the script above will be set as system variables, so we can create an additional powershell task to display all variables into the log so we can check of the variables were set correctly:

  • Click + Add Task to add a taks to the build definition and select PowerShell
    • Version: 1.*
    • Display Name: Get System Environment Variables
    • Type: Inline Script
    • Inline Script: get-childitem -path env:*

You can now run a testbuild to check if the variables are set correctly.

Replace Tokens in Index.html

To replace the variables in index.html we need the Replace Tokens extensions we added earlier:

  • Click + Add Task to add a taks to the build definition and select Replace Tokens
    • Version: 3.*
    • Display Name: Replace tokens in index.html
    • Target files: /index.html
    • Missing Variables: Action: Log warning and select Keep Token
    • Under Advanced change the token prefix to __ (double underscore)
    • Under Advanced change the token suffix to __ (double underscore)

Publish Artifact

Now that we have created a build we need to store the files (also known as an artifact) to a temporary directory so the release can pick this up for deployment:

  • Click + Add Task to add a taks to the build definition and select Publish Artifact
    • Version: 1.*
    • Display Name: Publish Artifact HTMLCode
    • Path to publish: code (you can click the three dots on the right to browse to the folder containing your html code)
    • Artifact Name: HTMLCode
    • Artifact Type: Server
Note that when your run a build now you can go to the build by clicking on the build number and then to Artifacts, and select Explore to actually see the files that are stored in the temporary folder and download them for inspection to check if everything went well.

Create Release

Follow these steps to create a release:

  • In your project, go to Build and Release and select the Releases tab.
  • Click the + and select Create Release Definition
  • Select the “IIS Website Deployment” template
  • Provide a name for your environment, for example Test, Acceptance or Production
  • In the Environment section Click on the phase and tasks link. It shows a red exclamation sign as it needs more data
    • Click on the IIS Deployment phase
    • Select the Deployment Group from the dropdown box we created earlier
  • Click Save

You have now created a Release definition, but it won't work yet. In our artifact we did not create a zip file, but we just have some code, which means we have to change the file(s) that have to be deployed. For easy browsing, we will first add the artifact so we can browse to the files later on.

Note that the default name for the Release is “New Release Definition”. You can change this by hovering your mouse over the name and clicking the pencip icon which appears when you do so.

Add Artifact

You need to add the artifact which was published in the build. Click on the pipeline tab, click on +Add in the Artifact section and select the Artifact from the Source dropdown.

Change IIS Web App Deploy Task

In the pipeline tab, in the environments section, click the phase and tasks link again. Select the IIS Web App Deploy Task and change the “Package or Folder” from the default:

  • $(System.DefaultWorkingDirectory)\**\*.zip
    • to:
  • $(System.DefaultWorkingDirectory)/HTMLCode/htmlcode (you can click the three dots on the right to browse to the folder)

Configure CI/CD

Continuous Integration

If you want every commit you make in the code to be automatically added in the build, you can enable Continuous Integration (CI). Follow these steps to do so:

  • Go to your build definition and select Edit
  • Go to the triggers tab
  • Enable the Continuous Integration switch
    • Optional: If you expect to do a lot of commits close after each other enable the “Batch changes while a build is in progress”
  • Click Save

See here for more information on preventing an automatic build on each checkin, while still keeping Continuous Integration enabled.

Batch Changes

From here:

Select this check box if you have a lot of team members uploading changes often and you want to reduce the number of builds you are running. If you select this option, when a build is running, the system waits until the build is completed and then queues another build of all changes that have not yet been built.

Daily Trigger

In the same section where you enable CI you can also enable a scheduled build. If you enable the Scheduled trigger you get a default schedule to build on weekdays at 03:00 (AM). You can modify this, but unfortunately only for weekly schedules. It is not possible yet to create a monthly schedule, or a one-time scheduled build.

Continuous Deployment

If you want every build to be automatically deployed into an environment you can enable Continuous Deployment (CD). Follow these steps to do so:

  • Go to your release definition and select Edit
  • Click the little lightning bolt icon on the top right corner of the artifact on which you want to set the CD trigger
  • Enable the Continuous Deployment switch
  • Click Save
Note that if you have multiple environments you can add approvals to prevent the release to also deploy to the next environment

Next Steps



Enter your comment. Wiki syntax is allowed:
N᠎ A H L S
tfsbuildrelease.txt · Last modified: 2020/02/25 12:59 by sjoerd