Last active
January 24, 2025 20:31
-
-
Save ShepardToTheStars/0d05f53724dc9064c33ef44ca9ca6c90 to your computer and use it in GitHub Desktop.
TeamCity Build Agent Automated Install
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#https://vanessa.louwagie.io/2017/09/08/automated-teamcity-build-agent-install-for-windows-server/ | |
#Agent requires Java to be installed, and have the java bin directory exist in the path directory. | |
Param( | |
#The parent installation directory. Will create [$NumberOfBuildAgents] directories, one for each build agent. | |
[Parameter(Mandatory=$true)] | |
$InstallationDiskDrive = "C:\", | |
#The path to the Java Runtime Environment which the build agent runs on top of. | |
[Parameter(Mandatory=$true)] | |
$JavaPath = "C:\JRE", | |
#The number of build agents to install. | |
[Parameter(Mandatory=$false)] | |
[ValidateRange(1,100)] | |
[int] $NumberOfBuildAgents = 3, | |
#The TeamCity server to download the build agent install from, and connect the agent to. | |
[Parameter(Mandatory=$false)] | |
$TeamCityServerUrl = "http://localhost", | |
[Parameter(Mandatory=$false)] | |
$TeamCityServerPort = "80", | |
#If no service user or password is provided, will install under local system | |
[Parameter(Mandatory=$false)] | |
$NtServiceUser = "", | |
[Parameter(Mandatory=$false)] | |
$NtServicePassword = "", | |
#The start port of the range of ports to set the build agents to | |
[Parameter(Mandatory=$false)] | |
$BuildAgentStartPort = 9091, | |
#Prefix the agent service names with a short string. Ex: abbv- | |
[Parameter(Mandatory=$false)] | |
$SmallPrefix = "" | |
) | |
$ErrorActionPreference = "Stop" | |
function Download-Agent { | |
[Cmdletbinding()] | |
Param | |
( | |
[Parameter(Mandatory=$true)] | |
[string] $InstallDirectory, | |
[Parameter()] | |
[string] $TeamCityServerUrl = "http://localhost", | |
[Parameter()] | |
[string] $TeamCityServerPort = 80 | |
) | |
#Download the agent | |
$_zipFile = "$env:Temp\buildAgent.zip" | |
if(!(Test-Path -Path $_zipFile)) { | |
Write-Host "Downloading build agent zip file from TeamCity server." | |
Start-BitsTransfer -Source "$($TeamCityServerUrl):$TeamCityServerPort/update/buildAgent.zip" -Destination "$env:Temp" | |
} | |
else { | |
Write-Host "Build agent already downloaded. Re-using zip file." | |
} | |
if(!(Test-Path -Path $InstallDirectory)) { | |
Write-Host "Creating installation folder: $InstallDirectory" | |
New-Item -Path $InstallDirectory -ItemType Directory | |
} | |
Write-Host "Expanding the zip file into the installation location." | |
#TODO: Adapt extract method for PowerShell versions under v5 | |
Expand-Archive -Path "$_zipFile" -DestinationPath "$InstallDirectory" -Force | |
} | |
function Configure-AgentProperties { | |
[Cmdletbinding()] | |
Param ( | |
[Parameter(Mandatory=$true)] | |
[string] $BuildAgentRootFolder, | |
[Parameter(Mandatory=$true)] | |
[string] $BuildAgentId, | |
[Parameter(Mandatory=$true)] | |
[string] $BuildAgentPort, | |
[Parameter(Mandatory=$true)] | |
[string] $JavaPath, | |
[Parameter()] | |
[string] $TeamCityServerUrl = "http://localhost", | |
[Parameter()] | |
[string] $TeamCityServerPort = 80 | |
) | |
$_propertiesFile = "$BuildAgentRootFolder\conf\buildAgent.properties" | |
$_distPropertiesFile = "$BuildAgentRootFolder\conf\buildAgent.dist.properties" | |
$_propertiesContent = Get-Content "$_distPropertiesFile" | |
Write-Host "Editing buildAgent.properties file..." | |
Write-Host " Updating serverUrl: $($TeamCityServerUrl):$TeamCityServerPort" | |
$_propertiesContent = $_propertiesContent -replace "serverUrl=http://localhost:8111/", "serverUrl=$($TeamCityServerUrl):$TeamCityServerPort" | |
Write-Host " Updating name: $BuildAgentId" | |
$_propertiesContent = $_propertiesContent -replace "name=", "name=$BuildAgentId" | |
Write-Host " Adding ownPort: $BuildAgentPort" | |
$_propertiesContent = $_propertiesContent -replace "#env.exampleEnvVar=example Env Value", "#env.exampleEnvVar=example Env Value`r`nownPort=$BuildAgentPort" | |
Write-Host " Adding env.TEAMCITY_JRE: $JavaPath" | |
$_propertiesContent = $_propertiesContent -replace "#env.exampleEnvVar=example Env Value", "#env.exampleEnvVar=example Env Value`r`nenv.TEAMCITY_JRE=$JavaPath" | |
Write-Host "Writing changes to file: $_propertiesFile`n" | |
$_propertiesContent | Set-Content "$_propertiesFile" | |
} | |
function Configure-AgentServiceWrapper() { | |
[Cmdletbinding()] | |
Param ( | |
[Parameter(Mandatory=$true)] | |
[string] $BuildAgentRootFolder, | |
[Parameter(Mandatory=$true)] | |
[string] $BuildAgentId, | |
#TODO: Add parameter set | |
[Parameter()] | |
[string] $NtServiceUser = "", | |
[Parameter()] | |
[string] $NtServicePassword = "" | |
) | |
$_wrapperConfigFile = "$BuildAgentRootFolder\launcher\conf\wrapper.conf" | |
$_wrapperConfigContent = Get-Content "$_wrapperConfigFile" | |
Write-Host "Editing wrapper.conf file..." | |
# | |
$_consoleTitle = "TeamCity Build Agent $BuildAgentId" | |
Write-Host " Updating wrapper.console.title: $_consoleTitle" | |
$_wrapperConfigContent = $_wrapperConfigContent -replace "wrapper.console.title=TeamCity Build Agent", "wrapper.console.title=$_consoleTitle" | |
# | |
$_ntServiceName = "TCBuildAgent-$BuildAgentId" | |
Write-Host " Updating wrapper.ntservice.name: $_ntServiceName" | |
$_wrapperConfigContent = $_wrapperConfigContent -replace "wrapper.ntservice.name=TCBuildAgent", "wrapper.ntservice.name=$_ntServiceName" | |
$_ntServiceDescription = "TeamCity Build Agent Service - $BuildAgentId" | |
Write-Host " Updating wrapper.ntservice.description: $_ntServiceDescription" | |
$_wrapperConfigContent = $_wrapperConfigContent -replace "wrapper.ntservice.description=TeamCity Build Agent Service", "wrapper.ntservice.description=$_ntServiceDescription" | |
Write-Host " Updating wrapper.ntservice.displayname: $_ntServiceDescription" | |
$_wrapperConfigContent = $_wrapperConfigContent -replace "wrapper.ntservice.displayname=TeamCity Build Agent", "wrapper.ntservice.displayname=$_ntServiceDescription" | |
if(!([string]::IsNullOrEmpty($NtServiceUser))) { | |
Write-Host " Adding wrapper.ntservice.account: $NtServiceUser" | |
$_wrapperConfigContent = $_wrapperConfigContent + "`r`nwrapper.ntservice.account=$NtServiceUser" | |
Write-Host " Adding wrapper.ntservice.password: ********" | |
$_wrapperConfigContent = $_wrapperConfigContent + "`r`nwrapper.ntservice.password=$NtServicePassword" | |
} | |
Write-Host "Writing changes to file: $_wrapperConfigFile`n" | |
$_wrapperConfigContent | Set-Content "$_wrapperConfigFile" | |
} | |
function Set-FolderPermissions() { | |
[Cmdletbinding()] | |
Param ( | |
[Parameter(Mandatory=$true)] | |
[string] $BuildAgentRootFolder, | |
[Parameter(Mandatory=$true)] | |
[string] $NtServiceUser = "" | |
) | |
$Acl = Get-Acl "$BuildAgentRootFolder" | |
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule("$NtServiceUser","FullControl","Allow") | |
$Acl.SetAccessRule($Ar) | |
Set-Acl "$BuildAgentRootFolder" $Acl | |
} | |
function Start-AgentService { | |
[Cmdletbinding()] | |
Param ( | |
[Parameter(Mandatory=$true)] | |
[string] $BuildAgentRootFolder | |
) | |
Push-Location | |
& { | |
Set-Location "$BuildAgentRootFolder\bin" | |
cmd.exe /c "service.install.bat" | |
cmd.exe /c "service.start.bat" | |
} | |
Pop-Location | |
} | |
function Install-BuildAgent { | |
[Cmdletbinding()] | |
Param ( | |
[Parameter(Mandatory=$true)] | |
[string] $BuildAgentRootFolder, | |
[Parameter(Mandatory=$true)] | |
[string] $BuildAgentId, | |
[Parameter(Mandatory=$true)] | |
[string] $BuildAgentPort, | |
[Parameter(Mandatory=$true)] | |
[string] $JavaPath, | |
[Parameter()] | |
[string] $TeamCityServerUrl = "http://localhost", | |
[Parameter()] | |
[string] $TeamCityServerPort = 80, | |
[Parameter()] | |
[string] $NtServiceUser = "", | |
[Parameter()] | |
[string] $NtServicePassword = "" | |
) | |
Download-Agent -InstallDirectory "$BuildAgentRootFolder" -TeamCityServerUrl "$TeamCityServerUrl" -TeamCityServerPort $TeamCityServerPort | |
Configure-AgentProperties -BuildAgentRootFolder "$BuildAgentRootFolder" -BuildAgentId "$BuildAgentId" -BuildAgentPort "$BuildAgentPort" -JavaPath "$JavaPath" -TeamCityServerUrl "$TeamCityServerUrl" -TeamCityServerPort "$TeamCityServerPort" | |
Configure-AgentServiceWrapper -BuildAgentRootFolder "$BuildAgentRootFolder" -BuildAgentId "$BuildAgentId" -NtServiceUser "$NtServiceUser" -NtServicePassword "$NtServicePassword" | |
#If there was a service user specified, set the permissions for the agent directory. | |
if(!([string]::IsNullOrEmpty($NtServiceUser))) { | |
Set-FolderPermissions -BuildAgentRootFolder "$BuildAgentRootFolder" -NtServiceUser "$NtServiceUser" | |
} | |
Start-AgentService -BuildAgentRootFolder "$BuildAgentRootFolder" | |
} | |
Write-Warning "Make sure that the path variable includes the Java bin folder." | |
#Escape JavaPath (first \\ is regex, 2nd is not) | |
$JavaPath = $JavaPath -replace "\\", "\\" | |
for($i = 0; $i -lt $NumberOfBuildAgents; $i++) { | |
$agentID = $($i+1) | |
Write-Host "Installing Build Agent #$($i+1)" | |
Install-BuildAgent -BuildAgentRootFolder "$($InstallationDiskDrive)\ba$($agentID)" -BuildAgentId "$($SmallPrefix)ba$($agentID)" -BuildAgentPort "$(($BuildAgentStartPort+$i).ToString())" -JavaPath "$JavaPath" -TeamCityServerPort $TeamCityServerPort -NtServiceUser "$NtServiceUser" -NtServicePassword "$NtServicePassword" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment