feat(backend): /info meldet die Taiga-Web-Basis für Ticket-Links (D91)
WERKBAUM_TAIGA_WEB_URL (das Taiga-Frontend, nicht aus der API-URL ableitbar) kommt als taigaWeb in GET /api/v1/info — ohne Schrägstrich am Ende, fehlt unkonfiguriert. deploy-backend.sh zieht die Zeile aus der lokalen .env idempotent in die Server-Umgebung nach. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
83eb6ff77f
commit
55cade1a65
@@ -46,3 +46,6 @@ BACKEND_SSH=mih00@mih00.hostsharing.net
|
|||||||
# WERKBAUM_TAIGA_API_URL in die Server-Umgebung (<BACKEND_DIR>/env) nach.
|
# WERKBAUM_TAIGA_API_URL in die Server-Umgebung (<BACKEND_DIR>/env) nach.
|
||||||
# Fehlt sie, bleibt das Feature aus und die Server-Zeile unangetastet.
|
# Fehlt sie, bleibt das Feature aus und die Server-Zeile unangetastet.
|
||||||
#TAIGA_API_URL=https://plan-api.hostsharing.net/api/v1
|
#TAIGA_API_URL=https://plan-api.hostsharing.net/api/v1
|
||||||
|
# Basis-URL des Taiga-FRONTENDS (nicht aus der API-URL ableitbar) — nur für
|
||||||
|
# die Ticket-Links des Editors (Strg+Klick öffnet #US-123 in Taiga).
|
||||||
|
#TAIGA_WEB_URL=https://plan.hostsharing.net
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ class DocumentsController(
|
|||||||
// Feature-Meldung des Taiga-Proxys (D91): Der Editor zeigt die
|
// Feature-Meldung des Taiga-Proxys (D91): Der Editor zeigt die
|
||||||
// Ticket-Aktionen nur, wo ein konfiguriertes Backend antwortet.
|
// Ticket-Aktionen nur, wo ein konfiguriertes Backend antwortet.
|
||||||
taiga = taigaProperties.configured,
|
taiga = taigaProperties.configured,
|
||||||
|
// Für die Ticket-Links des Editors (D91-Nachtrag 5); ohne
|
||||||
|
// abschließenden Schrägstrich, damit der Client schlicht anhängt.
|
||||||
|
taigaWeb = taigaProperties.webUrl.trimEnd('/').ifBlank { null },
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,15 @@ data class TaigaProperties(
|
|||||||
*/
|
*/
|
||||||
val apiUrl: String = "",
|
val apiUrl: String = "",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basis-URL des Taiga-**Frontends** (`https://plan.hostsharing.net`) —
|
||||||
|
* nicht aus der API-URL ableitbar, bei der Zielinstanz liegen beide auf
|
||||||
|
* verschiedenen Hosts. Nur für die Links des Editors (`GET /info` meldet
|
||||||
|
* sie als `taigaWeb`); leer heißt: keine Links, die Anlage funktioniert
|
||||||
|
* trotzdem.
|
||||||
|
*/
|
||||||
|
val webUrl: String = "",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login-Typ für `POST /auth`: `ldap` (LDAP-Plugin, so die Zielinstanz)
|
* Login-Typ für `POST /auth`: `ldap` (LDAP-Plugin, so die Zielinstanz)
|
||||||
* oder `normal`. Nur der Auth-Endpunkt braucht ihn; bei der angekündigten
|
* oder `normal`. Nur der Auth-Endpunkt braucht ihn; bei der angekündigten
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ werkbaum:
|
|||||||
# bei der Zielinstanz z. B. https://plan-api.hostsharing.net/api/v1
|
# bei der Zielinstanz z. B. https://plan-api.hostsharing.net/api/v1
|
||||||
taiga:
|
taiga:
|
||||||
api-url: ${WERKBAUM_TAIGA_API_URL:}
|
api-url: ${WERKBAUM_TAIGA_API_URL:}
|
||||||
|
# Basis-URL des Taiga-FRONTENDS (z. B. https://plan.hostsharing.net) -
|
||||||
|
# nicht aus der API-URL ableitbar. Nur fuer die Ticket-Links des Editors.
|
||||||
|
web-url: ${WERKBAUM_TAIGA_WEB_URL:}
|
||||||
# Login-Typ der Instanz fuer POST /taiga/auth: "ldap" (LDAP-Plugin,
|
# Login-Typ der Instanz fuer POST /taiga/auth: "ldap" (LDAP-Plugin,
|
||||||
# plan.hostsharing.net) oder "normal".
|
# plan.hostsharing.net) oder "normal".
|
||||||
auth-type: ${WERKBAUM_TAIGA_AUTH_TYPE:ldap}
|
auth-type: ${WERKBAUM_TAIGA_AUTH_TYPE:ldap}
|
||||||
|
|||||||
@@ -872,6 +872,14 @@ components:
|
|||||||
true, wenn eine Taiga-Instanz konfiguriert ist
|
true, wenn eine Taiga-Instanz konfiguriert ist
|
||||||
(`werkbaum.taiga.api-url`) - der Editor zeigt die Ticket-Aktionen
|
(`werkbaum.taiga.api-url`) - der Editor zeigt die Ticket-Aktionen
|
||||||
im Knoten-Fenster nur dann (D91).
|
im Knoten-Fenster nur dann (D91).
|
||||||
|
taigaWeb:
|
||||||
|
type: string
|
||||||
|
description: >
|
||||||
|
Basis-URL des Taiga-Frontends (`werkbaum.taiga.web-url`), ohne
|
||||||
|
abschliessenden Schraegstrich - der Editor baut daraus die Links
|
||||||
|
zum Oeffnen einer Ticket-Referenz
|
||||||
|
(`<web>/project/<slug>/us/<ref>` bzw. `.../task/<ref>`).
|
||||||
|
Fehlt, wenn nicht konfiguriert; das Oeffnen entfaellt dann.
|
||||||
|
|
||||||
TaigaAuthRequest:
|
TaigaAuthRequest:
|
||||||
type: object
|
type: object
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ class TaigaApiTest {
|
|||||||
val result = client.get().uri("/api/v1/info").exchange().returnResult(String::class.java)
|
val result = client.get().uri("/api/v1/info").exchange().returnResult(String::class.java)
|
||||||
result.status.value() shouldBe 200
|
result.status.value() shouldBe 200
|
||||||
result.responseBody!! shouldContain "\"taiga\":true"
|
result.responseBody!! shouldContain "\"taiga\":true"
|
||||||
|
// Die Web-Basis für die Ticket-Links (D91-Nachtrag 5) — ohne den
|
||||||
|
// konfigurierten Schrägstrich am Ende.
|
||||||
|
result.responseBody!! shouldContain "\"taigaWeb\":\"https://plan.example.test\""
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -154,6 +157,8 @@ class TaigaApiTest {
|
|||||||
fun taigaUrl(registry: DynamicPropertyRegistry) {
|
fun taigaUrl(registry: DynamicPropertyRegistry) {
|
||||||
startStub()
|
startStub()
|
||||||
registry.add("werkbaum.taiga.api-url") { "http://127.0.0.1:${stub.address.port}/api/v1" }
|
registry.add("werkbaum.taiga.api-url") { "http://127.0.0.1:${stub.address.port}/api/v1" }
|
||||||
|
// Mit abschließendem Schrägstrich — /info muss ihn abstreifen.
|
||||||
|
registry.add("werkbaum.taiga.web-url") { "https://plan.example.test/" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package de.werkbaum.api
|
|||||||
|
|
||||||
import io.kotest.matchers.shouldBe
|
import io.kotest.matchers.shouldBe
|
||||||
import io.kotest.matchers.string.shouldContain
|
import io.kotest.matchers.string.shouldContain
|
||||||
|
import io.kotest.matchers.string.shouldNotContain
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient
|
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient
|
||||||
@@ -36,6 +37,9 @@ class TaigaDisabledTest {
|
|||||||
val result = client.get().uri("/api/v1/info").exchange().returnResult(String::class.java)
|
val result = client.get().uri("/api/v1/info").exchange().returnResult(String::class.java)
|
||||||
result.status.value() shouldBe 200
|
result.status.value() shouldBe 200
|
||||||
result.responseBody!! shouldContain "\"taiga\":false"
|
result.responseBody!! shouldContain "\"taiga\":false"
|
||||||
|
// Ohne konfigurierte Web-Basis gibt es keine Ticket-Links — und keine
|
||||||
|
// leere Zeichenkette, an die ein Client Pfade anhängen könnte.
|
||||||
|
result.responseBody!! shouldNotContain "\"taigaWeb\":\""
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -74,9 +74,11 @@ DIR="$(env_value BACKEND_DIR)"; DIR="${DIR:-opt/werkbaum}"
|
|||||||
JDK_DIR="$(env_value BACKEND_JDK_DIR)"; JDK_DIR="${JDK_DIR:-opt/jdk21}"
|
JDK_DIR="$(env_value BACKEND_JDK_DIR)"; JDK_DIR="${JDK_DIR:-opt/jdk21}"
|
||||||
PORT="$(env_value BACKEND_PORT)"; PORT="${PORT:-9080}"
|
PORT="$(env_value BACKEND_PORT)"; PORT="${PORT:-9080}"
|
||||||
XMX="$(env_value BACKEND_XMX)"; XMX="${XMX:-192m}"
|
XMX="$(env_value BACKEND_XMX)"; XMX="${XMX:-192m}"
|
||||||
# Taiga-Proxy (D91): API-URL aus der lokalen .env; der Deploy zieht sie als
|
# Taiga-Proxy (D91): API- und Web-URL aus der lokalen .env; der Deploy zieht
|
||||||
# WERKBAUM_TAIGA_API_URL in die Server-Umgebung nach (leer = nichts anfassen).
|
# sie als WERKBAUM_TAIGA_API_URL / WERKBAUM_TAIGA_WEB_URL in die
|
||||||
|
# Server-Umgebung nach (leer = nichts anfassen).
|
||||||
TAIGA_API_URL="$(env_value TAIGA_API_URL)"
|
TAIGA_API_URL="$(env_value TAIGA_API_URL)"
|
||||||
|
TAIGA_WEB_URL="$(env_value TAIGA_WEB_URL)"
|
||||||
|
|
||||||
# Derselbe Pfad in DREI Schreibweisen, weil ihn drei Werkzeuge lesen:
|
# Derselbe Pfad in DREI Schreibweisen, weil ihn drei Werkzeuge lesen:
|
||||||
#
|
#
|
||||||
@@ -150,7 +152,7 @@ ssh "$SSH_TARGET" "mkdir -p \"$DIR_SH\" \"\$HOME/.config/systemd/user\""
|
|||||||
rsync -az --chmod=F644 "$STAGE/werkbaum-backend.service" \
|
rsync -az --chmod=F644 "$STAGE/werkbaum-backend.service" \
|
||||||
"$SSH_TARGET:~/.config/systemd/user/werkbaum-backend.service"
|
"$SSH_TARGET:~/.config/systemd/user/werkbaum-backend.service"
|
||||||
|
|
||||||
ssh "$SSH_TARGET" DIR="$DIR_SH" PORT="$PORT" RESTART="$RESTART" TAIGA_URL="$TAIGA_API_URL" 'bash -s' <<'REMOTE'
|
ssh "$SSH_TARGET" DIR="$DIR_SH" PORT="$PORT" RESTART="$RESTART" TAIGA_URL="$TAIGA_API_URL" TAIGA_WEB="$TAIGA_WEB_URL" 'bash -s' <<'REMOTE'
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
DIR="$(eval echo "$DIR")"
|
DIR="$(eval echo "$DIR")"
|
||||||
|
|
||||||
@@ -184,6 +186,8 @@ WERKBAUM_MASTER_PASSWORD_HASH=
|
|||||||
# Zielinstanz liegt sie auf einem eigenen Host. Leer = Feature aus;
|
# Zielinstanz liegt sie auf einem eigenen Host. Leer = Feature aus;
|
||||||
# GET /api/v1/info meldet es (taiga).
|
# GET /api/v1/info meldet es (taiga).
|
||||||
#WERKBAUM_TAIGA_API_URL=https://plan-api.hostsharing.net/api/v1
|
#WERKBAUM_TAIGA_API_URL=https://plan-api.hostsharing.net/api/v1
|
||||||
|
# Basis-URL des Taiga-FRONTENDS — nur fuer die Ticket-Links des Editors.
|
||||||
|
#WERKBAUM_TAIGA_WEB_URL=https://plan.hostsharing.net
|
||||||
ENV
|
ENV
|
||||||
chmod 600 "$DIR/env"
|
chmod 600 "$DIR/env"
|
||||||
echo " ! $DIR/env angelegt — Master-Passwort-Hash dort eintragen,"
|
echo " ! $DIR/env angelegt — Master-Passwort-Hash dort eintragen,"
|
||||||
@@ -203,6 +207,14 @@ if [ -n "${TAIGA_URL:-}" ]; then
|
|||||||
fi
|
fi
|
||||||
echo " WERKBAUM_TAIGA_API_URL -> ${TAIGA_URL}"
|
echo " WERKBAUM_TAIGA_API_URL -> ${TAIGA_URL}"
|
||||||
fi
|
fi
|
||||||
|
if [ -n "${TAIGA_WEB:-}" ]; then
|
||||||
|
if grep -q '^WERKBAUM_TAIGA_WEB_URL=' "$DIR/env"; then
|
||||||
|
sed -i "s#^WERKBAUM_TAIGA_WEB_URL=.*#WERKBAUM_TAIGA_WEB_URL=${TAIGA_WEB}#" "$DIR/env"
|
||||||
|
else
|
||||||
|
printf 'WERKBAUM_TAIGA_WEB_URL=%s\n' "$TAIGA_WEB" >> "$DIR/env"
|
||||||
|
fi
|
||||||
|
echo " WERKBAUM_TAIGA_WEB_URL -> ${TAIGA_WEB}"
|
||||||
|
fi
|
||||||
|
|
||||||
if ! loginctl show-user "$(id -un)" -p Linger 2>/dev/null | grep -q 'Linger=yes'; then
|
if ! loginctl show-user "$(id -un)" -p Linger 2>/dev/null | grep -q 'Linger=yes'; then
|
||||||
echo " ! Linger ist nicht gesetzt — der Dienst endet mit der Sitzung."
|
echo " ! Linger ist nicht gesetzt — der Dienst endet mit der Sitzung."
|
||||||
|
|||||||
Reference in New Issue
Block a user