Skip to content

pt9912/d-migrate

Repository files navigation

d-migrate

Datenbankunabhängiges CLI-Tool für Schema-Migration und Datenmanagement.

Build License: MIT Kotlin


Was ist d-migrate?

d-migrate ist ein Kommandozeilenwerkzeug für datenbankunabhängige Schema-Migration und Datenmanagement. Du definierst dein Schema einmalig in einem neutralen Format (YAML) und kannst es für PostgreSQL, MySQL und SQLite validieren, vergleichen und als DDL generieren. Darüber hinaus unterstützt d-migrate Reverse-Engineering bestehender Datenbanken, streaming-basierten Datenexport/-import/-transfer zwischen Datenbanken sowie die Integration in bestehende Migrations-Toolchains (Flyway, Liquibase, Django, Knex).

Aktuelle Fähigkeiten:

  • Phasenbezogene DDL-Ausgabe mit --split pre-post fuer importfreundliche Schema-Artefakte (pre-data/post-data)
  • Neutrales Schemamodell mit 18 integrierten Typen plus Spatial Geometry
  • YAML-basierte Schemadefinition und -parsing
  • Schemagültigkeitsprüfung mit 18+ Fehlercodes (E001-E018, E120/E121)
  • Schema-Vergleich mit schema compare (file/file, file/db, db/db)
  • Reverse-Engineering bestehender Datenbanken mit schema reverse (PostgreSQL, MySQL, SQLite)
  • DDL-Generierung für PostgreSQL, MySQL und SQLite
  • Spatial-DDL: PostGIS, MySQL native, SpatiaLite (--spatial-profile)
  • Transformation von View-Queries (17 SQL-Funktionen)
  • Transformationsberichte (YAML-Seitenschatten)
  • Streaming-Datenexport (JSON, YAML, CSV) mit benannten Verbindungen
  • Transaktionaler Datenimport mit UPSERT, Truncate, Trigger-Handling und Reseeding
  • Direkter DB-zu-DB-Datentransfer mit data transfer
  • Inkrementeller Export über --since-column / --since
  • Line-orientierte Fortschrittsanzeige für data export, data import und data transfer
  • CLI mit schema validate, schema generate, schema compare, schema reverse, data export, data import, data transfer und data profile
  • MCP-Server (d-migrate mcp serve --transport stdio|http) per MCP 2025-11-25 mit Transport, Auth (JWT-JWKS, JWT-Introspection, stdio-Token-Registry), Discovery (tools/list, resources/list, resources/templates/list), JSON-Schema-Vertrag und produktiven MCP-Tool-Handlern inklusive kontrollierter Start-Tools
  • Internationalisierte CLI-Ausgabe (EN/DE) mit ResourceBundle-Fallback, ICU4J-Unicode-Utilities, expliziter Zeitzonen-/Temporal-Policy und konsolidiertem CSV-/BOM-Encoding-Vertrag
  • OCI-Image für die Nutzung mit Docker

Schnellstart

Voraussetzungen

  • JDK 21 oder neuer — oder Docker (siehe unten, kein lokales JDK erforderlich)

Installation

GitHub Release Assets

Für veröffentlichte Releases stehen ZIP, TAR und Fat JAR auf der Releases-Seite bereit.

# Launcher-basierte Distribution entpacken
tar -xf d-migrate-<version>.tar
./d-migrate-<version>/bin/d-migrate --help

# Alternativ das Fat JAR direkt ausführen
java -jar d-migrate-<version>-all.jar --help

Hinweis: Die Homebrew-Formula wird in 0.5.0 im Repository mitgeführt, ist aber noch kein vollautomatischer Standard-Installationspfad.

Aus Quellcode bauen

./gradlew build

Makefile-Komfortziele

Das Top-Level-Makefile ist ein duenner Wrapper um die kanonischen Gradle-, Docker- und Script-Einstiegspunkte. Die verfuegbaren Kurzbefehle zeigt:

make help

Haeufige Ziele:

make build             # ./gradlew build
make test              # ./gradlew test
make gates             # Gradle check, Coverage-Gate und docs-check
make ci                # ./gradlew build plus Coverage-Gate und docs-check
make smoke             # CLI-Distribution bauen und --version/--help pruefen
make integration       # Testcontainers-Integrationstests via Docker-Script
make docs-check        # Markdown-Linkziele in docs/ pruefen
make docker-gates      # Docker-Runtime-Build, Coverage-Gate und Runtime-Smoke
make docker-full-gates # docker-gates plus Docker-Integrationstests
make release-assets    # ZIP, TAR, Fat JAR und SHA256 bauen

Release-Assets lokal bauen

./gradlew :adapters:driving:cli:assembleReleaseAssets
ls -1 adapters/driving/cli/build/release

CLI ausführen

# Schema validieren
./gradlew :adapters:driving:cli:run --args="schema validate --source schema.yaml"

# Zwei Schemas vergleichen
./gradlew :adapters:driving:cli:run --args="schema compare --source schema.yaml --target schema-new.yaml"

# PostgreSQL-DDL generieren
./gradlew :adapters:driving:cli:run --args="schema generate --source schema.yaml --target postgresql"

# MySQL-DDL mit Rollback generieren
./gradlew :adapters:driving:cli:run --args="schema generate --source schema.yaml --target mysql --generate-rollback"

# Schema aus bestehender Datenbank extrahieren
./gradlew :adapters:driving:cli:run --args="schema reverse --source mydb --output reverse.yaml --report reverse.report.yaml"

# DB-basierter Schema-Vergleich
./gradlew :adapters:driving:cli:run --args="schema compare --source file:schema.yaml --target db:mydb"

# DB-zu-DB Datentransfer
./gradlew :adapters:driving:cli:run --args="data transfer --source sourcedb --target targetdb --tables users,orders"

Docker

Veröffentlichtes Image nutzen

Kein lokales JDK erforderlich — einfach Image ziehen und ausführen:

# Validierung
docker run --rm -v $(pwd):/work ghcr.io/pt9912/d-migrate:latest schema validate --source /work/schema.yaml

# Compare (file/file)
docker run --rm -v $(pwd):/work ghcr.io/pt9912/d-migrate:latest schema compare --source file:/work/schema.yaml --target file:/work/schema-new.yaml

# DDL generieren
docker run --rm -v $(pwd):/work ghcr.io/pt9912/d-migrate:latest schema generate --source /work/schema.yaml --target postgresql

# Reverse-Engineering
docker run --rm -v $(pwd):/work ghcr.io/pt9912/d-migrate:latest \
  --config /work/.d-migrate.yaml schema reverse --source mydb --output /work/reverse.yaml

Mit Dockerfile lokal bauen und testen

Das Repository liefert ein Multi-Stage Dockerfile, das das Projekt im Container baut und testet und danach die CLI-Distribution in ein schlankes JRE-Laufzeitimage verpackt. Das ist der einfachste Weg, den vollständigen Build ohne lokale JDK-Installation auszuführen.

# Vollständiger Build inkl. Tests und Coverage-Validierung (Standard)
docker build -t d-migrate:dev .

# Erzwungener vollständiger Test/Coverage-Lauf (Docker-Layer-Cache UND Gradle-Cache werden umgangen)
docker build --no-cache \
  --progress=plain \
  --build-arg GRADLE_TASKS="build :adapters:driving:cli:installDist --rerun-tasks" \
  -t d-migrate:dev .

# Aggregierten Kover-HTML-Report bauen und lokal im Browser ansehen
docker build --target coverage -t d-migrate:coverage .
docker run --rm -p 8080:8080 d-migrate:coverage
# dann http://localhost:8080 im Browser öffnen

# Aggregierten Kover-JSON-Report direkt auf stdout ausgeben
docker build --target coverage-json -t d-migrate:coverage-json .
docker run --rm d-migrate:coverage-json > coverage.json

# Optional den 90%-Kover-Gate wie in CI hart prüfen
docker build --target coverage-verify -t d-migrate:coverage-verify .

# Tests überspringen — nur CLI-Distribution erstellen
docker build --build-arg GRADLE_TASKS="assemble :adapters:driving:cli:installDist" \
  -t d-migrate:dev .

# Nur einen Build-Stage-Teil ausführen, ohne finales Runtime-Image zu erzeugen
docker build --target build \
  --build-arg GRADLE_TASKS=":hexagon:core:test :adapters:driven:driver-common:test" \
  -t d-migrate:phase-a .

# Lokal gebaute CLI ausführen
docker run --rm -v $(pwd):/work d-migrate:dev schema validate --source /work/schema.yaml

# Testcontainers-basierte Integrationssuite ausführen
./scripts/test-integration-docker.sh

# Oder nur eine Teilmenge der Integrationstests ausführen
./scripts/test-integration-docker.sh :adapters:driven:driver-postgresql:test

Hinweise:

  • Die Build-Stage nutzt eclipse-temurin:21-jdk-noble und cached Gradle-Abhängigkeiten über BuildKit-Cache-Mounts, sodass wiederholte Builds schnell sind.
  • Die Runtime-Stage nutzt eclipse-temurin:21-jre-noble (dasselbe Basisimage wie das veröffentlichte OCI-Image aus :adapters:driving:cli:jibDockerBuild).
  • Die coverage-Stage führt test koverHtmlReport koverXmlReport aus und liefert den aggregierten Root-Kover-HTML-Report über einen eingebauten HTTP-Server auf Port 8080 aus.
  • Die coverage-json-Stage gibt denselben aggregierten Root-Kover-Report als normalisiertes, JaCoCo-artiges JSON per ENTRYPOINT auf stdout aus, sodass du ihn direkt in eine Datei umleiten kannst.
  • Die coverage-Stage baut den HTML-Report bewusst auch dann, wenn der 90%-Kover-Gate aktuell unterschritten wird.
  • Die separate coverage-verify-Stage führt koverVerify aus und bricht docker build --target coverage-verify absichtlich mit einem Fehler ab, sobald der konfigurierte Kover-Mindestwert nicht erreicht wird.
  • scripts/verify-doc-refs.sh prüft Markdown-Link-Targets (Markdown links) in docs/, spec/, README.md und CHANGELOG.md gegen das Dateisystem. Externe HTTP-Links werden ignoriert. Exit-Code 1 bei kaputten Links.
  • Ein vollständiger docker build erreicht immer die Runtime-Stage. Wenn du GRADLE_TASKS überschreibst, füge :adapters:driving:cli:installDist hinzu; für Build-/Test-Only-Subsets nutze alternativ --target build.
  • Testcontainers-basierte Integrationstests sollten nicht in docker build laufen. Nutze dafür scripts/test-integration-docker.sh, das einen kurzlebigen JDK-Container startet und den Docker-Socket des Hosts mountet, damit Testcontainers PostgreSQL/MySQL normal starten kann.
  • Um Build-Artefakte aus der Build-Stage zu extrahieren:
    docker build --target build -t d-migrate:build .
    docker create --name d-migrate-tmp d-migrate:build
    docker cp d-migrate-tmp:/src/adapters/driving/cli/build/distributions ./dist
    docker rm d-migrate-tmp

Minimales Schema-Beispiel

Lege eine Datei namens schema.yaml an:

schema_format: "1.0"
name: "My App"
version: "1.0.0"

tables:
  users:
    columns:
      id:
        type: identifier
        auto_increment: true
      email:
        type: text
        max_length: 254
        required: true
        unique: true
      created_at:
        type: datetime
        default: current_timestamp
    primary_key: [id]

Dann validierst du es so:

./gradlew :adapters:driving:cli:run --args="schema validate --source schema.yaml"

Und vergleichst zwei Versionen so:

./gradlew :adapters:driving:cli:run --args="schema compare --source schema.yaml --target schema-v2.yaml"

Aktueller Stand

Aktuelles Release: v0.9.6 — MCP-Server — d-migrate ist jetzt als Model Context Protocol v1 Server über stdio und Streamable HTTP nutzbar (Phasen A–G), mit asynchronen Jobs, Idempotenz, Policy/Approval, Quotas, JDBC-Persistenz, file-backed Artifact-Stores, Bundle-Import und KI-nahen Tools (procedure_transform_*, testdata_*). Daneben: deterministische DDL-Generierung (--deterministic/SOURCE_DATE_EPOCH), bigint Identity-Columns für PostgreSQL/MySQL, partial Index-Predicates, Index-Sortierung pro Spalte und ein robusterer schema reverse/--split=pre-post-Pfad.

Alle Releases und Details: CHANGELOG.md | GitHub Releases

Unterstützte Datenbanken

Datenbank Status
PostgreSQL DDL-Generierung, Reverse-Engineering, Datenexport/-import/-transfer
MySQL DDL-Generierung, Reverse-Engineering, Datenexport/-import/-transfer
SQLite DDL-Generierung, Reverse-Engineering, Datenexport/-import/-transfer
Oracle Geplant
MSSQL Geplant

Roadmap

Die vollständige Roadmap und den Meilensteinplan findest du in docs/planning/roadmap.md.

Dokumentation

Detaillierte Dokumentation findest du in docs/ und spec/:

Mitmachen

Beiträge sind willkommen! Bitte erstelle ein Issue oder einen Pull Request auf GitHub.

  1. Forke das Repository
  2. Erstelle einen Feature-Branch von develop
  3. Schreibe Tests für deine Änderungen
  4. Stelle sicher, dass alle Tests laufen (./gradlew build)
  5. Reiche einen Pull Request gegen develop ein

Lizenz

Dieses Projekt ist unter der MIT-Lizenz lizenziert.

About

Framework für datenbankunabhängige Migrationen und Datenverwaltung

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors