
main 5 Umgebungsvariablen.
Aber andere, als in dem development-Branch des Projekts!?Mise-en-place hilft dir dabei, solche Aspekte bei deinen Softwareprojekten vorzubereiten und zu organisieren.
Gemeinsam mit einer Versionsverwaltung wie Git kannst du damit auch alle Nötige für dein Team vorbereiten:
alle Tools und nötige Schritte für Tests und Releases sind dann unter einheitlichen Kommandos für alle verfügbar.
Aber eins nach dem Anderen…
Hinweis:
"Mise en place" ist eigentlich ein Konzept, wie Küchen in der Gastronomie organisiert und angeordnet werden.
Dabei geht es um die optimale Anordnung von Zutaten, Utensilien und Material, sodass Abläufe effizient organisiert sind.
Das klingt doch schon mal lecker!
Mit dem in der Programmiersprache Rust geschriebenen Tool "Mise-en-place" (im Folgenden kurz: "mise"), breitest du für dein Projekt eine TOML-Konfigurationsdatei (z.B. mise.toml oder versteckt unter Linux: .mise.toml) vor.
Diese Konfigurationsdatei hinterlegst du einfach in deinem Projekt-Ordner, und - schwupps! - kannst du loslegen!
Je nach Softwareprojekt werden oft unterschiedlichste Tools benötigt:
Diese vielen Tools direkt zu installieren, lässt dein System irgendwann sehr unübersichtlich werden. Außerdem kannst du oft nicht unterschiedliche Versionen des selben Tools installieren (dafür brauchst du ja dann "virtuelle Umgebungen").
Am besten wäre es ja, wenn pro Projekt genau die Tools in der Version installiert sind, die dafür benötigt werden und die dann auch nur in diesem Projekt verfügbar sind.
Genau das kannst du mit mise erreichen.
Mise bietet im Hintergrund eine Vielzahl von Backends, über die diese Tools installiert werden:
von Paketmanagern wie pip über npm ist hier fast alles möglich.
Dabei kannst du in den unterschiedlichen Projekt-Konfigurationen dann auch direkt die Versionen benennen, die du dort benötigst.
Nehmen wir an, du brauchst für dein Projekt die neueste Version von jq um .JSON-Dateien zu verarbeiten.
Außerdem benötigst du eine bestimmte (veraltete) Version von kubectl für die Interaktion mit einem Kubernetes Cluster.
Hier eine Beispieldatei mise.toml, die du auch interaktiv mit den beiden Kommandos mise use jq und mise use kubectl@1.30.0 im Verzeichnis erstellen kannst:
[tools]
jq = "latest"
kubectl = "1.30.0"
Hinweis:
mise muss der Konfiguration in einem Ordner zunächst vertrauen.
Damit das geschieht, warnt dich mise möglicherweise zunächst, dass der Konfiguration noch nicht vertraut wird.
Das musst du nun entscheiden - am besten mit einem kurzen Blick, was die Datei enthält.
Mit mise install werden beide Tools so installiert, dass sie im Projekt-Ordner durch mise automatisch geladen und genutzt werden.
In dieser virtuellen Umgebung stehen dir diese installierten Tools zur Verfügung - aber eben nur in diesem Ordner.
Sobald du in einen anderen als den Projekt-Ordner wechselst, sind die Tools nicht mehr aufrufbar.
Mise kann bestimmte Umgebungsvariablen laden bzw. setzen, sobald du einen Ordner im Terminal betrittst. Praktisch ist das, wenn du z.B. in einem bestimmten Projekt ganz bestimmte Server ansteuern musst, Credentials vorhalten oder bestimmte Usernamen und Passwörter dafür benötigst. Diese Variablen kannst du wie folgt definieren (hier als Beispiel einen Useraccount für eine Datenbank und eine Version der fiktiven, selbst entwickelten App):
[env]
DB_USER = "dbuser"
APP_NAME = "MyWonderfulApp"
Diese Umgebungsvariablen werden nun automatisch von mise gesetzt, sobald du den Projekt-Ordner über das Terminal betrittst. Sobald du den Ordner verlässt, existieren diese Umgebungsvariablen nicht mehr oder können anderweitig mit Werten belegt sein.
Tipp:
Mit mise kannst du auch Secrets - also sicherheitskritische Inhalte, wie etwa Passwörter oder API-Tokens - sicher in solchen Variablen speichern.
Was wäre ein gemeinsames Projekt ohne Teamarbeit? Und da bringen alle ihren bevorzugten Weg bzw. Befehl mit…
Deswegen kannst du mit mise kurze Befehle mit fest definierten Kürzeln definieren.
Auch bereits bestehende Skripte kannst du mit mise aufrufen, um etwa bestimmte Shell-Befehle nacheinander ausführen.
So könntest du dir anstelle langer, projektspezifischer Befehle nur noch ein einheitliches mise deploy merken, um einen komplizierten Prozess im Hintergrund anzustoßen - egal in welcher Programmiersprache.
Tipp:
In einem anderen Artikel stellen wir dir den Task-Runner just vor, mit dem du auf ganz ähnliche Weise Kürzel für lange Befehle, Aufgaben und Skripte anlegen kannst.
Mise geht hier aber mit mehr Funktionen noch einen ganzen Schritt weiter.
Das Tolle dabei: diese Tasks können aufeinander aufbauen bzw. voneinander abhängen. Beispielsweise muss zuerst Code kompiliert werden, um ihn dann auszuführen. Oder die Tests sollen ausgeführt werden - nur nicht, wenn die Code-Dateien sich gar nicht verändert haben. Genau solche Zusammenhänge lassen sich mich mit Tasks sicherstellen. So kannst du sogar kompliziertere "Wenn, Dann"-Logiken unterbringen, dass etwas aktuellere Dateien vorliegen müssen, damit eine Aufgabe nicht übersprungen wird.
Tipp:
Unnötige Arbeit kannst du bei Tasks vermeiden, indem du die Artefakte (also die ggf. bereits existierenden Dateien) nicht erneut anlegst oder bearbeitest.
Du kannst solche bei einem Task ggf. bereits vorliegenden Artefakte benennen, dann wird mise diese Schritte nicht noch einmal ausführen, solange sie sich nicht verändert haben.
Hier ein Beispiel für 3 Tasks, die teils voneinander abhängen (ebenfalls in der mise.toml im Projekt-Ordner).
Ein Befehl legt einen Ordner an (prepare), ein anderer eine Textdatei in dem angelegten Order (doit) und clean schließlich löscht sowohl Datei als auch Ordner wieder.
Alle Befehle bekommen eine kurze Beschreibung ("description"), damit klar ist, was sie tun.
[tasks.prepare]
description = "Legt den Ordner 'prep' im selben Verzeichnis an"
run = "mkdir prep"
sources = "prep"
[tasks.doit]
description = "Schreibt eine vordefinierte Ausgabe in eine Textdatei 'testdatei.txt' unter 'prep'"
depends = "prepare"
run = [
cd prep,
"echo 'Dies steht gleich (nochmal) in einer Textdatei' >> prep/testdatei.txt"
]
[tasks.clean]
description = "Löscht testdatei und Ordner 'prep' wieder"
depends = ["prepare", "doit"]
run = [
"rm prep/testdatei.txt",
"rmdir prep"
]
Wenn du mise tasks in diesem Projekt-Ordner ausführst, erhältst du eine Liste und die folgende Beschreibung der definierten Tasks:
clean Löscht testdatei und Ordner 'prep' wieder
doit Schreibt eine vordefinierte Ausgabe in eine Textdatei
prepare Legt den Ordner 'prep' im selben Verzeichnis an
Arbeitest du mit mehreren Personen zusammen, sind damit jetzt projektspezifische, gemeinsame Tasks definiert, die alle nutzen können. Dabei bist du aber nicht auf einzelne Terminal-Befehle (wie oben gezeigt) festgelegt, sondern kannst auch ganze Skripte mit zusätzlichen Parametern aufrufen. Durch die Möglichkeit, diese als Abhängigkeiten zu definieren, lassen sich auch mit einzelnen Skripten kompliziertere Workflows beschreiben.
Zu guter Letzt: mise kann mittels Hooks auf Ereignisse reagieren. Beispielsweise könntest du immer beim Betreten des Ordners direkt eine Willkommensnachricht anzeigen lassen, eine Liste der letzten Änderungen ausgeben oder alle definierten Tasks auflisten. Das geht auch beim Verlassen eines Ordners, oder wenn sich eine Datei verändert hat. Hooks "haken" sich in diesen Vorgang ein und führen dann weitere Schritte durch.
Tipp: Mise lässt sich auch in CI/CD-Abläufe integrieren, indem du es etwa in eigenen Container-Images verwendest.
Mit mise steht dir ein mächtiges Werkzeug zur Verfügung, um deine Projekte vorzubereiten und zu standardisieren. Du kannst damit Vorbereitungen treffen, für einfachere Abläufe sorgen und letztlich die Teamarbeit am Code verbessern. Denn du kennst ja das Sprichwort: viele Köche verderben den Brei nur, wenn sie unkoordiniert kochen.
"Mise version manager: number one tool for a developer" von Andrey Fadeev (YouTube; Sprache: EN)
"mise, the glue for managing all your dev projects" von Let's Chat with Stephen (YouTube; Sprache: EN)