SHIFT

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

User Tools

Site Tools


tfsbuildrelease
Differences

This shows you the differences between two versions of the page.

Link to this comparison view

tfsbuildrelease [2021/09/24 00:25] (current)
Line 1: Line 1:
 += Creating a Build and Release Pipeline in TFS 2018 =
 +
 +After [[tfs2018|installing all requirements]] we can now create a build and release it to the deployment group. 
 +
 += Create Code =
 +
 +== HTML ==
 +
 +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:
 +
 +<code html>
 +<!DOCTYPE html>
 +<html lang="en">
 +<head>
 +  <title>SHIFT Portal</title>
 +  <meta charset="utf-8">
 +  <meta name="viewport" content="width=device-width, initial-scale=1">
 +  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
 +  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
 +  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
 +  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
 +</head>
 +<body>
 +
 +<div class="jumbotron text-center" style="margin-bottom:0">
 +  <h1>SHIFT Portal</h1>
 +</div>
 +
 +<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="https://www.getshifting.com" role="button" class="btn btn-danger">Go</a>
 +    </div>
 +  </div>
 +</div>
 +
 +<div id="contact" class="jumbotron text-center" style="margin-bottom:0">
 +  <p>Contact information</p>
 +</div>
 +
 +</body>
 +</html>
 +</code>
 +
 +> Note that there is already an environment with variables that will be replaced in the process. 
 +
 +== PowerShell ==
 +
 +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:
 +
 +<code powershell>
 +Param(
 +   [string]$mgtuser,
 +   [string]$mgtpass 
 +)
 +
 +# 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 = $cloud.name
 + $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"
 +}
 +</code>
 +
 +> 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 [[tfs2018|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 [[tfs2018|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 [[tfs2018|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 [[tfs2018|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 [[tfsholdci|here]] for more information on preventing an automatic build on each checkin, while still keeping Continuous Integration enabled. 
 +=== Batch Changes ===
 +
 +From [[https://msdn.microsoft.com/en-us/library/vs/alm/build/define/triggers|here]]:
 +<code>
 +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.
 +</code>
 +
 +== 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 =
 +
 +You can also add [[tfspsselenium|automatic testing using selenium and powershell]]. 
 +
 += Resources =
 +
 +* [[https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml&viewFallbackFrom=vsts#secret-variables|All predefined variables]]
 +
 +
 +{{tag>devops scripts iis}}
  
tfsbuildrelease.txt ยท Last modified: 2021/09/24 00:25 (external edit)