✨ 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.
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
---
|
||||
name: deployment
|
||||
description: 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
|
||||
|
||||
```bash
|
||||
# Domain des Kunden suchen
|
||||
mcp_call(server="basispanel", tool="bp_list_domains", args={"search": "<kunde>"})
|
||||
# → liefert Customer-ID, Domain-ID, Company, Username
|
||||
```
|
||||
|
||||
### Subdomain anlegen
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```env
|
||||
# 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`)
|
||||
|
||||
```yaml
|
||||
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:
|
||||
|
||||
```makefile
|
||||
# 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 |
|
||||
Reference in New Issue
Block a user