Migrate all repos into monorepo context folders
Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)
Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
# Skills
|
||||
|
||||
Dieser Ordner sammelt **Kiro Skills** des Einfachbahn-Teams.
|
||||
|
||||
> Was ist ein Skill? Ein Skill ist eine wiederverwendbare Anleitung/Fähigkeit, die
|
||||
> Kiro bei Bedarf aktiviert, um eine bestimmte Aufgabe nach einem festen Vorgehen zu
|
||||
> lösen. Skills liegen lokal unter `~/.kiro/skills/` (user-level) oder `.kiro/skills/`
|
||||
> (workspace-level).
|
||||
|
||||
## Struktur
|
||||
|
||||
Lege pro Skill einen eigenen Unterordner an:
|
||||
|
||||
```
|
||||
skills/
|
||||
├── README.md # diese Datei
|
||||
└── <skill-name>/
|
||||
└── SKILL.md # Definition des Skills
|
||||
```
|
||||
|
||||
## Skill hinzufügen
|
||||
|
||||
1. Ordner `skills/<skill-name>/` anlegen.
|
||||
2. `SKILL.md` mit Beschreibung, Trigger/Keywords und Schritt-für-Schritt-Anleitung
|
||||
erstellen.
|
||||
3. Tabelle unten aktualisieren, committen, pushen.
|
||||
|
||||
## Verwenden
|
||||
|
||||
Skill-Datei nach `~/.kiro/skills/<skill-name>/` (user-level) oder
|
||||
`.kiro/skills/<skill-name>/` (workspace-level) kopieren. Kiro aktiviert den Skill dann
|
||||
über die Skill-/Kontext-Auswahl.
|
||||
|
||||
## Enthaltene Skills
|
||||
|
||||
| Skill | Zweck | Trigger |
|
||||
|-------|-------|---------|
|
||||
| [`pytest-hypothesis`](pytest-hypothesis/) | Python-Tests mit pytest + hypothesis (Property-Based Testing) | pytest, hypothesis, unit test, python test, fixture, parametrize |
|
||||
| [`docker-build-db`](docker-build-db/) | Dockerfiles für DB-Umgebung (Artifactory-Mirror, non-root, OpenShift) | Dockerfile, Docker, Container, Image, Artifactory, bahnhub, OpenShift |
|
||||
| [`scm-info-setup`](scm-info-setup/) | `scm-info.yaml` erstellen und validieren (Pflichtdatei für DB-GitLab) | scm-info, compliance, beam-id, DBISL, license |
|
||||
@@ -0,0 +1,189 @@
|
||||
---
|
||||
name: docker-build-db
|
||||
description: >
|
||||
Erstellt optimierte Dockerfiles und Docker-Compose-Konfigurationen für den DB-Konzern.
|
||||
Berücksichtigt DB-spezifische Anforderungen: Artifactory-Mirror statt Docker Hub,
|
||||
linux/amd64 Pflicht, non-root Security Context, OpenShift-Kompatibilität.
|
||||
Keywords: Dockerfile, Docker, Container, Image, docker-compose, Artifactory, bahnhub, OpenShift, non-root, multi-stage.
|
||||
compatibility: >
|
||||
Docker Desktop oder Podman. Zugang zu bahnhub.tech.rz.db.de (Artifactory).
|
||||
Für Push: API-Key über Artifactory-Profil.
|
||||
metadata:
|
||||
version: "1.0.0"
|
||||
author: "#Einfachbahn Lab"
|
||||
---
|
||||
|
||||
# Docker-Images für DB-Umgebung bauen
|
||||
|
||||
Skill für die Erstellung von Dockerfiles und Container-Images, die im DB-Konzern
|
||||
(Artifactory, OpenShift/DBCS) funktionieren.
|
||||
|
||||
## DB-spezifische Regeln (MUST)
|
||||
|
||||
1. **Immer `--platform linux/amd64`** — auch auf Apple Silicon / ARM
|
||||
2. **Base-Images aus Artifactory-Mirror** — kein direkter Docker-Hub-Zugriff im Cluster
|
||||
3. **Non-root** — Container laufen unter zufälliger UID (OpenShift `restricted` SCC)
|
||||
4. **Keine Secrets im Image** — nur über K8s-Secrets / Env-Vars zur Laufzeit
|
||||
5. **Feste Tags** — semantische Versionierung (`1.2.3`), kein `latest` für Deployments
|
||||
|
||||
## Ablauf
|
||||
|
||||
### Schritt 1: Kontext erfassen
|
||||
|
||||
1. **Sprache/Framework** — Python, Node.js, Java, Go, ...?
|
||||
2. **Artifactory-Repo** — Name des Docker-Repos (z. B. `einfachbahnlab-docker-stage-local`)
|
||||
3. **Braucht der Container Schreibzugriff?** — Falls ja: welche Pfade?
|
||||
4. **Health-Check-Endpoint** — Gibt es `/health` o. ä.?
|
||||
5. **Deployment-Ziel** — OpenShift (DBCS), lokal, AWS?
|
||||
|
||||
### Schritt 2: Dockerfile erstellen
|
||||
|
||||
## Dockerfile Patterns
|
||||
|
||||
### Python (Multi-Stage)
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM docker-hub-remote.bahnhub.tech.rz.db.de/python:3.14-slim AS builder
|
||||
|
||||
WORKDIR /build
|
||||
COPY pyproject.toml .
|
||||
COPY src/ src/
|
||||
RUN pip install --no-cache-dir --target=/install .
|
||||
|
||||
FROM docker-hub-remote.bahnhub.tech.rz.db.de/python:3.14-slim
|
||||
|
||||
# Non-root: OpenShift vergibt zufällige UID
|
||||
RUN useradd -r -u 1001 appuser
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=builder /install /usr/local/lib/python3.14/site-packages
|
||||
COPY src/ src/
|
||||
|
||||
# Schreibbare Verzeichnisse (falls nötig)
|
||||
RUN mkdir -p /app/data && chmod 777 /app/data
|
||||
|
||||
USER 1001
|
||||
EXPOSE 8000
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
|
||||
CMD python -c "import httpx; httpx.get('http://localhost:8000/health').raise_for_status()"
|
||||
|
||||
ENTRYPOINT ["python", "-m", "ai_orchestrator.cli"]
|
||||
```
|
||||
|
||||
### Node.js (Multi-Stage)
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM docker-hub-remote.bahnhub.tech.rz.db.de/node:22-slim AS builder
|
||||
|
||||
WORKDIR /build
|
||||
COPY package*.json ./
|
||||
RUN npm ci --omit=dev
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM docker-hub-remote.bahnhub.tech.rz.db.de/node:22-slim
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=builder /build/dist ./dist
|
||||
COPY --from=builder /build/node_modules ./node_modules
|
||||
COPY package.json .
|
||||
|
||||
USER 1001
|
||||
EXPOSE 3000
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
|
||||
CMD node -e "fetch('http://localhost:3000/health').then(r=>{if(!r.ok)throw r})"
|
||||
|
||||
CMD ["node", "dist/index.js"]
|
||||
```
|
||||
|
||||
### Go (Scratch)
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM docker-hub-remote.bahnhub.tech.rz.db.de/golang:1.24 AS builder
|
||||
|
||||
WORKDIR /src
|
||||
COPY go.* ./
|
||||
RUN go mod download
|
||||
COPY . .
|
||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /app ./cmd/server
|
||||
|
||||
FROM scratch
|
||||
COPY --from=builder /app /app
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
|
||||
USER 65534
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["/app"]
|
||||
```
|
||||
|
||||
## docker-compose.yml (Entwicklung)
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
platforms:
|
||||
- linux/amd64
|
||||
ports:
|
||||
- "8000:8000"
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- app-data:/app/data
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
volumes:
|
||||
app-data:
|
||||
```
|
||||
|
||||
## Build & Push Workflow
|
||||
|
||||
```bash
|
||||
# 1. Login ins Artifactory
|
||||
docker login einfachbahnlab-docker-stage-local.bahnhub.tech.rz.db.de
|
||||
# User: DeBi-Kürzel, Password: API-Key aus Artifactory-Profil
|
||||
|
||||
# 2. Build (IMMER mit platform!)
|
||||
docker build --platform linux/amd64 \
|
||||
-t einfachbahnlab-docker-stage-local.bahnhub.tech.rz.db.de/myapp:1.0.0 .
|
||||
|
||||
# 3. Push
|
||||
docker push einfachbahnlab-docker-stage-local.bahnhub.tech.rz.db.de/myapp:1.0.0
|
||||
```
|
||||
|
||||
## OpenShift-Kompatibilität Checkliste
|
||||
|
||||
- [ ] Base-Image aus `docker-hub-remote.bahnhub.tech.rz.db.de` (Mirror)
|
||||
- [ ] `USER 1001` (oder andere nicht-root UID) gesetzt
|
||||
- [ ] Keine `privileged`-Operationen (kein `apt-get` zur Laufzeit)
|
||||
- [ ] Schreibbare Pfade: `chmod 777` oder als Volume mounten
|
||||
- [ ] `HEALTHCHECK` definiert (wird für Liveness/Readiness-Probes genutzt)
|
||||
- [ ] Keine Secrets im Image — nur Env-Vars / K8s-Secrets
|
||||
- [ ] Festes Tag (semantisch), kein `:latest`
|
||||
- [ ] `--platform linux/amd64` beim Build
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Problem | Ursache | Lösung |
|
||||
|---------|---------|--------|
|
||||
| `exec format error` | Falsches Architektur | `--platform linux/amd64` beim Build |
|
||||
| `permission denied` auf Dateien | Non-root UID hat keinen Zugriff | `chmod 777` oder `chown 1001` |
|
||||
| `ImagePullBackOff` | Image nicht im Cluster erreichbar | Image-Pull-Secret prüfen, Registry-URL korrekt? |
|
||||
| `unauthorized` beim Push | Nicht eingeloggt oder kein Recht | `docker login` + API-Key prüfen, Repo existiert? |
|
||||
| Base-Image nicht gefunden | Docker-Hub-Mirror-Pfad falsch | `docker-hub-remote.bahnhub.tech.rz.db.de/<image>` |
|
||||
|
||||
## Best Practices
|
||||
|
||||
- **Multi-Stage Builds** — Build-Dependencies nicht im finalen Image
|
||||
- **`.dockerignore`** — `.git`, `__pycache__`, `node_modules`, `.env` ausschließen
|
||||
- **Reproducible Builds** — Lock-Files verwenden (`pip freeze`, `npm ci`)
|
||||
- **Kleine Images** — `slim` oder `alpine` Base-Images bevorzugen
|
||||
- **Layer-Caching** — Dependencies vor Source-Code kopieren
|
||||
- **SBOM** — Image-SBOM mit Syft generieren (pipeship macht das automatisch)
|
||||
@@ -0,0 +1,236 @@
|
||||
---
|
||||
name: pytest-hypothesis
|
||||
description: >
|
||||
Erstellt und verbessert Unit Tests in Python mit pytest und hypothesis (Property-Based Testing).
|
||||
Nutze diesen Skill wenn der User Tests für Python-Code schreiben, verbessern oder die
|
||||
Test-Coverage erhöhen möchte. Umfasst pytest-Patterns, hypothesis-Strategien, Fixtures,
|
||||
parametrisierte Tests und Coverage-Optimierung.
|
||||
Keywords: pytest, hypothesis, unit test, property-based, test coverage, python test, fixture, parametrize.
|
||||
compatibility: >
|
||||
Python 3.12+ mit pytest (>=8.0), pytest-asyncio (>=1.0), hypothesis (>=6.100).
|
||||
Optional: pytest-cov für Coverage-Reports.
|
||||
metadata:
|
||||
version: "1.0.0"
|
||||
author: "#Einfachbahn Lab"
|
||||
---
|
||||
|
||||
# Python Testing mit pytest + hypothesis
|
||||
|
||||
Skill für qualitativ hochwertige Python-Tests: klassische Unit Tests mit pytest und
|
||||
Property-Based Tests mit hypothesis.
|
||||
|
||||
## Grundprinzipien
|
||||
|
||||
- **pytest** für determinstische Tests mit konkreten Ein-/Ausgaben
|
||||
- **hypothesis** für Property-Based Tests: automatisch generierte Eingaben prüfen Invarianten
|
||||
- Beide ergänzen sich: pytest für bekannte Szenarien, hypothesis für unerwartete Edge Cases
|
||||
|
||||
## Ablauf
|
||||
|
||||
### Schritt 1: Kontext erfassen
|
||||
|
||||
1. **Zu testende Komponente** — Welche Datei/Klasse/Funktion?
|
||||
2. **Vorhandene Tests?** — Gibt es bereits Tests, die ergänzt werden sollen?
|
||||
3. **Async?** — Nutzt der Code `async/await`?
|
||||
4. **Externe Abhängigkeiten?** — Welche müssen gemockt werden?
|
||||
|
||||
### Schritt 2: Test-Typ wählen
|
||||
|
||||
| Situation | Test-Typ |
|
||||
|-----------|----------|
|
||||
| Konkrete Ein-/Ausgabe bekannt | pytest (klassisch) |
|
||||
| Invariante/Eigenschaft prüfbar | hypothesis (property-based) |
|
||||
| Async I/O | pytest-asyncio |
|
||||
| Mehrere ähnliche Fälle | `@pytest.mark.parametrize` |
|
||||
| Komplexes Setup | Fixtures (`@pytest.fixture`) |
|
||||
|
||||
### Schritt 3: Tests implementieren
|
||||
|
||||
## Conventions
|
||||
|
||||
### Dateistruktur
|
||||
```
|
||||
tests/
|
||||
├── __init__.py
|
||||
├── test_<modul>.py # Klassische Tests
|
||||
├── test_<modul>_properties.py # Property-Based Tests (Suffix!)
|
||||
└── conftest.py # Shared Fixtures
|
||||
```
|
||||
|
||||
### Namenskonvention
|
||||
```python
|
||||
# Klassischer Test
|
||||
def test_<funktion>_<szenario>_<erwartung>():
|
||||
...
|
||||
|
||||
# Property-Based Test
|
||||
@given(...)
|
||||
def test_<funktion>_<eigenschaft>(value):
|
||||
...
|
||||
```
|
||||
|
||||
## pytest Patterns
|
||||
|
||||
### AAA-Pattern (Arrange-Act-Assert)
|
||||
```python
|
||||
def test_calculate_total_with_valid_items_returns_sum():
|
||||
# Arrange
|
||||
items = [Item(price=10.0), Item(price=20.0)]
|
||||
calculator = PriceCalculator()
|
||||
|
||||
# Act
|
||||
result = calculator.total(items)
|
||||
|
||||
# Assert
|
||||
assert result == 30.0
|
||||
```
|
||||
|
||||
### Parametrize
|
||||
```python
|
||||
@pytest.mark.parametrize("input_val,expected", [
|
||||
("valid@email.de", True),
|
||||
("invalid", False),
|
||||
("", False),
|
||||
("a@b.c", True),
|
||||
])
|
||||
def test_validate_email(input_val, expected):
|
||||
assert validate_email(input_val) == expected
|
||||
```
|
||||
|
||||
### Fixtures
|
||||
```python
|
||||
@pytest.fixture
|
||||
def sample_config():
|
||||
"""Liefert eine Test-Konfiguration."""
|
||||
return Config(
|
||||
endpoint="https://test.example.com",
|
||||
api_key="test-key-123",
|
||||
timeout_ms=5000,
|
||||
)
|
||||
|
||||
def test_client_uses_config_endpoint(sample_config):
|
||||
client = Client(sample_config)
|
||||
assert client.base_url == "https://test.example.com"
|
||||
```
|
||||
|
||||
### Async Tests
|
||||
```python
|
||||
import pytest
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fetch_data_returns_items():
|
||||
client = AsyncClient(base_url="https://test.example.com")
|
||||
result = await client.fetch_items()
|
||||
assert len(result) > 0
|
||||
```
|
||||
|
||||
### Mocking
|
||||
```python
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_orchestrator_dispatches_task():
|
||||
mock_tracker = AsyncMock()
|
||||
mock_tracker.get_ready_tasks.return_value = [task]
|
||||
|
||||
orchestrator = Orchestrator(tracker=mock_tracker)
|
||||
await orchestrator.poll()
|
||||
|
||||
mock_tracker.move_task.assert_called_once_with(task.id, "in_progress")
|
||||
```
|
||||
|
||||
## hypothesis Patterns
|
||||
|
||||
### Einfache Strategien
|
||||
```python
|
||||
from hypothesis import given, settings, assume
|
||||
from hypothesis import strategies as st
|
||||
|
||||
@given(st.integers(), st.integers())
|
||||
def test_addition_is_commutative(a, b):
|
||||
assert add(a, b) == add(b, a)
|
||||
|
||||
@given(st.text(min_size=1))
|
||||
def test_parse_never_crashes(text):
|
||||
# Darf Exception werfen, aber nie crashen
|
||||
try:
|
||||
parse(text)
|
||||
except ValidationError:
|
||||
pass # Erwartetes Verhalten
|
||||
```
|
||||
|
||||
### Composite Strategien (eigene Datentypen)
|
||||
```python
|
||||
@st.composite
|
||||
def config_strategy(draw):
|
||||
"""Generiert zufällige aber valide Config-Objekte."""
|
||||
return Config(
|
||||
endpoint=draw(st.from_regex(r"https://[a-z]+\.example\.com", fullmatch=True)),
|
||||
api_key=draw(st.text(min_size=8, max_size=64, alphabet=st.characters(whitelist_categories=("L", "N")))),
|
||||
timeout_ms=draw(st.integers(min_value=100, max_value=30000)),
|
||||
)
|
||||
|
||||
@given(config_strategy())
|
||||
def test_config_serialization_roundtrip(config):
|
||||
serialized = config.to_dict()
|
||||
restored = Config.from_dict(serialized)
|
||||
assert restored == config
|
||||
```
|
||||
|
||||
### Settings anpassen
|
||||
```python
|
||||
from hypothesis import settings, Phase
|
||||
|
||||
@settings(
|
||||
max_examples=200, # Mehr Beispiele für kritische Funktionen
|
||||
deadline=None, # Kein Timeout für langsame Tests
|
||||
)
|
||||
@given(st.lists(st.integers()))
|
||||
def test_sort_produces_sorted_output(lst):
|
||||
result = custom_sort(lst)
|
||||
assert all(result[i] <= result[i+1] for i in range(len(result) - 1))
|
||||
```
|
||||
|
||||
### Typische Properties (Invarianten)
|
||||
|
||||
| Property | Beispiel |
|
||||
|----------|----------|
|
||||
| Roundtrip | `deserialize(serialize(x)) == x` |
|
||||
| Idempotenz | `f(f(x)) == f(x)` |
|
||||
| Kommutativität | `f(a, b) == f(b, a)` |
|
||||
| Monotonie | `a <= b → f(a) <= f(b)` |
|
||||
| Invariante | `len(filter(lst)) <= len(lst)` |
|
||||
| Keine Crashes | `f(random_input)` wirft keinen unerwarteten Error |
|
||||
|
||||
## Coverage
|
||||
|
||||
### Coverage messen
|
||||
```bash
|
||||
pytest --cov=src --cov-report=html --cov-report=term-missing
|
||||
```
|
||||
|
||||
### Ziele
|
||||
- **Gesamtprojekt:** ≥ 80% Line Coverage
|
||||
- **Domain-Logik:** ≥ 90% Branch Coverage
|
||||
- **Integrationspunkte:** Property-Based Tests für Serialisierung/Parsing
|
||||
|
||||
## Checkliste
|
||||
|
||||
- [ ] Alle öffentlichen Funktionen/Methoden haben mindestens einen Test
|
||||
- [ ] Positive und negative Szenarien abgedeckt
|
||||
- [ ] Edge Cases: leere Listen, None, Grenzwerte
|
||||
- [ ] Property-Based Tests für Serialisierung/Roundtrips
|
||||
- [ ] Async-Code mit `@pytest.mark.asyncio` getestet
|
||||
- [ ] Externe Abhängigkeiten gemockt (kein Netzwerk/DB in Unit Tests)
|
||||
- [ ] Testnamen beschreiben das erwartete Verhalten
|
||||
- [ ] Coverage ≥ 80%
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Problem | Lösung |
|
||||
|---------|--------|
|
||||
| `hypothesis.errors.DeadlineExceeded` | `@settings(deadline=None)` oder Code beschleunigen |
|
||||
| `hypothesis.errors.Flaky` | Test ist nicht deterministisch → externe Abhängigkeit mocken |
|
||||
| `pytest.mark.asyncio` nicht erkannt | `pytest-asyncio` installieren, `asyncio_mode = "auto"` in pyproject.toml |
|
||||
| Fixtures nicht gefunden | In `conftest.py` verschieben (gleiche oder übergeordnete Ebene) |
|
||||
| Coverage zu niedrig | Branch-Report prüfen: `--cov-branch`, fehlende Error-Pfade testen |
|
||||
@@ -0,0 +1,117 @@
|
||||
---
|
||||
name: scm-info-setup
|
||||
description: >
|
||||
Erstellt und validiert die scm-info.yaml für DB-GitLab-Repos.
|
||||
Stellt sicher, dass die Datei schema-konform ist und alle Pflichtfelder
|
||||
(version, license, contacts, confidentiality, reference-ids) korrekt gesetzt sind.
|
||||
Keywords: scm-info, scm-info.yaml, compliance, beam-id, DBISL, license, reference-ids.
|
||||
compatibility: >
|
||||
Jedes Projekt im DB-GitLab (git.tech.rz.db.de). Keine speziellen Tools nötig.
|
||||
metadata:
|
||||
version: "1.0.0"
|
||||
author: "#Einfachbahn Lab"
|
||||
---
|
||||
|
||||
# scm-info.yaml erstellen und validieren
|
||||
|
||||
Skill für die korrekte Erstellung der Pflichtdatei `scm-info.yaml` in DB-GitLab-Repos.
|
||||
|
||||
## Warum?
|
||||
|
||||
Die `scm-info.yaml` ist **Pflicht** für jedes Repo im DB-GitLab:
|
||||
- Verknüpft das Repo mit Beam/LeanIX (Anwendungskontext)
|
||||
- Ermöglicht VMP-Export von Security-Findings (nur mit gültiger Beam-ID)
|
||||
- Liefert Kontaktdaten für automatische Container-Annotations
|
||||
- Wird von der DXP Compliance Suite geprüft — fehlt sie, entstehen Findings
|
||||
|
||||
## Harte Regeln (MUST)
|
||||
|
||||
1. **Dateiendung `.yaml`** — `.yml` wird NICHT akzeptiert
|
||||
2. **Liegt im Repo-Root** — nicht in Unterordnern
|
||||
3. **Schema-valide** — wird gegen das scm-info JSON Schema geprüft
|
||||
4. **`reference-ids` muss gesetzt sein** — echte Beam-ID oder `none`
|
||||
|
||||
## Ablauf
|
||||
|
||||
### Schritt 1: Informationen ermitteln
|
||||
|
||||
1. **Beam-/Referenz-ID** — Aus LeanIX/Beam ermitteln (Format: `A-123456`). Falls unbekannt: `none`
|
||||
2. **Kontakt-E-Mail** — Team oder Person (wird Container-Annotation `GA_CONTACT`)
|
||||
3. **Lizenz** — Fast immer `LicenseRef-DBISL` (DB-intern). Open Source: passende Lizenz
|
||||
4. **Vertraulichkeitsstufe** — `internal` (Standard), `public`, `confidential`
|
||||
|
||||
### Schritt 2: Datei erstellen
|
||||
|
||||
### Minimal-Template
|
||||
```yaml
|
||||
---
|
||||
version: v3
|
||||
license: LicenseRef-DBISL
|
||||
contacts: team@deutschebahn.com
|
||||
confidentiality: internal
|
||||
reference-ids: none
|
||||
```
|
||||
|
||||
### Erweitert (mit Beam-ID und Custom-Feldern)
|
||||
```yaml
|
||||
---
|
||||
version: v3
|
||||
license: LicenseRef-DBISL
|
||||
contacts: team@deutschebahn.com
|
||||
confidentiality: internal
|
||||
reference-ids: A-123456
|
||||
custom:
|
||||
production-branch: main
|
||||
integrity: normal
|
||||
availability: normal
|
||||
confidentiality: normal
|
||||
it-service-id: itaps-service-id-1
|
||||
```
|
||||
|
||||
### Schritt 3: Validierung
|
||||
|
||||
Prüfe nach Erstellung:
|
||||
- [ ] Datei heißt `scm-info.yaml` (nicht `.yml`!)
|
||||
- [ ] Liegt im Repo-Root
|
||||
- [ ] `version: v3` gesetzt
|
||||
- [ ] `license` ist gültig (`LicenseRef-DBISL` oder Open-Source-Lizenz)
|
||||
- [ ] `contacts` enthält gültige E-Mail-Adresse
|
||||
- [ ] `confidentiality` ist einer von: `public`, `internal`, `confidential`
|
||||
- [ ] `reference-ids` gesetzt (Beam-ID oder `none`)
|
||||
|
||||
## Felder-Referenz
|
||||
|
||||
| Feld | Pflicht | Werte | Hinweis |
|
||||
|------|---------|-------|---------|
|
||||
| `version` | ✅ | `v3` | Schema-Version |
|
||||
| `license` | ✅ | `LicenseRef-DBISL`, `Apache-2.0`, `MIT`, ... | Lizenzkompass beachten |
|
||||
| `contacts` | ✅ | E-Mail-Adresse(n) | Wird Container-Annotation |
|
||||
| `confidentiality` | ✅ | `public`, `internal`, `confidential` | Repo-Sichtbarkeit anpassen |
|
||||
| `reference-ids` | ✅ | Beam-ID (`A-123456`) oder `none` | Ohne ID kein VMP-Export |
|
||||
| `custom.production-branch` | ❌ | Branch-Name | Für pipeship |
|
||||
| `custom.integrity` | ❌ | `normal`, `high`, `very_high` | Schutzbedarf |
|
||||
| `custom.availability` | ❌ | `normal`, `high`, `very_high` | Schutzbedarf |
|
||||
| `custom.it-service-id` | ❌ | ITAPS-ID | Service-Zuordnung |
|
||||
|
||||
## Häufige Fehler
|
||||
|
||||
| Fehler | Finding | Lösung |
|
||||
|--------|---------|--------|
|
||||
| Datei heißt `scm-info.yml` | „scm-info invalid" | Umbenennen zu `.yaml` |
|
||||
| `reference-ids` fehlt | „scm-info invalid" | Feld ergänzen (auch `none` ist valide) |
|
||||
| Keine `contacts` | Schema-Fehler | Gültige E-Mail eintragen |
|
||||
| YAML-Syntaxfehler | „scm-info invalid" | YAML-Linting prüfen |
|
||||
| VMP-Export geht nicht | — | Echte Beam-ID statt `none` eintragen |
|
||||
|
||||
## Zusammenspiel mit pipeship
|
||||
|
||||
Wenn pipeship aktiv ist, werden aus `scm-info.yaml` automatisch:
|
||||
- **`GA_REFERENCE_ID`** ← `reference-ids` (Container-Annotation)
|
||||
- **`GA_CONTACT`** ← `contacts` (Container-Annotation)
|
||||
- Compliance Suite prüft zusätzlich: Protected Branches, README, LICENSE
|
||||
|
||||
## Weiterführend
|
||||
|
||||
- Schema: `git.tech.rz.db.de/db-inner-source/scm-info-json-schema`
|
||||
- Schnellstart: Developer-Portal-Template `init-app-general` (legt scm-info + README + LICENSE an)
|
||||
- Compliance-Findings: https://dp.dxc.comp.db.de/compliance/repositories
|
||||
Reference in New Issue
Block a user