Bei uns auf Arbeit ist der TFS im Einsatz. Wir haben gerade mühevoll den Umstieg auf das Studio 2017 durchgeführt. Mühevoll, weil unsere alten XAML-Build auf neue vNext-Builds umgesetzt werden mussten. Bisher haben wir irgendwo die Versionsnummer fix verdrahtet gehabt. Und nun wollten wir die Möglichkeiten der neuen Technologie nutzen.
Aus einem riesigen Nightly Build haben wir viele kleine Builds gemacht, die alle nacheinander angetriggert werden. Das hat natürlich den Nachteil, dass jede Builddefinition ihren eigenen kleinen Satz an Variablen mitbringt. Und wenn wir von einem Zweig auf den nächsten wechseln, muss das ganze Gewirr mitgenommen und angepasst werden. Bisher läuft es ja so, dass wir per Variable von außen die Versionsnummer im Build setzen und dann ein Buildstep losläuft und alle abgerufenen Projekte bearbeitet und dort die Versionsnummer einträgt.
Was uns jetzt noch fehlte, war die Möglichkeit, dass alle Builds auf eine gemeinsame Datei zugreifen können, um von dort die Versionsnummer für den jeweiligen Entwicklungszweig zu ermitteln. Dazu bieten sich zwei Möglichkeiten an, die beide über Aufrufe der PowerShell laufen. Für beide Möglichkeiten muss der Account unter dem der Agent läuft Rechte haben, die Builddefinitionen auslesen ggf. noch mehr.
1. Möglichkeit: Builddefinition anpassen
Voraussetzungen:
- Die Variable ist definiert.
- Der Buildagent läuft mit einem Account, der die Berechtigung hat, vNext-Builddefinitionen zu modifizieren.
Nachteil: Es wirkt nicht auf den aktuellen Build, sondern erst auf den nächsten. D.h. diese Lösung ist eher dafür geeignet automatisiert den Build-Counter hochzusetzen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | [String]$buildID = "$env:BUILD_BUILDID" Write-Host "Meine Build-ID ist $buildID." $MajorValue = 5 $MinorValue = 1 $apiVersion ="3.1" $uriRoot = $env:SYSTEM_TEAMFOUNDATIONSERVERURI $ProjectName = $env:SYSTEM_TEAMPROJECT $uri = "$uriRoot$ProjectName/_apis/build/builds/" + $buildID + "?api-version=$apiVersion" Write-Host "Builds abrufen: $uri" $builds = Invoke-RestMethod -Uri "$uri" -Method Get -ContentType "application/json" -UseDefaultCredentials | select definition $definitionid = $builds.definition.id Write-Host "Meine Build-Definition-ID ist $definitionid" $defuri = "$uriRoot$ProjectName/_apis/build/definitions/" + $definitionid + "?api-version=$apiVersion" Write-Host "Builddefinition abrufen $defuri" $projectDef = Invoke-RestMethod -Uri "$defuri" -Method Get -ContentType "application/json" -UseDefaultCredentials if ($projectDef.variables.Major -eq $null) { Write-Error "Variable 'Major' nicht in der Builddefinition gefunden." -ErrorAction Stop } if ($projectDef.variables.Minor -eq $null) { Write-Error "Variable 'Minor' nicht in der Builddefinition gefunden." -ErrorAction Stop } Write-Host "Setze Major auf $MajorValue." Write-Host "Setze Minor auf $MinorValue." $projectDef.variables.Major.Value = $MajorValue $projectDef.variables.Minor.Value = $MinorValue $projectDefJson = $projectDef | ConvertTo-Json -Depth 99 Write-Host "Builddefinition aktualisieren" Invoke-RestMethod -Method Put -Uri "$defuri" -UseDefaultCredentials -ContentType "application/json" -Body $projectDefJson |
2. Möglichkeit: Variablen im Build direkt modifizieren
Das Schöne an dieser Lösung ist, dass die Variablen nicht mal im Build definiert sein müssen.
1 2 3 4 5 | $MajorValue = 5 $MinorValue = 1 Write-Host ("##vso[task.setvariable variable=Major;]$MajorValue") Write-Host ("##vso[task.setvariable variable=Minor;]$MinorValue") |
Eine dieser beiden Dateien legt man im TFS ab, ruft das entsprechende Verzeichnis ab und muss jetzt nur noch einen Buildstep zum Aufruf des Powershell-Skipts einfügen. Ich lasse mir immer die URIs ausgeben, die das Skript aufruft, weil man die zu Debugzwecken in den Firefox kopieren kann und dann das JSON schön formatiert angezeigt bekommt.