1. Voraussetzung
- Ein Microsoft Konto
- Zugang zu einem DevOps Verzeichnis
- Visual Studio
- Eine VS Solution mit einer Klassenbibliothek
- Ein Git Repository in DevOps, welches die VS Solution mit der Klassenbibliothek enthält
2. Feed erstellen
Feeds sind Behälter für allerlei Dinge und eignen sich bestens, NuGet Packages aufzunehmen und allfälligen Konsumenten zur Verfügung zu stellen.
1. Im DevOps Verzeichnis der Wahl navigiere man zu Artifacts und klicke die Create Feed Schaltfläche:
2. In der Feed-Konfigurationsseite wird dem Feed ein Sinn spendender Name gegeben und die übrigen Parameter nach Bedarf gesetzt:
- Mit Visibility wird bestimmt, wer den Feed mit seinem Inhalt sehen kann.
Die Option Specific people ist wohl eher nützlich wenn man einen Public Feed haben will, der prinzipiell für die ganze Welt sichtbar ist – so kann man den Feed zwar organisationsübergreifend global zur Verfügung stellen, aber nur einem ausgewählten Personenkreis.
Nur Feeds mit dem Scope Project können öffentlich sein und auch dann nur, wenn das Projekt auch öffentlich ist. - Wenn Include packages from common public sources angehakt ist, kann man über diesen Feed auch Packages aus öffentlichen Quellen konsumieren.
- Mit Scope wird die Gültigkeit des Feeds auf das Projekt gesetzt oder auf die ganze Organisation
3. Ein Klick auf Create ganz unten im Fenster erzeugt den Feed.
3. NutGet Package erstellen
Als Erstes muss sichergestellt werden, dass das Git Repository im DevOps auf dem neuesten Stand ist. Hier heisst das Repo NuGetPackageDemo:
3.1. YAML Pipeline erstellen
Das NuGet Package wird durch eine Pipeline gebaut, also müssen wir so eine haben.
1. In DevOps in dem Projekt, das auch das Repository enthält, Pipelines anwählen:
2. New pipeline klicken:
3. Azure Repos Git (YAML) auswählen – mit diesem Template wird ein YAML File erzeugt, das bereits viele Dinge enthält, die benötigt werden:
4. Nun wird das Repository gewählt, von dessen Projekten NuGet Packages erstellt werden sollen:
5. Die Template .NET Desktop aus der Template-Liste auswählen:
6. Nun wird das automatisch erzeugte YAML File erst mal gespeichert
(Save, nicht Save and run)
7. Auf dem Bestätigungsprompt muss vor einem Klick auf Save eine Commit-Message eingegeben werden und man kann wählen, ob man in den Master (Main) Branch committen oder dafür lieber einen neuen Branch erzeugen will.
3.1.1. YAML Template editieren
Die YAML Datei, die automatisch beim Erstellen der Pipeline erzeugt worden ist, muss noch ein wenig angepasst werden, bis sie aus den Projekten im Repository NuGet Pakete machen kann.
1. In DevOps wieder Pipelines und dort über der Liste die Option All anwählen – die eben erstellte Pipeline wird gelistet mit dem Vermerk No runs yet
2. Pipeline selektieren und Edit klicken
Das automatisch generierte YAML File sieht jetzt etwa so aus:
Einige der Parameter müssen ediert werden, einige werden hinzugefügt und wir brauchen auch ein paar zusätzliche Tasks. Das gehen wir jetzt Schritt für Schritt durch.
3.1.1.1. Trigger
Der trigger ist der Name des Branches mit dem Repository welches die Pipeline verwenden wird (meistens main, hier ist es master). Das lassen wir so stehen.
3.1.1.2. pool
Hier kann ein Agent Pool angegeben werden, den die Pipeline für Builds und Releases verwenden soll.
Windows Agent Pool
Per Default ist hier 'windows-latest' eingetragen. Das bedeutet, dass die Pipeline einen von Microsoft gehosteten Agenten verwenden wird. Mit dieser Einstellung wird jedes Mal, wenn die Pipeline ausgeführt wird, eine neue VM erstellt und wenn die den Job erledigt hat, wird sie wieder gelöscht.
Das funktioniert gut, aber manchmal muss man schon eine ganze Weile warten, bis freie Ressourcen zur Verfügung stehen um die Pipeline auszuführen.
Self hosted Agents
Wenn man Wartezeiten vermeiden möchte oder etwas mehr Kontrolle über die Build- und Deployment Prozesse haben will, bietet es sich an, Self hosted Agents zu verwenden.
So kann man Self hosted Agent Pools finden und die Capabilities der Agents überprüfen:
1. Auf der DevOps Home Page, auf Organization settings klicken
2. In den Organization Settings unter Pipelines auf Agent pools klicken:
3. Den Agent Pool auswählen, der verwendet werden soll:
4. Den Reiter Agents anwählen und auf einen Agent in dem Pool klicken
5. Den Reiter Capabilities anwählen, um die Fähigkeiten des Agents zu überprüfen (System und User-defined).
In unserem Beispiel wollen wir den Agent-Pool verwendet, der in den Screenshots oben gezeigt wird (der Default heisst) und so ändern wir den entsprechenden Eintrag im YAML File von
pool:
vmImage: 'windows-latest'
nach
pool:
name: Default
demands:
- msbuild
- visualstudio
name hier ist der Name des Self hosted Agent Pools und unter demands sind zwei System Capabilities aufgeführt, welche die Pipeline benötigt. Zu beachten ist, dass der Name des Agent-Pools nicht in Hochkommas steht.
Die beiden Einträge unter demands stellen sicher, dass ein Agent aus dem Pool gewählt wird, der auch über die entsprechenden Capabilities verfügt.
Anmerkung: Die Einzüge der einzelnen Zeilen im YAML File bestimmen, welcher Parameter zu welchem Block gehört und welcher Unterparameter zu welchem Parameter – die sind nicht bloss zur besseren Lesbarkeit hier, also muss man aufpassen, dass man die auch korrekt setzt.
3.1.1.3. variables
Der Variablen Block wird mit folgenden Default Werten erzeugt:
variables:
solution: '**/*.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
'**/*.sln' als Wert für die Variable solution bedeutet, dass jegliche Solution in dem gegebenen Repository zur Verarbeitung gelangt, wo immer diese Variable verwendet wird. Ist das nicht erwünscht, können die zu verarbeitenden Solutions eingeengt werden, indem hier ein spezifischerer Wert angegeben wird, bis hin zum exakten Nam der einen Solution die verarbeitet werden soll.
Die Werte für die übrigen beiden Variablen lassen wir so stehen.
3.1.1.4. steps
Nach steps stehen alle Prozess Schritte, die von der Pipeline ausgeführt werden, als einzelne tasks. Hier wird also konfiguriert, was die Pipeline tatsächlich tun soll.
Im automatisch generierten YAML File stehen die folgenden drei Tasks als Erste gleich nach steps:
steps:
- task: NuGetToolInstaller@1
- task: NuGetCommand@2
inputs:
restoreSolution: '$(solution)'
- task: VSBuild@1
inputs:
solution: '$(solution)'
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
Die lassen wir genau so stehen.
Die vierte und letzte Task im YAML File ist die hier:
- task: VSTest@2
inputs:
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
Die wird nicht gebraucht und wir löschen sie.
Nun müssen wir noch ein paar weitere Prozess Schritte hinzufügen.
- Nach der letzten Zeile configuration der nun letzten Task VSBuild@1 zwei Leerzeilen einfügen – die müssen leer sein, also sind allfällig automatisch eingefügte Leerzeichen zu entfernen.
Wenn der Cursor in der letzten leeren Zeile im YAML File sitzt, aus der Tasks Liste die Task Grupp .NET Core anklicken:
- Dann in der Command Dropdown Box pack auswählen:
- Die Task kann konfiguriert werden, bevor man sie einfügt:
Die Felder Configuration to Package und Package Folder werden geleert und Do not build angehakt – dann wird die Task mit einem Klick auf die Schaltfläche Add ganz unten im Konfigurationsfenster eingefügt
- Die neue Task im YAML File sieht jetzt so aus:
- task: DotNetCoreCLI@2
inputs:
command: 'pack'
packagesToPack: '**/*.csproj'
configuration:
packDirectory:
nobuild: true
versioningScheme: 'off'
Die beiden leeren Parameter configuration und packDirectory werden gelöscht und wenn gewünscht, kann '**/*.csproj' für packagesToPack durch eine etwas spezifischere Maske ersetzt werden, um die zu verarbeitenden Projekte einzugrenzen.
- Wiederum müssen zwei leere Zeilen am Ende des YAML Files eingefügt werden.
- Ganz oben im Task Konfigurationsfenster den Zurück Pfeil klicken um wieder in die Tasks Liste zu kommen, nuget ins Suchfenster schreiben um die NuGet Task Gruppe zu finden und diese auswählen
- In der Dropdown Box Command den Eintrag push auswählen:
- Im Konfigurationsfenster für diese Task werden die Parameter wie folgt gesetzt:
- Mit einem Klick auf die Schaltfläche Add ganz unten im Konfigurationsfenster den Task einfügen.
Die neue Task im YAML File sieht jetzt so aus:
- task: NuGetCommand@2
inputs:
command: 'push'
packagesToPush:
nuGetFeedType: 'internal'
publishVstsFeed: '50e97363-[…]-8f37beee/5f071406-[…]-cac9e984'
allowPackageConflicts: true
Das müssen wir noch ein wenig editieren…
- Ein Display Name muss (nicht zwingend, aber sinnvollerweise) eingefügt werden, der im Output der Ausführungen der Pipeline für diesen Task angezeigt wird. Dazu wird der Cursor ans Ende der ersten Zeile der Task nach NuGetCommand@2 gesetzt und <CR> gedrückt.
Nun müssen zwei Leerschläge eingefügt werden (siehe die Anmerkung über die Einzüge weiter oben) und Intellisense merkt, dass ein neuer Parameter für diesen Task eingefügt werden soll und zeigt eine Liste mit den verfügbaren Parametern an, woraus wir displayName auswählen:
(sollte Intellisense keine Parameterliste anzeigen, 'd' eintippen um Intellisense zu triggern)
- Nun kann der gewünschte Display Name in einfachen Anführungszeichen eingegeben werden, wobei sicher gestellt werden muss, dass auf den Parameternamen displayName unmittelbar ein Doppelpunkt und dann ein Blank folgt (wird nicht immer automatisch eingefügt).
Die Zeile mit dem leeren Parameter packagesToPush im inputs Parameter Block wird gelöscht.
- Beim Parameter publishVstsFeed die zwei GUIDS (project/feed) mit den Namen des Projektes und des Feeds ersetzen, was die Lesbarkeit erhöht (sicherstellen, dass der ganze String nach der Ersetzung immer noch in einfachen Anführungszeichen steht).
Den Cursor ans Ende der Zeile mit dem Parameter allowPackageConflicts setzen und <CR> drücken.
Der Einzug (vier Leerzeichen), den es braucht um einen neuen Parameter für den inputs Parameter Block zu erstellen, wird automatisch eingefügt (falls nicht, diesen bitte manuell einfügen).
'v' auf der Tastatur drücken um rasch zum Parameter versioningScheme in der Parameter Liste von Intellisense zu gelangen und diesen auswählen:
- Bevor die nächste Task eingefügt wird müssen wir abermals zwei Leerzeilen einfügen und den Cursor dann auf der letzten Zeile stehen lassen
Im Suchfeld in der Tasks Liste publish build eintippen um die Task Gruppe Publish build artifacts angezeigt zu bekommen und diese auswählen:
Im Task Konfigurationsfenster in Artifact name den Namen des gewünschten Feeds eintragen, die übrigen Parameter auf ihren Default Werten belassen und die Schaltfläche Add klicken, um die Task in das YAML File einzufügen:
- Die Task, die eingefügt wurde, sieht etwa so aus:
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'NuGetPackageDemoFeed'
publishLocation: 'Container' Auch für diese Task sollte ein Display Name eingegeben werden.
Den Cursor am Ende der ersten Zeile dieser Task nach dem Tasknamen platzieren und <CR> drücken.- Zwei Mal die Leertaste drücken und dann ein 'd' tippen, um Intellisense dazu zu bringen, den Parameter displayName in der Liste anzuzeigen und den dann auswählen:
- Falls nach dem Parameter Namen nicht bereits ein Doppelpunkt gefolgt von einem Blank steht, diese bitte eingeben
Nun kann der gewünschte Display Namen in einfachen Anführungszeichen eingegeben werden und die ganze Task sieht nun etwa so aus:
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: NuGetPackageDemoFeed'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'NuGetPackageDemoFeed'
publishLocation: 'Container'Fertig – unser YAML Pipeline ist komplett.
Um sie zu speichern, bitte die Save Schaltfläche rechts in der Kopfzeile des Editors klicken:Das Speichern einer Pipeline committet diese ins Repository und so wird man aufgefordert eine Commit Message einzugeben.
Dann kann man in der entsprechenden Optionsgruppe noch auswählen, ob man in den master (oder main) Branch committen will oder ob man dafür einen neuen Branch erstellen will.
Durch einen Klick auf die Schaltfläche Save ganz unten im Fenster wird die Pipeline schliesslich gespeichert und committet:Nachdem wir die 'Build succeeded' Nachricht erhalten haben, können wir unter Artifacts unseren Feed auswählen und da finden wir jetzt unser frisches NuGet Paket:
Geschrieben von Robert Cavigelli, Lead Developer QUIBIQ Schweiz AG