LunaPack ist da: Projektstandards installieren statt kopieren
Wenn du heute ein Projekt aufsetzt oder ein bestehendes erweiterst, kopierst du dann noch Dateien aus einem anderen Repository? Fast jedes Team braucht dieselben Grundlagen: Formatierungsregeln, Build-Konfiguration, Pipelines, Security-Prüfungen und Dokumentationsvorlagen. Die Kopie ist schnell erledigt. Das Problem beginnt, wenn diese Dateien Monate später noch immer im Projekt liegen, der gemeinsame Standard sich aber weiterentwickelt hat.
Genau dafür veröffentlichen wir LunaPack. Das Open-Source-Kommandozeilenwerkzeug macht aus gemeinsam genutzten Projektdateien versionierte Engineering-Packs. Es hält Quelle, Version und verwaltete Ziele im Repository fest, zeigt geplante Änderungen vor der Anwendung und schafft einen kontrollierten Updatepfad für neue und bestehende Projekte.
Wenn die Kopie ihre Herkunft verliert
Ein typischer Fall beginnt mit einer Änderung an einer gemeinsamen Pipeline. Ein zusätzlicher Security-Check soll in alle Services gelangen. Zwei Teams übernehmen ihn sofort, ein Repository hat eine lokal angepasste Pipeline und ein weiteres wird in der Suche übersehen. Der Check selbst war schnell geschrieben, aber seine kontrollierte Verteilung kostet Zeit.
Ein Template oder Generator löst den Start gut. Nach der Erstellung gehört die Kopie jedoch dem Projektteam und die Verbindung zur Vorlage ist häufig nicht mehr Teil des Ablaufs. Tools wie Copier bieten dafür eigene Updatewege, doch bei vielen klassischen Template-Repositories bleibt nur der manuelle Vergleich.
LunaPack setzt genau an dieser verlorenen Verbindung an. Ein Projekt hält fest, welchen Pack-Stand es angefordert hat, welche Version aufgelöst wurde und welche Ziele LunaPack verwaltet. Innerhalb eines Repositories wird dadurch sichtbar, woher eine Datei kommt und wie ein Update aussehen würde. LunaPack konzentriert sich dabei auf den nachvollziehbaren Zustand im einzelnen Repository. Eine organisationsweite Übersicht lässt sich darauf aufbauend über die committed Lock-Dateien der Repositories inventarisieren.
Wo LunaPack in die Werkzeuglandschaft passt
LunaPack ersetzt nicht jedes Werkzeug, das Dateien oder Standards verteilt. Entscheidend ist, welche Art von Inhalt verwaltet werden soll und wo seine Ownership liegt.
| Bedarf | Passendes Werkzeug | Rolle von LunaPack |
|---|---|---|
| Bibliotheken und Laufzeitabhängigkeiten | npm, NuGet, pip oder Cargo | Bleiben Aufgabe des Paketmanagers |
| Zentral ausgeführter CI-Ablauf | Wiederverwendbare GitHub Actions oder Pipeline-Templates | Kann die aufrufenden Projektdateien ergänzen, ersetzt den zentralen Workflow aber nicht |
| Wiederverwendbare Infrastrukturbausteine | Terraform- oder Bicep-Module | Verwaltet bei Bedarf die umgebenden Repository-Dateien |
| Projekterstellung mit Template-Updates | Beispielsweise Copier | Alternative, wenn ein Template-Modell die passende Änderungsgrenze ist |
| Gemeinsam versionierte Projektgrundlage | LunaPack | Verwaltet mehrere Dateien, Pack-Abhängigkeiten und ihren Zustand im Zielprojekt |
LunaPack ergänzt damit Paketmanager, Templates und zentrale CI-Bausteine um eine lokale, versionierte Projektgrundlage. Zentrale Durchsetzung und automatische Pull Requests bleiben Aufgabe der vorhandenen CI- und Repository-Automation. LunaPack liefert dafür den nachvollziehbaren Zustand im Zielprojekt.
Was ein Pack im Projekt hinterlässt
Ein Pack ist ein versionierter Ordner mit einer pack.yml-Datei und den Inhalten, die er verwaltet.
Er kann Dateien, Parameter, Bedingungen, Verweise auf andere Packs und optionale Lifecycle-Hooks für Anweisungen oder Prozesse beschreiben.
lunapack.yml beschreibt, was das Projekt verwenden will.
lunapack-lock.yml hält fest, was LunaPack tatsächlich aufgelöst hat.
Dazu gehören exakte Pack-Versionen, Abhängigkeiten, Quellidentität, Git-Commit, Parameter, Zielpfade, Strategien und Inhaltsdigests.
Dieser nachvollziehbare Dateibesitz heißt im LunaPack-Modell Ownership.
Packs lassen sich zusammensetzen. Ein organisationsspezifischer Pack kann beispielsweise eine allgemeine Repository-Basis, .NET-Konfiguration und einen Pull-Request-Check in exakt festgelegten Versionen verbinden. Parameter und Projektvariablen liefern Werte wie Firmenname oder aktivierte Features, ohne für jede Variante einen neuen Pack zu kopieren.
Je nach Inhalt kann ein Pack Dateien vollständig besitzen oder klar definierte Teile zusammenführen. LunaPack unterstützt beim Zusammenführen verwalteter Inhalte unter anderem eindeutige Zeilen, markerbegrenzte Abschnitte und JSON-Inhalte. Das ist hilfreich, verlangt aber Tests mit realistischen Projektdateien, weil Merge-Reihenfolge, Großschreibung und vorhandene Formatierung das Ergebnis beeinflussen können.
Bestehende Repositories schrittweise anbinden
LunaPack ist nicht nur für neue Projekte interessant.
Mit --adopt-existing kann ein Projekt bereits vorhandene Dateien unter Ownership stellen, wenn ihr gerenderter Inhalt exakt dem Pack entspricht.
Weicht eine Datei ab, bleibt sie unverändert und LunaPack meldet den Konflikt, statt sie still zu ersetzen.
Unterschiedliche Repository-Strukturen müssen ebenfalls nicht zu unterschiedlichen Packs führen.
Remappings verschieben Ziele dauerhaft an projektspezifische Pfade.
Mit @ignore lässt sich eine bewusste Ausnahme ausklammern und aus der Ownership entfernen.
Manuell verschobene verwaltete Dateien können mit luna mv neu gebunden werden.
Für Quellen, die noch keinen Pack bereitstellen, können Luna Links ausgewählte Dateien, Verzeichnisse oder Globs aus einem lokalen oder Git-basierten Repository übernehmen. Damit kann ein Team eine bestehende Standardquelle zunächst anbinden und später entscheiden, ob daraus ein eigener Pack werden soll.
Diese Fähigkeiten lösen ein anderes Problem als reines Scaffolding. Sie ermöglichen eine schrittweise Einführung in einem heterogenen Repository-Portfolio, ohne am ersten Tag jede Ordnerstruktur und jede lokale Ausnahme vereinheitlichen zu müssen.
Einen kontrollierten Pilot aufsetzen
Für einen reproduzierbaren ersten Pilot legst du die verwendeten Versionen am besten explizit fest. Das folgende Beispiel installiert die zum Veröffentlichungszeitpunkt aktuelle Luna-Version 1.2.0, bindet den zugehörigen Git-Commit ein und plant eine exakte Pack-Version. Lifecycle-Skripte und Anweisungen bleiben für den ersten Lauf deaktiviert.
npm install --global @lunarisdigitalsolutions/lunapack
mkdir lunapack-pilot
cd lunapack-pilot
luna init
luna sources add github lunapack lunarisdigitalsolutions/lunapack --path projects/packs --ref main
luna discover
luna install dotnet-project@1.0.0 --dry-run
Der Dry Run löst Pack und Abhängigkeiten auf und prüft geplante Ziele, ohne Projektdateien oder LunaPack-Zustand zu verändern. Prüfe danach Dateipfade, Strategien, Parameter, Abhängigkeiten und mögliche Hooks. Erst wenn dieser Plan zur erwarteten Projektgrundlage passt, wendest du ihn an und kontrollierst den Zustand.
luna install dotnet-project@1.0.0 --scripts skip --skip-instructions
luna audit
Ein überzeugender Pilot endet nicht mit einer erfolgreichen Installation. Ändere eine verwaltete Datei lokal, plane ein Update und teste auch eine bewusste Ausnahme per Remapping. So siehst du früh, ob die ausgegebenen Entscheidungen für dein Team verständlich sind und ob die Pack-Strategien zu eurer tatsächlichen Ownership passen.
Updates bleiben bewusste Änderungen
Mit luna outdated prüfst du, ob für ein direkt installiertes Pack eine neuere Version verfügbar ist.
Danach gehört der Updateplan in denselben Reviewprozess wie eine manuell erstellte Änderung.
luna outdated
luna update dotnet-project --dry-run --scripts skip --skip-instructions
LunaPack aktualisiert Projektdateien und Lock-Zustand gemeinsam.
Wenn sich der gewünschte Pack-Inhalt nicht geändert hat, plant ein Update keine Dateiaktion und eine lokale Änderung bleibt bestehen.
Für normale Pack-Dateien zeigt luna audit die Ownership, aber keinen Status für lokale Änderungen.
Prüfe diese Abweichungen deshalb mit dem Git-Diff des Projekts.
Ändert sich der Pack-Inhalt, entscheidet die im Pack definierte Strategie, ob LunaPack die aktuelle Datei ersetzt, sichert, behält, ablehnt oder mit dem neuen Inhalt zusammenführt.
Besondere Aufmerksamkeit verdienen Ziele, die eine neue Pack-Version nicht mehr enthält.
Der Updateplan kann solche Dateien auch dann zur Entfernung vorsehen, wenn sie lokal verändert wurden.
Der Dry Run macht diese Aktion vorab sichtbar, sodass das Team die Datei bei Bedarf mit @ignore erhalten und aus der Ownership lösen kann.
Bei behandelten Fehlern rollt LunaPack seine geplanten Dateischritte zurück. Seiteneffekte freigegebener Skripte, externe Aufrufe und parallele Änderungen liegen außerhalb dieses Rollbacks. Führe Updates deshalb in einem sauberen Git-Workspace aus, prüfe anschließend den Diff und übernimm ihn per Pull Request.
Sicher und nachvollziehbar einführen
Packs und ihre Quellen solltest du wie Code behandeln.
Lifecycle-Skripte laufen mit den Rechten des aufrufenden Benutzers und werden nicht in einer Sandbox isoliert.
Prüfe sie deshalb wie Build- oder Installationsskripte aus anderen Quellen.
Im interaktiven Standardmodus verwendet Luna gespeichertes Vertrauen oder fragt vor einem noch nicht freigegebenen Skript nach Zustimmung.
In Continuous Integration sollte die Skriptentscheidung immer explizit sein und für einen ersten Pilot --scripts skip lauten.
LunaPack unterstützt lokale und Git-basierte Quellen, bietet aber keinen gehosteten Pack-Marktplatz. Eine Quellbezeichnung ist keine kryptografische Publisher-Identität. Für reproduzierbare Abläufe solltest du die Luna-Version, einen vollständigen Git-Commit und exakte Pack-Versionen festlegen.
LunaPack steht unter der MIT-Lizenz und sein öffentlicher Einsatz beginnt gerade. Ein kleiner Pilot bietet deshalb einen guten Rahmen, um die Eignung für die eigene Repository-Landschaft zu prüfen und früh Feedback einzubringen.
Quellcode, Releases und Issues sind im Open-Source-Repository sichtbar. Die Sicherheitsdokumentation beschreibt Schutzmaßnahmen, Vertrauensgrenzen und Verantwortlichkeiten. Diese Transparenz erleichtert eine technische Bewertung und liefert eine konkrete Grundlage für euren eigenen Security-Review und das Betriebsmodell interner Packs.
Mit klaren Erfolgskriterien entscheiden
Ein sinnvoller Pilot umfasst ein neues und ein bestehendes Repository. Wähle zunächst eine Grundlage, deren Ownership klar ist, etwa eine Dokumentationsvorlage, eine EditorConfig oder einen abgegrenzten CI-Check. Teste Installation, lokale Abweichung, Update, Ausnahme und Uninstall, bevor du breitere Packs zusammensetzt.
Vor dem Einsatz muss außerdem feststehen, wer das Pack-Repository besitzt, Releases prüft, Breaking Changes kommuniziert und Kompatibilität mit den unterstützten Stacks testet. Projektteams brauchen einen benannten Weg für Ausnahmen und eine klare Verantwortung für Update-Pull-Requests. LunaPack verwaltet Dateien, aber es erzeugt dieses Governance-Modell nicht.
Miss im Pilot nicht nur, ob Befehle erfolgreich sind. Vergleiche, wie lange eine Standardänderung bis zu einem reviewbaren Pull Request benötigt, welche manuellen Konflikte entstehen, ob der Dry Run verständlich ist und wie viele bewusste Ausnahmen notwendig werden. Die Ergebnisse zeigen außerdem, wo der Pack-Schnitt noch nachgeschärft werden sollte und an welchen Stellen der bisherige Prozess einfacher bleiben darf.
Wenn der Pilot dagegen zeigt, dass Änderungen schneller auffindbar, erklärbar und reviewbar werden, hat LunaPack sein wichtigstes Versprechen erfüllt. Dann ist der nächste Schritt kein größerer Rollout, sondern ein zweiter kleiner Pack mit derselben klaren Ownership.
Wie würdest du einen Pilot für versionierte Projektstandards aufsetzen? Schau gerne bei uns auf LinkedIn vorbei und diskutiere mit.
Autoren
Florian Bader
Florian ist Solution Architect und Microsoft Most Valuable Professional (MVP) für Azure & Azure IoT mit langjähriger Erfahrung im Bereich DevOps, Cloud und Digitalisierung. Er unterstützt Unternehmen dabei, effiziente und effektive Lösungen zu entwickeln, die ihre digitalen Projekte nachhaltig zum Erfolg führen.