CI/CD ist ein etabliertes Dogma der Softwareentwicklung. Das Internet ist voll von Artikeln und Seiten, die sich mit CI/CD befassen. Sie haben immer das gleiche CI/CD -Image. Ich wette, Sie kennen das Bild, von dem ich spreche.
Ich habe Dutzende Artikel zu diesem Thema gelesen und die Implementierung einer End-to-End-CI/CD-Pipeline erlebt. Die Realität ist, dass die Implementierung einer CI/CD-Pipeline weitaus komplexer ist als das Lesen von Artikeln, das Verstehen des CI/CD-Gesamtbildes und die Anwendung der Theorie. Eine CI/CD-Pipeline-Entwicklung erfordert interdisziplinäre und erfahrene Teams.
In diesem Artikel wird erläutert, wie Sie eine minimal funktionsfähige CI-Pipeline einer Python-Anwendung erstellen. Sie können den Artikelinhalt an andere Sprachen und Anforderungen anpassen. Das Beispiel verwendet FastAPI- und GitHub-Aktionen.
GitHub-Beispiel:
CI: Kontinuierliche Integration
Lassen Sie mich meinen Beitrag zu den bestehenden Beschreibungen der kontinuierlichen Integration leisten. Kontinuierliche Integration steht für die regelmäßige automatische Zusammenführung getesteter, genehmigter und lieferbarer Codeänderungen in das Projekt-Repository.
In diesem Beispiel werden verwendet, um bei jedem „Pull Request“- oder „Push to Main“-Ereignis automatisch die erforderlichen Prüfungen durchzuführen, um sicherzustellen, dass der Code den Repository-Qualitätsstandards entspricht. Der Markt bietet eine vielfältige Sammlung von CI/CD-Tools: , , , GitLab usw. Wählen Sie dasjenige aus, das Ihren Pipeline-Anforderungen am besten entspricht.
Der Beispielworkflow prüft, ob der neue Code den Formatierungsregeln entspricht, die ausgeführt werden. Anschließend werden die kleinen Tests mit ausgeführt und schließlich die mittleren Tests, bei denen die Anwendung auf einem D-Cluster installiert wird.
Ihr Continuous-Integration-Workflow hängt von der Größe Ihres Teams, Ihrem Reifegrad, Ihren Anwendungsanforderungen und Ihrer Verzweigungsstrategie ab.
Statische Code-Analyse
Analysieren Sie die Codeänderungen, ohne sie auszuführen. Die statischen Analysetools prüfen, ob Ihr Code den Formatierungsregeln entspricht, keine veralteten oder beschädigten Abhängigkeiten verwendet und lesbar und einfach genug ist. Sie schlagen außerdem vor, abhängig von der Programmiersprache Anti-Patterns und Bugs zu programmieren.
Wir erklären Ihnen, wie Sie Pre-Commit installieren, konfigurieren und ausführen. Sie können Pre-Commit mit anderen Analysetools wie oder kombinieren.
Vorab festlegen
ist ein in Python geschriebenes Tool. Um es in Ihrem Repository zu konfigurieren, müssen Sie lediglich eine YAML-Datei erstellen und die versionierten Hooks hinzufügen, die Sie vor jedem Commit ausführen möchten. Pre-Commit verwaltet automatisch die von den Hooks benötigten Abhängigkeiten und behebt automatisch die gefundenen Fehler. Es unterstützt mehrere Dateitypen: JSON, YAML, tf, py, ts usw.
Sparen Sie Infrastrukturkosten, indem Sie Ihre Codeprüfungen vor der Veröffentlichung lokal durchführen. Sie können Pre-Commit auf Ihrem CI ausführen, um das Format des gepushten Codes zu überprüfen.
Installieren, konfigurieren und führen Sie das Pre-Commit-Tool aus:
repos: - repo: //github.com/pre-commit/pre-commit-hooks rev: v2.3.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace
$ pip install pre-commit $ pre-commit install $ pre-commit run --all-files
Vorschläge für Python-Hooks:
- Mypy: Statischer Typprüfer für Python
- Ruff: Statischer Formatprüfer für Python
- Refurb: Schlagen Sie Best Practices für die Codierung für Python vor
- Commitizen: Stellen Sie die Verwendung von Standard-Commits und die Versionsverwaltung sicher
Prüfen
Die Definitionen und der Umfang von Unit-, Integrations- und End-to-End-Tests sind manchmal unklar. Wie bei der Beschreibung der kontinuierlichen Integration werde ich auch meinen Beitrag zu den Testtypen leisten:
Klein : Schnelle Tests. Testen Sie kleine Codeteile. Verwenden Sie Testdoppelte oder simulierte Umgebungen (z. B. SQLite). Es ist nicht erforderlich, ein Artefakt zu bauen. Zeit: ~ 60 Sekunden.
Mittel : Testen Sie die Interaktion zwischen mehreren Codeteilen. Dazu können das Erstellen der Artefakte, die Verwendung von Artefakten von Drittanbietern (z. B. Datenbanken ) und die Verbindung mit dem Localhost-Netzwerk gehören. Verwendung gefälschter Umgebungen (z. B. Docker-Compose, Kind, Minikube usw.) oder externer Dienste (z. B. Azure Blob Storage oder AWS S3). Zeit: ~ 300 Sekunden.
Groß : Sie verwenden produktionsähnliche Umgebungen (z. B. Leistungstests). Zeit: + 900 Sekunden.
Ob mittlere/große Tests in Ihrer Continuous-Integrations-Pipeline vorhanden sind oder nicht, hängt von Ihren Anforderungen ab.
Klein
Das Beispiel verwendet Pytest, um die Tests auszuführen, und den FastAPI-Testclient, um die Umgebung zu simulieren. Keine Geheimnisse; Ihr Tool zum Testen Ihrer Programmiersprache sollte Ihnen alle erforderlichen Abhängigkeiten zum Testen Ihrer Anwendung bieten.
Darüber hinaus können Sie eine Prüfung der Mindesttestabdeckung hinzufügen und diese als Teil Ihrer Ergebnisse hochladen. Die Testabdeckung ist eine knifflige Messgröße. Eine hohe Testabdeckung bedeutet nicht unbedingt, dass der Code gut getestet wurde, aber 50 % sind mehr als 0 % getesteter Code.
Mittel
D ist ein leichtgewichtiger Docker-in-Docker-Kubernetes-Cluster, der für lokale Entwicklung oder CI verwendet wird. Wir verwenden Kind, um eine Testumgebung einzurichten und die Tests damit durchzuführen:
- Erstellen Sie den Kind-Cluster
- Erstellen Sie das Docker-Image
- Laden Sie das Docker-Image in Kind
- Installieren Sie MetalLB und wenden Sie die erforderlichen CDRs an
- Installieren Sie Ingress-Nginx
- Installieren Sie Ihr Helm-Diagramm
- Richten Sie Ihren Betriebssystemhost ein
Docker-Images laden
Kind kann Ihr Bild nicht herunterladen, da es nicht aus einer Registrierung heruntergeladen werden kann. Kind erfordert, dass das Bild geladen wird, bevor es verwendet werden kann.
MetalLB
ist ein Bare-Metal-Kubernetes-Load-Balancer. Lesen Sie mehr darüber, warum ein Load-Balancer erforderlich ist, auf der Webseite.
Nach der Installation mithilfe des Helm-Diagramms können wir die erforderlichen CRDs erstellen:
--- apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: kind-advertisement --- apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: kind-address-pool spec: addresses: - "172.26.255.0/24"
Docker erstellt ein Subnetz für den Kind-Cluster (z. B. 172.26.0.0/16). Überprüfen Sie die Netzwerkschnittstelle „Kind“, um den zugewiesenen IP-Adressbereich zu ermitteln, und verwenden Sie die Adresse als Wert für die IPAddressPool-Ressource. Weitere Informationen zur MetalLB-Konfiguration finden Sie auf der Webseite.
Anwendung freigeben
Installieren Sie das Ingress-Nginx-Helm-Chart. Installieren Sie dann Ihre Anwendung Helm Chart und definieren Sie ein Ingress-Objekt. Setzen Sie die Eigenschaft ingressClassName auf nginx und definieren Sie einen Host (z. B. api.local). Ändern Sie abschließend die /etc/host, um die folgende Zeile anzuhängen:
192.168.1.10 api.local
Sie können beliebig viele Hosts definieren, die auf dieselbe Adresse verweisen. Den Rest erledigt Nginx.
Entwickeln Sie ein Tool zum Starten, Aktualisieren und Löschen einer lokalen Umgebung mithilfe von Kind. Entwickler können damit die Anwendung einfach debuggen, gemeldete Fehler lokal reproduzieren oder den Test auf CI ausführen.
Dieses Beispiel funktioniert für Linux-basierte Distributionen. Da Windows/MacOS möglicherweise nicht so funktioniert, wie es ist, sind möglicherweise Änderungen erforderlich.
Lieferung
Bevor die erforderlichen Artefakte bereitgestellt werden, führt der Workflow die Linting- und Testschritte aus.
Wir verwenden , um die Veröffentlichungen der Artefakte zu verwalten. Commtizen aktualisiert automatisch die Artefaktversion und überträgt die Änderungen. Es erstellt ein neues Git-Tag mit dem konfigurierten Tag-Format. Sie können Commtizen auch so konfigurieren, dass Ihr Changelog mit den neuesten Änderungen aktualisiert wird.
[tool.commitizen] tag_format = "v$major.$minor.$patch" version_scheme = "semver" version_provider = "pep621" major_version_zero = true update_changelog_on_bump = true version_files = [ "charts/ci-example/Chart.yaml:version", "charts/ci-example/Chart.yaml:appVersion" ]
Der Workflow verwendet die Commitizen-Ausgabeversion, um das Docker-Image und das Helm-Chart-Tag festzulegen.
Sie können für jedes Artefakt (Bild und Diagramm) unterschiedliche Versionen haben. Dann müssen Ihre Diagramm- und Bildänderungen jedoch abwärtskompatibel sein. Dadurch wird der Entwicklungs- und Veröffentlichungsprozess komplexer. Um dies zu vermeiden, verwenden wir für beide Artefakte dieselbe Version.
Schlussfolgerungen
In diesem Artikel wird ein einfacher, aber funktionaler Continuous-Integration-Workflow skizziert. Möglicherweise sind Änderungen erforderlich, damit es für andere Programmiersprachen funktioniert oder Ihren Anforderungen entspricht. Einige Schritte sollten jedoch leicht exportierbar sein und so funktionieren, wie sie sind.
CI/CD Hands-on: Continuous Deployment [Teil 2] Demnächst erhältlich …