Für Skripte und CI
Alle Befehle lassen sich ohne Rückfragen und mit maschinenlesbarer Ausgabe nutzen, etwa in einer GitLab- oder GitHub-Pipeline. Feste Exit-Codes sagen deinem Skript, was schiefging.
Anmelden ohne login
In der CI setzt du den Zugangscode als geschützte Variable GOODDEPLOY_TOKEN. gooddeploy nimmt ihn dann statt der Datei aus gooddeploy login.
| Variable | Wirkung |
|---|---|
GOODDEPLOY_TOKEN | Zugangscode (Vorrang vor der gespeicherten Anmeldung) |
GOODDEPLOY_PROJECT | Projekt, wenn du nicht --project angibst |
GOODDEPLOY_API_URL | andere API-Adresse (nur, wenn goodDEV dir eine nennt) |
GOODDEPLOY_NO_UPDATE_CHECK=1 | kein Hinweis auf neue Versionen (in der CI mit CI=true ohnehin aus) |
NO_COLOR=1 | keine Farben in der Ausgabe |
GOODDEPLOY_DEBUG=1 | zur Fehlersuche: jeden Aufruf der API (ohne Zugangscode) und bei einem Absturz die Details auf der Fehlerausgabe zeigen |
Farben (grünes ✓, rotes ✗) gibt es nur, wenn gooddeploy direkt ins Terminal schreibt. Leitest du die Ausgabe in eine Datei oder ein anderes Programm um oder nutzt du --json, kommt sie ohne Farben und ohne mitlaufende Fortschrittszeile.
Gib dem Zugangscode in der CI nur die Rechte, die die Pipeline braucht, z. B. read und deploy für Previews (siehe Rechte).
Ohne Rückfragen
Ohne Terminal fragt gooddeploy nie nach, sondern bricht mit Exit-Code 1 ab und sagt, welche Option fehlt:
| Befehl | ohne Rückfrage |
|---|---|
promote | --yes |
rm | --yes |
projects rm | --yes --confirm <projektname> |
protect --env … | --user <name> --password-stdin, Passwort als erste Zeile auf der Standardeingabe |
login | --email <adresse>, --token <code> oder Code auf der Standardeingabe (in der CI besser GOODDEPLOY_TOKEN); ohne alles Fehler mit Exit-Code 1 |
deploy | ein Projekt, das es schon gibt (--project, GOODDEPLOY_PROJECT oder .gooddeploy/project.json) |
link | link <name>; ein neues Projekt nur mit --yes (Postgres zusätzlich mit --postgres) |
env add | Wert auf der Standardeingabe, z. B. printf '%s' "$WERT" | gooddeploy env add NAME; mit --apply --production zusätzlich --yes, sonst nur der Hinweis auf promote |
env pull | --yes, falls .env.local schon existiert |
rollback fragt nie nach. Ein unbekanntes Projekt legen deploy und link ohne Terminal nie nebenbei an: Sie enden mit NOT_FOUND (Exit-Code 1) und dem Hinweis auf gooddeploy link <name>. Lege neue Projekte deshalb einmal im Terminal an oder im Skript mit gooddeploy link <name> --yes.
Beispiel für eine Pipeline, die jeden Commit als Preview baut und main live schaltet. link --yes verknüpft den frischen Checkout und legt das Projekt beim ersten Lauf an. deploy findet das Projekt danach auch ohne --project; gibst du --project oder GOODDEPLOY_PROJECT an, muss es dasselbe Projekt sein wie bei link:
gooddeploy link kunde-website --yes
gooddeploy deploy --project kunde-website --json > deploy.ndjson
if [ "$CI_COMMIT_BRANCH" = "main" ]; then
gooddeploy promote --project kunde-website --yes --wait
fi
Eigene Prüfungen, etwa E2E-Tests gegen die Preview, meldet die Pipeline mit gooddeploy checks report <id> <name> success|failure an das Deployment (siehe Logs, Checks und Datenbank; kommt später).
promote ohne ID nimmt die neueste Preview des Projekts. Laufen mehrere Pipelines parallel, gib die ID aus dem Deploy mit (Feld deployment.shortId im Ergebnis).
Ausgabe im Terminal, in Pipes und in der CI
Im Terminal zeigt gooddeploy Farben, Kästen, Etiketten und während längerer Schritte einen Spinner mit der laufenden Zeit. Das stellt es selbst um, ohne Einstellung:
| Lage | Ausgabe |
|---|---|
| Terminal ab 80 Spalten | mit Kästen, Etiketten, Spinner und Farben |
| Terminal schmaler als 80 Spalten | ohne Kästen und Spinner, mit Farben |
Pipe oder Datei (gooddeploy deploy | tee log.txt) | ohne Kästen, Spinner und Farben; jede Zeile einmal, das Build-Log vollständig |
CI (Variable CI gesetzt) | wie in einer Pipe |
NO_COLOR gesetzt | ohne Farben; Kästen und Spinner bleiben im Terminal |
FORCE_COLOR gesetzt | mit Farben auch in der CI oder in einer Pipe (ohne Kästen und Spinner); NO_COLOR gewinnt |
TERM=dumb | wie in einer Pipe |
Terminal ohne UTF-8 (z. B. LANG=C) | Zeichen und Rahmen aus ASCII (+ statt ✓, x statt ✗) |
--json | nur JSON, nie Farben oder Steuerzeichen |
Nichts ist nur an der Farbe zu erkennen: Zeichen (✓, ✗, ●) und Wörter tragen die Bedeutung. In iTerm2, WezTerm, VS Code und einigen anderen Terminals sind Adressen anklickbar. Fehler nennen immer ihren Code und den Exit-Code (Code SCOPE_MISSING · Exit 3).
Ausgabe mit --json
Mit --json (vor oder nach dem Befehl) schreibt gooddeploy eine JSON-Zeile je Ereignis auf die Standardausgabe (NDJSON) und keine Fortschrittszeilen für Menschen.
status,ls,whoami,logout,link,inspect(ohne--wait),protect,rm,projects rm,update,launch,open,version: genau eine Zeile mit dem Ergebnis.versionliefertversion(mit Commit in Klammern, wie bisher) und zusätzlich das Feldcommit.loginmit Zugangscode: eine Zeile;login --email: zuerst{"event":"device","userCode":…}mit dem Code für die Bestätigungsseite, dann das Ergebnis mituserEmailundexpiresAt.inspect --wait: Zustandswechsel wie beideploy, zuletzt{"deployment":…}, bei einem Fehler mit Felderror.deploy: zuerst{"event":"uploaded",…}, dann je Zustandswechsel{"event":"state","id":…,"state":…,"from":…,"elapsedMs":…,"phaseMs":…}, zuletzt{"event":"result",…}mitstatus,deployment,previewUrlunddurationMs; bei einem gescheiterten Build zusätzlichlogTailmit den letzten Zeilen des Build-Logs, soweit die Plattform es liefert. Mit--json --streamkommen dazwischen auch die Ereignisse der Plattform, erkennbar am Feldtypestattevent:log(Zeile im Build-Log),phase,checkundstatus(kommt später; bis dahin gibt es nur die Zeilen mitevent).env add: je Umgebung{"event":"env",…}mitvariable(ohne Wert),warningsund bei--applydeployment;env rm: je Umgebung{"event":"env-removed",…};env lsundenv pull: eine Zeile, nie mit Werten.logs: je Log-Zeile ein Objekt mitline,node,streamundat.checks report,db info,db dump: eine Zeile mit dem Ergebnis.promoteundrollback: Zustandswechsel wie oben, mit--waitzusätzlich{"event":"live",…}, sobald die Version live ist, und zuletzt{"event":"result",…}mitliveUrls,productionUrl,liveAfterMsundfrom(die vorherige Live-Version).
Die letzte Zeile ist immer das Ergebnis, auch bei Fehlern. Scheitert ein Deploy, Promote oder Rollback, enthält das result ein Feld error. Andere Fehler kommen als:
{"error":{"code":"SCOPE_MISSING","message":"Recht \"deploy\" für Projekt kunde-website fehlt.","hint":"…","requestId":"req_…"}}
Ohne --json stehen Fehler als ✗ Meldung mit → Hinweis auf der Fehlerausgabe. Die requestId hilft goodDEV, einen Fehler schnell zu finden; gib sie bei Rückfragen mit an.
Meldet die Plattform einen gescheiterten Deploy, Promote oder Rollback ausnahmsweise ohne Fehlercode, endet gooddeploy trotzdem nie mit 0. Auch ein Absturz von gooddeploy selbst endet mit INTERNAL und Exit-Code 6, ohne technische Details; die zeigt GOODDEPLOY_DEBUG=1.
Exit-Codes
| Exit-Code | Bedeutung | Fehlercodes |
|---|---|---|
| 0 | alles in Ordnung | – |
| 1 | Aufruf oder Eingabe falsch (auch fehlende Bestätigung ohne Terminal) | NOT_FOUND, VALIDATION_FAILED, ARCHIVE_TOO_LARGE, CONFIG_INVALID |
| 2 | Git-Zustand oder Upload abgelehnt | GIT_DIRTY, NOT_GIT_REPO, GIT_SUBMODULES, GIT_LFS, ARCHIVE_REJECTED, TREE_MISMATCH |
| 3 | Anmeldung oder Recht fehlt | UNAUTHENTICATED, SCOPE_MISSING, LOGIN_CODE_INVALID, LOGIN_LINK_EXPIRED, LOGIN_LINK_USED |
| 4 | Build fehlgeschlagen | BUILD_FAILED, BUILD_TIMEOUT, BUILD_OUTPUT_MISSING, BUILD_NOT_ALLOWED, BUILDPACK_UNSUPPORTED, BUILDPACK_UNKNOWN, STATIC_INDEX_MISSING, SECRET_IN_IMAGE |
| 5 | Prüfung rot oder Vorgang abgelehnt (z. B. Promote, Rollback, rm) | DEPLOYMENT_NOT_READY, CHECK_FAILED, VERIFY_FAILED_ROLLED_BACK, PROMOTE_IN_PROGRESS, ROLLBACK_TARGET_UNAVAILABLE, DEPLOYMENT_IS_PRODUCTION, DEPLOYMENT_IN_PROGRESS, REQUIRED_CHECK_MISSING, REQUIRED_CHECK_FAILED, BUILD_ENV_MISMATCH, BUILD_ENV_CHANGED |
| 6 | Plattform nicht erreichbar, CLI zu alt oder Fehler auf unserer Seite | PLATFORM_UNAVAILABLE, CLI_TOO_OLD, RATE_LIMITED, INTERNAL, CONCURRENT_MODIFICATION, INVALID_TRANSITION, HOST_OWNED_BY_OTHER_PROJECT, SLOT_POOL_EXHAUSTED, AGENT_PROTOCOL_ERROR, ROLE_NOT_ALLOWED |
Ein unbekannter Fehlercode (etwa von einer neueren Plattform) endet ebenfalls mit 6. Pflicht-Checks (REQUIRED_CHECK_…), Build-Variablen (BUILD_ENV_…), Projekteinstellungen (CONFIG_INVALID), die Prüfung auf Geheimnisse im Build (SECRET_IN_IMAGE) und die Anmeldung per Link (LOGIN_LINK_…, LOGIN_CODE_INVALID) kommen später; die Codes sind schon festgelegt, damit Skripte stabil bleiben. Was die einzelnen Codes bedeuten und was du tun kannst, steht unter Häufige Fehler.