• Blog
  • Info Support
  • Career
  • Training
  • International Group
  • Info Support
  • Blog
  • Career
  • Training
  • International Group
  • Search
logo InfoSupport
  • Latest blogs
  • Popular blogs
  • Categories
      • .NET
      • Advanced Analytics
      • Agile
      • Akka
      • Alexa
      • Algorithms
      • Api's
      • Architectuur
      • Artificial Intelligence
      • ATDD
      • Augmented Reality
      • AWS
      • Azure
      • Big Data
      • Blockchain
      • Business Intelligence
      • Cloud
      • Code Combat
      • Cognitive Services
      • Communicatie
      • Containers
      • Continuous Delivery
      • CQRS
      • Cyber Security
      • Data
      • Data & Analystics
      • Data Science
      • Data Warehousing
      • Databricks
      • DevOps
      • Docker
      • eHealth
      • Enterprise Architecture
      • Hacking
      • Infrastructure & Hosting
      • Innovatie
      • Integration
      • Internet of Things
      • Java
      • Machine Learning
      • Microservices
      • Microsoft
      • Microsoft Bot Framework
      • Microsoft Data Platform
      • Mobile Development
      • Mutation Testing
      • Open source
      • Pepper
      • Power BI
      • Privacy & Ethiek
      • Python
      • Quality Assistance & Test
      • Quality Assurance & Test
      • Requirements Management
      • Scala
      • Scratch
      • Security
      • SharePoint
      • Software Architecture
      • Software development
      • Software Factory
      • SQL Server
      • SSL
      • Start-up
      • Startup thinking
      • Test Quality
      • Testing
      • TLS
      • TypeScript
      • Various
      • Web Development
      • Web-scale IT
      • Xamarin
  • Experts
      • Alles
      • Bloggers
      • Speakers
  • Meet us
  • About us
    • nl
    • en
    • .NET
    • Advanced Analytics
    • Agile
    • Akka
    • Alexa
    • Algorithms
    • Api's
    • Architectuur
    • Artificial Intelligence
    • ATDD
    • Augmented Reality
    • AWS
    • Azure
    • Big Data
    • Blockchain
    • Business Intelligence
    • Cloud
    • Code Combat
    • Cognitive Services
    • Communicatie
    • Containers
    • Continuous Delivery
    • CQRS
    • Cyber Security
    • Data
    • Data & Analystics
    • Data Science
    • Data Warehousing
    • Databricks
    • DevOps
    • Docker
    • eHealth
    • Enterprise Architecture
    • Hacking
    • Infrastructure & Hosting
    • Innovatie
    • Integration
    • Internet of Things
    • Java
    • Machine Learning
    • Microservices
    • Microsoft
    • Microsoft Bot Framework
    • Microsoft Data Platform
    • Mobile Development
    • Mutation Testing
    • Open source
    • Pepper
    • Power BI
    • Privacy & Ethiek
    • Python
    • Quality Assistance & Test
    • Quality Assurance & Test
    • Requirements Management
    • Scala
    • Scratch
    • Security
    • SharePoint
    • Software Architecture
    • Software development
    • Software Factory
    • SQL Server
    • SSL
    • Start-up
    • Startup thinking
    • Test Quality
    • Testing
    • TLS
    • TypeScript
    • Various
    • Web Development
    • Web-scale IT
    • Xamarin
    • Alles
    • Bloggers
    • Speakers
Home » Modifying TFS2015 build definitions using Powershell
  • Modifying TFS2015 build definitions using Powershell

    • By Léon Bouquiet
    • .NET 4 years ago
    • .NET 0 comments
    • .NET .NET
    Modifying TFS2015 build definitions using Powershell

    In this post, I’ll show how to use the TFS2015 REST API from Powershell to update build definitions, in this case to modify build variables. The TFS2015 REST API is well documented and consists of several areas, of which we’ll be using the build definitions API.

    By the way, the TFS2015 Web Portal uses this same REST API as well, so a good way to get to know your way around the API is to monitor the network traffic (for example, using your browser’s developer toolbar) while you’re clicking through the portal to see which parts of the REST API are being accessed.

    I’m using TFS2015 Update 3 in combination with Powershell 5.0 and Json.NET 9.0.1.

    Requesting a JSON build definition

    We’ll start by piecing together the url that contains an overview of all build definitions, and perform a GET request. The -UseDefaultCredentials switch means that the credentials of the currently logged on user should be used to authenticate against TFS.

    $baseUrl = "https://tfs.mycorp.net/tfs"
    $targetCollection = "DefaultCollection"
    $targetProject = "Acme"
    $targetBuildName = "Acme - My Build Definition"
    $definitionsOverviewUrl = "$baseUrl/$targetCollection/$targetProject/_apis/build/Definitions"
    
    $definitionsOverviewResponse = Invoke-WebRequest -UseDefaultCredentials -Uri $definitionsOverviewUrl
    

    This provides us with an overview of all build definitions. The $definitionsOverviewResponse.Content contains a JSON string that, when displayed in Visual Studio, looks like the following:

    BuildDefinitionOverview

    Next, we’ll use ConvertFrom-Json to convert the JSON string to an object representation of this information, so that we can locate the build definition entry with the name we’re looking for. This entry contains the url from which we can request the actual build definition:

    $definitionsOverview = (ConvertFrom-Json $definitionsOverviewResponse.Content).value
    $definitionUrl = ($definitionsOverview | Where-Object { $_.name -eq $targetBuildName } | Select-Object -First 1).url
    
    $response = Invoke-WebRequest $buildDefinitionUrl -UseDefaultCredentials
    

    And indeed, we have received a JSON string with the build definition:

    BuildDefinitionResponse

    Using Newtonsoft.Json from Powershell

    Although the standard ConvertFrom-Json and ConvertTo-Json cmdlets are fine for basic JSON querying, when used to convert a JSON build definition to a PSCustomObject and then back to a JSON string again, the resulting JSON string is not accepted by the TFS2015 rest endpoint – it could have something to do with the behaviour discussed here on UserVoice.

    So instead, we’ll use the widely-known Newtonsoft.Json library to do the manipulation with. To use it from your Powershell script, do the following:

    1. Browse to the Json.NET package on nuget.org
    2. Click the “Download” link in the left area to download the raw nuget package file. This .nupkg file is nothing more than a .zip file with a specific folder structure.
    3. Rename the .nupkg file to end in .zip and extract its contents.
    4. From the \lib\net45\ folder, copy the Newtonsoft.Json.dll file and place it in the same directory as where you’re developing your Powershell script.

    Now we can load the Newtonsoft.Json.dll into our powershell session and use its JsonConvert method. When using the non-generic overload, it converts the JSON data to an object model of JObject, JArray, etc. instances.

    # This assumes the working directory is the location of the assembly:
    [void][System.Reflection.Assembly]::LoadFile("$pwd\Newtonsoft.Json.dll")
    $buildDefinition = [Newtonsoft.Json.JsonConvert]::DeserializeObject($response.Content)
    

    Note that if you write $buildDefinition to stdout, by default JObject‘s IEnumerable implementation will cause Powershell to treat it like an array and display *all* properties of the object model, which is not really intuitive. To display the contents of a JObject as JSON, you should explicitly invoke its ToString() method, i.e.:

    $buildDefinition.ToString()
    

    Modifying a build variable and updating the build definition

    Now that we have the build definition in an object model, we can start manipulating it. For example, suppose we have a build variable named “MajorMinor” which contains the major and minor parts of the version to be used as the build number. Displaying its current value and updating it becomes:

    # JObjects implement IDictionary and therefore support dot notation
    $buildDefinition.variables.MajorMinor.value.ToString()
    $buildDefinition.variables.MajorMinor.value = "3.4"
    

    The modified $buildDefinition can now be serialized to JSON again:

    $serialized = [Newtonsoft.Json.JsonConvert]::SerializeObject($buildDefinition)
    

    Updating the build definition is done by uploading the JSON document to the same build definition url using a HTTP PUT. However, Invoke-WebRequest appears to perform some strange string mangling when it encounters special characters (such as the “é” from my name), and I found that one way to circumvent that is to perform the encoding to UTF-8 ourselves and instead pass it the raw byte data:

    $postData = [System.Text.Encoding]::UTF8.GetBytes($serialized)
    
    # The TFS2015 REST endpoint requires an api-version header, otherwise it refuses to work properly.
    $headers = @{ "Accept" = "api-version=2.3-preview.2" }
    $response = Invoke-WebRequest -UseDefaultCredentials -Uri $buildDefinitionUrl -Headers $headers `
                  -Method Put -Body $postData -ContentType "application/json"
    $response.StatusDescription
    

    Uploading the updated build definition should now succeed with an “Ok” result.

    Modifying multiple build variables

    This seems a bit cumbersome to just update a single variable, but obviously, the real power lies in being able to update multiple build definitions at once. For example, to update the MajorMinor variable of all build definitions that have “Acme” in their name, you can do something like the following:

    [void][System.Reflection.Assembly]::LoadFile("$pwd\Newtonsoft.Json.dll")
    
    $baseUrl = "https://tfs.mycorp.net/tfs"
    $targetCollection = "DefaultCollection"
    $targetProject = "Acme"
    $majorMinor = "3.5"
    
    # Get an overview of all build definitions in this team project
    $definitionsOverviewUrl = "$baseUrl/$targetCollection/$targetProject/_apis/build/Definitions"
    $definitionsOverviewResponse = Invoke-WebRequest -UseDefaultCredentials -Uri $definitionsOverviewUrl
    $definitionsOverview = (ConvertFrom-Json $definitionsOverviewResponse.Content).value
    
    # Process all builds that have "Acme" in their name
    foreach($definitionEntry in ($definitionsOverview | Where-Object { $_.name -like '*Acme*' }))
    {
        $definitionUrl = $definitionEntry.url
        $response = Invoke-WebRequest $buildDefinitionUrl -UseDefaultCredentials
        $buildDefinition = [Newtonsoft.Json.JsonConvert]::DeserializeObject($response.Content)
    
        # If the build has a MajorMinor variable, update it.
        if($buildDefinition.variables.MajorMinor)
        {
            Write-Output "Updating build ""$($definitionEntry.name)""..."
    
            $buildDefinition.variables.MajorMinor.value = $majorMinor
    
            $serialized = [Newtonsoft.Json.JsonConvert]::SerializeObject($buildDefinition)
            $postData = [System.Text.Encoding]::UTF8.GetBytes($serialized)
    
            $headers = @{ "Accept" = "api-version=2.3-preview.2" }
            $response = Invoke-WebRequest -UseDefaultCredentials -Uri $buildDefinitionUrl `
                           -Headers $headers -Method Put -Body $postData `
                           -ContentType "application/json"
            $response.StatusDescription
        }
    }
    

    Obviously, in the same way you could also change paths or arguments in existing build steps, or add new steps.
    Again, the sky’s the limit 🙂

    Share this

Léon Bouquiet

View profile

Leave a Reply

Klik hier om je antwoord te annuleren.

Related IT training

Go to training website

Related Consultancy solutions

Go to infosupport.com

Related blogs

  • Using the OpenCV VideoCapture class with the name of a …

    Using the OpenCV VideoCapture class with the name of a … Michaël Hompus - 2 weeks ago

  • An update on MSBuild.Sdk.SqlProj

    An update on MSBuild.Sdk.SqlProj Info Support - 4 months ago

  • Handling technical ids in Gherkin with SpecFlow

    Handling technical ids in Gherkin with SpecFlow Ronald Bosma - 5 months ago

Related downloads

  • Beslisboom voor een rechtmatig ‘kopietje productie’

  • Klantreferentie: Remmicom zet wetgeving om in intellige…

  • Klantreferentie RDW: Samenwerken voor veilig en vertrou…

  • Klantreferentie BeFrank: Strategische IT voor een innov…

  • Wie durft te experimenteren met data in de zorg?

Related videos

  • mijnverzekeringenopeenrij.nl

    mijnverzekeringenopeenrij.nl

  • Winnaar | Innovation Projects 2017

    Winnaar | Innovation Projects 2017

  • Explore | Info Support & HAN & Poliskluis

    Explore | Info Support & HAN & Poliskluis

  • LifeApps bij HagaZiekenhuis

    LifeApps bij HagaZiekenhuis

  • Info Support | Bedrijfsfilm

    Info Support | Bedrijfsfilm

Tagcloud

.NET .NET 3.5 .NET development Analysis and Design Anything else ASP.NET Azure BI Business Intelligence & DWH C# Coding Design Eclipse Future Stuff General .NET Development Hyper-V Java Microsoft Microsoft general Mobile Office System 2007 Off topic Other PerformancePoint PowerShell reporting services Requirements Management rup SharePoint Portal Server Silverlight software development Software Engineering SQL Server System Center Team System Virtual Server Vista Visual Studio 2008 Visual Studio Team System WCF Windows Server 2008 Windows Server 2008 (aka Longhorn) Windows Sharepoint Services v3 Windows Workflow Foundation WPF

Nieuwsbrief

* verplichte velden

Contact

  • Head office NL
  • Kruisboog 42
  • 3905 TG Veenendaal
  • T +31 318 552020
  • Call
  • Mail
  • Directions
  • Head office BE
  • Generaal De Wittelaan 17
  • bus 30 2800 Mechelen
  • T +32 15 286370
  • Call
  • Mail
  • Directions

Follow us

  • Twitter
  • Facebook
  • Linkedin
  • Youtube

Newsletter

Sign in

Extra

  • Media Library
  • Disclaimer
  • Algemene voorwaarden
  • ISHBS Webmail
  • Extranet