Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

Oder wie man sich an einem Abend entspannten Codings schöne Abzeichen für sein Projekt besorgt

Wahrscheinlich hat jeder Entwickler, der mindestens ein Nebenprojekt hat, irgendwann den Impuls für schöne Abzeichen mit Status, Codeabdeckung, Paketversionen in NuGet... Und dieser Impuls hat mich dazu gebracht, diesen Artikel zu schreiben. Während der Vorbereitung für das Schreiben habe ich mir in einem meiner Projekte diese Schönheit zugelegt:

Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

In diesem Artikel wird die grundlegende Einrichtung der kontinuierlichen Integration und Lieferung für ein Klassenbibliotheksprojekt auf .Net Core in GitLab behandelt, einschließlich der Veröffentlichung der Dokumentation in GitLab Pages und dem Versand der erstellten Pakete an einen privaten Feed in Azure DevOps.

Als Entwicklungsumgebung wurde VS Code mit der Erweiterung verwendet GitLab Workflow (zur Validierung der Konfigurationsdatei direkt aus der Entwicklungsumgebung).

Kurze Einführung

CD — das ist, wenn du gerade gepusht hast und beim Kunden schon alles abgestürzt ist?

Was CI/CD ist und warum es notwendig ist, kann man leicht googeln. Die umfangreiche Dokumentation zur Einrichtung von Pipelines in GitLab zu finden ist ebenfalls nicht schwierig. Hier werde ich den Prozess der Funktionsweise des Systems aus der Vogelperspektive kurz und nach Möglichkeit ohne Fehler beschreiben:

  • der Entwickler sendet einen Commit an das Repository, erstellt über die Website eine Merge-Anfrage, oder startet auf andere Weise explizit oder implizit die Pipeline,
  • aus der Konfiguration werden alle Aufgaben ausgewählt, deren Bedingungen sie im gegebenen Kontext ausführen dürfen,
  • die Aufgaben werden entsprechend ihren Phasen organisiert,
  • die Phasen werden nacheinander ausgeführt — d.h. parallel werden alle Aufgaben dieser Phase ausgeführt,
  • wenn eine Phase fehlschlägt (d.h. wenn mindestens eine der Aufgaben der Phase fehlschlägt) — wird die Pipeline gestoppt (so gut wie immer),
  • wenn alle Phasen erfolgreich abgeschlossen sind, gilt die Pipeline als erfolgreich durchlaufen.

Somit haben wir:

  • eine Pipeline — eine Sammlung von Aufgaben, organisiert in Phasen, in der man Code kompilieren, testen, verpacken, die fertige Build in einen Cloud-Service bereitstellen und vieles mehr kann,
  • eine Phase (stage) — eine Einheit zur Organisation der Pipeline, enthält 1+ Aufgabe,
  • eine Aufgabe (job) — eine Arbeitseinheit in der Pipeline. Besteht aus einem Skript (unbedingt), Ausführungsbedingungen, Einstellungen zur Veröffentlichung/Caching von Artefakten und vielem mehr.

Dementsprechend besteht die Aufgabe bei der Konfiguration von CI/CD darin, eine Reihe von Aufgaben zu erstellen, die alle erforderlichen Schritte zur Erstellung, Testung und Veröffentlichung von Code und Artefakten umsetzen.

Vor dem Start: warum?

  • Warum GitLab?

Weil die Notwendigkeit bestand, private Repositories für Pet-Projekte zu erstellen, und diese bei GitHub kostenpflichtig waren, und ich – geizig. Die Repositories sind jetzt kostenlos, aber das ist für mich noch kein ausreichender Grund, um zu GitHub zu wechseln.

  • Warum keine Azure DevOps Pipelines?

Weil die Einrichtung dort einfach ist – man benötigt nicht einmal Kenntnisse der Kommandozeile. Die Integration mit externen Git-Anbietern erfolgt in ein paar Klicks, der Import von SSH-Schlüsseln zum Senden von Commits ins Repository ebenfalls, und die Pipeline lässt sich sogar ohne Vorlage leicht konfigurieren.

Ausgangsposition: was ist vorhanden und was wird gewünscht

Wir haben:

  • ein Repository in GitLab.

Wir wollen:

  • eine automatische Erstellung und Testung für jede Merge-Anfrage,
  • die Erstellung von Paketen für jede Merge-Anfrage und das Pushen ins Master, sofern im Commit-Message eine bestimmte Zeile vorhanden ist,
  • das Senden der erstellten Pakete an einen privaten Feed in Azure DevOps,
  • die Erstellung von Dokumentation und deren Veröffentlichung in GitLab Pages,
  • Badges!11

Die beschriebenen Anforderungen passen organisch in das folgende Pipeline-Modell:

  • Etappe 1 – Erstellung
    • Wir stellen den Code zusammen, veröffentlichen die Ausgabedateien als Artefakte
  • Etappe 2 – Testen
    • Wir erhalten die Artefakte von der Erstellungsstufe, führen die Tests durch und sammeln Daten zur Codeabdeckung
  • Etappe 3 – Versand
    • Aufgabe 1 – wir erstellen das NuGet-Paket und senden es an Azure DevOps
    • Aufgabe 2 – wir erstellen die Website aus xmldoc im Quellcode und veröffentlichen sie in GitLab Pages

Lass uns anfangen!

Wir stellen die Konfiguration zusammen

Wir bereiten die Konten vor

  1. Wir erstellen ein Konto in Microsoft Azure

  2. Gehen Sie zu Azure DevOps

  3. Wir erstellen ein neues Projekt

    1. Name – beliebig
    2. Sichtbarkeit – beliebig
      Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

  4. Nach dem Klicken auf die Schaltfläche Erstellen wird das Projekt erstellt, und es erfolgt ein Wechsel zu seiner Seite. Auf dieser Seite können über die Projekteinstellungen nicht benötigte Funktionen deaktiviert werden (unterer Link in der linken Liste -> Übersicht -> Block Azure DevOps Services)
    Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

  5. Wir wechseln zu Artefakten, klicken auf Feed erstellen

    1. Wir geben den Namen der Quelle ein
    2. Wir wählen die Sichtbarkeit
    3. Wir entfernen das Häkchen Pakete aus allgemeinen öffentlichen Quellen einschließen, damit die Quelle nicht zu einem Müllhaufen von NuGet-Klons wird
      Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

  6. Wir klicken auf Feed verbinden, wählen Visual Studio, aus dem Block Maschinenkonfiguration kopieren wir die Quelle
    Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

  7. Wir gehen zu den Kontoeinstellungen, wählen Personal Access Token
    Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

  8. Wir erstellen ein neues Zugriffstoken

    1. Name – beliebig
    2. Organisation – aktuell
    3. Gültigkeitsdauer – maximal 1 Jahr
    4. Geltungsbereich (scope) — Packaging/Read & Write
      Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

  9. Wir kopieren das erstellte Token — nach dem Schließen des Modals ist der Wert nicht mehr verfügbar

  10. Gehen Sie zu den Repository-Einstellungen in GitLab, wählen Sie die CI/CD-Einstellungen aus
    Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

  11. Klappen Sie den Abschnitt Variablen auf, fügen Sie eine neue hinzu

    1. Name — beliebig, ohne Leerzeichen (wird in der Kommandozeile verfügbar sein)
    2. Wert — Zugangstoken aus Punkt 9
    3. Wählen Sie Mask variable
      Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

Damit ist die vorläufige Konfiguration abgeschlossen.

Wir bereiten das Grundgerüst der Konfiguration vor

Standardmäßig wird für die CI/CD-Konfiguration in GitLab eine Datei verwendet .gitlab-ci.yml aus dem Stammverzeichnis des Repositories. Es ist möglich, einen beliebigen Pfad zu dieser Datei in den Repository-Einstellungen zu konfigurieren, aber in diesem Fall ist das nicht notwendig.

Wie man am Dateityp sieht, enthält die Datei die Konfiguration im Format YAML. Die Dokumentation beschreibt detailliert, welche Schlüssel auf der obersten Ebene der Konfiguration enthalten sein können und in jeder der darunterliegenden Ebenen.

Zuerst fügen wir die Verknüpfung zum Docker-Image in die Konfigurationsdatei ein, in dem die Aufgaben ausgeführt werden. Dazu suchen wir die .Net Core-Images-Seite im Docker Hub. In GitHub es gibt eine detaillierte Anleitung, welches Image für verschiedene Aufgaben am besten geeignet ist. Für den Build benötigen wir das Image mit .Net Core 3.1, also fügen wir es sicherheitshalber an erster Stelle in die Konfiguration ein

image: mcr.microsoft.com/dotnet/core/sdk:3.1

Jetzt wird beim Starten des Pipelines aus dem Microsoft-Image-Repository das angegebene Image heruntergeladen, in dem alle Aufgaben aus der Konfiguration ausgeführt werden.

Der nächste Schritt — hinzufügen von stageSchritten. Standardmäßig definiert GitLab 5 Schritte:

  • .pre — wird vor allen Schritten ausgeführt,
  • .post — wird nach allen Schritten ausgeführt,
  • build — erster nach .pre Schritt,
  • test — zweiter Schritt,
  • deploy — dritter Schritt.

Nichts hindert daran, sie explizit zu deklarieren. Die Reihenfolge, in der die Schritte angegeben sind, beeinflusst die Reihenfolge, in der sie ausgeführt werden. Um das Ganze zu vervollständigen, fügen wir in die Konfiguration ein:

stages:
  - build
  - test
  - deploy

Um die Umgebung, in der die Aufgaben ausgeführt werden, zu debuggen, ist es sinnvoll, Informationen darüber zu sammeln. Fügen wir ein globales Command-Set hinzu, das vor jeder Aufgabe ausgeführt wird, mithilfe von before_script:

before_script:
  - $PSVersionTable.PSVersion
  - dotnet --version
  - nuget help | select-string Version

Nun bleibt es, mindestens eine Aufgabe hinzuzufügen, damit beim Senden von Commits der Pipeline gestartet wird. Vorläufig fügen wir eine leere Aufgabe zur Demonstration hinzu:

dummy job:
  script:
    - echo ok

Wir starten die Validierung, erhalten die Nachricht, dass alles in Ordnung ist, committen, pushen und schauen uns die Ergebnisse auf der Website an… Und wir erhalten einen Skriptfehler — bash: .PSVersion: Befehl nicht gefunden. WTF?

Alles logisch — standardmäßig verwenden die Runner (die für die Ausführung von Job-Skripten verantwortlich sind und von GitLab bereitgestellt werden) bash zur Ausführung von Befehlen. Dies kann korrigiert werden, indem in der Job-Beschreibung explizit angegeben wird, welche Tags der ausführende Pipeline-Runner haben sollte:

dummy job auf Windows:
  script:
    - echo ok
  tags:
    - windows

Hervorragend! Jetzt wird die Pipeline ausgeführt.

Ein aufmerksamer Leser, der die angegebenen Schritte wiederholt, wird feststellen, dass die Aufgabe in der Phase test, obwohl wir keine Phase angegeben haben. Wie man erraten kann, test ist die Standardphase.

Lassen Sie uns mit dem Aufbau des Konfigurationsgerüsts fortfahren, indem wir alle oben beschriebenen Aufgaben hinzufügen:

build job:
  script:
    - echo "building..."
  tags:
    - windows
  stage: build

test and cover job:
  script:
    - echo "running tests and coverage analysis..."
  tags:
    - windows
  stage: test

pack and deploy job:
  script:
    - echo "packing and pushing to nuget..."
  tags:
    - windows
  stage: deploy

pages:
  script:
    - echo "creating docs..."
  tags:
    - windows
  stage: deploy

Wir haben eine nicht besonders funktionale, aber dennoch korrekte Pipeline erhalten.

Trigger einrichten

Da für keine der Aufgaben Auslösefilter angegeben sind, wird die Pipeline vollständig bei jedem Push von Commits ins Repository ausgeführt. Da dies im Allgemeinen nicht das gewünschte Verhalten ist, werden wir Auslösefilter für die Aufgaben einrichten.

Filter können in zwei Formaten konfiguriert werden: only/except und rules. Kurz gesagt, only/except erlaubt die Einrichtung von Filtern nach Triggern (merge_request, zum Beispiel — konfiguriert die Aufgabe zur Ausführung bei jedem Erstellen eines Merge-Requests und bei jedem Push von Commits in den Branch, der die Basis im Merge-Request ist) und Branch-Namen (einschließlich der Verwendung von regulären Ausdrücken); rules ermöglicht das Einrichten einer Reihe von Bedingungen und optional die Änderung der Ausführungsbedingungen der Aufgabe abhängig vom Erfolg der vorhergehenden Aufgaben (when in GitLab CI/CD).

Erinnern wir uns an die Anforderungen — Build und Test nur für Merge-Requests, Packen und Pushen in Azure DevOps — für Merge-Requests und Pushes in den Master, Generierung von Dokumentation — für Pushes in den Master.

Zuerst richten wir die Build-Aufgabe so ein, dass sie nur bei Merge-Requests auslöst:

build job:
  # snip
  only:
    - merge_request

Jetzt richten wir die Pack-Aufgabe so ein, dass sie bei Merge-Requests und beim Hinzufügen von Commits zum Master auslöst:

pack and deploy job:
  # snip
  only:
    - merge_request
    - master

Wie zu sehen ist, ist alles einfach und direkt.

Es ist auch möglich, die Aufgabe so einzurichten, dass sie nur ausgelöst wird, wenn ein Merge-Request mit einem bestimmten Ziel- oder Quellbranch erstellt wird:

  regeln:
    - wenn: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"

In den Bedingungen können die hier aufgelisteten Variablen verwendet werden; Regeln rules sind nicht mit Regeln only/except.

Einstellung zur Speicherung von Artefakten

Während der Ausführung der Aufgabe Build-Job werden Artefakte erstellt, die in nachfolgenden Aufgaben wiederverwendet werden können. Dazu müssen in der Aufgaben-Konfiguration die Pfade, Dateien angegeben werden, die gespeichert und in den nachfolgenden Aufgaben wiederverwendet werden sollen, im Schlüssel artefakte:

Build-Job:
  # Ausschnitt
  artefakte:
    pfade:
      - pfad/zum/bau/artefakte
      - ein/anderer/pfad
      - MyCoolLib.*/bin/Release/*

Die Pfade unterstützen Wildcards, was die Angabe erleichtert.

Wenn die Aufgabe Artefakte erstellt, können alle nachfolgenden Aufgaben darauf zugreifen – sie werden sich an denselben Pfaden relativ zum Stamm des Repositories befinden, an denen sie aus der ursprünglichen Aufgabe gesammelt wurden. Außerdem sind die Artefakte auf der Website zum Download verfügbar.

Jetzt, da wir das Gerüst der Konfiguration fertig (und überprüft) haben, können wir zu schreiben von Skripten für die Aufgaben übergehen.

Skripte schreiben

Vielleicht war es einmal vor langer Zeit in einer weit, weit entfernten Galaxie schmerzhaft, Projekte (einschließlich .net) von der Befehlszeile aus zu erstellen. Jetzt kann man ein Projekt mit 3 Befehlen erstellen, testen und veröffentlichen:

dotnet build
dotnet test
dotnet pack

Natürlich gibt es einige Feinheiten, die es uns etwas komplizierter machen werden.

  1. Wir wollen einen Release-Build und keinen Debug-Build, daher fügen wir zu jedem Befehl hinzu -c Release
  2. Beim Testen wollen wir Daten zur Codeabdeckung sammeln, daher müssen wir einen Coverage-Analyzer in die Testbibliotheken einbinden:
    1. In alle Testbibliotheken sollte das Paket coverlet.msbuild: dotnet add package coverlet.msbuild aus dem Projektverzeichnis
    2. Zum Testlauf-Befehl fügen wir hinzu /p:CollectCoverage=true
    3. In die Konfiguration der Testaufgabe fügen wir den Schlüssel zur Erfassung der Abdeckungs-Ergebnisse hinzu (siehe unten)
  3. Bei der Paketierung von Code in NuGet-Pakete legen wir das Ausgabeverzeichnis für die Pakete fest: -o .

Wir sammeln Daten zur Codeabdeckung

Coverlet gibt nach dem Testlauf die Statistiken zur Ausführung in der Konsole aus:

Berechnung des Abdeckungsresultats...
  Erstellen des Berichts 'C:Usersxxxsourcereposmy-projectmyProject.testscoverage.json'

+-------------+--------+--------+--------+
| Modul       | Zeile  | Branch | Methode |
+-------------+--------+--------+--------+
| Projekt 1   | 83,24% | 66,66% | 92,1%  |
+-------------+--------+--------+--------+
| Projekt 2   | 87,5%  | 50%    | 100%   |
+-------------+--------+--------+--------+
| Projekt 3   | 100%   | 83,33% | 100%   |
+-------------+--------+--------+--------+

+---------+--------+--------+--------+
|         | Zeile  | Branch | Methode |
+---------+--------+--------+--------+
| Gesamt  | 84,27% | 65,76% | 92,94% |
+---------+--------+--------+--------+
| Durchschnitt | 90,24% | 66,66% | 97,36% |
+---------+--------+--------+--------+

GitLab erlaubt es, einen regulären Ausdruck anzugeben, um Statistiken zu erhalten, die dann in Form eines Badges bereitgestellt werden können. Der reguläre Ausdruck wird in den Einstellung der Aufgabe mit dem Schlüssel angegeben coverage; im Ausdruck muss eine Capture-Gruppe enthalten sein, deren Wert dann im Badge übergeben wird:

Test- und Abdeckungsjob:
  # Auszug
  coverage: \/|s*Totals*|s*(d+[,.]d+%)\/

Hier erhalten wir die Statistiken aus der Zeile mit der Gesamtabdeckung der Zeilen.

Pakete und Dokumentation veröffentlichen

Beide Aktionen sind für die letzte Phase der Pipeline vorgesehen — da der Build und die Tests erfolgreich waren, können wir unsere Ergebnisse mit der Welt teilen.

Lassen Sie uns zunächst die Veröffentlichung in die Paketquelle betrachten:

  1. Wenn im Projekt keine nuget-Konfigurationsdatei vorhanden ist (nuget.config), erstellen wir eine neue: dotnet new nugetconfig

    Warum: Im Image kann der Zugriff auf die globalen (Benutzer- und Maschinen-) Konfigurationen für das Schreiben gesperrt sein. Um Fehler zu vermeiden, erstellen wir einfach eine neue lokale Konfiguration und arbeiten damit.

  2. Fügen wir der lokalen Konfiguration eine neue Paketquelle hinzu: nuget sources add -name -source -username -password -configfile nuget.config -StorePasswordInClearText
    1. name — lokaler Name der Quelle, nicht entscheidend
    2. url — URL der Quelle aus dem Schritt "Konten vorbereiten", Punkt 6
    3. organisation — Name der Organisation in Azure DevOps
    4. gitlab variable — Name der Variablen mit dem Zugriffstoken, das in GitLab hinzugefügt wurde ("Konten vorbereiten", Punkt 11). Natürlich im Format $variableName
    5. -StorePasswordInClearText — Hack zur Umgehung von Zugriffsfehlern (ich bin nicht der Erste, der auf diese Fallstricke gestoßen ist)
    6. Zur Fehlervermeidung kann es hilfreich sein, -verbosity detailed
  3. Das Paket an die Quelle senden: nuget push -source -skipduplicate -apikey *.nupkg
    1. Wir senden alle Pakete aus dem aktuellen Verzeichnis, daher *.nupkg.
    2. name — aus dem vorherigen Schritt.
    3. key — beliebiger String. In Azure DevOps wird im Fenster "Mit dem Feed verbinden" immer ein Beispiel-String angegeben, az.
    4. -skipduplicate — beim Versuch, ein bereits vorhandenes Paket ohne diesen Schlüssel zu senden, wird der Quell-Fehler zurückgeben. 409 Konflikt; mit dem Schlüssel wird die Übertragung übersprungen.

Jetzt richten wir die Dokumentationserstellung ein:

  1. Zunächst initialisieren wir das docfx-Projekt im Repository im master-Zweig. Dazu muss der Befehl aus dem Stammverzeichnis ausgeführt werden docfx init und im interaktiven Modus werden wir die Schlüsselparameter für die Dokumentationserstellung festlegen. Eine detaillierte Beschreibung der minimalen Projekteinstellungen hier.
    1. Bei der Konfiguration ist es wichtig, das Ausgabeverzeichnis anzugeben ..public — GitLab verwendet standardmäßig den Inhalt des public-Ordners im Stammverzeichnis des Repositories als Quelle für Pages. Da das Projekt in einem im Repository verschachtelten Ordner liegt, fügen wir dem Pfad eine Ebene nach oben hinzu.
  2. Wir senden die Änderungen an GitLab.
  3. Wir fügen der Pipeline-Konfiguration die Aufgabe hinzu pages (reserviertes Wort für die Aufgaben der Veröffentlichung von Seiten in GitLab Pages):
    1. Script:
      1. nuget install docfx.console -version 2.51.0 — installiert docfx; Die Version wurde angegeben, um die Korrektheit der Installationspfade des Pakets zu gewährleisten.
      2. .docfx.console.2.51.0toolsdocfx.exe .docfx_projectdocfx.json — wir erstellen die Dokumentation
    2. Der Abschnitt artifacts:

pages:
  # snip
  artifacts:
    paths:
      - public

Lyrische Ablenkung über docfx

Früher gab ich bei der Projektkonfiguration den Quellcode für die Dokumentation als Projektdatei an. Der Hauptnachteil besteht darin, dass die Dokumentation auch für Testprojekte erstellt wird. Falls dies nicht erforderlich ist, kann man dem Knoten metadata.src:

{
  "metadata": [
    {
      "src": [
        {
          "src": "..\/",
          "files": [
            "**\/*.csproj"
          ],
          "exclude":[
            "*.tests*\/**"
          ]
        }
      ],
      \/\/ --- snip ---
    },
    \/\/ --- snip ---
  ],
  \/\/ --- snip ---
}

  1. metadata.src.src: "..\/" — wir gehen eine Ebene nach oben relativ zur Position docfx.json, da die Suche nach oben in Verzeichnisbäumen in Mustern nicht funktioniert.
  2. metadata.src.files: ["**\/*.csproj"] — globales Muster, wir sammeln alle C#-Projekte aus allen Verzeichnissen.
  3. metadata.src.exclude: ["*.tests*\/**"] — globales Muster, wir schließen alles aus den Ordnern mit .tests im Namen

Zwischenergebnis

Eine so einfache Konfiguration kann man buchstäblich in einer halben Stunde und mit ein paar Tassen Kaffee erstellen, die es ermöglichen wird, bei jedem Merge-Request und dem Push zur Master zu überprüfen, ob der Code kompiliert und die Tests bestehen, ein neues Paket zu erstellen, die Dokumentation zu aktualisieren und das Auge mit schönen Badges im README des Projekts zu erfreuen.

Endgültige .gitlab-ci.yml

image: mcr.microsoft.com/dotnet/core/sdk:3.1

before_script:
  - $PSVersionTable.PSVersion
  - dotnet --version
  - nuget help | select-string Version

stages:
  - build
  - test
  - deploy

build job:
  stage: build
  script:
    - dotnet build -c Release
  tags:
    - windows
  only:
    - merge_requests
    - master
  artifacts:
    paths:
      - your/path/to/binaries

test and cover job:
  stage: test
  tags:
    - windows
  script:
    - dotnet test -c Release /p:CollectCoverage=true
  coverage: /|s*Totals*|s*(d+[,.]d+%) /
  only:
    - merge_requests
    - master

pack and deploy job:
  stage: deploy
  tags:
    - windows
  script:
    - dotnet pack -c Release -o .
    - dotnet new nugetconfig
    - nuget sources add -name feedName -source https://pkgs.dev.azure.com/your-organization/_packaging/your-feed/nuget/v3/index.json -username your-organization -password $nugetFeedToken -configfile nuget.config -StorePasswordInClearText
    - nuget push -source feedName -skipduplicate -apikey az *.nupkg
  only:
    - master

pages:
  tags:
    - windows
  stage: deploy
  script:
    - nuget install docfx.console -version 2.51.0
    - $env:path = "$env:path;$($(get-location).Path)"
    - .docfx.console.2.51.0/tools/docfx.exe .docfx/docfx.json
  artifacts:
    paths:
      - public
  only:
    - master

Übrigens, die Badges

Das war doch der Grund für alles!

Die Badges mit dem Status der Pipeline und der Testabdeckung sind in GitLab in den CI/CD-Einstellungen im Bereich Gtntral pipelines verfügbar:

Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

Das Badge mit dem Link zur Dokumentation habe ich auf der Plattform Shields.io — dort ist alles recht unkompliziert, man kann sein eigenes Badge erstellen und es über eine Anfrage abrufen.

![Beispiel mit Shields.io](https://img.shields.io/badge/custom-badge-blue)

Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

Azure DevOps Artifacts ermöglicht ebenfalls das Erstellen von Badges für Pakete mit Angabe der aktuellen Version. Dazu muss man im Quellbereich auf der Azure DevOps-Website auf Create badge bei dem gewählten Paket klicken und die Markdown-Markierung kopieren:

Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

Leitfaden für CI/CD in GitLab für (fast) absolute Anfänger

Wir fügen etwas Schönheit hinzu

Wir heben die gemeinsamen Konfigurationsfragmente hervor

Während ich die Konfiguration schrieb und in der Dokumentation suchte, stieß ich auf eine interessante Möglichkeit in YAML – das Wiederverwenden von Fragmenten.

Wie aus den Job-Einstellungen ersichtlich ist, benötigen sie alle ein Tag windows für den Runner und werden bei der Übertragung in den Master/der Erstellung eines Merge-Requests ausgelöst (außer der Dokumentation). Lassen Sie uns dies in das Fragment aufnehmen, das wir wiederverwenden werden:

.common_tags: &common_tags
  tags:
    - windows
.common_only: &common_only
  only:
    - merge_requests
    - master

Und jetzt können wir im Beschreibungstext des Jobs das zuvor erklärte Fragment einfügen:

build job:
  <<: *common_tags
  <<: *common_only

Die Namen der Fragmente müssen mit einem Punkt beginnen, um nicht als Job interpretiert zu werden.

Versionierung von Paketen

Beim Erstellen des Pakets überprüft der Compiler die Befehlszeilenparameter und in deren Abwesenheit die Projektdateien; findet er den Knoten Version, nimmt er dessen Wert als Version des zu erstellenden Pakets. Das bedeutet, um ein Paket mit einer neuen Version zu erstellen, muss man entweder die Version in der Projektdatei aktualisieren oder sie als Befehlszeilenargument übergeben.

Lassen Sie uns eine weitere Anforderung hinzufügen - die letzten beiden Zahlen in der Version sollen das Jahr und das Datum des Paketerstellungs sein, und wir fügen die Pre-Release-Versionen hinzu. Diese Daten in die Projektdatei hinzuzufügen und vor jedem Push zu überprüfen, ist natürlich möglich - aber es wäre auch möglich, das im Pipeline zu tun, indem man die Version des Pakets aus dem Kontext erstellt und über ein Befehlszeilenargument übergibt.

Vereinbaren wir, dass, wenn die Commit-Nachricht eine Zeile der Art enthält release (v. / ver. / version) <version number> (rev. / revision <revision>)?, dann werden wir aus dieser Zeile die Version des Pakets entnehmen, sie mit dem aktuellen Datum ergänzen und als Argument an den Befehl dotnet packübergeben. In Abwesenheit dieser Zeile - werden wir das Paket einfach nicht erstellen.

Das folgende Skript löst diese Aufgabe:

# регулярное выражение для поиска строки с версией
$rx = "releases+(v.?|ver.?|version)s*(?<maj>d+)(?<min>.d+)?(?<rel>.d+)?s*((rev.?|revision)?s+(?<rev>[a-zA-Z0-9-_]+))?"
# ищем строку в сообщении коммита, передаваемом в одной из предопределяемых GitLab'ом переменных
$found = $env:CI_COMMIT_MESSAGE -match $rx
# совпадений нет - выходим
if (!$found) { Write-Output "no release info found, aborting"; exit }
# извлекаем мажорную и минорную версии
$maj = $matches['maj']
$min = $matches['min']
# если строка содержит номер релиза - используем его, иначе - текущий год
if ($matches.ContainsKey('rel')) { $rel = $matches['rel'] } else { $rel = ".$(get-date -format "yyyy")" }
# в качестве номера сборки - текущие месяц и день
$bld = $(get-date -format "MMdd")
# если есть данные по пререлизной версии - включаем их в версию
if ($matches.ContainsKey('rev')) { $rev = "-$($matches['rev'])" } else { $rev = '' }
# собираем единую строку версии
$version = "$maj$min$rel.$bld$rev"
# собираем пакеты
dotnet pack -c Release -o . /p:Version=$version

Fügen Sie das Skript zur Aufgabe hinzu pack and deploy job und überwachen Sie die Paketerstellung genau, wenn die angegebene Zeile in der Commit-Nachricht vorhanden ist.

Insgesamt

Nach etwa einer halben bis einer Stunde Zeit für das Schreiben der Konfiguration, das Debuggen im lokalen PowerShell und möglicherweise ein paar fehlerhaften Ausführungen haben wir eine einfache Konfiguration für die Automatisierung banaler Aufgaben erhalten.

Natürlich ist GitLab CI/CD viel umfangreicher und vielschichtiger, als es nach dem Lesen dieses Handbuchs erscheinen mag - das ist ganz und gar nicht der Fall. Dort gibt es sogar Auto DevOps,das es ermöglicht

automatisch Ihre Anwendungen zu erkennen, zu erstellen, zu testen, bereitzustellen und zu überwachen.

Jetzt planen wir, eine Pipeline für die Bereitstellung von Anwendungen in Azure zu konfigurieren, mithilfe von Pulumi und automatischer Erkennung der Zielumgebung, die im nächsten Artikel behandelt wird.

Quelle: habr.com

60GB SSD 8Gb DDR4