Skip to content

Commit 35c88c1

Browse files
committed
Adapt Jupyter Example
1 parent 22c8ef4 commit 35c88c1

4 files changed

Lines changed: 366 additions & 450 deletions

File tree

20_ContinuousIntegration.md

Lines changed: 216 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
author: Sebastian Zug, Galina Rudolf & André Dietrich
44
email: sebastian.zug@informatik.tu-freiberg.de
5-
version: 1.0.9
5+
version: 1.0.10
66
language: de
77
narrator: Deutsch Female
88
comment: Continuous Intergration, GitHub CI, Anwendungsbeispiele
@@ -72,6 +72,9 @@ Das übergreifende Datenformat macht die Nachvollziehbarkeit von Code Änderunge
7272
},
7373
{
7474
"cell_type": "code",
75+
76+
77+
7578
"execution_count": null,
7679
"id": "6c91aadb",
7780
"metadata": {},
@@ -97,9 +100,72 @@ Das übergreifende Datenformat macht die Nachvollziehbarkeit von Code Änderunge
97100
98101
> **Merke:** Jupyter Notebooks sind ein hervorragendes Werkzeug für schnelle Prototypen, API-Dokumentationen oder Vorträge mit Live Hacks aber ungeeignet für Projekte [persönliche Meinung des Vortragenden :-)].
99102
100-
> **Hinweis:** Eine Beschreibung der Installationsprozedur für einen C#-Kernel finden Sie unter [Link](https://github.com/dotnet/interactive)
103+
> **Beispiel:** Ein lauffähiges C#-Notebook samt Datensatz finden Sie unter [`code/18_ContinuousIntegration/JupyterExample`](https://github.com/TUBAF-IfI-LiaScript/VL_Softwareentwicklung/tree/master/code/18_ContinuousIntegration/JupyterExample).
104+
105+
> **Hinweis:** Eine Beschreibung der Installationsprozedur für einen C#-Kernel finden Sie unter [Link](https://github.com/dotnet/interactive). Praktisch:
106+
>
107+
> ```bash
108+
> dotnet tool install -g Microsoft.dotnet-interactive
109+
> dotnet interactive jupyter install
110+
> ```
111+
>
112+
> Danach steht in VS Code (Jupyter-Extension) bzw. JupyterLab der Kernel `.NET (C#)` zur Verfügung.
113+
114+
> **Achtung:** Das frühere VSC-Plugin "Polyglot Notebooks" sowie `.NET Interactive` werden seit 2026 nicht mehr weiterentwickelt (deprecated). Der oben genannte Kernel funktioniert weiterhin, erhält aber keine Updates. Microsofts heutiger Weg für schnelles C# ohne Projektdatei sind stattdessen *file-based apps*: `dotnet run app.cs` (ab .NET 10).
115+
116+
## Exkurs: C#-Bibliotheken aus Python heraus nutzen
117+
118+
Sprachgrenzen sind in der Praxis selten scharf: Eine bestehende, getestete C#-Bibliothek soll
119+
aus einem Python-Skript heraus aufgerufen werden – etwa um in einem Data-Science-Workflow eine
120+
bereits implementierte Fachlogik wiederzuverwenden, statt sie neu zu schreiben.
121+
122+
Die Brücke bildet das Paket [pythonnet](https://github.com/pythonnet/pythonnet). Es bindet die
123+
.NET-Laufzeitumgebung in den Python-Prozess ein, sodass .NET-Assemblies (`*.dll`) geladen und
124+
ihre Typen wie gewöhnliche Python-Objekte verwendet werden können.
125+
126+
Der prinzipielle Ablauf:
127+
128+
1. **Laufzeit wählen** – pythonnet auf die .NET-Core-/CoreCLR-Runtime festlegen.
129+
2. **Assembly referenzieren** – die kompilierte `*.dll` über `clr.AddReference` bekanntmachen.
130+
3. **Typen importieren** – die Klassen des C#-Namespaces wie ein Python-Modul ansprechen.
131+
132+
````````````
133+
+----------------+ pythonnet +-------------------------+
134+
| Python-Skript | <-------------------> | .NET-Runtime (CoreCLR) |
135+
| calc.divide() | lädt CalcService.dll | CalcService.Calculator |
136+
+----------------+ +-------------------------+
137+
````````````
138+
139+
Am Beispiel der `CalcService`-Bibliothek (eine Division mit Behandlung der Division durch Null)
140+
aus der letzten Vorlesung:
141+
142+
```python calc_wrapper.py
143+
import pythonnet
144+
pythonnet.set_runtime("coreclr") # 1. .NET-Core-Runtime festlegen
145+
146+
import clr
147+
import sys
148+
149+
# Pfad zur kompilierten DLL bekanntmachen
150+
sys.path.append("../CalcService/bin/Debug/net9.0")
151+
152+
clr.AddReference("CalcService") # 2. Assembly referenzieren
153+
import CalcService # 3. Namespace wie ein Python-Modul nutzen
154+
155+
result = CalcService.Calculator.Divide(10.0, 2.0)
156+
print(result.Success, result.Result) # -> True 5.0
157+
```
158+
159+
> **Voraussetzung:** Die C#-Bibliothek muss zuvor mit `dotnet build` übersetzt worden sein –
160+
> Python lädt die *kompilierte* `*.dll`, nicht den Quelltext.
161+
162+
> **Stolperstein:** Mit pythonnet 3.x ist die Reihenfolge entscheidend – der Namespace darf erst
163+
> *nach* `clr.AddReference` importiert werden. Ein zu früher Import landet leer im Modul-Cache,
164+
> und der Zugriff auf die Klasse schlägt mit `module 'CalcService' has no attribute ...` fehl.
101165
102-
> **Hinweis:** Deutlich einfacher ist die Installation mit dem VSC Plugin "Polyglot Notebooks".
166+
So lässt sich dieselbe Fachlogik sowohl über C#-Unittests absichern (vgl. Vorlesung 19) als auch
167+
aus einem Python-Workflow heraus weiterverwenden – ein typisches Muster, wenn etablierte
168+
Bibliotheken in eine andere Sprachumgebung eingebunden werden sollen.
103169

104170
## Exkurs: Konfigurationsfiles
105171

@@ -204,19 +270,31 @@ person:
204270
**Beispielanwendung**
205271

206272
```text data.yaml
207-
person:
208-
name: John Doe
209-
age: 30
210-
address:
211-
street: 123 Main St
212-
city: Anytown
213-
state: CA
214-
postalCode: 12345
215-
phoneNumbers:
216-
- type: home
217-
number: "123-456-7890"
218-
- type: work
219-
number: "098-765-4321"
273+
persons:
274+
- name: John Doe
275+
age: 30
276+
address:
277+
street: 123 Main St
278+
city: Anytown
279+
state: CA
280+
postalCode: 12345
281+
phoneNumbers:
282+
- type: home
283+
number: "123-456-7890"
284+
- type: work
285+
number: "098-765-4321"
286+
- name: Jane Smith
287+
age: 28
288+
address:
289+
street: 456 Oak Ave
290+
city: Springfield
291+
state: IL
292+
postalCode: 67890
293+
phoneNumbers:
294+
- type: home
295+
number: "555-111-2222"
296+
- type: work
297+
number: "555-333-4444"
220298
```
221299
```python readYAML.py
222300
import yaml
@@ -226,15 +304,84 @@ with open('data.yaml', 'r') as file:
226304
data = yaml.safe_load(file)
227305

228306
# Greife auf die Daten zu und verarbeite sie
229-
print(f"Name: {data['person']['name']}")
230-
print(f"Age: {data['person']['age']}")
231-
print(f"Address: {data['person']['address']['street']}, {data['person']['address']['city']}, {data['person']['address']['state']} {data['person']['address']['postalCode']}")
232-
print("Phone Numbers:")
233-
for phone in data['person']['phoneNumbers']:
234-
print(f" {phone['type']}: {phone['number']}")
307+
# data['persons'] ist nun eine Liste -> wir iterieren über alle Einträge
308+
for person in data['persons']:
309+
print(f"Name: {person['name']}")
310+
print(f"Age: {person['age']}")
311+
print(f"Address: {person['address']['street']}, {person['address']['city']}, {person['address']['state']} {person['address']['postalCode']}")
312+
print("Phone Numbers:")
313+
for phone in person['phoneNumbers']:
314+
print(f" {phone['type']}: {phone['number']}")
315+
print()
235316
```
236317
@LIA.eval(`["data.yaml", "main.py"]`, `none`, `python3 main.py`)
237318

319+
**Vom Dictionary zum Objekt**
320+
321+
Bisher greifen wir mit `person['name']` auf die Daten zu – das ist fehleranfällig
322+
(Tippfehler im Schlüssel fallen erst zur Laufzeit auf) und ohne Typinformationen.
323+
In der Praxis werden die eingelesenen Daten daher in **Objekte** überführt
324+
(_Deserialisierung_). Aus `person['name']` wird `person.name`.
325+
326+
<section class="flex-container">
327+
328+
<div class="flex-child" style="min-width: 320px">
329+
330+
```python objects.py
331+
import yaml
332+
from dataclasses import dataclass
333+
334+
@dataclass
335+
class Person:
336+
name: str
337+
age: int
338+
339+
with open('data.yaml', 'r') as file:
340+
data = yaml.safe_load(file)
341+
342+
# Jeden Listeneintrag (dict) auf ein Person-Objekt abbilden
343+
persons = [Person(name=p['name'], age=p['age'])
344+
for p in data['persons']]
345+
346+
for person in persons:
347+
# typisierter Zugriff: person.name statt person['name']
348+
print(f"{person.name} ({person.age})")
349+
```
350+
@LIA.eval(`["data.yaml", "objects.py"]`, `none`, `python3 objects.py`)
351+
352+
</div>
353+
354+
<div class="flex-child" style="min-width: 320px">
355+
356+
```csharp objects.cs
357+
using YamlDotNet.Serialization;
358+
359+
public class Person
360+
{
361+
public string Name { get; set; }
362+
public int Age { get; set; }
363+
}
364+
365+
var yaml = File.ReadAllText("data.yaml");
366+
var deserializer = new DeserializerBuilder().Build();
367+
368+
// YAML direkt in eine Liste typisierter Objekte überführen
369+
var persons = deserializer
370+
.Deserialize<Dictionary<string, List<Person>>>(yaml)["persons"];
371+
372+
foreach (var person in persons)
373+
Console.WriteLine($"{person.Name} ({person.Age})");
374+
```
375+
376+
</div>
377+
378+
</section>
379+
380+
> **Merke:** In beiden Sprachen ist die Idee identisch – die hierarchischen
381+
> Schlüssel-Wert-Daten werden auf **Klassen** abgebildet. Der Compiler (C#)
382+
> bzw. die `@dataclass` (Python) kennt die Felder, sodass der Zugriff
383+
> typsicher über `.name` statt über `['name']` erfolgt.
384+
238385

239386
## Continuous integration (CI)
240387

@@ -279,12 +426,42 @@ Damit ergeben sich folgende Aktivitäten, die für einen CI Realisierung benöti
279426

280427
> Merke: Unterschätzen Sie den Aufwand für die Realisierung und Wartung der Tool-Chain nicht. Häufig müssen hier zu Beginn des Projektes grundsätzliche Entscheidungen getroffen werden, die zumindest mittelfristige Auswirkungen auf das Projekt haben.
281428
282-
## Continuous Deployment
429+
## Continuous Delivery / Deployment
283430

284431
Continuous Deployment (CD) ist ein Softwareentwicklungsprozess, der darauf abzielt, Codeänderungen automatisch und kontinuierlich in die Produktionsumgebung zu integrieren und bereitzustellen. Dies geschieht oft ohne menschliches Eingreifen, sobald der Code durch automatisierte Tests und andere Qualitätssicherungsmaßnahmen validiert wurde.
285432

286433
![](https://upload.wikimedia.org/wikipedia/commons/c/c3/Continuous_Delivery_process_diagram.svg "Beispielhafter schematischer Ablauf einer Continous Delivery Pipeline - Autor Grégoire Détrez, original by Jez Humble, Wikmedia [Link](https://commons.wikimedia.org/wiki/File:Continuous_Delivery_process_diagram.svg) Creative Commons Attribution-Share Alike 4.0 International")
287434

435+
Die Abbildung zeigt die **vollständige** Pipeline – nicht nur den abschließenden
436+
Deployment-Schritt. Auf jeden `Check in` folgt ein automatisch ausgelöster
437+
(`Trigger`) Durchlauf, der die Software stufenweise absichert und am Ende
438+
ausrollt.
439+
440+
> **Warum stehen hier auch Build und Unit-Test?** Weil CD nicht *neben* CI
441+
> steht, sondern CI **umschließt**: Man kann nichts ausrollen, das sich nicht
442+
> bauen lässt und dessen Bausteine nicht funktionieren. Build und Unit-Test sind
443+
> der gemeinsame Anfang beider Pipelines – CI ist die *linke Hälfte*, CD die
444+
> *ganze* Kette.
445+
446+
```text
447+
Check in → Trigger → Build → Unit Test → Acceptance → Integration → System → UAT → ┊ → Produktion
448+
└──────── CI: ist der Code integrierbar? ───────┘ ┊
449+
└────────────── Continuous Delivery: jederzeit auslieferbar ─────┘┊ manuelles "Go"
450+
└────────────── Continuous Deployment: ... vollautomatisch in die Produktion ──────┘
451+
```
452+
453+
> **Delivery ≠ Deployment.** Beide kürzt man mit **CD** ab – sie unterscheiden
454+
> sich nur im *letzten* Schritt:
455+
>
456+
> - **Continuous _Delivery_**: Die Pipeline stellt sicher, dass jeder Stand
457+
> *jederzeit auslieferbar* ist. Der Sprung in die Produktion erfolgt aber
458+
> bewusst per **manueller Freigabe** (ein „Go"-Klick).
459+
> - **Continuous _Deployment_**: Auch dieser letzte Schritt läuft **automatisch**
460+
> besteht der Code alle Stufen, geht er *ohne menschliches Eingreifen* live.
461+
>
462+
> Die obige Abbildung zeigt eine *Delivery*-Pipeline (mit Freigabepunkt vor der
463+
> Produktion); dieser Abschnitt beschreibt die konsequente Weiterführung,
464+
> *Deployment*, bei der dieser Punkt entfällt.
288465
289466
Die Hauptmerkmale von Continuous Deployment sind:
290467

@@ -296,17 +473,25 @@ Die Hauptmerkmale von Continuous Deployment sind:
296473

297474
+ Schnelles Feedback: Entwickler erhalten schneller Feedback zu ihren Änderungen, da diese schnell in der Produktion verfügbar sind. Dies erleichtert das schnelle Erkennen und Beheben von Fehlern.
298475

299-
> Continuous Deployment baut auf der Praxis der Continuous Integration auf, bei der Codeänderungen regelmäßig in ein gemeinsames Repository integriert und getestet werden.
300-
301-
Techniken des CD sind:
302-
303-
+ Blue-Green Deployment (harter Wechsel zwischen zwei Produktionsumgebung)
304-
+ Canary Deployment (Selektives Ausrollen der neuen Version)
305-
306476
## Einordnung
307477

308478
DevOps (eine Kombination aus Development und Operations) ist ein ganzheitlicher Ansatz, der den gesamten Lebenszyklus von Software betrachtet – von der Planung und Entwicklung über das Testen, die Bereitstellung bis hin zum Betrieb und der Überwachung von Anwendungen im Produktivsystem.
309479

480+
Klassisch wird DevOps als **Endlosschleife** dargestellt: Die Entwicklung
481+
(`Dev`) geht nahtlos in den Betrieb (`Ops`) über, und die Erkenntnisse aus dem
482+
Betrieb (`Monitor`) fließen direkt in die nächste Planung zurück.
483+
484+
```ascii
485+
.----------- Dev -------. .--------- Ops -------------.
486+
| \ / |
487+
v \ / v
488+
Plan → Code → Build → Test ------>O-------> Release → Deploy → Operate → Monitor
489+
^ |
490+
| (CI / CD) │
491+
└────────────────────────────────────────────────────────────────────────┘
492+
Feedback aus dem Betrieb fließt in die nächste Iteration
493+
```
494+
310495
Ziel von DevOps ist es, die Zusammenarbeit zwischen Entwicklungs- und Betriebsteams zu verbessern. Historisch waren diese beiden Bereiche oft getrennt: Entwickler wollten neue Funktionen möglichst schnell implementieren, während das Betriebsteam auf Stabilität und Sicherheit achtete – oft mit widersprüchlichen Zielen. DevOps überbrückt diese Kluft, indem es eine gemeinsame Verantwortung für den gesamten Prozess schafft.
311496

312497
Dabei spielen Kultur, Prozesse und Werkzeuge eine zentrale Rolle:
@@ -315,7 +500,7 @@ Dabei spielen Kultur, Prozesse und Werkzeuge eine zentrale Rolle:
315500
+ Prozesse: DevOps strebt kontinuierliche Verbesserungen durch kurze Feedbackzyklen, häufige Releases und automatisierte Qualitätssicherung an.
316501
+ Werkzeuge: Die Nutzung von Automatisierungstools zur Codeintegration, Testausführung, Infrastrukturverwaltung und Überwachung ist essenziell, um manuelle Fehler zu reduzieren und schnell auf Änderungen reagieren zu können.
317502

318-
> Continuous Integration (CI) und Continuous Delivery bzw. Deployment (CD) sind zentrale Bausteine innerhalb von DevOps.
503+
> Continuous Integration (CI) sowie Continuous Delivery und Continuous Deployment (beide **CD**) sind zentrale Bausteine innerhalb von DevOps. Delivery und Deployment unterscheiden sich, wie oben gezeigt, nur darin, ob der letzte Schritt in die Produktion manuell freigegeben oder vollautomatisch ausgeführt wird.
319504
320505
## CI Umsetzung mit GitHub
321506

0 commit comments

Comments
 (0)