fix(testkit): Remote-Testen, das wirklich traegt - vier Fehler und ein Weg
Die Testwege waren beschrieben, aber nicht begehbar. Auf der Test-VM lag die Anleitung vom 26.08. ohne das gesamte Testkit-Kapitel, ein Laufzeit-Token ohne Rechte, und ein Testkit, das 236 Zeilen aelter war als das ausgelieferte - beide meldeten 1.0.0. Deshalb sagte "doctor" dort "Bereit", waehrend nichts davon lauffaehig war. Vier Fehler, die beim Nachpruefen herauskamen: * doctor brach unter "set -e" wortlos ab. Der Rueckgabewert von version_lt wurde nicht aufgefangen - das beendet die Sitzung, sobald der Server neu genug ist (Rueckgabewert 1, also der Normalfall). Token und Projekt wurden nie geprueft. * Die Konfigurationsdatei ueberschrieb die Umgebung, genau umgekehrt zur dokumentierten Rangfolge. "DC_PROJECT=x dc-testkit report" meldete stillschweigend in das Projekt aus der Datei. * Der doctor-Bericht ging teils auf stderr. Ueber SSH werden beide Kanaele getrennt uebertragen und beim Aufrufer verschraenkt - die Befunde standen unter der falschen Ueberschrift. Genau so liest ein Pruefagent den Bericht. * "~/bin" liegt ueber SSH nicht im PATH: .profile wird nur von einer Login-Shell gelesen. Die Antwort war "Kommando nicht gefunden" - das sieht aus wie ein fehlgeschlagener Bezug und ist keiner. Neu im Testkit (1.1.0): * selfupdate mit --pruefen. Unterscheidet die Richtung: Eine neuere lokale Fassung ist ein Entwicklungsstand und kein Grund zum Update; der Rueckschritt wird verweigert (--force hebt es auf). Gleiche Nummer bei anderem Inhalt ist ein Befund, kein Achselzucken - genau daran ist es unbemerkt vorbeigelaufen. * doctor prueft den eigenen Stand, die Herkunft des Tokens, die fehlende Projektbindung, die Oberflaechenwerkzeuge und das eigene Display. * display start|stop|status und shot: der generische Teil des Verfahrens aus 5.8. Das sind die drei Stellen, an denen Eigenbau-Skripte danebengreifen - :0 statt eigenem Display, pkill ohne Nummer, Dateinamen ohne Projektpraefix. * DC_PROJECT_DIR: Das Werkbank-Token kommt aus der .mcp.json des Projekt-Repos, wo es fuer den MCP-Adapter ohnehin liegt. Kein zweiter Ablageort, der beim naechsten Wechsel vergessen wird. Fehlt die Datei, sagt das Testkit warum - sie ist gitignored und kommt ueber Git nie mit. dc-testkit-remote (neu): Der Agent laeuft auf dem Arbeitsplatz, der Testlauf auf der VM. Der Wrapper haelt das Token aus "ps aux" der geteilten Maschine (es geht ueber die Standardeingabe in die Umgebung), ruft bash -l, schuetzt die Argumente vor drei Ebenen Quoting und buendelt ganze Pruefplaene in eine Verbindung. Auf der VM wird keine Konfiguration mehr gelesen - was dort liegt, bleibt wirkungslos. Doku: TESTUMGEBUNG.md auf den Remote-Betrieb umgestellt, 4.2 auf den realen Ablageort der Token, neuer 4.8 "Ein Agent, der nur prueft", Belegung in 7 von der Maschine erhoben statt fortgeschrieben. Baustein E in der Prompt-Vorlage zieht die Rollengrenze, die serverseitig noch kein Recht zieht: bugtracker:manage erlaubt auch resolve. Richtiggestellt: Ein Token OHNE Projektbindung ist nicht eingeschraenkt, sondern uneingeschraenkt. Der Server leitet kein Heimatprojekt ab, also zaehlt jede Meldung als Heimmeldung - ohne Begruendungspflicht, ohne Deckelung auf medium, ohne triage_external, ohne reported_from. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
b4450c5f63
commit
60731c5104
+593
-30
@@ -15,14 +15,26 @@
|
||||
# war. Ein Weg, den alle nehmen, ist der einzige, dessen Fehler man findet.
|
||||
#
|
||||
# Abhaengigkeiten: curl und python3. Beides ist auf der VM vorhanden; jq wird
|
||||
# bewusst NICHT vorausgesetzt, weil es dort nicht installiert ist und eine
|
||||
# Installation nur fuer das Lesen von JSON die Maschine fuer alle veraendert.
|
||||
# bewusst NICHT vorausgesetzt. Inzwischen ist es dort zwar installiert - aber
|
||||
# das Skript soll auf einer frisch aufgesetzten Maschine sofort laufen, ohne
|
||||
# dass jemand sie erst fuer alle veraendert. Was vorausgesetzt wird, muss
|
||||
# ueberall gelten, nicht nur auf der einen Maschine, die man vor sich hat.
|
||||
#
|
||||
# Vollstaendige Anleitung: docs/TESTUMGEBUNG.md im Deploymentcenter-Repo.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
DC_TESTKIT_VERSION="1.0.0"
|
||||
# Fassung dieses Skripts. MUSS bei jeder Aenderung hochgezaehlt werden.
|
||||
#
|
||||
# Warum das eine Regel und keine Empfehlung ist: Das Skript liegt auf jeder
|
||||
# Testmaschine als Kopie. Bleibt die Zahl stehen, meldet eine Maschine mit dem
|
||||
# Stand von vorletzter Woche dieselbe Fassung wie eine frisch bezogene - und
|
||||
# niemand kann erkennen, warum derselbe Aufruf hier scheitert und dort nicht.
|
||||
# Genau so ist es passiert: doctor meldete auf einer Maschine "Bereit", waehrend
|
||||
# die ausgelieferte Fassung die fehlenden Rechte des Tokens laengst angemeckert
|
||||
# haette. Dieselbe Falle, in die vorher die Serverfassung getappt ist (2.0.0 in
|
||||
# der Konfiguration, waehrend 2.7.0 lief).
|
||||
DC_TESTKIT_VERSION="1.1.0"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Konfiguration
|
||||
@@ -35,11 +47,36 @@ DC_TESTKIT_VERSION="1.0.0"
|
||||
|
||||
CONFIG_FILE="${DC_TESTKIT_CONFIG:-$HOME/.config/dc-testkit/config}"
|
||||
|
||||
# Die Datei wird mit "." gelesen, ihre Zeilen sind also gewoehnliche
|
||||
# Zuweisungen - und die ueberschrieben, was in der Umgebung stand. Damit war
|
||||
# die Rangfolge oben genau verkehrt herum: "DC_PROJECT=x dc-testkit report"
|
||||
# meldete stillschweigend in das Projekt aus der Datei. Auf einer Maschine mit
|
||||
# mehreren Projekten ist das die teuerste Art von Fehler - es geht nichts
|
||||
# kaputt, es landet nur alles am falschen Ort, und niemand sieht es.
|
||||
#
|
||||
# Deshalb: vorher merken, was in der Umgebung stand, hinterher wieder
|
||||
# durchsetzen. Leere Werte zaehlen als "nicht gesetzt" - ein "DC_TOKEN=" in
|
||||
# der Umgebung soll das Token aus der Datei nicht loeschen.
|
||||
DC_KONFIGURIERBAR='DC_URL DC_TOKEN DC_PROJECT DC_CHANNEL DC_INSTANCE DC_DISPLAY
|
||||
DC_PROJECT_DIR DC_MIN_SERVER DC_TESTKIT_URL DC_TESTKIT_STATE'
|
||||
|
||||
for _dc_name in $DC_KONFIGURIERBAR; do
|
||||
printf -v "_dcenv_$_dc_name" '%s' "${!_dc_name-}"
|
||||
done
|
||||
|
||||
if [ -f "$CONFIG_FILE" ]; then
|
||||
# shellcheck disable=SC1090
|
||||
. "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
for _dc_name in $DC_KONFIGURIERBAR; do
|
||||
_dc_gemerkt="_dcenv_$_dc_name"
|
||||
if [ -n "${!_dc_gemerkt-}" ]; then
|
||||
printf -v "$_dc_name" '%s' "${!_dc_gemerkt}"
|
||||
fi
|
||||
done
|
||||
unset _dc_name _dc_gemerkt
|
||||
|
||||
DC_URL="${DC_URL:-https://dc.mhdf.de}"
|
||||
DC_URL="${DC_URL%/}"
|
||||
DC_PROJECT="${DC_PROJECT:-}"
|
||||
@@ -53,11 +90,35 @@ DC_CHANNEL="${DC_CHANNEL:-prod}"
|
||||
# doctor kannte sie nicht und meldete "Bereit" auf einem zu alten Server.
|
||||
DC_MIN_SERVER="${DC_MIN_SERVER:-2.6.1}"
|
||||
|
||||
# Bezugsquelle dieses Skripts. Daraus zieht doctor die ausgelieferte Fassung
|
||||
# und selfupdate den neuen Stand. Die Adresse haengt am DC_URL der Instanz:
|
||||
# Wer gegen die Testinstanz arbeitet, soll auch deren Testkit bekommen.
|
||||
DC_TESTKIT_URL="${DC_TESTKIT_URL:-$DC_URL/testkit/dc-testkit.sh}"
|
||||
|
||||
# Die Maschinenkennung entscheidet, welchen DEV-Schluessel der Server
|
||||
# heraussucht. Sie muss ueber Laeufe hinweg gleich bleiben - sonst sammelt sich
|
||||
# je Lauf ein weiterer Schluessel an, bis die Grenze je Projekt greift.
|
||||
DC_INSTANCE="${DC_INSTANCE:-$(hostname -s 2>/dev/null || hostname)}"
|
||||
|
||||
# Virtuelles Display dieses Projekts, fest vergeben (TESTUMGEBUNG.md 5.5).
|
||||
# Ohne Vorgabe: keines - dann bleibt die Oberflaechenpruefung ausgeschaltet,
|
||||
# statt sich eine Nummer zu nehmen. Genau das macht "xvfb-run -a", und es
|
||||
# beginnt bei :99, also auf der Nummer eines anderen Projekts.
|
||||
DC_DISPLAY="${DC_DISPLAY:-}"
|
||||
|
||||
# Verzeichnis des Projekt-Repos auf dieser Maschine. Ist es gesetzt und steht
|
||||
# kein DC_TOKEN fest, holt sich das Testkit das Werkbank-Token von dort - aus
|
||||
# der .mcp.json, in der es fuer den MCP-Adapter ohnehin schon liegt.
|
||||
#
|
||||
# Das ist der Ablageort, den die Projekte bereits benutzen: eine Datei je
|
||||
# Projekt, per .gitignore ausgeschlossen, mit dem Token in env.DC_TOKEN. Es ein
|
||||
# zweites Mal in ~/.config/dc-testkit zu hinterlegen hiesse, dasselbe Geheimnis
|
||||
# an zwei Orten zu pflegen - und beim naechsten Wechsel einen davon zu
|
||||
# vergessen. Genau das war auf der Test-VM passiert: In der Testkit-Konfiguration
|
||||
# lag noch ein altes Laufzeit-Token, waehrend das richtige Werkbank-Token im
|
||||
# Projekt langst ein anderes war.
|
||||
DC_PROJECT_DIR="${DC_PROJECT_DIR:-}"
|
||||
|
||||
STATE_ROOT="${DC_TESTKIT_STATE:-$HOME/.local/state/dc-testkit}"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -75,6 +136,13 @@ note() { printf '%s\n' "$*"; }
|
||||
step() { printf '%s==>%s %s\n' "$C_BLUE" "$C_RESET" "$*"; }
|
||||
ok() { printf '%s ok%s %s\n' "$C_GREEN" "$C_RESET" "$*"; }
|
||||
warn() { printf '%swarn%s %s\n' "$C_YELLOW" "$C_RESET" "$*" >&2; }
|
||||
|
||||
# Wie warn, aber auf stdout. Fuer doctor: Sein Bericht ist das Ergebnis des
|
||||
# Befehls, kein Fehlerkanal - das Ergebnis traegt der Rueckgabewert. Ueber SSH
|
||||
# werden stdout und stderr getrennt uebertragen und beim Aufrufer verschraenkt;
|
||||
# die Befunde standen dann unter der falschen Ueberschrift. Genau so liest ein
|
||||
# Pruefagent den Bericht - und ordnet die Zeile dem falschen Schritt zu.
|
||||
befund() { printf '%swarn%s %s\n' "$C_YELLOW" "$C_RESET" "$*"; }
|
||||
dim() { printf '%s%s%s\n' "$C_DIM" "$*" "$C_RESET"; }
|
||||
|
||||
die() {
|
||||
@@ -220,8 +288,83 @@ require_project() {
|
||||
[ -n "$DC_PROJECT" ] || die "Kein Projekt gesetzt. DC_PROJECT=<slug> oder --project <slug>."
|
||||
}
|
||||
|
||||
# Liest env.DC_TOKEN aus der .mcp.json eines Projektverzeichnisses.
|
||||
#
|
||||
# Gesucht wird an den ueblichen Stellen: im Verzeichnis selbst und eine Ebene
|
||||
# tiefer - Projekte legen die Datei mal neben die .sln, mal in den Unterordner
|
||||
# mit dem gleichnamigen Projekt. Ein Platzhalter wie ${DC_TOKEN} zaehlt nicht
|
||||
# als Token; sonst laeuft der Aufruf mit einer Zeichenkette los, die der Server
|
||||
# nur mit 401 beantworten kann.
|
||||
token_aus_projekt() {
|
||||
local wurzel="$1" datei
|
||||
|
||||
for datei in "$wurzel/.mcp.json" "$wurzel"/*/.mcp.json; do
|
||||
[ -f "$datei" ] || continue
|
||||
|
||||
python3 -c '
|
||||
import json, re, sys
|
||||
|
||||
try:
|
||||
with open(sys.argv[1], encoding="utf-8-sig") as fh:
|
||||
daten = json.load(fh)
|
||||
except Exception:
|
||||
sys.exit(1)
|
||||
|
||||
for server in (daten.get("mcpServers") or {}).values():
|
||||
tok = (server.get("env") or {}).get("DC_TOKEN")
|
||||
if isinstance(tok, str) and tok and not re.search(r"[$%<]", tok):
|
||||
print(tok)
|
||||
sys.exit(0)
|
||||
|
||||
sys.exit(1)
|
||||
' "$datei" && return 0
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Wird einmal in main() aufgerufen, bevor irgendein Befehl laeuft - damit auch
|
||||
# doctor dasselbe Token sieht wie jeder andere Aufruf. Setzt DC_TOKEN_QUELLE
|
||||
# fuer die Auskunft: Wo etwas herkommt, gehoert zu einem Bericht dazu.
|
||||
DC_TOKEN_QUELLE=''
|
||||
|
||||
token_aufloesen() {
|
||||
if [ -n "$DC_TOKEN" ]; then
|
||||
DC_TOKEN_QUELLE="Konfiguration/Umgebung"
|
||||
return 0
|
||||
fi
|
||||
|
||||
[ -n "$DC_PROJECT_DIR" ] || return 0
|
||||
|
||||
DC_TOKEN="$(token_aus_projekt "$DC_PROJECT_DIR" || true)"
|
||||
[ -n "$DC_TOKEN" ] && DC_TOKEN_QUELLE="$DC_PROJECT_DIR/.mcp.json"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
require_token() {
|
||||
[ -n "$DC_TOKEN" ] || die "Kein Token gesetzt. DC_TOKEN in $CONFIG_FILE hinterlegen."
|
||||
[ -n "$DC_TOKEN" ] && return 0
|
||||
|
||||
# Die Meldung nennt beide Wege und sagt ausdruecklich, warum die Datei
|
||||
# fehlen KANN, ohne dass etwas kaputt ist. Ohne diesen Satz sucht der
|
||||
# Naechste den Fehler im Repo, im Netz oder in seinen Rechten - und findet
|
||||
# keinen, weil es keinen gibt.
|
||||
printf '%sFehler%s Kein Werkbank-Token.\n\n' "$C_RED" "$C_RESET" >&2
|
||||
|
||||
if [ -n "$DC_PROJECT_DIR" ]; then
|
||||
printf 'In %s liegt keine .mcp.json mit einem DC_TOKEN.\n\n' "$DC_PROJECT_DIR" >&2
|
||||
printf 'Das ist kein Fehler im Repo: .mcp.json ist per .gitignore ausgeschlossen\n' >&2
|
||||
printf 'und wird ueber Git NICHT mitgeliefert. Auf einer frisch geklonten\n' >&2
|
||||
printf 'Maschine fehlt sie deshalb immer.\n\n' >&2
|
||||
printf 'Das Dev-Agent-Token dieses Projekts muss von Hand hierher gebracht\n' >&2
|
||||
printf 'werden - es steht in der .mcp.json des Projekts auf dem Arbeitsplatz.\n' >&2
|
||||
else
|
||||
printf 'Zwei Wege, einer genuegt:\n\n' >&2
|
||||
printf ' DC_PROJECT_DIR=<pfad zum Projekt-Repo> - Token aus dessen .mcp.json\n' >&2
|
||||
printf ' DC_TOKEN=<token> in %s\n' "$CONFIG_FILE" >&2
|
||||
fi
|
||||
|
||||
exit 1
|
||||
}
|
||||
|
||||
state_dir() {
|
||||
@@ -294,6 +437,285 @@ has_scope() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Der eigene Stand
|
||||
#
|
||||
# Das Skript liegt auf jeder Testmaschine als Kopie und altert dort still vor
|
||||
# sich hin. Genau daran ist die Rechtepruefung in doctor einmal gescheitert:
|
||||
# Sie war laengst geschrieben, aber auf der Maschine lag der Stand von davor -
|
||||
# und weil beide dieselbe Fassung meldeten, sah es niemand.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Wo liegt dieses Skript wirklich? readlink loest einen Verweis in ~/bin auf -
|
||||
# sonst ersetzte selfupdate den Verweis und nicht die Datei dahinter.
|
||||
own_path() {
|
||||
local p="$0"
|
||||
|
||||
if command -v readlink >/dev/null 2>&1 && readlink -f "$p" >/dev/null 2>&1; then
|
||||
readlink -f "$p"
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$p" in
|
||||
/*) printf '%s\n' "$p" ;;
|
||||
*) printf '%s/%s\n' "$(pwd)" "$p" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Fassung aus einer Skriptdatei lesen - der eigenen oder einer bezogenen.
|
||||
testkit_version_of() {
|
||||
sed -n 's/^DC_TESTKIT_VERSION="\([^"]*\)".*/\1/p' "$1" | head -n 1
|
||||
}
|
||||
|
||||
# Holt das ausgelieferte Skript nach $1.
|
||||
# 0 = da und plausibel, 1 = Bezug fehlgeschlagen, 2 = das ist kein Testkit
|
||||
#
|
||||
# Der Plausibilitaetstest ist nicht ueberflaessig: Faellt die Adresse aus oder
|
||||
# steht dort eine Anmeldeseite, schriebe der Bezug eine HTML-Seite in die
|
||||
# Datei. Danach laesst sich nichts mehr aufrufen - auch nicht das selfupdate,
|
||||
# das den Schaden beheben koennte.
|
||||
fetch_testkit() {
|
||||
local ziel="$1"
|
||||
|
||||
curl -fsSL --max-time 60 "$DC_TESTKIT_URL" -o "$ziel" 2>/dev/null || return 1
|
||||
|
||||
head -n 1 "$ziel" | grep -q '^#!' || return 2
|
||||
grep -q '^DC_TESTKIT_VERSION=' "$ziel" || return 2
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
cmd_selfupdate() {
|
||||
local pruefen=0 erzwingen=0
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--pruefen|--check) pruefen=1 ;;
|
||||
--force) erzwingen=1 ;;
|
||||
*) die "Unbekannter Schalter: $1" ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
local ziel tmp neu rc=0
|
||||
ziel="$(own_path)"
|
||||
|
||||
step "Bezug von $DC_TESTKIT_URL"
|
||||
|
||||
# Die Zwischendatei muss neben dem Ziel liegen: nur im selben Dateisystem
|
||||
# ist das abschliessende mv ein Umbenennen und damit unteilbar. Ueber eine
|
||||
# Dateisystemgrenze hinweg kopiert mv Byte fuer Byte - und wer das Skript
|
||||
# in genau dem Moment aufruft, bekommt eine halbe Datei.
|
||||
tmp="$ziel.neu.$$"
|
||||
|
||||
fetch_testkit "$tmp" || rc=$?
|
||||
case $rc in
|
||||
1) rm -f "$tmp"; die "Bezug fehlgeschlagen - erreichbar? $DC_TESTKIT_URL" ;;
|
||||
2) rm -f "$tmp"; die "Dort liegt kein Testkit. Nichts veraendert." ;;
|
||||
esac
|
||||
|
||||
neu="$(testkit_version_of "$tmp")"
|
||||
|
||||
if cmp -s "$tmp" "$ziel"; then
|
||||
rm -f "$tmp"
|
||||
ok "bereits aktuell (${neu:-?})"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# In welche Richtung geht der Unterschied? Davon haengt alles Weitere ab -
|
||||
# der Rat genauso wie die Frage, ob ueberhaupt ersetzt werden darf. Eine
|
||||
# aeltere Fassung ueber eine neuere zu ziehen ist fast immer ein Versehen:
|
||||
# typisch der Fall, dass jemand im Repo am Skript arbeitet und dem Rat
|
||||
# "beheben mit selfupdate" folgt. Rueckgaengig machen laesst sich das
|
||||
# nicht, wenn die Aenderung noch nirgends sonst liegt.
|
||||
local abstieg=0
|
||||
version_lt "${neu:-0}" "$DC_TESTKIT_VERSION" || abstieg=$?
|
||||
|
||||
local gleiche_nummer=0
|
||||
[ "$DC_TESTKIT_VERSION" = "${neu:-}" ] && gleiche_nummer=1
|
||||
|
||||
if [ "$pruefen" = '1' ]; then
|
||||
rm -f "$tmp"
|
||||
|
||||
if [ "$gleiche_nummer" = '1' ]; then
|
||||
warn "gleiche Fassung ($DC_TESTKIT_VERSION), aber anderer Inhalt"
|
||||
note " Entweder ist diese Kopie von Hand geaendert worden, oder beim"
|
||||
note " Ausliefern wurde DC_TESTKIT_VERSION nicht hochgezaehlt."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$abstieg" = '0' ]; then
|
||||
ok "neuer als ausgeliefert ($DC_TESTKIT_VERSION > ${neu:-?}) - Entwicklungsstand"
|
||||
note " Kein selfupdate noetig; es holte die aeltere Fassung zurueck."
|
||||
return 0
|
||||
fi
|
||||
|
||||
warn "veraltet: hier laeuft $DC_TESTKIT_VERSION, ausgeliefert wird ${neu:-?}"
|
||||
note " Beziehen mit: dc-testkit selfupdate"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$erzwingen" != '1' ]; then
|
||||
if [ "$gleiche_nummer" = '1' ]; then
|
||||
rm -f "$tmp"
|
||||
warn "Gleiche Fassung ($DC_TESTKIT_VERSION), aber anderer Inhalt."
|
||||
die "Welche der beiden neuer ist, sagt hier nichts. Wenn du es weisst: --force"
|
||||
fi
|
||||
|
||||
if [ "$abstieg" = '0' ]; then
|
||||
rm -f "$tmp"
|
||||
warn "Ausgeliefert wird ${neu:-?} - hier laeuft bereits $DC_TESTKIT_VERSION."
|
||||
die "Das waere ein Rueckschritt. Wenn das gewollt ist: --force"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -w "$ziel" ]; then
|
||||
rm -f "$tmp"
|
||||
die "Nicht beschreibbar: $ziel"
|
||||
fi
|
||||
|
||||
chmod +x "$tmp" 2>/dev/null || true
|
||||
|
||||
# Eine Sicherung, bevor etwas ersetzt wird. Der Rueckweg muss ohne Netz
|
||||
# gehen: Wer sich gerade eine kaputte Fassung geholt hat, kann sie nicht
|
||||
# noch einmal herunterladen, um das rueckgaengig zu machen.
|
||||
cp -p "$ziel" "$ziel.vorher" 2>/dev/null || true
|
||||
|
||||
mv "$tmp" "$ziel"
|
||||
|
||||
ok "$DC_TESTKIT_VERSION -> ${neu:-?}"
|
||||
dim " Vorherige Fassung: $ziel.vorher"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Oberflaechenpruefung
|
||||
#
|
||||
# Der generische Teil des Verfahrens aus TESTUMGEBUNG.md 5.8: ein eigenes
|
||||
# Display starten, aufnehmen, wieder abraeumen. Was dazwischen geklickt wird,
|
||||
# bleibt projektspezifisch und gehoert nicht hierher.
|
||||
#
|
||||
# Warum ueberhaupt gekapselt: Drei Fehler wiederholen sich sonst in jedem
|
||||
# Eigenbau-Skript - DISPLAY nicht gesetzt (dann landet alles auf :0, dem
|
||||
# echten Desktop), "pkill Xvfb" ohne Nummer (das erschlaegt die Sitzungen der
|
||||
# anderen Projekte), und Dateinamen ohne Projektpraefix (zwei Laeufe
|
||||
# ueberschreiben sich gegenseitig die Aufnahmen).
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
require_display() {
|
||||
[ -n "$DC_DISPLAY" ] \
|
||||
|| die "Kein Display gesetzt. DC_DISPLAY=:<nr> in $CONFIG_FILE - die Nummer steht in TESTUMGEBUNG.md 7."
|
||||
|
||||
case "$DC_DISPLAY" in
|
||||
:0|:1)
|
||||
die "$DC_DISPLAY ist der echte Desktop bzw. der Anmeldebildschirm. Nimm die Nummer deines Projekts."
|
||||
;;
|
||||
:[0-9]*) ;;
|
||||
*) die "DC_DISPLAY muss die Form :<nr> haben, nicht \"$DC_DISPLAY\"." ;;
|
||||
esac
|
||||
}
|
||||
|
||||
display_nr() {
|
||||
printf '%s' "${DC_DISPLAY#:}"
|
||||
}
|
||||
|
||||
# Laeuft auf diesem Display ein Xvfb? 0 = ja.
|
||||
display_laeuft() {
|
||||
pgrep -f "Xvfb $DC_DISPLAY" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Gibt es den Socket, aber keinen Prozess? Dann ist die Nummer scheinbar
|
||||
# belegt und in Wahrheit frei - das Ueberbleibsel eines hart beendeten Xvfb.
|
||||
display_verwaist() {
|
||||
[ -e "/tmp/.X11-unix/X$(display_nr)" ] && ! display_laeuft
|
||||
}
|
||||
|
||||
cmd_display() {
|
||||
local aktion="${1:-status}"
|
||||
require_display
|
||||
|
||||
case "$aktion" in
|
||||
status)
|
||||
step "Display $DC_DISPLAY"
|
||||
if display_laeuft; then
|
||||
ok "belegt - $(pgrep -af "Xvfb $DC_DISPLAY" | head -1)"
|
||||
elif display_verwaist; then
|
||||
befund "verwaister Socket /tmp/.X11-unix/X$(display_nr) - kein Prozess dazu"
|
||||
note " Aufraeumen: sudo rm -f /tmp/.X11-unix/X$(display_nr)"
|
||||
return 1
|
||||
else
|
||||
ok "frei"
|
||||
fi
|
||||
|
||||
step "Belegt insgesamt"
|
||||
ls /tmp/.X11-unix/ 2>/dev/null | tr '\n' ' ' | sed 's/^/ Sockets: /'
|
||||
printf '\n'
|
||||
pgrep -af Xvfb 2>/dev/null | sed 's/^/ /' || note " kein Xvfb"
|
||||
;;
|
||||
|
||||
start)
|
||||
require_project
|
||||
local geometrie="${2:-1600x1000x24}"
|
||||
|
||||
if display_laeuft; then
|
||||
ok "Display $DC_DISPLAY laeuft bereits"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if display_verwaist; then
|
||||
die "Socket /tmp/.X11-unix/X$(display_nr) ohne Prozess. Erst aufraeumen (sudo rm -f), sonst startet Xvfb nicht."
|
||||
fi
|
||||
|
||||
command -v Xvfb >/dev/null 2>&1 || die "Xvfb ist nicht installiert."
|
||||
|
||||
step "Display $DC_DISPLAY starten ($geometrie)"
|
||||
Xvfb "$DC_DISPLAY" -screen 0 "$geometrie" >/dev/null 2>&1 &
|
||||
sleep 2
|
||||
|
||||
display_laeuft || die "Xvfb ist nicht hochgekommen. Ist $DC_DISPLAY anderweitig belegt?"
|
||||
ok "laeuft - in eigenen Aufrufen: export DISPLAY=$DC_DISPLAY"
|
||||
;;
|
||||
|
||||
stop)
|
||||
if ! display_laeuft; then
|
||||
ok "Display $DC_DISPLAY laeuft nicht"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Mit Nummer, nie ohne: "pkill Xvfb" beendet die Sitzungen aller
|
||||
# anderen Projekte auf dieser Maschine gleich mit.
|
||||
step "Display $DC_DISPLAY beenden"
|
||||
pkill -f "Xvfb $DC_DISPLAY" 2>/dev/null || true
|
||||
sleep 1
|
||||
display_laeuft && die "Xvfb auf $DC_DISPLAY laeuft weiter."
|
||||
ok "beendet"
|
||||
;;
|
||||
|
||||
*)
|
||||
die "Aufruf: dc-testkit display [status|start [BxHxT]|stop]"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
cmd_shot() {
|
||||
require_project
|
||||
require_display
|
||||
|
||||
local name="${1:-}"
|
||||
[ -n "$name" ] || die "Aufruf: dc-testkit shot <name> (z.B. dc-testkit shot 1_start)"
|
||||
|
||||
display_laeuft || die "Auf $DC_DISPLAY laeuft kein Xvfb. Erst: dc-testkit display start"
|
||||
command -v import >/dev/null 2>&1 || die "ImageMagick fehlt (import)."
|
||||
|
||||
# Projektpraefix ist Pflicht, nicht Geschmack: /tmp gehoert allen, und
|
||||
# /tmp/1_start.png ueberschreibt die Aufnahme des Nachbarprojekts.
|
||||
local ziel="/tmp/${DC_PROJECT}_${name}.png"
|
||||
|
||||
DISPLAY="$DC_DISPLAY" import -window root "$ziel" \
|
||||
|| die "Aufnahme fehlgeschlagen. Zeichnet auf $DC_DISPLAY ueberhaupt etwas?"
|
||||
|
||||
ok "$ziel"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# doctor - laeuft hier ueberhaupt etwas?
|
||||
#
|
||||
@@ -309,7 +731,7 @@ cmd_doctor() {
|
||||
if command -v "$tool" >/dev/null 2>&1; then
|
||||
ok "$tool $(command -v "$tool")"
|
||||
else
|
||||
warn "$tool fehlt - ohne das geht nichts"
|
||||
befund "$tool fehlt - ohne das geht nichts"
|
||||
failed=1
|
||||
fi
|
||||
done
|
||||
@@ -326,18 +748,24 @@ cmd_doctor() {
|
||||
# Server wirklich braucht, scheiterte danach mit "kennt
|
||||
# /api/license/v1/dev-key noch nicht".
|
||||
if [ -z "$server_version" ]; then
|
||||
warn "der Server nennt keine Fassung - $DC_MIN_SERVER nicht pruefbar"
|
||||
befund "der Server nennt keine Fassung - $DC_MIN_SERVER nicht pruefbar"
|
||||
else
|
||||
version_lt "$server_version" "$DC_MIN_SERVER"
|
||||
case $? in
|
||||
# Der Rueckgabewert MUSS mit || aufgefangen werden. Ohne das
|
||||
# beendet "set -e" das Skript, sobald version_lt etwas anderes als
|
||||
# 0 liefert - also ausgerechnet im Normalfall "Server ist neu
|
||||
# genug" (Rueckgabewert 1). doctor stieg dann wortlos nach der
|
||||
# Health-Pruefung aus, ohne Token und Projekt je anzusehen.
|
||||
local vergleich=0
|
||||
version_lt "$server_version" "$DC_MIN_SERVER" || vergleich=$?
|
||||
case $vergleich in
|
||||
0)
|
||||
warn "zu alt: $server_version - gebraucht wird mindestens $DC_MIN_SERVER"
|
||||
warn " Es fehlen: dc-testkit license (dev-key), der Bezug ueber /testkit/"
|
||||
warn " und die Rechtepruefung. Der Server muss deployt werden."
|
||||
befund "zu alt: $server_version - gebraucht wird mindestens $DC_MIN_SERVER"
|
||||
befund " Es fehlen: dc-testkit license (dev-key), der Bezug ueber /testkit/"
|
||||
befund " und die Rechtepruefung. Der Server muss deployt werden."
|
||||
failed=1
|
||||
;;
|
||||
2)
|
||||
warn "Fassung \"$server_version\" ist nicht auswertbar - $DC_MIN_SERVER ungeprueft"
|
||||
befund "Fassung \"$server_version\" ist nicht auswertbar - $DC_MIN_SERVER ungeprueft"
|
||||
;;
|
||||
*)
|
||||
ok "erfuellt die Mindestfassung $DC_MIN_SERVER"
|
||||
@@ -345,13 +773,75 @@ cmd_doctor() {
|
||||
esac
|
||||
fi
|
||||
else
|
||||
warn "nicht erreichbar: $(api_error)"
|
||||
befund "nicht erreichbar: $(api_error)"
|
||||
failed=1
|
||||
fi
|
||||
|
||||
# Der eigene Stand. Diese Pruefung gehoert VOR alles Weitere: Meldet ein
|
||||
# veraltetes Testkit "Bereit", ist jede folgende Zeile dieses Berichts
|
||||
# unter Vorbehalt - sie stammt aus einer Fassung, die niemand mehr liest.
|
||||
step "Dieses Testkit"
|
||||
dim " Fassung $DC_TESTKIT_VERSION - $(own_path)"
|
||||
|
||||
local tk_tmp tk_rc=0 tk_neu
|
||||
tk_tmp="${TMPDIR:-/tmp}/dc-testkit.pruefung.$$"
|
||||
|
||||
fetch_testkit "$tk_tmp" || tk_rc=$?
|
||||
if [ "$tk_rc" = '0' ]; then
|
||||
tk_neu="$(testkit_version_of "$tk_tmp")"
|
||||
if cmp -s "$tk_tmp" "$(own_path)"; then
|
||||
ok "aktuell - entspricht der ausgelieferten Fassung ${tk_neu:-?}"
|
||||
else
|
||||
# Drei verschiedene Lagen, und nur eine davon ruft nach selfupdate.
|
||||
# Sie zu verwechseln waere teuer: Wer im Repo am Skript arbeitet,
|
||||
# haette auf den Rat "beheben mit selfupdate" hin seine eigene,
|
||||
# noch nicht ausgelieferte Arbeit ueberschrieben.
|
||||
local tk_cmp=0
|
||||
version_lt "$DC_TESTKIT_VERSION" "${tk_neu:-0}" || tk_cmp=$?
|
||||
case $tk_cmp in
|
||||
0)
|
||||
befund "veraltet: hier laeuft $DC_TESTKIT_VERSION, ausgeliefert wird ${tk_neu:-?}"
|
||||
befund " Beheben mit: dc-testkit selfupdate"
|
||||
failed=1
|
||||
;;
|
||||
1)
|
||||
if [ "$DC_TESTKIT_VERSION" = "${tk_neu:-}" ]; then
|
||||
# Der stillste Fall und deshalb der gefaehrlichste:
|
||||
# gleiche Nummer, anderer Inhalt. Genau daran ist die
|
||||
# Rechtepruefung einmal unbemerkt vorbeigelaufen.
|
||||
befund "gleiche Fassung ($DC_TESTKIT_VERSION), aber anderer Inhalt"
|
||||
befund " Entweder ist diese Kopie von Hand geaendert worden, oder beim"
|
||||
befund " Ausliefern wurde DC_TESTKIT_VERSION nicht hochgezaehlt."
|
||||
failed=1
|
||||
else
|
||||
ok "neuer als ausgeliefert ($DC_TESTKIT_VERSION > ${tk_neu:-?}) - Entwicklungsstand"
|
||||
dim " Kein selfupdate: das holte die aeltere Fassung zurueck."
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
befund "Fassungen nicht vergleichbar: $DC_TESTKIT_VERSION / ${tk_neu:-?}"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
befund "ausgelieferte Fassung nicht abrufbar - der eigene Stand bleibt ungeprueft"
|
||||
dim " $DC_TESTKIT_URL"
|
||||
fi
|
||||
rm -f "$tk_tmp"
|
||||
|
||||
step "Token"
|
||||
if [ -z "$DC_TOKEN" ]; then
|
||||
warn "kein Token gesetzt (DC_TOKEN)"
|
||||
befund "kein Werkbank-Token"
|
||||
if [ -n "$DC_PROJECT_DIR" ]; then
|
||||
befund " In $DC_PROJECT_DIR liegt keine .mcp.json mit DC_TOKEN."
|
||||
befund " Das ist kein Fehler im Repo: .mcp.json ist per .gitignore"
|
||||
befund " ausgeschlossen und kommt ueber Git nicht mit. Auf einer frisch"
|
||||
befund " geklonten Maschine fehlt sie deshalb immer - das Token muss von"
|
||||
befund " Hand hierher, aus der .mcp.json des Projekts auf dem Arbeitsplatz."
|
||||
else
|
||||
befund " Entweder DC_PROJECT_DIR auf das Projekt-Repo zeigen lassen"
|
||||
befund " (Token aus dessen .mcp.json) oder DC_TOKEN in $CONFIG_FILE."
|
||||
fi
|
||||
failed=1
|
||||
elif api GET /api/tokens/v1/whoami; then
|
||||
# Fruehere Fassungen meldeten hier nur "gueltig - der Bugtracker
|
||||
@@ -367,23 +857,39 @@ cmd_doctor() {
|
||||
|
||||
ok "gueltig - \"$tok_name\", Besitzerart $tok_owner, Projekt ${tok_project:-keins}"
|
||||
dim " Rechte: $tok_scopes"
|
||||
dim " Herkunft: ${DC_TOKEN_QUELLE:-unbekannt}"
|
||||
|
||||
if [ "$tok_workbench" != 'true' ]; then
|
||||
warn "kein Werkbank-Token: Besitzerart ist $tok_owner, gebraucht wird dev_agent"
|
||||
warn " Ein Laufzeit-Token darf nicht in fremde Projekte melden (TESTUMGEBUNG.md 4.2)."
|
||||
befund "kein Werkbank-Token: Besitzerart ist $tok_owner, gebraucht wird dev_agent"
|
||||
befund " Ein Laufzeit-Token darf nicht in fremde Projekte melden (TESTUMGEBUNG.md 4.2)."
|
||||
failed=1
|
||||
fi
|
||||
|
||||
for want in bugtracker:manage license:dev updateservice:read; do
|
||||
if ! has_scope "$tok_scopes" "$want"; then
|
||||
warn "Recht fehlt: $want"
|
||||
befund "Recht fehlt: $want"
|
||||
failed=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$tok_project" ] && [ -n "$DC_PROJECT" ] && [ "$tok_project" != "$DC_PROJECT" ]; then
|
||||
warn "Token gehoert zu $tok_project, gearbeitet wird an $DC_PROJECT"
|
||||
warn " Je Projekt ein eigenes Token - sonst ist die Herkunft einer Meldung nicht mehr ablesbar."
|
||||
# Ein Token ohne Projektbindung rutschte hier bisher durch: geprueft
|
||||
# wurde nur, ob eine vorhandene Bindung zum Projekt passt. Genau so ein
|
||||
# Token lag auf der Test-VM - dev_agent, aber project_slug leer.
|
||||
#
|
||||
# Ohne Bindung ist das Token nicht eingeschraenkt, sondern
|
||||
# uneingeschraenkt: Der Server leitet kein Heimatprojekt ab, also ist
|
||||
# fuer ihn jede Meldung eine Heimmeldung. Damit faellt der ganze Schutz
|
||||
# fuer Fremdmeldungen weg - keine Begruendungspflicht, keine Deckelung
|
||||
# auf medium, kein Eingang in triage_external, kein reported_from.
|
||||
if [ -z "$tok_project" ]; then
|
||||
befund "Token ohne Projektbindung (project_slug ist leer)"
|
||||
befund " Damit zaehlt JEDE Meldung als Heimmeldung: ohne Begruendungspflicht,"
|
||||
befund " ohne Deckelung auf medium, direkt in die offene Liste des fremden"
|
||||
befund " Projekts - und ohne nachweisbare Herkunft. Im WebUI nachtragen."
|
||||
failed=1
|
||||
elif [ -n "$DC_PROJECT" ] && [ "$tok_project" != "$DC_PROJECT" ]; then
|
||||
befund "Token gehoert zu $tok_project, gearbeitet wird an $DC_PROJECT"
|
||||
befund " Je Projekt ein eigenes Token - sonst ist die Herkunft einer Meldung nicht mehr ablesbar."
|
||||
failed=1
|
||||
fi
|
||||
elif [ "$API_STATUS" = '404' ]; then
|
||||
@@ -391,38 +897,83 @@ cmd_doctor() {
|
||||
# der ausdrueckliche Hinweis, dass die Rechte ungeprueft sind. Still
|
||||
# "gueltig" zu melden waere genau der Fehler, der hier behoben wird.
|
||||
if api GET /api/bugtracker/v1/projects; then
|
||||
warn "gueltig, aber die Rechte sind ungeprueft"
|
||||
warn " /api/tokens/v1/whoami gibt es erst ab $DC_MIN_SERVER."
|
||||
befund "gueltig, aber die Rechte sind ungeprueft"
|
||||
befund " /api/tokens/v1/whoami gibt es erst ab $DC_MIN_SERVER."
|
||||
else
|
||||
warn "Token wird nicht angenommen: $(api_error)"
|
||||
befund "Token wird nicht angenommen: $(api_error)"
|
||||
failed=1
|
||||
fi
|
||||
else
|
||||
warn "Token wird nicht angenommen: $(api_error)"
|
||||
befund "Token wird nicht angenommen: $(api_error)"
|
||||
failed=1
|
||||
fi
|
||||
|
||||
step "Projekt"
|
||||
if [ -z "$DC_PROJECT" ]; then
|
||||
warn "kein Projekt gesetzt (DC_PROJECT)"
|
||||
befund "kein Projekt gesetzt (DC_PROJECT)"
|
||||
failed=1
|
||||
elif [ -z "$DC_TOKEN" ]; then
|
||||
# Ohne Token ist die Projektliste nicht abrufbar. Das stillschweigend
|
||||
# zu ueberspringen liesse den Eindruck entstehen, das Projekt sei
|
||||
# geprueft worden.
|
||||
warn "$DC_PROJECT nicht pruefbar - dafuer wird ein Token gebraucht"
|
||||
befund "$DC_PROJECT nicht pruefbar - dafuer wird ein Token gebraucht"
|
||||
elif api GET /api/bugtracker/v1/projects; then
|
||||
if printf '%s' "$API_BODY" | grep -q "\"$DC_PROJECT\""; then
|
||||
ok "$DC_PROJECT ist im Deploymentcenter bekannt"
|
||||
else
|
||||
warn "$DC_PROJECT kommt in der Projektliste nicht vor"
|
||||
befund "$DC_PROJECT kommt in der Projektliste nicht vor"
|
||||
failed=1
|
||||
fi
|
||||
else
|
||||
warn "Projektliste nicht abrufbar: $(api_error)"
|
||||
befund "Projektliste nicht abrufbar: $(api_error)"
|
||||
failed=1
|
||||
fi
|
||||
|
||||
# Die Oberflaechenpruefung ist der zweite Grund, warum es diese Maschine
|
||||
# gibt (5.8) - doctor sah sie bisher gar nicht an. Wer sie braucht, merkte
|
||||
# das Fehlen erst mitten im Lauf, mit einem "XOpenDisplay failed" statt
|
||||
# einer Auskunft.
|
||||
step "Oberflaechenpruefung"
|
||||
local gui_fehlt=''
|
||||
for tool in Xvfb xdotool import convert; do
|
||||
command -v "$tool" >/dev/null 2>&1 || gui_fehlt="$gui_fehlt $tool"
|
||||
done
|
||||
|
||||
if [ -n "$gui_fehlt" ]; then
|
||||
# Kein failed=1: Ein Projekt ohne Oberflaeche braucht davon nichts.
|
||||
# Ein Befund waere hier eine Falschmeldung - aber schweigen darf das
|
||||
# Werkzeug auch nicht.
|
||||
note " nicht moeglich, es fehlt:$gui_fehlt"
|
||||
note " Nur noetig, wenn dieses Projekt eine Oberflaeche hat."
|
||||
else
|
||||
ok "Xvfb, xdotool, ImageMagick vorhanden"
|
||||
fi
|
||||
|
||||
if [ -z "$DC_DISPLAY" ]; then
|
||||
dim " Kein DC_DISPLAY gesetzt - display/shot bleiben aus."
|
||||
dim " Die Nummer dieses Projekts steht in TESTUMGEBUNG.md 7."
|
||||
else
|
||||
case "$DC_DISPLAY" in
|
||||
:0|:1)
|
||||
befund "DC_DISPLAY=$DC_DISPLAY ist der echte Desktop bzw. der Anmeldebildschirm"
|
||||
befund " Darauf zu zeichnen stoert den Menschen, der dort arbeitet."
|
||||
failed=1
|
||||
;;
|
||||
*)
|
||||
if display_laeuft; then
|
||||
ok "Display $DC_DISPLAY - belegt (vermutlich von einem eigenen Lauf)"
|
||||
elif display_verwaist; then
|
||||
befund "Display $DC_DISPLAY - verwaister Socket, kein Prozess dazu"
|
||||
befund " Die Nummer wirkt belegt und ist frei. Aufraeumen:"
|
||||
befund " sudo rm -f /tmp/.X11-unix/X${DC_DISPLAY#:}"
|
||||
failed=1
|
||||
else
|
||||
ok "Display $DC_DISPLAY - frei"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
step "Arbeitsplatz"
|
||||
if [ -n "$DC_PROJECT" ]; then
|
||||
dim " Zustand: $(state_dir)"
|
||||
@@ -1254,7 +1805,8 @@ dc-testkit $DC_TESTKIT_VERSION - Testlaeufe gegen das Deploymentcenter
|
||||
dc-testkit [--project <slug>] [--channel <kanal>] [--url <adresse>] <befehl>
|
||||
|
||||
Einrichten und pruefen
|
||||
doctor Werkzeuge, Netz, Token und Projekt pruefen
|
||||
doctor Werkzeuge, Netz, eigener Stand, Token und Projekt
|
||||
selfupdate [--pruefen] Dieses Skript auf die ausgelieferte Fassung bringen
|
||||
license [--ttl N] [--print] [--revoke]
|
||||
DEV-Lizenzschluessel holen, verlaengern, zurueckgeben
|
||||
agent [--force] update-agent herunterladen, Pruefsumme abgleichen
|
||||
@@ -1281,6 +1833,10 @@ Bugtracker
|
||||
confirm <id> [notiz] "der Fix eines anderen traegt" -> schliesst
|
||||
unclaim <id> [grund] Uebernahme zurueckgeben
|
||||
|
||||
Oberflaeche pruefen (braucht DC_DISPLAY)
|
||||
display [status|start|stop] Eigenes virtuelles Display
|
||||
shot <name> Aufnahme nach /tmp/<projekt>_<name>.png
|
||||
|
||||
Aufraeumen
|
||||
cleanup [--sandbox] Sandkasten weg, Schluessel zurueckgeben
|
||||
|
||||
@@ -1288,7 +1844,9 @@ Schweregrade: idea, wishlist, low, medium, high, critical
|
||||
Typen: bug, feature ("idea" ist ein Schweregrad, kein Typ)
|
||||
|
||||
Konfiguration: $CONFIG_FILE
|
||||
DC_URL, DC_TOKEN, DC_PROJECT, DC_CHANNEL, DC_INSTANCE
|
||||
DC_URL, DC_TOKEN, DC_PROJECT, DC_CHANNEL, DC_INSTANCE, DC_DISPLAY
|
||||
DC_PROJECT_DIR - Projekt-Repo; ohne DC_TOKEN wird es aus dessen
|
||||
.mcp.json gelesen (env.DC_TOKEN)
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -1308,8 +1866,13 @@ main() {
|
||||
local command="${1:-}"
|
||||
[ $# -gt 0 ] && shift
|
||||
|
||||
token_aufloesen
|
||||
|
||||
case "$command" in
|
||||
doctor) cmd_doctor "$@" ;;
|
||||
selfupdate) cmd_selfupdate "$@" ;;
|
||||
display) cmd_display "$@" ;;
|
||||
shot) cmd_shot "$@" ;;
|
||||
license) cmd_license "$@" ;;
|
||||
agent) cmd_agent "$@" ;;
|
||||
check) cmd_check "$@" ;;
|
||||
|
||||
Reference in New Issue
Block a user