TeamCity - Run Build

Octopus.Script exported 11/03/2020 by harrisonmeister belongs to 'TeamCity' category.

Trigger a specific Team City build from an Octopus Deploy process and wait for the result. The step will fail if the build fails.

Parameters

When steps based on the template are included in a project's deployment process, the parameters below can be set.

BuildConfigurationId

tcrb_TeamCityBuildConfigurationId

The Id of the build configuration to trigger.

TeamCityUrl

tcrb_TeamCityUrl

The URL of the Team City server. E.g. http://teamcity.example.com

TeamCityUsername

tcrb_TeamCityUsername

The username to use for accessing TeamCity.

TeamCityPassword

tcrb_TeamCityPassword

The password for the TeamCity user.

TeamCityInterval

tcrb_TeamCityInterval = 5

Number of seconds to wait between each check of the build's state.

BuildParameters

tcrb_BuildParams

Line-delimited list of parameters to add to the build in the form = and can be contained in quotes. E.g. param1=param_value1 env.param2="env_param2" system.param3=sys_param2

Script body

Steps based on this template will execute the following PowerShell script.
Show script
# Set TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12

$teamCityBuildConfigId = $OctopusParameters['tcrb_TeamCityBuildConfigurationId']
$teamCityUrl = $OctopusParameters['tcrb_TeamCityUrl']
$teamCityUsername = $OctopusParameters['tcrb_TeamCityUsername']
$teamCityPassword = $OctopusParameters['tcrb_TeamCityPassword']
$teamCityInterval = [int]::Parse($OctopusParameters['tcrb_TeamCityInterval'])
$teamCityBuildParams = $OctopusParameters['tcrb_BuildParams']

function Start-TeamCityBuild($Url, $Username, $Password, $BuildConfigId, $BuildParams) {
    $endpoint = "${Url}/httpAuth/app/rest/buildQueue"
    $content = "<build><buildType id=`"${BuildConfigId}`" /><properties>"
    if (-not [String]::IsNullOrEmpty($BuildParams)) {
        foreach ($param in (ConvertFrom-Csv -Delimiter '=' -Header Name,Value -InputObject $BuildParams)) {
            $name = $param.Name.Replace('"', '&quot;')
            $value = $param.Value.Replace('"', '&quot;')
            $content += "<property name=`"${name}`" value=`"${value}`" />"
        }
    }
    $content += "</properties></build>"    
    $encodedContent = [System.Text.Encoding]::UTF8.GetBytes($content)

    Write-Host "Triggering build with Id ${BuildConfigId} in TeamCity. Server: ${Url}"

    $req = [System.Net.WebRequest]::Create($endpoint)
    $req.Credentials = New-Object System.Net.NetworkCredential($Username, $Password)
    $req.Method = "POST"
    $req.ContentType = "application/xml"

    $req.ContentLength = $encodedContent.length
    $requestStream = $req.GetRequestStream()
    $requestStream.Write($encodedContent, 0, $encodedContent.length)
    $requestStream.Close()

    $resp = $req.GetResponse()
    $reader = New-Object System.IO.StreamReader($resp.GetResponseStream())
    $result = [xml]$reader.ReadToEnd()
    $buildUrl = $result.build.webUrl

    Write-Host $buildUrl
    Write-Host "================================================================================"

    return $result
}

function Get-TeamCityBuildState($Url, $Username, $Password, $BuildInfo) {
    $href = $BuildInfo.href
    $buildId = $BuildInfo.id
    $endpoint = "${Url}${href}"

    Write-Host "Getting state of build ${buildId} in TeamCity. Server: ${Url}"

    $req = [System.Net.WebRequest]::Create($endpoint)
    $req.Credentials = New-Object System.Net.NetworkCredential($Username, $Password)
    $req.Method = "GET"

    $resp = $req.GetResponse()
    $reader = New-Object System.IO.StreamReader($resp.GetResponseStream())
    return [xml]$reader.ReadToEnd();
}

function Invoke-TeamCityBuild ($Url, $Username, $Password, $BuildConfigId, $Interval, $BuildParams) {
    $build = Start-TeamCityBuild -Url $Url -Username $Username -Password $Password -BuildConfigId $BuildConfigId -BuildParams $teamCityBuildParams
    $buildInfo = $build.build

    while ($true) {
        $buildState = Get-TeamCityBuildState -Url $teamCityUrl -Username $teamCityUsername -Password $teamCityPassword -BuildInfo $buildInfo
        Write-Host $buildState.build.state
        if ($buildState.build.state -eq 'finished') {
            return $buildState.build
        }
        
        Start-Sleep -Seconds $Interval
    }
}

$buildResult = Invoke-TeamCityBuild -Url $teamCityUrl -Username $teamCityUsername -Password $teamCityPassword -BuildConfigId $teamCityBuildConfigId -Interval $teamCityInterval -BuildParams $teamCityBuildParams
$message = $buildResult.statusText
Write-Host "================================================================================"
Write-Host $buildResult.webUrl
if ($buildResult.status -eq 'FAILURE') {
    Write-Host "Build failed: ${message}"
    exit 1
}
elseif ($message -eq 'Canceled') {
    Write-Host "Build canceled: ${message}"
    exit 2
}
else {
    Write-Host "Build successful: ${message}"
    exit 0
}

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

Show JSON
{
  "Id": "a7fa3e51-14aa-4bb9-8686-781adc9bf93e",
  "Name": "TeamCity - Run Build",
  "Description": "Trigger a specific Team City build from an Octopus Deploy process and wait for the result. The step will fail if the build fails.",
  "Version": 3,
  "ExportedAt": "2020-11-03T09:42:34.506Z",
  "ActionType": "Octopus.Script",
  "Author": "harrisonmeister",
  "Packages": [],
  "Parameters": [
    {
      "Name": "tcrb_TeamCityBuildConfigurationId",
      "Label": "BuildConfigurationId",
      "HelpText": "The Id of the build configuration to trigger.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "tcrb_TeamCityUrl",
      "Label": "TeamCityUrl",
      "HelpText": "The URL of the Team City server.\nE.g. `http://teamcity.example.com`",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "tcrb_TeamCityUsername",
      "Label": "TeamCityUsername",
      "HelpText": "The username to use for accessing TeamCity.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "tcrb_TeamCityPassword",
      "Label": "TeamCityPassword",
      "HelpText": "The password for the TeamCity user.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Sensitive"
      }
    },
    {
      "Name": "tcrb_TeamCityInterval",
      "Label": "TeamCityInterval",
      "HelpText": "Number of seconds to wait between each check of the build's state.",
      "DefaultValue": "5",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "tcrb_BuildParams",
      "Label": "BuildParameters",
      "HelpText": "Line-delimited list of parameters to add to the build in the form <name>=<value>\n<name> and <value> can be contained in quotes.\nE.g.\nparam1=param_value1\nenv.param2=\"env_param2\"\nsystem.param3=sys_param2",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "MultiLineText"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptBody": "# Set TLS 1.2\n[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12\n\n$teamCityBuildConfigId = $OctopusParameters['tcrb_TeamCityBuildConfigurationId']\n$teamCityUrl = $OctopusParameters['tcrb_TeamCityUrl']\n$teamCityUsername = $OctopusParameters['tcrb_TeamCityUsername']\n$teamCityPassword = $OctopusParameters['tcrb_TeamCityPassword']\n$teamCityInterval = [int]::Parse($OctopusParameters['tcrb_TeamCityInterval'])\n$teamCityBuildParams = $OctopusParameters['tcrb_BuildParams']\n\nfunction Start-TeamCityBuild($Url, $Username, $Password, $BuildConfigId, $BuildParams) {\n    $endpoint = \"${Url}/httpAuth/app/rest/buildQueue\"\n    $content = \"<build><buildType id=`\"${BuildConfigId}`\" /><properties>\"\n    if (-not [String]::IsNullOrEmpty($BuildParams)) {\n        foreach ($param in (ConvertFrom-Csv -Delimiter '=' -Header Name,Value -InputObject $BuildParams)) {\n            $name = $param.Name.Replace('\"', '&quot;')\n            $value = $param.Value.Replace('\"', '&quot;')\n            $content += \"<property name=`\"${name}`\" value=`\"${value}`\" />\"\n        }\n    }\n    $content += \"</properties></build>\"    \n    $encodedContent = [System.Text.Encoding]::UTF8.GetBytes($content)\n\n    Write-Host \"Triggering build with Id ${BuildConfigId} in TeamCity. Server: ${Url}\"\n\n    $req = [System.Net.WebRequest]::Create($endpoint)\n    $req.Credentials = New-Object System.Net.NetworkCredential($Username, $Password)\n    $req.Method = \"POST\"\n    $req.ContentType = \"application/xml\"\n\n    $req.ContentLength = $encodedContent.length\n    $requestStream = $req.GetRequestStream()\n    $requestStream.Write($encodedContent, 0, $encodedContent.length)\n    $requestStream.Close()\n\n    $resp = $req.GetResponse()\n    $reader = New-Object System.IO.StreamReader($resp.GetResponseStream())\n    $result = [xml]$reader.ReadToEnd()\n    $buildUrl = $result.build.webUrl\n\n    Write-Host $buildUrl\n    Write-Host \"================================================================================\"\n\n    return $result\n}\n\nfunction Get-TeamCityBuildState($Url, $Username, $Password, $BuildInfo) {\n    $href = $BuildInfo.href\n    $buildId = $BuildInfo.id\n    $endpoint = \"${Url}${href}\"\n\n    Write-Host \"Getting state of build ${buildId} in TeamCity. Server: ${Url}\"\n\n    $req = [System.Net.WebRequest]::Create($endpoint)\n    $req.Credentials = New-Object System.Net.NetworkCredential($Username, $Password)\n    $req.Method = \"GET\"\n\n    $resp = $req.GetResponse()\n    $reader = New-Object System.IO.StreamReader($resp.GetResponseStream())\n    return [xml]$reader.ReadToEnd();\n}\n\nfunction Invoke-TeamCityBuild ($Url, $Username, $Password, $BuildConfigId, $Interval, $BuildParams) {\n    $build = Start-TeamCityBuild -Url $Url -Username $Username -Password $Password -BuildConfigId $BuildConfigId -BuildParams $teamCityBuildParams\n    $buildInfo = $build.build\n\n    while ($true) {\n        $buildState = Get-TeamCityBuildState -Url $teamCityUrl -Username $teamCityUsername -Password $teamCityPassword -BuildInfo $buildInfo\n        Write-Host $buildState.build.state\n        if ($buildState.build.state -eq 'finished') {\n            return $buildState.build\n        }\n        \n        Start-Sleep -Seconds $Interval\n    }\n}\n\n$buildResult = Invoke-TeamCityBuild -Url $teamCityUrl -Username $teamCityUsername -Password $teamCityPassword -BuildConfigId $teamCityBuildConfigId -Interval $teamCityInterval -BuildParams $teamCityBuildParams\n$message = $buildResult.statusText\nWrite-Host \"================================================================================\"\nWrite-Host $buildResult.webUrl\nif ($buildResult.status -eq 'FAILURE') {\n    Write-Host \"Build failed: ${message}\"\n    exit 1\n}\nelseif ($message -eq 'Canceled') {\n    Write-Host \"Build canceled: ${message}\"\n    exit 2\n}\nelse {\n    Write-Host \"Build successful: ${message}\"\n    exit 0\n}\n",
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.Script.ScriptFileName": null
  },
  "Category": "TeamCity",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates/teamcity-run-build.json",
  "Website": "/step-templates/a7fa3e51-14aa-4bb9-8686-781adc9bf93e",
  "Logo": "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",
  "$Meta": {
    "Type": "ActionTemplate"
  }
}

History »