Just another Command Line Tool
Wiederkehrende Build-Kommandos gehören zum Alltag vieler Entwickler:innen. Wer sich dabei schon einmal über kryptische Makefiles oder komplexe Skripte geärgert hat, wird just lieben: Ein schlanker Task Runner, der Automatisierung einfach, portabel und übersichtlich macht – direkt auf der Command Line.
just ist ein leichtgewichtiger Task Runner, der das Schreiben und Ausführen von Befehlen in einer einzigen Datei (justfile) ermöglicht. Er richtet sich an Entwickler:innen, die wiederkehrende Build- oder Automatisierungsaufgaben definieren wollen, ohne die Komplexität von make, Rake oder ähnlichen Tools. just wird direkt auf der Command Line eingesetzt, d.h. verfügt über kein grafisches Userinterface. Kein Grund, an dieser Stelle mit dem Lesen aufzuhören! Basis für just ist das justfile, welches in einfacher YAML-Syntax erstellt und erweitert werden kann. Interessant dabei ist, dass das justfile portabel ist und auf verschiedenen Betriebssystemen ausgeführt werden kann.
Just Do It!
Bevor wir just lokal ausführen können, muss das Tool installiert werden. Dabei werden die
gängigen Betriebssysteme wie Unix/Linux, macOS, Windows, WSL, FreeBSD etc. unterstützt.
Voraussetzung ist zudem eine Python-Installation, Version 3.7 oder neuer.
sudo apt install python3.10 sudo apt install just
Schauen wir uns anhand eines Beispiels an, wie ein justfile geschrieben werden kann. Entwickler:innen kennen die oft wiederholten maven-Kommandos, die während der Entwicklung verwendet werden. Die aufwändigeren, komplexeren Kommandos sind prädestiniert, um im justfile definiert zu werden. Das justfile wird im Root-Verzeichnis des jeweiligen Projektes hinterlegt oder – projektübergreifend – in einem übergeordneten Verzeichnis. Ausgeführt wird der jeweilige Task z.B. mit just compile-fast.
clean: mvn clean compile: mvn compile compile-fast: mvn compile -Djooq.codegen.skip=true -Dopenapi.codegen.skip=true -Dspotless.skip=true test: mvn test test-fast: mvn test -Djooq.codegen.skip=true -Dopenapi.codegen.skip=true -Dspotless.skip=true rebuild: mvn clean install
- clean: führt den Clean-Befehl von maven aus; OK, just clean ist in etwa gleich wie
mvn clean und bringt an dieser Stelle noch nicht sehr viel, aber der Befehl ist auch
nicht gerade komplex! - compile: generiert alle Sourcen, formatiert diese und compiliert den Source Code,
analog zu clean keine wirkliche Vereinfachung, weil alle Default-Einstellungen
übernommen werden. - compile-fast: compiliert nur noch die Sourcen, ohne vorgängige Code-Generierung
(jooq, openapi), zudem wird die Code-Formatierung (spotless) übersprungen. Hier
kommt nun der Vorteil von just zum Tragen, weil nicht alle Command Line Parameter
eingegeben werden müssen. - test: analog zu compile, führt zudem die Tests durch
- test-fast: analog zu compile-fast, führt zudem die Tests durch
- rebuild: bevor alles generiert, compiliert, getestet und deployt wird, wird ein
Cleanup ausgeführt; minimale Vereinfachung gegenüber dem maven-Kommando
Just Advanced
Das vorgängige Einführungsbeispiel zeigt das grundlegende Prinzip von just auf. Wenn du auf den Geschmack gekommen bist, stellen wir dir gerne weitere coole Features vor, im Sinne von FAQs:
Gibt es einen Default Command?
Ja, es empfiehlt sich, im justfile ein Default Command zu definieren, welcher z.B. die möglichen Commands auflistet:
default: just --list
Können mit just mehrere Commands ausgeführt werden?
Ja, das geht sehr einfach, indem die Commands untereinander geschrieben werden, z.B. für die Code Coverage:
code-coverage: mvn jacoco:prepare-agent clean install mvn jacoco:report xdg-open target/site/jacoco/index.html
Können mit just Parameter übergeben werden?
Ja, zum Befehl können Parameter mitgegeben werden, welche dann im Command eingefügt werden, z.B. soll eine bestimmte Klasse getestet werden (Parameter targetClass):
test-class targetClass:
mvn test -Dtest="{{targetClass}}"
Eine zweite Variante sind die Export-Parameter: Diese können innerhalb und ausserhalb des justfile definiert werden, analog zu Environment-Variablen. Der folgende Command startet die Spring Boot App mit den exportierten Datenbank-Parametern:
export DB_URL := "jdbc:postgresql://just.dbms.puzzle.ch:5432/just-dev" export DB_USERNAME := "just-dev_appl" export DB_PASSWORD := "my-very-secret-password" run-remote-dev: mvn spring-boot:run
Falls die Datenbank-Parameter in einem Config File definiert werden, können diese in einer dritten Variante sehr elegant eingebunden werden:
# default environment if none is provided
default_env := ".env-dev"
# run app using environment variables
run envfile=default_env:
just --dotenv-path {{envfile}} run-internal
run-internal:
mvn spring-boot:run
-
Im ersten Schritt wird das Default Config File definiert, falls kein Parameter beim Aufruf mitgegeben wird.
-
Danach erfolgt der Run Command, welcher das Config File entgegennimmt oder das Default Config File verwendet und mit dieser Konfiguration den internen, effektiven Run Command aufruft.
-
Im letzten Schritt wird der interne Run Command ausgeführt, welcher die Spring Boot App mit maven startet.
Das Config File definiert in unserem Beispiel die Datenbank-Parameter:
DB_URL="jdbc:postgresql://just.dbms.puzzle.ch:5432/just-dev" DB_USERNAME="just-dev_appl" DB_PASSWORD="my-very-secret-password"
Als «nice to have» kann dasselbe Config File als Runtime Configuration in der IDE verwendet werden. Da das Config File sensitive Daten enthält, wird es nicht ins Source Repository aufgenommen, hingegen das justfile (ohne sensitive Daten) wird im Source Repository verwaltet und steht damit dem ganzen Entwicklungs-Team zur Verfügung.
Können justfiles «vererbt» werden?
Genau, auch das ist möglich mit just, indem z.B. auf Projektstufe ein justfile definiert wird. Zudem kann in einem übergeordneten Verzeichnis ein weiteres (allgemeines oder persönliches) justfile hinterlegt werden. just sucht nun «von unten nach oben» durch alle justfiles, bis der Command gefunden worden ist. Falls der Command nicht gefunden wird, führt just den Default aus. Dabei sind folgende Punkte zu beachten:
- Damit just in den übergeordneten Verzeichnissen sucht, muss das Setting set fallback gesetzt werden.
- Im übergeordneten justfile empfiehlt sich das Setting set allow-duplicate-recipes, damit doppelte Definitionen nicht zu einem Laufzeitfehler führen.
- Der Command wird immer im Verzeichnis des justfile ausgeführt, d.h. im lokalen Verzeichnis beim lokalen justfile bzw. im übergeordneten Verzeichnis des übergeordneten justfile, falls der Befehl in diesem File definiert ist.
- Mit dem Setting [no-cd] kann verhindert werden, dass das Verzeichnis gewechselt wird, d.h. das aktuelle Working Directory beibehalten wird.
Fazit
Wir setzen just in unserem Projekt konsequent für Frontend- und Backend-Entwicklung ein. Mit denselben just Commands können die gleichen Tasks ausgeführt werden, jeweils für Frontend und Backend spezifisch implementiert, z.B. kann mit dem Command just run-localhost sowohl das Frontend als auch das Backend lokal gestartet und getestet werden.
Die Vorteile gegenüber dem klassischen Tool make ist die einfachere, lesbare Syntax, die explizite Parameterübergabe und die einfache, schnelle Einrichtung unter den verschieden unterstützten Betriesbssystemen. Ferner sprechen für just die klareren Fehlermeldungen beim Debugging sowie ein modernes Ökosystem ohne das schwergewichtige, historisch gewachsene Regelwerk von make.
Quellen und weitere Informationen
- just: https://github.com/casey/just
- just doc: https://just.systems/man/en/