Archiv
2017.04.06
Ist das Daily wirklich ein Synchronisations-Meeting? (Teil 1)
By admin / 06 April / Entwickler / 0 comm.
Was macht ein wirklich gutes Daily-Scrum aus?
[+]Aller Anfang
Als ich das erste Mal mit dem Daily/Scrum vor einigen Jahren in Berührung kam, haben wir im Daily-Scrum folgendes Format gefahren. Jeder erzählt der Reihe nach:- Was habe ich gestern gemacht?
- Was möchte ich als nächstes tun?
- Was hat mich behindert? Welche Probleme sind aufgetreten?
Eine Verbesserung
Mit Blick auf das Sprint-Backlog haben wir angefangen die PBIs von oben nach unten zu besprechen mit den folgenden Fragen im Hintergrund:- Was haben wir gestern an diesem PBI erreicht?
- Was wollen wir heute an diesem PBI als nächstes tun?
- Was behindert uns um das PBI fertig zu bekommen?
Ist das schon alles?
Ist das das Ende? Sollten wir wirklich im Status eines Synchronisations-Meetings verweilen oder haben wir hier noch Luft nach oben. Was ist das Ziel eines guten Dailys? Wir wollen einen Einsatzplan für den kommenden Tag generieren. Wie komme ich zu einem guten Einsatzplan? Brauchen wir ein Tagesziel so dass wir uns auf die wichtigen Dinge des Tages fokussieren? Was macht ein gutes Tagesziel aus?- Es sollte gut erreichbar sein
- Es sollte uns einen positiven Spirit geben
- Es müssen nicht alle daran arbeiten
- Das Team sollte alles dafür tun, damit das Tagesziel erreicht wird.
[-]
Führt man bei einem Team das Schätzen in Story Points ein, kommen oft Diskussionen in gang wie: Was ist Komplexität? Was bringt uns das Schätzen? Warum schätzen wir in Story Points und nicht gleich in Zeit? Dieser Artikel bietet einen Überblick warum wir in Story Points schätzen und was die Vorteile dessen sind. Was sind […]
[+]- Die Verlässlichkeit der Velocity wird unter anderem durch die folgenden Faktoren beschränkt: Hindernisse, Impediments
- Motivation → was treibt uns an
- Wissen / Expertise / Kompetenz der Entwickler
- Entwicklungsumgebung (lokal wie auch TFS Infrastruktur etc.)
- Transparenz
- Zielvorstellungen
- Prozess
- Das Ziel (das Produkt)
- Krankheit
- Unvorhergesehene / ungeplante Ereignisse
- Aus unserer bisherigen Erfahrung ist das Schätzen in einer abstrakten Größe genauer als eine rein zeitbasierte Schätzung.
- Bei größeren Release-Planungen ist die Planung immer zyklisch anzupassen und es gilt zu beachten, dass auch die Velocity nur eine Planzahl ist.
- Scrum bietet zusätzlich den Vorteil, dass die Planungen nach jedem Sprint (alle 2-4 Wochen) angepasst werden können und somit eine gute Reaktionsfähigkeit gegeben ist, die es ermöglicht die wichtigen Dinge zuerst zu implementieren.
[-]
2016.11.22
Zusammenarbeit im Team fördern durch die richtigen Fragen
By admin / 22 November / Agile / 0 comm.
Ein Thema das Softwareentwicklungs-Teams oft beschäftigt: Wie können wir als Team besser zusammenarbeiten? Interessanterweise kommt diese Frage erst auf, wenn das Team bereits einen gewissen Reifegrad erreicht hat. Erst dann genügt es nicht, am selben Produkt zu arbeiten, Code zu sharen und vielleicht sogar ein Scrum-Team zu sein. Ein echtes Team zeichnet aus, dass alle […]
[+]Ein Thema das Softwareentwicklungs-Teams oft beschäftigt: Wie können wir als Team besser zusammenarbeiten? Interessanterweise kommt diese Frage erst auf, wenn das Team bereits einen gewissen Reifegrad erreicht hat. Erst dann genügt es nicht, am selben Produkt zu arbeiten, Code zu sharen und vielleicht sogar ein Scrum-Team zu sein. Ein echtes Team zeichnet aus, dass alle Mitglieder im Team ein gemeinsames Ziel teilen. Und das darf nicht nur lauten: “Wir wollen am Ende des Sprints alle versprochenen Backlog Items abgearbeitet haben”.
Wie sieht nun ideale Zusammenarbeit in einem Team aus? Sicher ist hier ein gegenseitiges Angebot zur Unterstützung bei Problemen alleine nicht ausreichend. Ich kenne kein Team bei dem der Kollege bei einer Frage oder einem Problem weggeschickt wird. Keiner sagt “Das ist nicht mein Problem, sehe selber zu, wie du das lösen kannst”. Also ist dieser Level der Zusammenarbeit höchstens ein Einstieg, aber es muss doch besser gehen.
Es geht es darum, wie können wir alle Teammitglieder so einbinden, dass wir Kompetenzen bündeln, Probleme schnell und effizient lösen und dabei gute Qualität liefern? Wie können wir durch gemeinsame Diskussionen gute Lösungen finden und wie können wir individuelle Schwächen kompensieren und Fehler vermeiden? Eine Voraussetzung für diese Punkte ist, dass wir nicht nur am selben Produkt, sondern am selben Thema arbeiten. Damit wird das Verständnis viel besser und jeder fühlt sich direkt betroffen.
Eine Methode diese Zusammenarbeit zu fördern, ist das sogenannte Swarming. Eine Technik mit der das Team gemeinsam zum Ziel hat, das wichtigste Backlog Item (PBI) so schnell wie möglich abzuarbeiten. Dazu stell sich jeder im Daily Scrum die Frage “Kann ich eine Aufgabe übernehmen, damit wir dieses PBI voranbringen?”. Wenn nicht, lautet die zweite Frage: “Kann ich einen Kollegen unterstützen, damit dieser mit seiner Aufgabe schneller vorankommt?”. Erst wenn beide Fragen mit “Nein” beantwortet werden, wird mit Arbeiten am zweitwichtigsten PBI begonnen.
Es genügt aber nicht, die Aufgaben im Daily gut zu verteilen, viel entscheidender ist die Frage, wie die Zusammenarbeit während des Tages läuft. Hier mache ich mit 2 Teams gerade ein Experiment, bei dem wir versuchen, die Zusammenarbeit durch Umformulierung der Frage “Kann ich dich bei deiner Aufgabe unterstützen?” zu verbessern. Zukünftig wollen wir so vorgehen, dass ein Entwickler, der eine Aufgabe abgeschlossen hat, überlegt, an welcher Stelle er gerade das größte Hindernis zur Fertigstellung des PBIs sieht. Den Kollegen der gerade an dieser Aufgabe arbeitet fragt er dann “Wo stehst du gerade?”. Den folgenden Kurzbericht kann der Entwickler der gerade seine Aufgabe abgeschlossen hat nutzen um konkrete Unterstützungspunkte zu identifizieren. Daraus entsteht dann entweder eine Arbeit im Pair oder auch eine Aufteilung der noch zu erledigenden Punkte.
Die Umformulierung des Unterstützungsangebots zu einer Statusabfrage aus meiner Sicht einen entscheidenden Vorteil: Während bei der klassischen Vorgehensweise der aktuell beschäftigte Kollege überlegen soll, wo eine Unterstützung möglicherweise Sinn macht, drehen wir das um. Er muss dann nur kurz berichten, wo er steht, das identifizieren von Unterstützungsmöglichkeiten liegt dann aber beim Kollegen der seine Aufgabe gerade abgeschlossen hat. Ich erhoffe mir aus dieser Vorgehensweise mehr Unterstützungen während des Tages, da beim bisherigen Vorgehen der Gefragte ja auch einfach sagen kann: “Danke, brauche gerade keine Unterstützung”, was für ihn meistens wohl der bequemere Weg ist. Zudem hilft dem Gefragten sicher mal kurz zu reflektieren, wo er gerade steht. Und er wird ja nicht aus seinem Kontext herausgerissen, da es ja genau um sein Thema geht.
Ich bin gespannt, wie sich das Vorgehen bei den beiden Teams auswirkt. Ich werde wieder berichten.
[-]
2016.06.07
Brauchen Softwareentwickler Leidenschaft für das Produkt das sie entwickeln?
By admin / 07 Juni / Agile / 0 comm.
Vor kurzem habe ich mit einem Team die interessante Frage aufgeworfen, ob Softwareentwickler Leidenschaft für das Produkt das sie entwickeln benötigen oder ob Leidenschaft für Technologie wichtiger ist. Und wie wirkt sich diese Frage auf die Zusammenarbeit im Team aus?Hintergrund der Frage ist, dass viele Teams mit denen ich zusammenarbeite, zwar Scrum nutzen, aber im […]
[+]Vor kurzem habe ich mit einem Team die interessante Frage aufgeworfen, ob Softwareentwickler Leidenschaft für das Produkt das sie entwickeln benötigen oder ob Leidenschaft für Technologie wichtiger ist. Und wie wirkt sich diese Frage auf die Zusammenarbeit im Team aus?
Hintergrund der Frage ist, dass viele Teams mit denen ich zusammenarbeite, zwar Scrum nutzen, aber im Grunde genommen im Sprint einzelne Backlog Items abarbeiten und am Ende des Sprints ein Inkrement an den Product Owner liefern. Bewusst oder unbewusst haben die Entwickler aber sehr wenig Kontakt mit Personen außerhalb des Scrum Teams. Und daraus ergibt sich die Frage, was ist das Ziel des Teams?
Nach Definition des Scrum Guides ist das Ziel eines Development Teams, ein „Done“ Inkrement des Produkts am Ende jedes Sprints abzuliefern. Das Development Team ist damit verantwortlich für die Qualität des Produktes. Hier ist nun genau die Frage, welche Qualität hier genau gemeint ist. Natürlich ist das Development-Team verantwortlich für die „innere Qualität“ des Produktes, also für die Wartbarkeit und Erweiterbarkeit des Codes und dafür, möglichst wenig technische Schuld aufzuhäufen. Auch für den Teilaspekt Fehlerfreiheit der „äußeren Qualität“ ist klar, dass das Development Team dafür die Verantwortung trägt. Wie sieht es aber mit anderen Aspekten wie Usability, Sicherheit oder allgemein mit dem Thema „Zufriedenheit des Anwenders“ aus? Kann ein Development Team sich ausschließlich auf die technischen Aspekte fokussieren und das Generieren von Mehrwert dem Product Owner überlassen? Schließlich ist das genau die Aufgabe dieser Rolle. Der Product Owner wird oft ja auch als „Value Maximizer“ bezeichnet.
Nach der Diskussion mit dem Team bin ich überzeugt, dass das Development Team eine Leidenschaft für das Produkt haben muss. Die Entwickler müssen zunächst das Interesse haben, ein gutes Produkt zu entwickeln, das die Anwender begeistert. Die Erstellung von gutem Code allein darf hier nicht genügen. Hier kommt mir ein Vergleich mit einer Fußballmannschaft in den Sinn. Wenn alle Spieler nur das Ziel haben technisch perfekt zu spielen und persönlich möglichst keine Fehler zu machen, wird das möglicherweise nicht ausreichen um das Spiel zu gewinnen. Wir brauchen also ein übergeordnetes Ziel. Im Fußball ist es, das Spiel zu gewinnen. In der Software ist es, mit unserer Software Anwender zu begeistern oder wenigstens zufrieden zu stellen.
Damit übernehmen die Entwickler auch eine gewisse Kontrolle, dass der Product Owner einen guten Job macht. Er trifft zwar letztendlich die Entscheidungen, aber wenn das Development Team das Gefühl hat, dass die falschen Schwerpunkte gesetzt werden und dass Potenziale nicht ausgeschöpft werden, dann muss es darüber zumindest eine Diskussion geben. Diese wird aber nur dann stattfinden, wenn sich die Entwickler nicht als reine Umsetzer verstehen, die einen Arbeitsauftrag bekommen und diesen möglichst gut umsetzen. Sie müssen sich mit Leidenschaft für den Erfolg ihres Produktes einsetzen – also nicht das Produkt des Product Owners. Diese Leidenschaft wird aber nur entstehen, wenn die Entwickler verstehen wie ihre Software genutzt wird, wenn sie direkt Feedback von Anwendern bekommen und selbst verstehen wie auf bestimmte Funktionen reagiert wird. Dieses Feedback kann im Sprint Review entstehen oder durch Telemetriedaten die die Nutzung durch die Anwender visualisieren oder durch soziale Medien oder, oder. Dem Product Owner erwächst hier eine zusätzliche Aufgabe. Er muss die Leidenschaft für das Produkt bei den Entwicklern wecken, indem er die Ziele und Vision erklärt, indem er Success-Stories mit den Entwicklern teilt und auch indem er Fehlschläge oder Misserfolge direkt kommuniziert.
Darüber hinaus ist auch wichtig, dass das Development Team an dieser Stelle einheitlich agiert. Sollten nur einzelne Teammitglieder diese Leidenschaft für das Produkt besitzen, so sind soziale Spannungen bereits vorprogrammiert. Wenn ich das tollste Produkt aller Zeiten entwickeln möchte und ich gleichzeitig das Gefühl habe, dass der Kollege ein anderes Ziel hat und seine persönliche Agenda verfolgt, wird das zu Spannungen führen. Ähnlich wie bei dem zuvor genannten Beispiel aus dem Fußball gehört natürlich die Fähigkeit und die Kompetenz auf technischer Ebene dazu, denn nur so werden wir in der Lage sein das Spiel zu gewinnen bzw. ein gutes Produkt zu bauen. Aber es ist eben nicht unser primäres Ziel. Um ein gutes Produkt zu erstellen gehört noch mehr dazu als Technologie zu beherrschen.
Aber letztendlich macht eines für mich eine Gruppe von Personen erst zu einem Team – wenn sie ein gemeinsames Ziel haben, das sie verfolgen. Für das sich jeder engagiert und seinen Beitrag leistet. Wo wir möglicherweise unterschiedlicher Meinung sind, wie wir das gemeinsame Ziel am besten erreichen. Wo wir aber diese Meinungsvielfalt nutzen, um aus verschiedenen Optionen die besten auszuwählen.
Vielleicht lohnt es sich für sie auch einmal die Frage zu stellen, ob ihre Softwareentwickler Leidenschaft für ihr Produkt haben und wie sie diese evtl. wecken oder steigern können. Denn letztendlich ist diese Leidenschaft nichts Anderes als Motivation und wer möchte denn nicht motivierte Mitarbeiter? Leidenschaft und Motivation werden aber nur entstehen, wenn den Teams auch Gestaltungsmöglichkeiten eingeräumt werden und nicht alles von außerhalb vorgegeben ist.
[-]
2016.06.06
Hardware Test Automatisierung
By admin / 06 Juni / Entwickler / 0 comm.
In letzter Zeit haben wir einige IoT Showcases gebaut und dabei häufig den Raspberry Pi eingesetzt. Leider kam es da immer wieder zu Problemen und der Raspberry hat manchmal nicht mehr gebootet. Die Vermutung war, dass das möglicherweise durch ein Ausschalten ohne vorheriges Herunterfahren zusammenhängt. Um diesen Verdacht aber zu erhärten und vor allem herauszufinden, […]
[+]In letzter Zeit haben wir einige IoT Showcases gebaut und dabei häufig den Raspberry Pi eingesetzt. Leider kam es da immer wieder zu Problemen und der Raspberry hat manchmal nicht mehr gebootet. Die Vermutung war, dass das möglicherweise durch ein Ausschalten ohne vorheriges Herunterfahren zusammenhängt. Um diesen Verdacht aber zu erhärten und vor allem herauszufinden, in welchen Konstellationen das Problem vermieden werden kann, stellte sich schnell heraus, dass ein manuelles Unterbrechen der Stromversorgung nicht wirklich praktikabel ist um statistisch belastbare Wiederholungsraten zu erzielen. Deshalb musste eine Automatisierung her.
Der Aufbau dazu ist recht einfach. Wir haben einen Raspberry (Power Switch), der über seinen GPIO ein Relais steuert. Das Relais wiederum schaltet einen Mehrfachstecker in dem nun unsere Testobjekte angesteckt werden können. So war es möglich, auch mehrere Devices mit unterschiedlichen Konfigurationen parallel zu testen. Der Raspberry Power Switch kann über eine REST Schnittstelle mit den Test-Devices kommunizieren und so feststellen, ob diese hochgefahren sind. Nachdem die Test-Devices alle gebootet sind, wartet er eine zufällige Zeit zwischen 0 und 5 Minuten und schaltet dann den Strom ab. Danach wartet er wieder, bis alle Devices hochgefahren sind.
Ist ein Device nach einer gewissen Zeitspanne nicht verfügbar, dann wird das entsprechend in einem Log vermerkt. Tatsächlich haben wir zwei Fehlerszenarien festgestellt. Teilweise hat ein Reboot geholfen und das Device hat wieder funktioniert, teilweise hat nur ein erneutes Flashen der SD-Karte geholfen.
Mit Hilfe dieses Testaufbaus konnten wir nun verschiedene Testreihen mit verschiedenen Devices und Konfigurationen durchführen und haben ausreichend viele Wiederholungen erzielen können – etwas das ohne Automatisierung nicht möglich gewesen wäre. Für mich ein schönes Beispiel, wie wichtig Testautomatisierung tatsächlich ist, auch wenn es auf den ersten Blick nicht möglich erscheint.
Tatsächlich haben unsere Tests ergeben, dass der Raspberry Pi Probleme mit Stromunterbrechungen hat, bis hin zu einem Zustand, in dem er sich gar nicht mehr booten lässt. Die Probleme sind mit dem Raspberry Pi 2 und Raspberry Pi 3 mit verschiedenen SD Karten aufgetreten, zumindest mal in Verbindung mit Windows 10 IoT. Tests mit anderen Betriebssystemen laufen aktuell noch. Das Verhalten ist natürlich nicht wirklich ideal für ein IoT Device das ja irgendwo ohne Wartung zuverlässig seinen Dienst verrichten sollte. Deutlich robuster hat sich dagegen das Dragonboard 410C verhalten. Damit konnten wir diese Probleme aktuell nicht feststellen
[-]
2016.04.12
Events in TFS 2015/VSTS mit Service Hooks verarbeiten
By admin / 12 April / Entwickler / 0 comm.
In diesem Post soll es darum gehen, wie man mit Hilfe von Service Hooks Events in TFS 2015/ VSTS verarbeiten und einen REST-Service aufrufen kann, der dann entsprechende Aktionen über die TFS REST API auslöst. In dem hier gezeigten Beispiel sollen beim Verschieben eines Product Backlog Items auf dem Board automatisiert entsprechende Tasks erzeugt werden. […]
[+]
Durch das Verschieben eines Product Backlog Items triggert VSTS den konfigurierten ServiceHook. Dieser sendet das WorkItemChanged Event an den Api Controller. Dieser handelt die Informationen ab und der Rest Client schickt die Anfrage für das Erstellen des WorkItems an die VSTS Rest Api. Konkret soll für jedes PBI, das in die Spalte Committed verschoben wird, automatisch ein Task „Make it done“ angelegt. Wir nutzen hierzu eine Azure Api App, wobei hier auch ein beliebiger anderer Service, z.B. lokaler REST Service, möglich wäre. Die Solution zu diesem Blogeintrag findet man hier: https://github.com/artiso-solutions/TfsServices
-
Api App auf Azure
-
Anlegen der Api App in Azure
Zunächst erstellt man eine Api App im Azure Portal.Anschließend kann für die Api App Name, Resourcengruppe und Region ausgewählt werden.
Nach der Fertigstellung wird man zur Portalseite der Api App weitergeleitet, auf der man seine Einstellungen vornehmen kann. Hier kann z.B. die Skalierung eingestellt werden, um die Kosten zu regulieren.
-
Konfiguration der Api App
Die Api App hat standardmäßig das Pricing Tier „Free“.Im Reiter/Tab „Application Setings kann man Remote Debugging für die jeweilige Visual Studio Version aktivieren.
Nach dem Speichern ist die Konfiguration in Azure vorerst abgeschlossen und man kann mit der Entwicklung der App beginnen.
-
-
Erstellen der App
Nachdem man im ersten Kapitel auf Azure die Api App angelegt hat wird im zweiten Kapitel des Blogs auf die Erstellung der Azure Api App eingegangen. Diese Api App soll jetzt die Events erhalten, die bei VSTS über die Sevice Hooks getriggert werden und danach über die TFS REST API Tasks anlegen soll.-
Anlegen eines neuen Azure Api App Projekts
Als Voraussetzung braucht man das Azure SDK für .NET, welches man hier bekommt (https://azure.microsoft.com/de-de/downloads/), falls es noch nicht installiert ist. Nach der Installation wird in Visual Studio ein neues Web Application Projekt angelegt.Bei der Auswahl des Templates wählt man die Api App aus. Diese hat keine Authentifizierung. Diesen Umstand können wir später beheben, indem man eine eigene Authentifizierung erstellt. Die checkbox „Host in the Cloud“ kann man ignorieren, da die Api App ja schon auf Azure regristriert ist.
-
Implementierung der API App
Nach dem Wizard wird eine Solution angelegt, die ein Controllers-Verzeichnis enthält. Darin ist eine Klasse enthalten, die von ApiController erbt. Diese benutzt man um Http-Requests abzuarbeiten. Dazu ändern wir diesen Controller und fügen unsere eigene Methode ein. Diese nimmt den POST-Request vom ServiceHook (siehe Kapitel 3) entgegen und generiert eine Antwort. Die weitere Logik kann man hier dann einbetten.public async Task<HttpResponseMessage> WorkItemChanged() { var content = this.Request.Content.ReadAsStringAsync().Result; return this.Request.CreateResponse(HttpStatusCode.Accepted, content); }
Um sich z.B. den Content anzusehen, liefert z.B. (https://jsonviewer.stack.hu/) eine schöne Darstellung. Der erhaltene JSON-String kann mit dem Nuget Package NewtonSoftJson deserialisiert werden. -
Eigene Authentifizierung erstellen
Um eine gewisse Sicherheit zu gewährleisten, kann man sich selbst Credentials erstellen, welche später bei der Konfiguration des Service Hooks, für eine Basic-Authentifizierung, verwendet werden können. Folgende Abfrage stellt sicher, dass nur authentifizierte Anfragen bearbeitet werden:if (this.Request.Headers.Authorization.Scheme == "Basic" && this.Request.Headers.Authorization.Parameter == Convert.ToBase64String(Encoding.ASCII.GetBytes($"{Username}:{Password}")))
-
Verbindungsaufbau über Security Token
Jetzt kann eine Verbindung zu VSTS aufgebaut werden, wozu ein Token benötigt wird, welches man sich auf dem VSTS Portal erstellen lässt. (https://{yourAccount}.visualstudio.com/_details/security/tokens)Bei der Erstellung kann die Lebensdauer und der Scope eingestellt werden. Die Lebensdauer bedeutet natürlich, daß man nachdem die Zeit abgelaufen ist, das Token erneuern muss und entsprechend in den Code einpflegen muss. Beim Scope wird eingestellt,welche Rechte der jeweilige Aufruf hat. In diesem Fall bekommt das Token Lese- und Schreibzugriff auf Work Items.
Nun kann man im Controller eine Verbindung zu VSTS aufbauen.
var uri = $"https://{this.account}.visualstudio.com/{this.collection}/{teamProject}/_apis/wit/workitems/${workItemType}?api-version=1.0"; using (HttpClient client = new HttpClient()) { client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json-patch+json")); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{this.user}:{this.password}"))); }
Hierbei ist der Username leer und das Passwort das vorher erzeugte Token. Die Uri kann natürlich angepasst werden. Mehr Informationen dazu findet man auf: https://www.visualstudio.com/en-us/integrate/api/overview -
Auslesen der wichtigen Informationen aus dem eingegangenen Service Hook Event
Die einzelnen Parameter können aus dem eingegangenen Event geholt werden. Die Id des WorkItems liegt auf dem folgenden Feld: var parentWorkItemId = deserializedWorkItem.Resource.WorkItemId; Aus der folgenden Methode bekommt man alle Informationen, die auf dem WorkItem gespeichert sind:public async Task ReadFullyExpandedWorkItem(int workItemId) { FullyExpandedWorkItem workItem; var uri = $"https://{this.account}.visualstudio.com/{this.collection}/_apis/wit/workitems/{workItemId}?$expand=all&api-version=1.0"; using (var client = new HttpClient()) { client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{this.user}:{this.password}"))); using (HttpResponseMessage response = client.GetAsync(uri).Result) { response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); workItem = JsonConvert.DeserializeObject (responseBody); } return workItem; } }
-
Erstellen des neuen WorkItems
Um jetzt ein WorkItem anzulegen, muss man analog zu der in der TFS REST API beschriebenen PATCH Operation (https://www.visualstudio.com/en-us/integrate/api/wit/work-items#CreateaworkitemWithaworkitemlink) vorgehen. Man kann diese JSON-PatchOperation gut mit dem Nuget-Package NewtonSoftJson nachbilden:private JsonPatchDocument CreateJsonPatchDocument(string newWorkItemTitle, int workItemId, string iteration, string description) { var json = new JsonPatchDocument { new JsonPatchOperation { Operation = Operation.Add, Path = "/fields/System.Title", Value = newWorkItemTitle } }; if (iteration != null) { json.Add(new JsonPatchOperation { Operation = Operation.Add, Path = "/fields/System.IterationPath", Value = iteration }); } if (description != null) { json.Add(new JsonPatchOperation { Operation = Operation.Add, Path = "/fields/System.Description", Value = description }); } /// Hier kommt der unten genannte Teil mit der Verlinkung hinein return json; }
Wichtig ist hier ein Teil, der die Verlinkung zu dem ParentWorkItem gewährleistet, damit der Task der erstellt wird auch unter dem richtigen Product Backlog Item erscheint:if (workItemId >= 0) { json.Add(new JsonPatchOperation { Operation = Operation.Add, Path = "/relations/-", Value = new WorkItemLink { Rel = "System.LinkTypes.Hierarchy-Reverse", Url = $"https://{this.account}.visualstudio.com/{this.collection}/_apis/wit/workItems/{workItemId}", Attributes = new Attributes() { Comment = "Created by TFSServicesForExpertBlog" } } }); }
-
Senden des Json-Patchdocuments an die TFS Rest API
Die nächste Methode beschreibt, wie man die erzeugte JSON-Patchoperation dann an die TFS REST API schickt.public async Task CreateNewLinkedWorkItem(string teamProject, string newWorkItemTitle, string workItemType, int parentWorkItemId, string iteration, string description) { WorkItem createdWorkItem; var json = this.CreateJsonPatchDocument(newWorkItemTitle, workItemId, iteration, description); var jsonString = JsonConvert.SerializeObject(json); var uri = $"https://{this.account}.visualstudio.com/{this.collection}/{teamProject}/_apis/wit/workitems/${workItemType}?api-version=1.0"; var content = new StringContent(jsonString, Encoding.UTF8, "application/json-patch+json"); using (HttpClient client = new HttpClient()) { client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json-patch+json")); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{this.user}:{this.password}"))); using (var response = client.PatchAsync(uri, content).Result) { response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); createdWorkItem = JsonConvert.DeserializeObject(responseBody); } } return createdWorkItem; }
-
Publishing der Azure Api App aus Visual Studio
Um die Azure Api App zu publishen klickt man mit der rechten Maustaste im Solution Explorer auf das Projekt und wählt „Publish“ aus.Über den Button Microsoft Azure App Service kann man sich bei Azure mit seinem Microsoft Account anmelden, und die vorher angelegte Api App wird angezeigt.
Dieser wird ausgewählt und der Wizard holt alle wichtigen Daten für das Publishen.
Nun können noch die Konfiguration und die Settings eingestellt werden.
Nach einem Klick auf „Next“ kann mit dem neu erstellten „Web Publish“-Profil die Api App auf Azure hochgeladen werden.
-
-
Registrieren der Api App im VSTS Service Hook
Nach dem Erstellen und Publishen der Api App soll jetzt im dritten Teil die Verbindung zum VSTS Service Hook erstellt werden.-
Erstellen des Service Hooks
Jetzt kann man zum VSTS Dashboard des TeamProjects wechseln.(https://{account}.visualstudio.com/{Collection}/{TeamProject}/_dashboards)Über das Zahnrad in der rechten oberen Ecke, wird zu Administrationsseite navigiert, und dort zum Tab für die Service Hooks.Hier wird ein neuer Service Hook vom Typ „Web Hooks“ erstellt:
-
Konfiguration des Service Hooks
Es kann ausgewählt werden welches Event die Api App triggern soll, sowie welche Bedingungen zusätzlich erfüllt sein sollen.Im Beispiel wird für den Trigger „Work item updated“ und für Work Item Type „Product Backlog Item“ gewählt um auf jegliche Änderung eines PBIs zu reagieren.Auf der letzten Konfigurationsseite kann nun die Api App URL mit dem Zusatz „/api/WorkItemChanged“ eingegeben werden. Damit hier die Authentifizierung nicht in Klartext verschickt wird, muss der URL https vorangestellt werden. Zur Authentifizierung geben wir nun den Username und das Passwort, das wir im zweiten Kapitel erstellt haben an.
Nach einem optionalen „Test“, ob die Api App angesprochen werden kann, wird die Konfiguration mit „Finish“ beendet. Im Ganzen haben wir jetzt also folgende Prozesskette:
Durch das Verschieben eines Product Backlog Items triggert VSTS den konfigurierten ServiceHook. Dieser sendet das WorkItemChanged Event an den Api Controller. Dieser handelt die Informationen ab und der Rest Client schickt die Anfrage für das Erstellen des Workitems an die VSTS Rest Api. Für den abschließenden Test wird auf dem Kanban Board ein Product Backlog Item in die Spalte „Committed“ verschoben. Daraufhin wird ein WorkItemChangedEvent ausgelöst, welches über den Service Hook eine Mitteilung an die Api App schickt. Die Api App legt dann über die REST API von VSTS den Task „Make it Done“ an. So bekommt man den Task, den man im Sprint immer braucht, automatisch angelegt.
-
-
Troubleshooting
-
Remote Debugging aus Visual Studio
Falls man Probleme hat kann man die Api App aus Visual Studio heraus debuggen.https://blogs.msdn.microsoft.com/webdev/2013/11/04/remote-debugging-a-window-azure-web-site-with-visual-studio-2013/
-
[-]
2016.03.22
Rückblick Spartakiade Workshop zu agiler Unternehmenskultur
By admin / 22 März / Entwickler / 0 comm.
Am Wochende war ich auf der Spartakiade und habe dort einen ganztägigen Workshop mit dem Titel “Ab morgen bitte Scrum” geleitet. Die Spartakiade ist eine Community-Konferenz die ausschließlich aus herausfordernden Workshops besteht – ein interessantes Konzept, das es erlaubt ein Thema auch mal mit entsprechender Tiefe zu bearbeiten. Mit diesem Post möchte ich ein paar […]
[+]Am Wochende war ich auf der Spartakiade und habe dort einen ganztägigen Workshop mit dem Titel “Ab morgen bitte Scrum” geleitet. Die Spartakiade ist eine Community-Konferenz die ausschließlich aus herausfordernden Workshops besteht – ein interessantes Konzept, das es erlaubt ein Thema auch mal mit entsprechender Tiefe zu bearbeiten.
Mit diesem Post möchte ich ein paar Eindrücke von der Konferenz und aus meinem Workshop berichten.
Die Konferenz
Inzwischen gibt es eine Reihe von sehr professionell organisierten Community-Veranstaltungen und die Spartakiade gehört auf jeden Fall mit in diesen Kreis. Ca. 150 Teilnehmer konnten sich an 2 Tagen in entsprechenden Workshops weiterbilden und untereinander austauschen. Persönlich hat mir das Konzept mit den Workshops sehr gut gefallen, da ich in meinem Workshop, bei dem es um die kulturellen Aspekte von Scrum geht, endlich nicht nur theoretisch bleiben musste wie bei Vorträgen, sondern ich konnte diese Themen für die Teilnehmer “erlebbar machen”.
Was auch auffällt, das Publikum auf Community-Konferenzen ist etwas anders. Dort treffen sie die Leute, denen ein Thema so sehr am Herzen liegt, dass sie sogar ihr Wochenende investieren und vielen bezahlen Reisekosten aus der eigenen Tasche statt sich das vom Arbeitgeber finanzieren zu lassen. Diese Motivation merkt man, auch, wie die Teilnehmer sich im Workshop engagiert haben.
Vielen Dank nochmals an Torsten Weber und Janek Fellien mit ihren Unterstützern dafür, dass sie diesen großartigen Rahmen für den Austausch in der Community geschaffen haben.
Der Workshop
In meinem Workshop ging es vor allem darum, wie die Unternehmenskultur Agilität beflügeln oder ausbremsen kann und wie man zu einer agilen Unternehmenskultur kommen kann.Da es dabei auch darum geht, einfach Dinge mal auszuprobieren und anders zu machen, habe ich die Vorstellungsrunde schon versucht etwas ungewöhnlich zu gestalten.
Vorstellungsrunde
Nach meiner Überzeugung ist ein wichtiger Aspekt der agilen Unternehmenskultur, Dinge einfach auch mal anders zu machen. Deshalb wollte ich eine Alternative zur klassischen Vorstellung bei der sich jeder reihum selbst vorstellt. Ich habe ein anderes Format gewählt, bei dem sich die Teilnehmer sich zu Paaren zusammengefunden haben. Dann gab es eine Timebox von 7,5 Min. in der sich die Paare untereinander kennenlernen konnten. Nach der Timebox hat jeder mit 3 kurzen Fakten bzw. Statements seinen Partner vorgestellt. Es hat zwar nicht perfekt geklappt, dass sich jeder auf 3 Aspekte der Vorstellung fokussiert hat, aber persönlich fand ich diese Form der Vorstellung deutlich besser. Man hat seinen Partner intensiver kennengelernt als in einer üblichen Vorstellungsrunde und bei der Vorstellung war interessant zu sehen, welche Aspekte ausgewählt wurden, um den Partner vorzustellen. Angenehmer Nebeneffekt war, dass die Vorstellungsrunde insgesamt zeitlich sogar kürzer war als beim klassischen Vorgehen.
Mit der Vorstellungsrunde konnte ich auch schon 2 wesentliche agile Werte bzw. Konzepte vermitteln. Timeboxing und Fokussierung. Durch die Timebox muss jeder darauf achten, innerhalb der gegebenen Zeit ein ausreichend gutes Ergebnis zu liefern und z.B. zu verhindern, dass das Kennenlernen bis zum Ende der Timebox nur in eine Richtung erfolgte. Und es ist einfach, in aller Länge viele Details über sich oder jemand anderen zu erzählen. Aber die 3 wesentlichen Kernpunkte auszuwählen und sich auf diese zu fokussieren ist deutlich schwieriger.
Impulsvortrag
Im anschließenden Impulsvortrag wollte ich die Teilnehmer auf das Thema einstimmen. Ich wollte nicht viel vorwegnehmen und auch nicht viel Zeit mit der Einführung vernichten, deshalb habe ich es sehr kurz gehalten. Meine Kernaussagen waren:
- Der Erfolg von Agilität hängt im Wesentlichen von der Kultur im Team und im Unternehmen ab. Die Mechanismen sind trivial.
- Leider wird Agilität oft als Tool installiert in der Annahme, dass sich bereits dadurch entsprechende Erwartungen erfüllen. Dadurch bleibt aber die Bereitschaft für einen echten Wandel auf der Strecke.
- Wir brauchen eine geeignete Wertebasis. Die gelebten Werte durch die beteiligten Personen habe ich als Kultur bezeichnet.
- Über Werte zu diskutieren ist schwierig, da die meistens positiv formuliert sind und eigentlich niemand gegen Werte wie Ehrlichkeit oder Offenheit argumentieren wird.
- Eine Kultur kann nicht verordnet werden. Demzufolge kann der Workshop auch eher Impulse und Denkanstöße liefern, keine “Best Practices”.
Hier die Notizen die ich für den Impulsvortrag genutzt habe:
Erwartungen und Erfolgskriterien festlegen
Danach haben wir in der Gruppe versucht zu definieren, wann der Workshop für die Teilnehmer erfolgreich ist und woran wir das festmachen können. Ich habe die Teilnehmer gebeten, ihre Erwartungen zu formulieren, woran sie am Abend erkennen können, ob sie den Workshop für sich persönlich als Erfolg bewerten. Hier sind die Ergebnisse:
Zudem haben wir begonnen konkrete Fragen und Problemstellungen zu sammeln die wir dann den Tag über in einzelnen Q&A Sessions bearbeiten können. Hier war die Aufforderung, auch den ganzen Tag über neu hinzukommende Fragen entsprechend zu ergänzen.
Wahl des ersten Themas
Damit wir den Workshop möglichst gut auf die Wünsche der Teilnehmer abstimmen konnten, habe ich eine Reihe von Themen vorgestellt, die ich vorbereitet hatte und diese dann zur Wahl gestellt. Die erste Frage lautete: Welches Thema wollt ihr als erstes angehen?
Für das anschließende Voting habe ich eine Anregung genutzt, die ich vor kurzem von meinem Kollegen Cédric bekommen habe. Oft macht man ja Dinge einfach so, weil man sie schon immer so macht, auch wenn man mit dem Vorgehen eigentlich nicht richtig glücklich ist. So ging es mir bisher mit solchen Votings die ich in meinen Workshops und Trainings sehr häufig mache. Das übliche Vorgehen sind Striche zu machen wobei jeder 5te Strich diagonal gezeichnet wird. Das hat aber oft nicht richtig gut funktioniert. Jeder musste darauf achten, wie viele Striche schon da sind und dann daran denken, den 5ten entsprechend diagonal zu zeichnen. Die Auswertung war hinterher auch entsprechend, da man nochmals kontrollieren musste, ob die 5er-Blöcke korrekt gesetzt wurde etc. Ich war nie glücklich mit dem Vorgehen, hab es aber immer wieder verwendet. Nun hat Cédric bei einem Voting eine andere Methode angewendet, die ich viel schöner fand und die habe ich auch gleich in den Workshop übernommen, auch um zu zeigen, dass es gut ist, ausgetretene Wege mal zu verlassen und neues zu probieren.
Das neue Voting funktioniert so, dass auch 5er-Blöcke gebildet werden aber in Form eines Quadrats, wobei die ersten 4 Stimmen die 4 Seiten des Quadrats bilden und die 5te eine Diagonale. Das ist aber viel klarer als bei den Strichen. Hier das Ergebnis des ersten Votings:
Das Ergebnis des Votings war dann folgendes:
Geschichten aus dem Alltag eines Scrum-Coaches
Als erstes haben sich die Teilnehmer für eine Gruppendiskussion entschieden. Ich habe verschiedene Situationen die ich beobachtet habe, beschrieben. Anschließend haben wir gemeinsam diskutiert, ob wir die Situation positiv oder negativ bewerten, warum das so ist, welche Auswirkungen diese Situation haben kann und was alternative Möglichkeiten gewesen wären.
Ich fand es sehr positiv, dass bereits in der ersten Runde eine ausgiebige Diskussion entstand und die Teilnehmer begonnen haben, über die offensichtliche Bewertung der Situation hinaus zu denken. Bei dieser Übung kam sehr gut heraus, dass es sich lohnt, nicht seinem ersten Impuls zu folgen, sondern etwas genauer hinzuschauen. So kann es beispielsweise hilfreich sein, sich in die jeweils handelnden Personen zu versetzen und sich zu überlegen, wie man selbst sich fühlen würde. Oder man muss versuchen, sich auf den Kern einer Sache zu fokussieren und sich nicht auf unnütze Nebendiskussionen einlassen. Dazu gehören beispielsweise Rechtfertigungen des Teams, wenn der Product Owner im Sprint Review die erstellte Lösung kritisiert und Änderungen haben möchte.Eine der beschriebenen Situationen sollte auch deutlich machen, dass es nicht genügt, Scrum einmal erfolgreich angewendet zu haben. Man muss kontinuierlich daran arbeiten, sonst fällt das Team schnell wieder in alte Muster zurück. Eine andere Situation zeigte, dass es wichtig ist, offen für Neues zu sein und Dinge nicht einfach abzulehnen, weil man nicht überzeugt davon ist. In einigen Situationen ist es besser, sich auf das Neue zunächst einmal einzulassen und die gewonnenen Erfahrungen dann auszuwerten um auf dieser Bassi dann zu entscheiden.
Wir konnten in der angestrebten Timebox nur 4 der 16 von mir vorbereiteten Situationen besprechen, aber die Diskussionen waren sehr fruchtbar und haben sehr gut aufgezeigt, warum die kulturellen Aspekte viel wichtiger sind, als die reinen Mechanismen von Scrum.
Team Values Game
In der nächsten Runde ging es dann in das Team Values Game. Ich werde das Spiel noch ausführlicher in einem separaten Post beschreiben. Deshalb hier kurz beschrieben, wie es in unserem Workshop abgelaufen ist. Bei diesem Spiel hatte ich 2 Beobachter. Die restlichen Teilnehmer bekamen einer Reihe von Zetteln auf denen verschiedene Aussagen standen.
Die Teilnehmer mussten diese nun in eine Reihenfolge bringen, die die persönliche Wichtigkeit ausdrückt. In der zweiten Runde war dann das Ziel, seine eigene Liste mit der von anderen Teilnehmern zusammenführen zu können. Dazu wurden die Unterschiede diskutiert und warum einem bestimmte Themen wichtig waren oder eben nicht. Ziel war, innerhalb der Gruppe möglichst wenige Listen zu haben zu denen aber alle auch wirklich stehen.
Dieses Spiel zeigt sehr gut auf, wie schwierig es ist, über Werte zu diskutieren. Das Verständnis bzw. die Interpretation der einzelnen Punkte können sehr voneinander abweichen. Dabei spielt der persönlicher Erfahrungshintergrund und die eigene aktuelle Situation eine wichtige Rolle. Diese unterschiedlichen Interpretationen sichtbar zu machen kann aber sehr wertvoll sein. Man beginnt auf einmal zu verstehen, warum jemand in bestimmten Situationen unerwartet reagiert oder sich jemand nicht verhält wie erwartet. Zudem beginnt man für sich ein Bewusstsein zu entwickeln, welche Werte einem wirklich wichtig sind und bei welchen man Kompromisse eingehen kann. Letztendlich stand die Frage im Raum, ob es erstrebenswert ist, sich in einem Team tatsächlich auf eine Liste zu einigen. In der Gruppe war die Meinung, dass das nicht sinnvoll ist, um auch eine bestimmte Meinungsvielfalt zu erlauben. Aber wir brauchen eine gemeinsame Basis und vor allem ein Verständnis, wo unsere Wertesysteme im Team abweichen.
Agile Product Management Game
Als nächstes stand dann das Agile Product Management Game oder Business Value Game auf dem Programm. Dabei handelt es sich um ein interessantes Spiel das leider etwas zeitaufwändiger ist (min. 90 Min.). Dabei geht es darum transparent zu machen, wie ein Product Owner bestimmte Entscheidungen für die Entwicklung eines Teams treffen muss / kann. Warum dieses Spiel aber nun bei einem Workshop zum Thema Kultur? Zunächst einmal war das Feedback der Teilnehmer, dass das Spiel sehr gut verdeutlicht hat, wie komplex solche Entscheidungsprozesse oftmals sind und dass der Entwickler ja nur eine sehr eingeschränkte Sicht darauf hat. Mit einem besseren Verständnis für die Einflussfaktoren werden viele Entscheidungen nachvollziehbar. Die Teilnehmer berichteten von Situationen bei denen sie in der Rolle als Entwickler tatsächlich schon hin und wieder Entscheidungen nicht nachvollziehen konnten und diese umgesetzt haben, obwohl sie nicht überzeugt davon waren, das richtige zu tun – eine Situation die wir im agilen Kontext unbedingt vermeiden möchten. Daraus entspannte sich dann eine Diskussion über Transparenz und vor allem darum wie viel Transparenz möglich / sinnvoll ist. In der Gruppe war der Status Quo hier auch sehr unterschiedlich. Während in einem Unternehmen die finanziellen Aspekte eines Kundenauftrages und die Kostensituation voll transparent gemacht werden, will man sich bei anderen eher nicht so tief in die Karten schauen lassen. Wir waren uns einig, dass diese Art der Transparenz sich entwickeln muss, sonst ist das Risiko eines Missbrauchs zu hoch. Ein wichtiger weiterer Aspekt war die Erkenntnis, dass es wichtig ist, dass alle im Team sich auf das eigentliche Ziel fokussieren, nämlich den Nutzen für den Kunden zu maximieren. Dieser Fokus gerät manchmal etwas aus dem Blick, wenn sich Entwickler ausschließlich auf die Umsetzung der Anforderungen konzentrieren. Hier ist wichtig, dass sich alle im Team entsprechend abstimmen und auch immer wieder hinterfragen, ob einzelne Punkte wirklich zielführend bzw. relevant für die Zielerreichung sind.
Ball Point Game
Zum Abschluss hat sich die Gruppe dann noch das Ball Point Game gewünscht. Dabei wird gezeigt, wie wichtig es ist, durch regelmäßige Retrospektiven seine aktuelle Vorgehensweise zu hinterfragen und zu optimieren. Im Spiel geht es darum, möglichst viele Bälle einmal durch das Team zu reichen. In der Realität zeigt das die Wichtigkeit und die Wirksamkeit von Retrospektiven. Retrospektiven werden von Teams oft als lästig und unbequem empfunden und am Ende ändert sich doch nichts. Das Spiel zeigt, dass das Team selbst in der Retrospektive Verantwortung für diese Veränderungen übernehmen muss.
Feedbackrunde
Zum Abschluss haben wir nochmals auf unsere Erfolgskriterien geschaut und die Teilnehmer haben kommentiert, was sie aus dem Workshop mitgenommen haben. Ich habe dann noch gebeten, die Einschätzung zum Workshop über einen Smiley und einem kurzen Satz zu geben. Hier das Feedback das mich sehr gefreut hat
Zusätzlich haben die Teilnehmer noch abgestimmt, welcher Teil des Workshops ihnen am besten gefallen hat. Hier das Ergebnis:
1. Impulsvortrag – 1
2. Vorstellungsrunde – 8
3. Aus dem Leben eines Scrum Coaches – 4
4. Team Values Game – 9
5. Agile Product Mgmt. Game – 1
6. Ball Point Game – 3
Überrascht hat mich dabei, dass die Vorstellungsrunde 8 Stimmen bekommen hat. Ich hoffe, dass die anderen Themen nicht zu langweilig waren und nehme das jetzt mal als die positivste Vorstellungsrunde die ich je gemacht habe Im persöänlichen Gespräch habe ich dann im Anschluss noch sehr viel positives Feedback der Teilnehmer bekommen.
Von meiner Seite aus auch nochmal ein dickes Dankeschön an meine Workshop-Teilnehmer. Ihr wart spitze!
Fazit
Die Spartakiade hat Spaß gemacht und es war ein Workshop bei dem ich auch als Trainer wieder sehr viel mitnehmen konnte. Ich mag das Format und die Leute.
Community rocks!
[-]
2016.01.31
Päckchen packen mit NuGet, TFS 2015 und Build vNext. Teil 4: Pakete debuggen
By admin / 31 Januar / ALM, Entwickler / 0 comm.
Funktionalität automatisiert für andere Anwendungen bereitstellen Anmerkung: Dies ist die für Visual Studio / TFS 2015 und Build vNext überarbeitete Version unseres Artikels auf entwickler.de. Es hat sich einiges getan: Das neue Buildsystem vereinfacht das zentrale Erstellen und Bereitstellen von NuGet-Paketen erheblich, und die NuGet-Integration in Visual Studio Team Services bietet einen Einfachen weg, eigene […]
[+]Blogserie
- Teil 1: Pakete verwenden
- Teil 2: Pakete erstellen
- Teil 3: Pakete verteilen
- Teil 4: Pakete debuggen (dieser Artikel)
Lokal erstellte Pakete debuggen
Im den bisherigen Teilen dieser Artikelserie haben wir gesehen, wie NuGet-Paketes schnell und einfach konsumiert, erstellt und verteilt werden können. Wie steht es aber mit dem Debugging, wenn diese Pakete in andere Projekte eingebunden werden? Haben wir das Paket auf unserem eigenen Rechner erstellt, dann ist die Sache recht einfach, weil die aktuellen Sourcen zu dem Paket lokal vorliegen und da vermutlich genau diese Version auch in unser Paket verpackt wurde. In diesem Fall genügt es einfach, die .pdb-Datei mit ein das Projekt einzufügen. Damit diese Datei in unserem regulären Paket nicht mitverpackt wird, legen wir einfach eine zweite .nuspec-Datei an, welche das entsprechende File enthält.





Debugging von Paketen aus dem Team Build
Wird das Package allerdings von einem Kollegen oder mit einem TFS Build erstellt, funktioniert der oben beschriebene Weg nicht mehr. Hier haben wir ja als Nutzer des Packages die Sourcen des Packages nicht zwingend in der richtigen Version an der gleichen Stelle auf unserem Entwicklungs-Rechner. Wir kommen zwar gegebenenfalls über unser spezielles Debugging-Package an die .pdb-Datei, aber die Code-Dateien fehlen uns auf jeden Fall. Deshalb muss hier eine andere Lösung gefunden werden. Die ist glücklicherweise aber – Sie ahnen es – sehr einfach. Wir brauchen zunächst einen weiteren Netzwerk-Share auf den die Entwickler und der TFS Team Build Zugriff haben. Dann geben wir in unserer Build Definition im Step Index Sources & Publish Symbols diesen Pfad unter Path to Publish Symbols an.







Die Zwei-Repository-Lösung
Wenn ein Package neu entwickelt wird oder wenn Anpassungen (z.B. ein Bugfix) gemacht wurden, dann möchte man das neue Package natürlich erst lokal einmal testen und dazu sollte es nicht notwendig sein, die Änderungen einzuchecken und zu warten, bis der Team Build durchgelaufen ist. Wie das geht, wurde weiter oben demonstriert. In der Praxis ist es sinnvoll, zwei Repositories zu verwenden – eines für die lokal gebauten Pakete zu Debugging-Zwecken und ein öffentliches, zentrales Repository. Wie wir Repositories anlegen haben wir ja schon gesehen- im vorliegenden Fall sind sowohl das lokale, Share-basierte Repository als auch der zentrale Server als Package Sources eingetragen.
- Wir haben die Consumer-Solution geöffnet. Diese benutzt bereits unser Package aus dem zentralen Repository in der Version 26.1.31.6. Das lokale Repository ist leer.
- Wir analysieren einen Bug und stellen fest, dass dieser in unserem Package liegen muss. Wir öffnen nun in einer zweiten Visual Studio Instanz die Package Solution und passen den Code entsprechend an.
- Ein lokaler Build in Visual Studio erzeugt nun das Package. Mit der zuvor beschriebenen Versionierungs-Methodik ergibt sich ein Package mit der Version 999.99.99.99. Wir kopieren das Symbol-Package in unser lokales Repository. Dieser Vorgang haben wir ja bereits durch unseren Post Build Event automatisiert.
- Durch ein einfaches Update wird das Package in der Consumer-Solution nun auf diese Version aktualisiert und wir können unsere Anpassungen einfach testen und debuggen.
- Nachdem wir die Änderungen geprüft und eingecheckt haben, starten wir einen TFS-Build. Erzeugt nun ein Package mit der nächst höheren Version, welches wir in unser zentrales Repository kopieren.
Fazit
Selbermachen lohnt sich: NuGet bietet nicht nur einen bequemen Weg, fremden Code in eigene Projekte einzubinden. Mit etwas MS-Build-Magie wird es zum idealen Werkzeug, um Code einfach, versionssicher und mit allem Debugging-Komfort zu verteilen – ob „nur“ in der eigenen Organisation oder für die ganze Welt. Viel Spaß dabei![-]
2016.01.31
Päckchen packen mit NuGet, TFS 2015 und Build vNext. Teil 1: Pakete verwenden
By admin / 31 Januar / ALM, Entwickler / 0 comm.
Funktionalität automatisiert für andere Anwendungen bereitstellen Anmerkung: Dies ist die für Visual Studio / TFS 2015 und Build vNext überarbeitete Version unseres Artikels auf entwickler.de. Es hat sich Einiges getan: Das neue Buildsystem vereinfacht das zentrale Erstellen und Bereitstellen von NuGet-Paketen erheblich, und die NuGet-Integration in Visual Studio Team Services bietet einen einfachen weg, eigene […]
[+]Blogserie
- Teil 1: Pakete verwenden (dieser Artikel)
- Teil 2: Pakete erstellen
- Teil 3: Pakete verteilen
- Teil 4: Pakete debuggen
Der Paketmanager NuGet ermöglicht es, Funktionalität in handliche, versionierte Pakete (NuGet-Packages) zu packen und diese dann einfach für mögliche Konsumenten bereitzustellen. Das Tool war zunächst als Visual Studio-Erweiterung und Konsolenprogramm verfügbar, ab Visual Studio 2012 ist NuGet in die Entwicklungsumgebung integriert. Über öffentlich verfügbare Paketserver wie NuGet.org ist es sehr einfach, solche Packages zu veröffentlichen. Mittlerweile gibt es praktisch keine populäre Bibliothek mehr, die nicht über NuGet einfach in das eigene Projekt eingebunden werden kann – auch Microsoft selbst nutzt NuGet extensiv für die Bereitstellung von wichtigen Komponenten. Viele Visual Studio-Projektvorlagen enthalten Referenzen auf NuGet Packages, und selbst Teile des .NET Frameworks selbst werden mittlerweile auf diesem Weg ausgeliefert. Im Januar 2016 standen allein auf NuGet.org über 48.000 Pakete zum Download bereit.

Fertige Pakete zum eigenen Projekt hinzufügen
Bereits verfügbare NuGet-Pakete zu nutzen ist sehr einfach: Packages werden in Visual Studio über den Befehl Manage Nuget Packages… in die Projekte eingebunden. Dabei können einzubindenden Packages für eine einzelnes Projekt oder für die gesamte Solution verwaltet werden. Sollen Pakete in mehrere Projekte eingebunden werden empfiehlt sich der Aufruf von Manage NuGet Packages for Solutions… auf dem Solution-Eintrag im Solution Explorer: Es öffnet sich ein Dialog, in dem man auswählen kann, auf welche Projekte innerhalb der Solution die betreffende Referenz gesetzt werden soll. Dieser Befehl steht in Visual Studio im Menü Tools/Package Manager zur Verfügung.
- Browse Hier werden alle Pakete angezeigt, die auf dem im Dropdown-Feld Package Source gewählten Server verfügbar sind. Über den kleinen Zahnrad-Button rechts oben lassen sich weitere Paketserver wie beispielsweise MyGet.org oder auch lokale Server zur Auswahl hinzufügen. Wir werden später noch sehen, wie man eigene Package Sources erstellt.
- Installed Hier werden alle Pakete angezeigt, die bereits im aktuellen Projekt bzw. in der Solution installiert sind.
- Update Hier werden alle Pakete angezeigt, die bereits installiert sind und für die Updates bereitstehen.
- Consolidate (nur für Solutions) Diese in Visual Studio 2015 neue Option ermöglicht es, auf einfache Weise alle Projekte in einer Solution auf die gleiche Version eines Pakets upzudaten.
- Im rechten Bereich des Fensters können Pakete für alle oder einzelne Projekte installiert und deinstalliert werden, und es werden wichtige Informationen zu den Paketen angezeigt.Im vorliegenden Beispiel geht es um eine kleine “Hello World”-Konsolenapplikation, in die das Logging-Framework log4net eingebunden werden soll. Zunächst muss der Server gewählt werden, von dem das Pakt heruntergeladen werden soll (1); die geschieht über den Reiter Package Source rechts oben. Bei öffentlichen Paketen ist dies in der Regel der offizielle Paketserver unter NuGet.org. Dann kann die Bibliothek über das Suchfeld (2) lokalisiert werden und es werden die wichtigsten Infos über die gewählte Bibliothek angezeigt. Danach kann über Checkboxen bestimmt werden, für welche Projekte in der aktuellen Solution die Referenz gesetzt werden soll (3). Über den Install-Button wird die Bibliothek schließlich heruntergeladen und dem Projekt hinzugefügt (4).
Vorher präsentiert NuGet noch die Änderungen, die an der Solution vorgenommen werden sollen und fragt ganz höflich um Erlaubnis. Hat die eingebundene Bibliothek weitere Abhängigkeiten werden diese hier ebenfalls aufgelistet und automatisch mitinstalliert.
Schließlich lässt sich der Downloadprozess im Output-Fenster von Visual Studio mitverfolgen.
Jetzt kann die Bibliothek im Programmcode verwendet werden.
NuGet-Paketreferenzen
Was passiert nun genau beim Einbinden einer NuGet-Paketreferenz? Beim Installieren eines Paketes legt NuGet automatisch innerhalb des entsprechenden Projektes eine Datei mit dem Namen packages.config an. In dieser Konfigurationsdatei merkt sich NuGet, welche Pakete in welcher Version im entsprechenden Projekt installiert sind.Die Pakete werden dann vom entsprechenden Server heruntergeladen und in einem Ordner namens packages abgelegt, der auf der Ebene des Solution-Files angelegt wird. Somit sind die Pakete auch nutzbar, wenn keine Verbindung zum Server besteht. Nun wird eine Referenz auf die entsprechende Datei unterhalb des packages-Ordners im Projekt eingetragen.
Pakete können zusätzlich auch noch weitere Dateien, zum Beispiel Hilfe- oder Beispieldateien in das Projekt einbinden. So kann die Verwendung eines Paketes für den Nutzer vereinfacht werden. Zudem besteht die Möglichkeit, Konfigurationsdateien zu manipulieren und dort zusätzliche Einträge einzufügen, die bei der Deinstallation des Paketes auch wieder entfernt werden.
Versionierung von Paketen
Ein wichtige Funktion eines jeden Paketmanagers ist die Möglichkeit, Abhängigkeiten zu anderen Paketen definieren zu können. Beim Installieren eines Packages werden diese Abhängigkeiten ausgewertet und die entsprechenden Pakete automatisch mitinstalliert. Eine Voraussetzung dafür, dass dieser automatische und komfortable Prozess funktioniert ist es, dass der NuGet einen Versionierungs- und Update-Mechanismus mitbringt. Jedes Paket hat eine eindeutige Versionsnummer. Die Referenz im Projekt wird von NuGet immer auf die in der packages.config angegebene Version gesetzt. Durch die Bereitstellung einer neuen Version eines Paketes verändert sich das Verhalten zunächst nicht, da das Projekt immer noch die alte Version nutzt. Im Package Manager werden alle Pakete angezeigt, für die es eine neuere Version gibt. Diese können von dort entsprechend aktualisiert werden. Die neue Version des Paketes wird dann in den packages-Ordner heruntergeladen und die Referenz auf die neue Version abgeändert. Mit Visual Studio 2015 kann erstmals für jedes Paket direkt im Paketmanager bestimmt werden, in welcher Version es zur Solution oder zum Projekt hinzugefügt werden soll. Das war bisher nur über den Umweg der Package Manager Console möglich, die weiterhin im Menü Tools/Package Manager bereitsteht. Diese spezielle PowerShell-Kommandozeile ermöglicht mittels diverser Commandlets fortgeschrittene NuGet-Operationen. Eine Dokumentation dazu findet sich auf der offiziellen NuGet-Website.NuGet und Versionsverwaltung Beim der Verwaltung von Solutions mit NuGet-Referenzen über die Versionsverwaltung zeigt NuGet auch in der aktuellen Version 2015 von Visual Studio ein nachvollziehbares aber trotzdem etwas unglückliches Verhalten: Standardmäßig wird der packages-Ordner in der Versionsverwaltung mit eingecheckt:
Dies hat zwar den Vorteil, dass die entsprechenden Pakete auch nach Auschecken der Solution durch einen anderen Benutzer sofort verfügbar sind – andererseits können die Pakete jederzeit vom jeweiligen Paketserver geladen werden. Das Einchecken in die Versionsverwaltung ist somit unnötig. Leider gibt es für den Ausschluss der Pakete aus der Versionsverwaltung keinen einfachen Befehl in den Visual Studio-Einstellungen. Stattdessen ist ein Eintrag (disableSourceControlIntegration) in der NuGet-Konfigurationsdatei nötig.
Diese Datei mit dem Namen nuget.config findet sich im Verzeichnis .nuget auf der Ebene der Solution – falls die Datei nicht existiert, kann sie auch manuell erstellt werden. Aber Achtung: Beim Anlegen des Ordners .nuget nicht verzweifeln! Der Windows Explorer kann keine Verzeichnisse erstellen, die mit einem Punkt beginnen. Hier hilft nur der gute alte DOS-Befehl mkdir weiter. Wichtig auch: Änderungen an der Konfigurationsdatei werden erst nach Neustart von Visual Studio wirksam.
Danach wird der packages-Ordner automatisch im aktuellen Workspace unter Excluded Changes gelistet und nicht mit eingecheckt.
Ein Klick auf die von Visual Studio erkannten, aber vom Check In ausgeschlossenen Dateien [Detected: X add(s)] bestätigt, dass der Mechanismus wie gewünscht funktioniert.
Package Restore – Fehlende Pakete automatisch nachladen Nachdem das Einchecken des packages-Ordners unterbunden wurde, müssen die fehlenden Pakete dem Projekt vor einem Build wieder hinzugefügt werden, wenn die Solution an anderem Ort wieder frisch ausgecheckt wird. Dies erledigt NuGet automatisch per Package Restore. NuGet lädt dabei vor der eigentlichen Kompilierung die benötigten Pakete automatisch herunter, sobald in Visual Studio ein Build gestartet wird. Auch Team Builds auf einem dedizierten Buildserver werden unterstützt – dazu später mehr. Standardmäßig ist die Package Restore-Funktion in Visual Studio aktiviert, kann jedoch in den NuGet-Einstellungen auch abgeschaltet werden. Ab der NuGet-Version 2.7 ist Package Restore in Visual Studio integriert. Bei unserem kleinen Beispielprojekt lässt sich Package Restore ganz einfach testen: Einfach den packages-Ordner beherzt löschen, und beim nächsten Build repariert Visual Studio selbstständig und vollautomatisch das referenzierte Paket.
Fazit und Ausblick
Soweit zum ersten Teil unserer kleinen NuGet-Serie. Im zweiten Teil werden wir uns damit beschäftigen, wie man eigene NuGet-Packages erstellt und für mögliche Konsumenten veröffentlicht. Vielen Dank für’s Lesen!
[-]
2016.01.31
Päckchen packen mit NuGet, TFS 2015 und Build vNext. Teil 2: Pakete erstellen
By admin / 31 Januar / ALM, Entwickler / 0 comm.
Funktionalität automatisiert für andere Anwendungen bereitstellen Anmerkung: Dies ist die für Visual Studio / TFS 2015 und Build vNext überarbeitete Version unseres Artikels auf entwickler.de. Es hat sich Einiges getan: Das neue Buildsystem vereinfacht das zentrale Erstellen und Bereitstellen von NuGet-Paketen erheblich, und die NuGet-Integration in Visual Studio Team Services bietet einen einfachen weg, eigene […]
[+]Funktionalität automatisiert für andere Anwendungen bereitstellen
Anmerkung: Dies ist die für Visual Studio / TFS 2015 und Build vNext überarbeitete Version unseres Artikels auf entwickler.de. Es hat sich Einiges getan: Das neue Buildsystem vereinfacht das zentrale Erstellen und Bereitstellen von NuGet-Paketen erheblich, und die NuGet-Integration in Visual Studio Team Services bietet einen einfachen weg, eigene Paket-Feeds in der Cloud zu hosten. Viel Spaß!
Der Open Source-Paketmanager NuGet hat sich in der .NET-Welt zur Standardmethode einwickelt, um Funktionalität zwischen mehreren Projekten zu teilen oder öffentlich bereitzustellen – fast jeder Programmierer hat schon ein NuGet-Paket in sein Projekt eingebunden. Doch NuGet kann mehr: Es bietet die Möglichkeit, wichtige Teile des Entwicklungsprozesses innerhalb der eigenen Organisation weiter zu verbessern und zu automatisieren.
Blogserie
- Teil 1: Pakete verwenden
- Teil 2: Pakete erstellen (dieser Artikel)
- Teil 3: Pakete verteilen
- Teil 4: Pakete debuggen
Pakete selbst erstellen
Im ersten Teil unserer kleinen Artikelserie zum Thema NuGet haben wir gesehen, wie einfach es ist, öffentlich verfügbare Pakete in eigene Projekte einzubinden. Auch der Erstellen eigener Pakete ist nicht sehr schwierig: Ein simples Kommandozeilentool (nuget.exe) ist alles, was man dafür braucht. Nuget.exe ist zum Download auf der NuGet-Website erhältlich.
Es empfiehlt sich, das Tool in einem Ordner auf der lokalen Festplatte abzulegen und die Windows-PATH-Umgebungsvariable mit diesem Installationspfad zu ergänzen, damit ein einfacher Zugriff auf nuget.exe von der Kommandozeile aus möglich ist.
In unserem Demo-Szenario soll eine Komponente eines Projekts – eine schockierend einfache Bibliothek namens HelloLib – als NuGet-Paket bereitgestellt werden. Dieses Paket wollen wir dann in der kleinen Hello World-Konsolenanwendung verwenden, die im ersten Teil der Artikelserie vorgestellt wurde.
Um ein nun Paket aus diesem Visual Studio-Projekt zu erzeugen reicht der folgende simple Befehl in einer DOS-Box:
nuget pack HelloLib.csproj
Das war’s auch schon! Im Projektverzeichnis findet sich das frisch erstellte NuGet-Paket:
Diese Methode erzeugt allerdings nur ein sehr einfaches Paket, das schlicht den Build-Output des Projektes enthält – es kann nichts weiter konfiguriert werden.
Auch beschwert sich NuGet darüber, das bestimmte Informationen (wie Autor und Beschreibung) nicht angegeben wurden, die für die späteren Nutzer des Paketes wichtig sind. Aber dieses Problem ist schnell gelöst: Die Definition des gewünschten Paketinhalts und von allen Paketattributen kann über ein Konfigurationsfile mit der Endung .nuspec erfolgen. Erfreulicherweise kann der nuget-Befehl auch gleich das Konfigurationsfile erzeugen, wenn der Parameter spec übergeben wird:
nuget spec HelloLib.csproj
Die frisch erzeugte Datei sieht dann so aus:
Was in der jungfräulichen HelloLib.nuspec-Datei sofort auffällt sind die eingebetteten Variablen, wie zum Beispiel $id$ und $version$. Dabei handelt es sich um Replacement Tokens. Beim Erstellen eines Packages mit dem oben beschriebenen Befehl wird die .nuspec-Datei herangezogen und die Variablen darin werden durch Informationen aus dem Projekt ersetzt. Das klappt jedoch leider nicht für alle Replacement Tokens. Manche Werte, wie beispielsweise Autor und Beschreibung müssen entweder in der .nuspec-Datei fest eintragen oder an den nuget pack-Befehl als Argument übergeben werden:
nuget pack HelloLib.csproj -p author=Uwe;description=“Hello Lib“
Mittels des .nuspec-Files kann der Inhalt des Pakets genau gesteuert werden, um beispielsweite weitere Dateien und Abhängigkeiten mit einzubinden. Da die .nuspec-Datei eine Projekt-Konfigurationsdatei ist sollte diese in das Projekt mit aufgenommen werden. Eine genaue Beschreibung aller Konfigurationsmöglichkeiten findet sich in der NuGet-Dokumentation.
Vorerst arbeiten wir mit einer einfachen, angepassten Version von HelloLib.nuspec:
Zusätzlich zu den Metadaten haben wir jetzt auch noch den eigentlichen Inhalt des Pakets explizit angegeben – das File HelloLib.dll soll in das Paket – und zwar in den lib-Ordner, der dafür sorgt dass die DLL später als Referenz in das Zielprojekt eingefügt wird.
Verpacken wir das Projekt jetzt neu, wird die Konfigurationsdatei automatisch angezogen und die darin definierten Metadaten in das Paket übernommen.
Pakete inspizieren
Soweit, so gut. Aber was genau befindet sich den nun im eben erzeugten Paket? Bei der Arbeit mit NuGet ist es immer wieder sinnvoll, den Inhalt von Paketen inspizieren zu können. Das ist auch mit Windows-Bordmitteln kein Problem, denn NuGet-Paketdateien sind in Wirklichkeit nichts anderes als getarnte ZIP-Archive! Einfach die Erweiterung .zip an den Dateinamen anhängen – und schon können Pakete mit dem Windows-Explorer geöffnet werden. Es zeigt sich: Ein Paket besteht aus der eigentlichen Nutzlast und zusätzlichen Konfigurationsdateien.
Eine elegantere Alternative bietet jedoch das frei erhältliche Tool NuGet Package Explorer. Damit werden Paketinhalte und Metadaten wunderbar übersichtlich dargestellt. Der Package Explorer kann übrigens auch – als Alternative zu nuget.exe – zum Erstellen von Paketen verwendet werden.
Pakete lokal automatisch bauen
Jetzt sind wir in der Lage, Pakete über die Kommandozeile erstellen zu lassen. Für etwas mehr Komfort wäre es wünschenswert, wenn das Paket bei jedem Build automatisch gebaut würde, oder? Ich höre Zustimmung…
Zu diesem Zweck bietet es sich an, den PostBuild-Event im Projekt einsprechend anzupassen (Menü Project/HelloLib Properties…) und dort die den nuget pack-Befehl auszuführen:
Übrigens: Wir übergeben hier auch gleich eine festeingestellte Versionsnummer – die “teuflische” 9999.99.99.99 – als Zeichen dafür, dass wir das Paket lokal gebaut haben. “Echte” Versionsnummern lassen wir nur für Pakete zu, die auf dem Buildserver mit Team Build sozusagen offiziell erstellt werden – dazu aber gleich mehr.
Kurz F5 gedrückt, und unser Paket wird auch prompt automatisch erzeugt. Was will man mehr? Einiges, aber dazu kommen wir später.
Pakete zentral bauen mit Team Build 2015
Noch mit Visual Studio / Team Foundation Server 2013 war die Erstellung von NuGet-Paketen auf einem Build Server nur mit relativ hohem Aufwand nötig: Es waren trickreiche Eingriffe in den MS Build-Code der Projektdatei nötig – machbar, aber fehleranfällig und unkomfortabel. In der oben bereits erwähnten Vorgängerversion dieses Artikels werden die “schmutzigen” Details beschrieben.
Mit Einführung des neuen Buildsystems in Team Foundation Server 2015 hat sich die Vorgehensweise erfreulicherweise grundlegend geändert. Team Build 2015 setzt auf modulare Skripte (Build Steps), mit denen ein individueller Buildvorgang orchestriert werden kann. Für die Wiederherstellung, Erstellung und Veröffentlichung von NuGet-Paketen während des Builds stehen allein drei verschiedene Build Steps zur Verfügung, die beim Entwurf einer Builddefinition hinzugefügt werden können:
- NuGet Installer dient der Wiederherstellung von fehlenden NuGet Paketen während des Builds – also dem oben beschriebenen Package Restore. Übrigens: Es ist weiterhin möglich, Pakete während der Ausführung von MS Build im Build Step Visual Studio Build wiederherzustellen – dort findet sich die Option Restore NuGet Packages. Die explizite Ausführung eines Package Restore vor dem eigentlichen MS Build ist jedoch meines Erachtens vorteilhafter, weil das Debugging leichter fällt. Zudem gibt es einige Pakete, die mit der Wiederherstellung während des MS Build-Laufs Probleme bekommen, da sie diesen selbst modifizieren.
- NuGet Packager erstellt während des Buildvorgangs Pakete durch Ausführung von nuget pack. Der Clou ist die Option Use Build number to version package. Diese übergibt den Bezeichner des aktuellen Builds als Parameter und erzeugt damit versionierte Pakete.
- NuGet Publisher bietet schließlich die Möglichkeit, die erstellten Pakete auf einen Paketserver hochzuladen und damit anderen Entwicklern zur Verfügung zu stellen.
Um aus unserer kleinen Beispielbibliothek ein Paket zu bauen, muss einfach nur ein NuGet Installer und ein NuGet Packager-Build Step in die Builddefinition eingefügt werden. Die Konfiguration ist denkbar einfach – Der NuGet Installer erledigt den Package Restore und muss vorerst gar nicht konfiguriert werden.
Für den NuGet Packager genügt der Ausgabepfad für das fertige Paket – in unserem Fall ein Share namens MyPackages. Außerdem kann wie oben schon erwähnt angegeben werden, ob das Paket automatisch mit der Buildnummer versioniert werden soll.
Damit alles klappt, sind jetzt noch zwei kleine Anpassungen nötig. Die automatische Versionierung über die Buildnummer verlangt ein ganz spezielles Format, das im Tab General der Builddefinition angepasst werden kann:
$(BuildDefinitionName)_$(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r)
Da wir unser Paket im Build Step NuGet Packager bauen wollen, müssen wir verhindern, dass der Erstellungsprozess noch an anderer Stelle im Build angeworfen wird – nämlich im Post Build Event unserer Projektdatei, der ja ausschließlich dazu dient, das Paket lokal zu bauen. Wir unterdrücken die Ausführung im Team Build kurzerhand, indem wir im Build Step Visual Studio Build einen leeren Parameter übergeben:
Das geht natürlich auch eleganter – wenn noch andere Schritte in das PostBuild-Event sollten, die auch im Team Build ausgeführt werden müssen ist ein solches Vorgehen sogar etwas zu brachial – in diesem Fall könnten wir beispielsweise ein eigenes Flag setzten.
Und wo wir gerade so schön dabei sind, entfernen wir auch noch das Häkchen bei Restore NuGet Packages im selben Dialog – dieses MS Build-basierte Package Restore ist unnötig, da wir ja einen eigenen Team Build Step dafür eingefügt haben.
Und natürlich müssen wir auch angeben, was genau wir bauen wollen (das hätten wir doch fast vergessen…):
Schließlich verändern wir noch die Reihenfolge, in der die Schritte abgearbeitet werden, denn zuerst müssen natürlich alle Pakete wiederhergestellt werden, dann wird gebaut, danach ein mysteriöser Schritt namens “Index Sources & Publish Symbols” durchgeführt von dem später noch die Rede sein wird, und dann wird endlich das NuGet-Paket erstellt.
Schnell die Builddefinition abspeichern und mit Queue Build… den Buildprozess starten.
Violà! Alle Schritte laufen wie erwartet durch. Zunächst wird das log4net-Package heruntergeladen und hinzugefügt, dann die Solution gebaut und schließlich verpackt.
Achtung, Falle: Package Sources spezifizieren in Team Build vNext
In der aktuellen Version von Visual Studio ist es noch nicht möglich, im NuGet Installer Build Step eigene Paketserver anzugeben! In Visual Studio Team Services existiert diese Option aber bereits und wird deshalb sehr wahrscheinlich bald auch für die On Premise-Version von TFS nachgerüstet.
Es existiert aber ein Workaround: Einfach auf dem Build Server im Verzeichnis C:Users{BuildService}AppDataRoamingNuGet eine weitere NuGet.config Datei anlegen (wobei {BuildService} für den Account steht, unter dem der Build ausgeführt wird).
Die NuGet-Server einfach in die NuGet.config mit aufnehmen:
<?xml version=“1.0″ encoding=“utf-8″?>
<configuration>
<packageSources>
<add key=“NuGet official package source“ value=“https://nuget.org/api/v2/“ />
<add key=“My Package Server“ value=“https://tfs-2015-1:9000/nuget“ />
</packageSources>
</configuration>
Das fertige Paket findet sich auf dem konfigurierten Share – versioniert mit der Buildnummer zur sofortigen Verwendung durch beliebige Konsumenten.
Wechseln wir also in die Hello World-Konsolenapplikation aus dem ersten Teil dieser Artikelserie. Im schon bekannten NuGet Package Manager lassen sich auf der Einstellungsseite neue Paketserver eintragen:
Wir können jetzt den Share eintragen, auf dem wir im Team Build das eben gebaute Paket veröffentlicht haben.
Und schon ist unser Paket bereit, in das aktuelle Projekt eingebunden zu werden.
Jetzt können wir die Funktionalität der HelloLib-Bibliothek im eigenen Code verwenden.
Fazit und Ausblick
“Weit gekommen wir sind!” würde Yoda an dieser Stelle sagen. Aber das ist noch nicht alles: Im dritten Teil der Serie kümmern wir uns darum, unsere Pakete sicher und effizient an potentielle Konsumenten zu verteilen – ein simples Share reicht uns dafür leider nicht aus. Schalten Sie auch nächstes Mal wieder ein, wenn es heißt “Ja, wir packen das!”.
[-]
Technologie
Devops
Aktuelles
Innovationslabor
Wir
Jobs