Files
tibi-svelte-starter/.agents/skills/deployment/SKILL.md
T
apairon 4020ad62c5 ✨ feat: enhance medialib image handling and add asset URL resolution
- Implemented `resolveApiAssetUrl` function to normalize asset URLs based on API base.
- Updated `MedialibImage` component to utilize new asset URL resolution and added support for alt text and class properties.
- Enhanced image loading behavior with improved width measurement and focal point handling.
- Added placeholder image handling and improved accessibility with alt text.
- Introduced new test script for auditing broken links in skill documentation.
- Expanded seeded test content to include medialib entries and updated related tests for pagebuilder previews.
- Improved global setup and teardown logging for clarity on seeded content management.
2026-05-17 00:52:41 +00:00

7.3 KiB
Raw Blame History

name, description
name description
deployment Production deployment setup for tibi-projects – Basispanel subdomain, .env, CI-Pipeline, Makefile. Use when deploying a new project to production or setting up a staging environment.

Deployment

Überblick

Ein tibi-Projekt wird per Gitea Actions CI gebaut und via rsync auf den Produktionsserver (dock4) deployed. Davor muss die Subdomain im Basispanel angelegt und der Kunde korrekt konfiguriert sein.

1. Basispanel – Subdomain anlegen

Kunde prüfen

# Domain des Kunden suchen
mcp_call(server="basispanel", tool="bp_list_domains", args={"search": "<kunde>"})
# → liefert Customer-ID, Domain-ID, Company, Username

Subdomain anlegen

# 1. Config holen (verfügbare Webserver + Storages sehen)
mcp_call(server="basispanel", tool="bp_get_config")

# 2. Subdomain erstellen (ohne Webserver)
mcp_call(server="basispanel", tool="bp_create_subdomain", args={
    "domainId": <domain-id>,
    "name": "<subdomain>",  # oder leer für bare domain
})

# 3. Löschen + neu mit Webserver (wenn Update nicht klappt)
mcp_call(server="basispanel", tool="bp_delete_subdomain", args={"id": <subdomain-id>})

mcp_call(server="basispanel", tool="bp_create_subdomain", args={
    "domainId": <domain-id>,
    "name": "<subdomain>",
    "webserverKey": "dock4_lamp2",
    "webserverStorage": "dock4_webroots2",
    "webserverSettings": {
        "redirectType": "docroot",
        "docroot": "/<subdomain>.<domain>/frontend",
        "gitbaseRepository": "<org>/<repo>",
        "deployRoot": "./..",
        "defaultAlias": "wwwAlias",
        "defaultSubdomain": "defaultSubdomain",
        "wwwRedirect": "wwwRedirect",
        "php": "phpDisabled",      # tibi-SPA kein PHP
        "https": "noHttps",        # erstmal aus, später aktivieren
        "certbot": "noCertbot",
    },
})

Wichtige Keys (aus bp_get_config):

Server Key Storage
dock4 dock4_lamp2 dock4_webroots2
dock1 dock1_... dock1_webroots...

Status prüfen

mcp_call(server="basispanel", tool="bp_get_subdomain_status", args={"id": <subdomain-id>})

Achtung: Health-Check zeigt DNS-Warnungen (externe Nameserver) – das ist normal solange der Kunde sein DNS selbst verwaltet.

2. .env konfigurieren

# Basis
PROJECT_NAME=<project>
TIBI_PREFIX=tibi
TIBI_NAMESPACE=<project>

# RSYNC für Deploy
RSYNC_HOST=ftp1.webmakers.de
RSYNC_PORT=22223
PRODUCTION_RSYNC_UID=100<customer-id>00    # z.B. 10051300
PRODUCTION_RSYNC_GID=33

# Production Server
PRODUCTION_SERVER=dock4.basehosts.de
PRODUCTION_TIBI_PREFIX=tibi
PRODUCTION_PATH=/webroots2/customers/<customer-id>/htdocs

# Staging
STAGING_PATH=/staging/<org>/<project>/dev

# URLs
LIVE_URL=http://<subdomain>.<domain>.dock4.basispanel.de   # Preview-URL
STAGING_URL=https://dev-<project>.staging.testversion.online
CODING_URL=https://<project>.code.testversion.online

3. CI-Pipeline (.gitea/workflows/deploy.yml)

name: deploy to production
on: "push"
jobs:
    deploy:
        steps:
            - checkout + git fetch --tags
            - node 22 + yarn install
            - yarn validate
            - ./scripts/ci-modify-config.sh # injiziert LIVE_URL, release, preview
            - yarn build # frontend
            - yarn build:server # SSR
            - sourcemaps → sentry
            - if dev-branch: ./scripts/ci-staging.sh
            - if master-branch: ./scripts/ci-deploy.sh

Wichtig: Das aktuelle Workflow-File führt yarn validate, yarn build und yarn build:server im CI aus. Wenn validate dort scheitert, behebe den eigentlichen Typ- oder Pfadfehler statt den Schritt stillschweigend zu entfernen.

4. Deploy-Skripte

scripts/ci-deploy.sh (Production)

  • Liest .env und api/config.yml.env
  • rsynct frontend/, api/, media/ via SSH zu RSYNC_HOST
  • deshalb muessen Collection-Dateiuploads auf den Repo-Root media/ zeigen, typischerweise via uploadPath: ../media/<collection> in api/collections/*.yml
  • api/media ist in diesem Setup nicht der persistente Deploy-Zielpfad fuer Uploads
  • Nutzt RSYNC_USER + RSYNC_PASS (aus Gitea Secrets)
  • Auf master: excludiert src/ und *.map
  • Reloadt den projektlokalen Proxy-Endpunkt via LIVE_URL/api/_/admin/reload mit Authorization: Bearer ${ADMIN_TOKEN}
  • Cleared SSR cache via LIVE_URL/api/ssr?clear=1

scripts/ci-staging.sh (Dev/Staging)

  • rsynct api/, frontend/dist, und frontend/assets nach /data/${{ github.repository }}/${{ github.ref_name }}
  • Startet docker-compose-staging.yml
  • Reloadt den projektlokalen Proxy-Endpunkt via STAGING_URL/api/_/admin/reload mit Authorization: Bearer ${ADMIN_TOKEN}

scripts/ci-modify-config.sh

  • Injiziert LIVE_URL als originURL in api/hooks/config-client.js
  • Injiziert LIVE_URL als PREVIEW_URL in api/config.yml.env
  • Setzt release + buildTime für Sentry
  • Kopiert frontend/spa.html → api/templates/spa.html (SSR-Template)
  • Ersetzt __TIMESTAMP__ in spa.html (Cache-Busting)

5. Makefile

Wichtige Targets:

# Media von Production syncen
media-sync-master-to-local:
    rsync -v -e "ssh ... -l $(PRODUCTION_RSYNC_UID),$(PRODUCTION_RSYNC_GID),$(PRODUCTION_PATH)/media" \
        -az $(RSYNC_HOST):/ media/

# MongoDB von Production syncen (via Chisel-Tunnel)
mongo-sync-master-to-local:
    chisel client --auth coder:$$PASSWORD http://$(PRODUCTION_SERVER):10987 27017:mongo:27017 &
    mongodump ... | mongorestore ...

6. DNS

Der Kunde verwaltet sein DNS selbst (externe Nameserver). Für die Subdomain muss ein A-Record gesetzt werden:

<subdomain>.<domain>  IN  A  45.129.180.102   (IP von dock4)

Die Preview-URL http://<subdomain>.<domain>.dock4.basispanel.de funktioniert ohne DNS (wird von Basispanel intern aufgelöst).

7. HTTPS nachträglich aktivieren

Sobald das Projekt live geht:

  1. Im Basispanel Subdomain updaten:
    • https: "https" (statt "noHttps")
    • certbot: "certbot" (automatisches Letsencrypt)
    • httpsRedirect: "httpsRedirect" (HTTP→HTTPS)
  2. .env: LIVE_URL auf https://www.<domain> ändern
  3. api/hooks/config-client.js: originURL entsprechend setzen (wird von CI überschrieben)

8. Typische Fehler

Problem Ursache Fix
invalid webserverKey: dock4 Falscher Key Mit bp_get_config prüfen → dock4_lamp2
subdomain exists Doppelt angelegt Mit bp_delete_subdomain löschen, neu anlegen
yarn validate scheitert in CI Typen/Submodule/Pfade nicht sauber eingecheckt Checkout-, Submodule- und Include-Pfade korrigieren; validate im Workflow belassen
Rsync "Permission denied" Falscher RSYNC_USER In Gitea Secrets prüfen
404 auf Subdomain DNS nicht gesetzt A-Record beim Kunden-DNS-Provider eintragen