CI / CD-Prozessaktualisierung: Teamcity

Bild
Dies ist der zweite Artikel in einer Reihe zum Aktualisieren von CI / CD-Prozessen. Bis zu diesem Zeitpunkt wurden Vorbereitungen für die Einrichtung neuer Instrumente getroffen, nämlich: Planung, tägliche Kundgebungen, Beilegung von Meinungsverschiedenheiten im Allgemeinen, ohne die es nicht möglich wäre, einen Arbeitsprozess kompetent aufzubauen. Und jetzt sind alle Probleme gelöst. Wir sind zuversichtlich, dass wir die Entwicklung fortsetzen können, und unser Code wird zu Beginn des Sommers nicht im Schwarzen Loch versinken. 

Ich möchte Sie an das Inhaltsverzeichnis der Artikelliste sowie an die kurzen Ergebnisse des vorherigen Teils erinnern.

Teil 1: Was ist, warum ist es nicht so, Planung, ein kleiner Schlag. Ich würde diesen Teil als nahezu technisch bezeichnen.
Teil 2: Teamcity.
Teil 3: Octopus Deploy.
Teil 4: hinter den Kulissen. Unangenehme Momente, Pläne für die Zukunft, möglicherweise FAQ. Höchstwahrscheinlich kann es auch als nahezu technisch bezeichnet werden.

Wir haben dem Kunden einen Proof-of-Concept für ein neues Update-Delivery-System zur Verfügung gestellt, die Mängel des vorhandenen Systems identifiziert, die Basis für das neue System ausgewählt, einen Übergangsplan erstellt und unser Quecksilber-Repository auf Git umgestellt. Außerdem haben wir im vorherigen Teil die Funktionen des Projekts beschrieben, die sich auf den gesamten nachfolgenden Prozess auswirken. 

Wie bereits erwähnt, entsprach die vorhandene Lösung nicht den modernen Anforderungen. Anfangs wurde höchstwahrscheinlich ein Build in ccnet konfiguriert. Der allererste Build, mit dem alles begann (wie ein Urknall, ja). Dann drückte anscheinend die Person, die alles eingerichtet hatte, Strg + C, Strg + V, korrigierte einige Zeilen und erhielt eine neue Konfiguration. Und für die gesamte nachfolgende Zeit wurde dies so oft durchgeführt, dass der Quellcode auf dem Build-Server mehr als 60 GB beanspruchte. Und das ist nur die Quelle! Und es gibt Protokolle, Build-Artefakte, temporäre Dateien und so weiter. Nur das brachte mich zum Nachdenken. Wenn man sich das alte System ansieht, sieht man Folgendes: Für jedes Modul wurde ein Erstellungsschritt ausgeführt. Tatsächlich wurde der gleiche Kern zusammengebaut. Diese Assembly wurde für jedes Modul (zusammen mit der Quelle) auf dem Server gespeichert.Die Build-Ergebnisse (90% identisch) wurden in lokale Repositorys verschoben (Git-Bereitstellung) und nahmen natürlich auch ihren Platz ein. Es war möglich und notwendig, dies zu verlassen. 

Allgemeine Einstellungen 


Zu diesem Zeitpunkt wird davon ausgegangen, dass bereits eine Teamstadt und ein Oktopus konfiguriert sind. Bei der Installation und Konfiguration hören wir nicht im Detail auf. Der Einfachheit halber schreiben wir die URL und das API-Token des Octopus in env teamcity auf, was für das Root-Projekt

Bild

übrigens folgendermaßen aussieht: env.apiUserName und env.apiUserPassword sind API-Zugriffe auf den teamcity-Benutzer (wird später benötigt), env.buildPath und env .sourcePath - der Standardpfad zu den Build- bzw. Quelldateien env.octoApiKey und env.octoUrl - das Token und die URL des Octopus. Sie fügten immer noch env.teamcityUrl hinzu. Nun, env.tt.exe- Pfad zum Dienstprogramm zur Texttransformation. Dieses Dienstprogramm generiert alle Konfigurationen.

Von den Plugins von Drittanbietern ist nur die Octopus Deploy-Integration installiert. 

Um die ohnehin schon große Textmenge nicht zu überladen, werden nur die Schritte im Detail untersucht, in denen es etwas gibt, das Aufmerksamkeit verdient. Es wird davon ausgegangen, dass alles andere aufgrund der präsentierten Daten und des Wissens des Lesers verständlich ist. Wenn Sie Fragen haben, beantworte ich diese auf jeden Fall gerne.

Projektaufschlüsselung, Versionierung, Namen


Das Ergebnis war ein solches Projektschema (als Bild, da beim Anzeigen einer mehrstufigen Liste ein Problem
Bild

auftritt ): Wir werden die Pakete wie folgt versionieren: major.minor.patch, wobei major bisher 1 ist, minor der Build-Zähler aus der Build-Konfiguration, patch der Build-Zähler für die Konfiguration Bereitstellen (für die Build-Konfiguration nicht erforderlich, daher immer 0).

Hinweis: Die alte Version wird hier beschrieben. Wir gestalten es so um, dass es auf dem Git-Tag basiert.

Bild

Zum Beispiel ist hier 1 Dur, 95 Moll und 1 Patch.

Im neuen Prozess für Module wird es einen Build geben, der dann für jedes Modul bereitgestellt wird. Das heißt, der Quellcode wird für jede Umgebung in einer einzigen Kopie gespeichert. Das Build-Ergebnis ist auch, da es für alle Module gleich ist. Einzigartige Konfigurationen und Bibliotheken werden in der Bereitstellungsphase in einem einzelnen Paket zusammengefasst. Dadurch wird der Speicherplatz effektiv genutzt und die Lieferzeit jedes Pakets verkürzt.

In der Vorbereitungsphase gab es ein separates kurzes Treffen zur Konvention der Benennung von Konfigurationsdateien. Früher war es (es war nur), aber nicht immer dasselbe. Außerdem enthielt der Konfigurationsname nicht immer genügend Informationen. Infolgedessen lauteten alle Konfigurationsnamen wie folgt:
ConfigurationType.Environment.ModName.configDabei kann ConfigurationType AppSettings, Web usw. sein. Umwelt - Entwicklung, Test, Inszenierung, Produktion. ModName ist der eindeutige Name des Moduls.

Module


Alle Modulprojekte arbeiten nach dem gleichen Prinzip. 

Jede Umgebung verfügt über eine Build-Konfiguration, die:

  1. Führt eine Nuget-Wiederherstellung durch (NuGet-Installationsprogramm, Nuget-Wiederherstellung)
  2. Erzeugt Konfigurationen (Befehlszeile, Texttransformation)
  3. Buildit-Lösung (Visual Studio SLN)
  4. Nimmt Dateien von env.buildPath in zip auf und verschiebt sie in octopus (Octopus deploy: Push-Pakete)
  5. Release-Erstellung (keine Bereitstellung) (Octopus Deploy-Release erstellen)
  6. Setzt die Patch-Version zurück (Powershell)

Es gibt auch Bereitstellungskonfigurationen, die auf der Vorlage basieren und Folgendes ausführen:

  1. Nimmt die Konfigurationen auf, die in der Erstellungsphase generiert wurden (Schritt 2) (Octopus stellt Push-Pakete bereit).
  2. Bereitstellen der Kernversion (die in Schritt 6 des Builds erstellt wurde) (Octopus Deploy: Bereitstellen der Version)
  3. Einzelne Release-Version (die in Schritt 1 der aktuellen Konfiguration erstellt wurde) (Octopus Deploy: Deployment-Version)
  4. Zeigt eine Liste aller Domänen für dieses Modul im Protokoll an (Schritt zur Vereinfachung für Tester und Entwickler). (Power Shell).

Für jede Bereitstellungskonfiguration wird die Buildkonfiguration zur Abhängigkeit hinzugefügt. Auf diese Weise kann der Build automatisch gestartet werden, wenn er bereitgestellt wird, wenn er nicht relevant ist, und die Patch-Version kann zurückgesetzt werden.

Deploy_all-Konfiguration. Tatsächlich handelt es sich um eine Build-Kette, die beschreibt, dass Sie zuerst Build ausführen müssen, wenn dies nicht relevant ist, und dann alle Modi gleichzeitig installieren müssen.

Es sieht

Bild

ungefähr so ​​aus : Schauen wir uns einige Schritte etwas genauer an.

Build.Allgemeine Einstellungen


Bild

Aus ungewöhnlichem Build-Number-Format. Wird später erklärt.

Build.env


Bild

Interessant sind hier:
env.coreProjectName - für das gesamte Projekt festgelegt. Wird benötigt, um das Projekt in Octopus zu identifizieren.
env.Environment - Set für das Teilprojekt Modules. Abhängig von der Umgebung müssen die richtigen Konfigurationen ausgewählt werden.
env.octoChannel - der Kanal im Oktopus, in den das Paket fällt. Gleich wie env.Environment .
env.serviceName ist der Name der Lösung. Grundsätzlich wird die Variable zur einfacheren Visualisierung hinzugefügt.
env.tenantRoleTag - Tenant- Tag im Octopus. Weitere Details im Abschnitt Oktopus.

Build.4


Bild

Fügen Sie dem Archiv mit dem Namen % env.serviceName%.% Build.number% .zip Dateien aus dem Verzeichnis mit dem Ergebnis des Builds , ausgenommen alle Konfigurationen, und DLL aus dem Ordner bin / native hinzu. Die letzten wurden einmal manuell zum Webserver hinzugefügt und niemand wird sie erneut berühren. Bei Bedarf werden sie auch manuell aktualisiert (dafür ist geplant, ein separates Skript zu schreiben, aber wir werden ehrlich sein). Dies liegt an der Tatsache, dass diese Bibliotheken vom IIS-Pool „gehalten“ werden. Für eine erfolgreiche Bereitstellung muss sie gestoppt und dann gestartet werden, was einige Zeit in Anspruch nimmt. Durch das Ausschließen dieser Bibliotheken von der Bereitstellung können wir den Schritt des Stoppens des Pools überspringen, wodurch die Bereitstellungszeit und dementsprechend Ausfallzeiten verkürzt werden.

Build.5


Bild

Ich denke, hier ist alles klar, außer warum das Feld Umwelt leer ist. In welcher Umgebung das Paket erhält, trifft der Octopus eine Entscheidung basierend auf dem Pre-Release-Tag (in den Kanälen konfiguriert). Dieses Tag ist in % build.number% enthalten (dieselbe Einstellung auf dem Bildschirm in Build.General). In diesem Fall stellte sich heraus, dass es bequemer war. Beachten Sie auch das Kontrollkästchen "Bereitstellungsprozess anzeigen" . Wenn es nicht installiert ist, betrachtet timsity den Build als erfolgreich, sobald der Octopus begonnen hat (aber noch nicht fertig ist!). Wenn das Kontrollkästchen nicht installiert ist und während der Bereitstellungsphase ein Fehler aufgetreten ist, wissen wir nichts darüber, ohne auf die Octopus-Oberfläche zu schauen.

Build.6


Nichts Ungewöhnliches, nur ein Powershell-Skript und Informationen aus der Teamcity-Dokumentation.

$pair = "%env.apiUserName%:%env.apiUserPassword%"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$depUri="%env.teamcityUrl%/app/rest/buildTypes?locator=snapshotDependency:(from:(build:(id:%teamcity.build.id%)),includeInitial:false)"
# Get all dependencies of main build
$result = (Invoke-RestMethod -Headers @{'Origin'='http://localhost:8090'; "Authorization"="$basicAuthValue"} -Uri $depUri)
foreach ($i in $result.buildTypes.buildType.Count) { $buildId += $result.buildTypes.buildType.id }
$buildId = $buildId | Where-Object { $_ -ne 'Module_DeployAll' }
# Reset all child build counters to 1. This build counters are patch versions in every build. (1.build.patch)
for ($i=0; $i -lt $buildId.Count; $i++) {
  $buildCounterUri = "%env.teamcityUrl%/httpAuth/app/rest/buildTypes/"+$buildId[$i]+"/settings/buildNumberCounter"
  Invoke-RestMethod -Method Put -Headers @{'accept'='text/plain'; 'Origin'='http://localhost:8090'; "Authorization"="$basicAuthValue"} -Uri $buildCounterUri -ContentType "text/plain" -Body 1
}

Hier brauchen wir einen API-Benutzer in Teamcity (env ist für ihn erstellt). Wir melden uns an, nehmen alle Konfigurationen, die von der Build-Konfiguration abhängig sind, und setzen ihren Build-Zähler auf 1 zurück. Dies ist in der Tat für jede Patch-Version ein Indikator dafür, wie oft derselbe Build für ein bestimmtes Modul bereitgestellt wurde. Wenn es keine 1 gibt, bedeutet dies, dass beim Bereitstellen oder Bearbeiten des Moduls in der aktuellen Version ein Fehler aufgetreten ist, und dass besondere Aufmerksamkeit erforderlich ist.

Deploy.General


Bild

Versionsformat: 1.% dep.Module_Build.build.counter%.% Build.counter% -staging , wobei
% dep.Module_Build.build.counter% die Teamcity-Systemvariable ist, deren Wert dem Build-Zähler der entsprechenden Build-Konfiguration entspricht (sollte hinzugefügt werden) Abhängigkeiten). Tatsächlich ist hier 1 die Hauptversion, % dep.Module_Build.build.counter% ist minor und % build.counter% ist patch. Staging ist ein Pre-Release-Tag.

Deploy.Env


Bild

Beim Hinzufügen eines neuen Moduls wird nur die Konfiguration für dessen Bereitstellung hinzugefügt und der Wert der Variablen env.modName angegeben . Alle anderen Variablen werden von den übergeordneten Projekten geerbt. Die Variable env.tenantModTag für einen Oktopus wird aus env.modName gebildet .

Deploy.2


Bild

Stellen Sie das Kernpaket bereit. 

Versionsnummer spätestens - Verwenden Sie die neueste verfügbare Version für diese Umgebung.
Mandanten-Tag - Client- / Organisations-Tag. Weitere Details im Abschnitt Oktopus.
Zusätzliche CLI-Parameter. Hier geben wir den Kanal an, in den unser Paket fallen wird, sowie zusätzliche Parameter. Dies wird auch im Abschnitt über Tintenfische gesondert erläutert.

Deploy.3


Wie bei Deploy.2 wird nur ein einzelnes Modulpaket bereitgestellt.

Deploy.4


Dieser Schritt wird im Folgenden ebenfalls ausführlich beschrieben, da er Daten von Octopus empfängt.

Die Konfigurationen für die Unternehmenswebsite und das Spezialmodul basieren auf demselben Prinzip, und die Hauptpunkte in ihnen sind dieselben. Daher sehe ich keinen Grund, sie im selben Detail zu beschreiben. Sie sind eins, sie müssen nicht viele Male bereitgestellt werden, und tatsächlich gibt es Nuget-Wiederherstellung, Texttransformation, MSbuild, Octopus Push, Octopus Create Release + Deploy.

Erfahren Sie mehr über einzigartige Konfigurationen. Für einige Mods gibt es möglicherweise keine Umgebungen (z. B. Staging), sie müssen auf anderen Servern bereitgestellt werden oder Sie müssen die Client-ID manuell festlegen (nehmen Sie die Grundkonfiguration und ändern Sie einige Felder darin mit Powershell). Das heißt, sie arbeiten nach dem gleichen Prinzip wie die Hauptmodule. Ihre Einzigartigkeit liegt in der Tatsache, dass Schritte für sie hinzugefügt / geändert werden oder der Bereitstellungsserver geändert wird und sie nicht in die Vorlage passen, sodass das Erstellen etwas länger dauert. Zum Glück gibt es nur wenige.

Teamcity: Zusammenfassung


Die Implementierung von Teamcity ermöglichte einen optimaleren Ansatz für den Prozess der Anwendungsmontage. Jetzt dauert es viel weniger Zeit: Anstatt jedes Mal denselben Code zu erstellen, erstellen wir ihn einmal. Wir nutzen auch den Speicherplatz, den Netzwerkverkehr und die Rechenzeit besser. Bisher entsprach die Anzahl der Pakete für die Bereitstellung (Repositorys mit Artefakten) der Anzahl der Module. Jede Packung wog ungefähr 100 M in komprimierter Form. Jetzt haben wir die Anzahl der Pakete eins mehr als die Anzahl der Module, wobei ein Paket ungefähr die gleichen 100 Millionen wiegt und der Rest ungefähr 500 KB. Plus eine benutzerfreundlichere Oberfläche, bequeme Protokolle und vor allem - Verkürzung der Zeit für die Wartung des Build-Systems und Hinzufügen von Konfigurationen. Das Hinzufügen eines neuen Moduls dauert nun 15 Minuten bis eine halbe Stunde.

Separat sollte über die Vorlagen gesprochen werden, da es die Standardisierung ist, die es uns ermöglicht, Zeit bei der Erstellung neuer Konfigurationen und deren weiterer Wartung zu sparen. Alle Konfigurationen für die Interaktion mit Octopus (Deployment) basieren auf einer einzigen Vorlage. Erstens ermöglicht es die Vereinheitlichung und damit die Vereinfachung des Prozesses. Zweitens spart es, wie bereits erwähnt, Zeit beim Hinzufügen neuer Konfigurationen: Wir haben eine Vorlage verbunden, eine Variable geändert und fertig. Und vor allem vereinfachen Vorlagen die Wartung. Alle an der Vorlage vorgenommenen Änderungen werden von darauf basierenden Konfigurationen übernommen. Wenn Sie also allen Konfigurationen gleichzeitig einen Schritt hinzufügen müssen, müssen Sie nicht auf alle klicken. Fügen Sie diesen Schritt einfach der Vorlage hinzu.

Natürlich ging der Teamcity-Setup-Prozess mit dem Octopus-Setup einher. Es ist einfach unmöglich, im Text parallel zu beschreiben, da große Verwechslungsgefahr besteht. Daher wurde die Beschreibung geteilt, und in diesem Teil werden nur die Schritte zum Bereitstellen von CI beschrieben. Der Octopus-Setup-Prozess wird im Folgenden beschrieben.

All Articles