Replace 'ext' tag with 'int-dev'
This commit is contained in:
parent
7c8471a41f
commit
f430c38c72
20
.cursorrules
20
.cursorrules
@ -42,7 +42,7 @@
|
||||
- Externaliser au maximum les variables d’environnement.
|
||||
- Toujours utiliser une clé SSH pour cloner les dépôts.
|
||||
- Monter en version les dépôts au début du travail.
|
||||
- Pousser les tags docker `ext` via la CI sur `git.4nkweb.com`.
|
||||
- Pousser les tags docker `int-dev` via la CI sur `git.4nkweb.com`.
|
||||
- Corriger systématiquement les problèmes, même mineurs, sans contournement.
|
||||
|
||||
## Scripts (règles critiques)
|
||||
@ -56,7 +56,7 @@
|
||||
- Installer en arrière-plan dans les images Docker :
|
||||
`curl, git, sed, awk, nc, wget, jq, telnet, tee, wscat, ping, npm (dernière version)`
|
||||
- Appliquer à tous les Dockerfiles et `docker-compose.yml`.
|
||||
- N'utilise pas les version test ou dev ou ext-dev mais toujours les version ext, relance leur compilation si nécessaire
|
||||
- N'utilise pas les version test ou dev ou int-dev-dev mais toujours les version int-dev, relance leur compilation si nécessaire
|
||||
|
||||
## Fichiers de configuration (règles critiques)
|
||||
- Vérifier l’écriture effective après chaque modification.
|
||||
@ -167,12 +167,12 @@ Chaque projet doit être prêt pour un dépôt sur `git.4nkweb.com` :
|
||||
# Déploiement
|
||||
|
||||
Dans lecoffre_node en utilisant les scripts de scripts/ :
|
||||
Il y a des branches git "ext", des images docker avec le tag "ext", pas de tag git "ext"
|
||||
Il y a des branches git "int-dev", des images docker avec le tag "int-dev", pas de tag git "int-dev"
|
||||
|
||||
pour tous les projets avec des Dockerfile:
|
||||
vérifie que le repos distant est public (si possible, non bloquant, pour info)
|
||||
vérifie que tu peux utiliser tes clés ssh pour le déploiement sur git
|
||||
vérifie que tu es sur la branche ext
|
||||
vérifie que tu es sur la branche int-dev
|
||||
met à jour les dépendances
|
||||
vérifie les variables d'environnement
|
||||
met à jour le Dockerfle pour une bonne maîtrise des pré-requis (intégre l'installation et la mise à jour avec un sudo apt udpate && sudo apt upgrade et jq curl sed awk telnet ping npm (dernière version) et wscat)
|
||||
@ -185,9 +185,9 @@ vérifie .dockerignore
|
||||
vérifie .cursorignore
|
||||
synchronise les confs sur lecoffre_node/conf
|
||||
synchronise les logs sur lecoffre_node/logs
|
||||
pousse toutes les modifications sur la branche git "ext"
|
||||
pousse toutes les modifications sur la branche git "int-dev"
|
||||
supprimer les fichiers distants non suivis sur le git
|
||||
pousse sur la tag docker "ext" via la CI
|
||||
pousse sur la tag docker "int-dev" via la CI
|
||||
analyse les logs
|
||||
corrige les erreurs petites et grosses sans déscactivation, sans simplification, sans contournement
|
||||
teste
|
||||
@ -199,13 +199,13 @@ recommence si besoin pour valider un déploiement parfait et fluide
|
||||
si tu as appres quelque chose techniquement ou fonctionnement écris le dans les docs
|
||||
synchronise les confs sur lecoffre_node/conf
|
||||
synchronise les logs sur lecoffre_node/logs
|
||||
pousse toutes les modifications sur la branche git "ext"
|
||||
pousse toutes les modifications sur la branche git "int-dev"
|
||||
|
||||
|
||||
pour tous les projets avec des sans Dockerfile avec sur git:
|
||||
vérifie que le repos distant est public (si possible, non bloquant, pour info)
|
||||
vérifie que tu peux utiliser tes clés ssh pour le déploiement sur git
|
||||
vérifie que tu es sur la branche ext
|
||||
vérifie que tu es sur la branche int-dev
|
||||
met à jour les dépendances
|
||||
vérifie les variables d'environnement
|
||||
met à jour le Dockerfle pour une bonne maîtrise des pré-requis (intégre l'installation et la mise à jour avec un sudo apt udpate && sudo apt upgrade et jq curl sed awk telnet ping npm (dernière version) et wscat)
|
||||
@ -218,7 +218,7 @@ vérifie .dockerignore
|
||||
vérifie .cursorignore
|
||||
synchronise les confs sur lecoffre_node/conf
|
||||
synchronise les logs sur lecoffre_node/logs
|
||||
pousse toutes les modifications sur la branche git "ext"
|
||||
pousse toutes les modifications sur la branche git "int-dev"
|
||||
supprimer les fichiers distants non suivis sur le git
|
||||
analyse les logs
|
||||
corrige les erreurs petites et grosses sans déscactivation, sans simplification, sans contournement
|
||||
@ -231,4 +231,4 @@ recommence si besoin pour valider un déploiement parfait et fluide
|
||||
si tu as appres quelque chose techniquement ou fonctionnement écris le dans les docs
|
||||
synchronise les confs sur lecoffre_node/conf
|
||||
synchronise les logs sur lecoffre_node/logs
|
||||
pousse toutes les modifications sur la branche git "ext"
|
||||
pousse toutes les modifications sur la branche git "int-dev"
|
||||
|
@ -94,7 +94,7 @@ cd /home/debian/4NK_env/lecoffre_node
|
||||
### Déploiement manuel
|
||||
```bash
|
||||
# 1. Construction de l'image
|
||||
docker build -f Dockerfile.master -t lecoffre-node-master:ext .
|
||||
docker build -f Dockerfile.master -t lecoffre-node-master:int-dev .
|
||||
|
||||
# 2. Démarrage du conteneur (utilise le port 80 du host)
|
||||
docker run -d \
|
||||
@ -106,7 +106,7 @@ docker run -d \
|
||||
-v $(pwd)/data:/app/data \
|
||||
-v $(pwd)/logs:/app/logs \
|
||||
-v $(pwd)/.env.master:/app/.env \
|
||||
lecoffre-node-master:ext
|
||||
lecoffre-node-master:int-dev
|
||||
```
|
||||
|
||||
### Désinstallation du Nginx du host (optionnel)
|
||||
@ -189,7 +189,7 @@ docker exec lecoffre-node-master tar -xzf /app/backup/backup-YYYYMMDD.tar.gz -C
|
||||
docker stop lecoffre-node-master
|
||||
|
||||
# 2. Reconstruire l'image
|
||||
docker build -f Dockerfile.master -t lecoffre-node-master:ext .
|
||||
docker build -f Dockerfile.master -t lecoffre-node-master:int-dev .
|
||||
|
||||
# 3. Redémarrer
|
||||
docker start lecoffre-node-master
|
||||
|
14
README.md
14
README.md
@ -1,6 +1,6 @@
|
||||
# LeCoffre Node - Plateforme de Gestion de Documents Sécurisée
|
||||
|
||||
[](https://git.4nkweb.com/4nk/lecoffre_node)
|
||||
[](https://git.4nkweb.com/4nk/lecoffre_node)
|
||||
[](https://mempool2.4nkweb.com)
|
||||
[](https://dev4.4nkweb.com/lecoffre)
|
||||
|
||||
@ -207,12 +207,12 @@ lecoffre_node/
|
||||
|
||||
| Projet | Branche | Description |
|
||||
|--------|---------|-------------|
|
||||
| `sdk_relay` | `ext` | Relay des transactions |
|
||||
| `sdk_signer` | `ext` | Service de signature |
|
||||
| `sdk_storage` | `ext` | Stockage temporaire |
|
||||
| `ihm_client` | `ext` | Interface de gestion |
|
||||
| `lecoffre-front` | `ext` | Frontend LeCoffre |
|
||||
| `lecoffre-back-mini` | `ext` | Backend API |
|
||||
| `sdk_relay` | `int-dev` | Relay des transactions |
|
||||
| `sdk_signer` | `int-dev` | Service de signature |
|
||||
| `sdk_storage` | `int-dev` | Stockage temporaire |
|
||||
| `ihm_client` | `int-dev` | Interface de gestion |
|
||||
| `lecoffre-front` | `int-dev` | Frontend LeCoffre |
|
||||
| `lecoffre-back-mini` | `int-dev` | Backend API |
|
||||
|
||||
## 📚 Documentation Complète
|
||||
|
||||
|
@ -78,7 +78,7 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
sdk_relay:
|
||||
image: git.4nkweb.com/4nk/sdk_relay:ext
|
||||
image: git.4nkweb.com/4nk/sdk_relay:int-dev
|
||||
container_name: sdk_relay
|
||||
depends_on:
|
||||
blindbit:
|
||||
@ -124,7 +124,7 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
lecoffre-back:
|
||||
image: git.4nkweb.com/4nk/lecoffre-back-mini:ext
|
||||
image: git.4nkweb.com/4nk/lecoffre-back-mini:int-dev
|
||||
container_name: lecoffre-back
|
||||
environment:
|
||||
- NODE_OPTIONS=${NODE_OPTIONS}
|
||||
@ -171,7 +171,7 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
lecoffre-front:
|
||||
image: git.4nkweb.com/4nk/lecoffre-front:ext
|
||||
image: git.4nkweb.com/4nk/lecoffre-front:int-dev
|
||||
container_name: lecoffre-front
|
||||
working_dir: /leCoffre-front
|
||||
environment:
|
||||
@ -216,7 +216,7 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
ihm_client:
|
||||
image: git.4nkweb.com/4nk/ihm_client:ext
|
||||
image: git.4nkweb.com/4nk/ihm_client:int-dev
|
||||
container_name: ihm_client
|
||||
environment:
|
||||
- VITE_JWT_SECRET_KEY=${VITE_JWT_SECRET_KEY}
|
||||
@ -253,7 +253,7 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
sdk_signer:
|
||||
image: git.4nkweb.com/4nk/sdk_signer:ext
|
||||
image: git.4nkweb.com/4nk/sdk_signer:int-dev
|
||||
container_name: sdk_signer
|
||||
ports:
|
||||
- "0.0.0.0:3001:9090"
|
||||
@ -291,7 +291,7 @@ services:
|
||||
- SIGNER_BASE_URL=https://dev3.4nkweb.com
|
||||
|
||||
sdk_storage:
|
||||
image: git.4nkweb.com/4nk/sdk_storage:ext
|
||||
image: git.4nkweb.com/4nk/sdk_storage:int-dev
|
||||
container_name: sdk_storage
|
||||
ports:
|
||||
- "0.0.0.0:8081:8080"
|
||||
@ -398,7 +398,7 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
promtail:
|
||||
image: promtail-custom:ext
|
||||
image: promtail-custom:int-dev
|
||||
container_name: promtail
|
||||
volumes:
|
||||
- ./logs:/var/log/lecoffre:ro
|
||||
|
@ -69,7 +69,7 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
sdk_relay:
|
||||
image: git.4nkweb.com/4nk/sdk_relay:ext
|
||||
image: git.4nkweb.com/4nk/sdk_relay:int-dev
|
||||
container_name: sdk_relay
|
||||
depends_on:
|
||||
blindbit:
|
||||
@ -114,7 +114,7 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
lecoffre-back:
|
||||
image: git.4nkweb.com/4nk/lecoffre-back-mini:ext
|
||||
image: git.4nkweb.com/4nk/lecoffre-back-mini:int-dev
|
||||
container_name: lecoffre-back
|
||||
environment:
|
||||
- NODE_OPTIONS=${NODE_OPTIONS}
|
||||
@ -161,7 +161,7 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
lecoffre-front:
|
||||
image: git.4nkweb.com/4nk/lecoffre-front:ext
|
||||
image: git.4nkweb.com/4nk/lecoffre-front:int-dev
|
||||
container_name: lecoffre-front
|
||||
working_dir: /leCoffre-front
|
||||
environment:
|
||||
@ -206,7 +206,7 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
ihm_client:
|
||||
image: git.4nkweb.com/4nk/ihm_client:ext
|
||||
image: git.4nkweb.com/4nk/ihm_client:int-dev
|
||||
container_name: ihm_client
|
||||
environment:
|
||||
- VITE_JWT_SECRET_KEY=${VITE_JWT_SECRET_KEY}
|
||||
@ -243,7 +243,7 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
sdk_signer:
|
||||
image: git.4nkweb.com/4nk/sdk_signer:ext
|
||||
image: git.4nkweb.com/4nk/sdk_signer:int-dev
|
||||
container_name: sdk_signer
|
||||
ports:
|
||||
- "0.0.0.0:3001:9090"
|
||||
@ -279,7 +279,7 @@ services:
|
||||
- SIGNER_BASE_URL=https://dev3.4nkweb.com
|
||||
|
||||
sdk_storage:
|
||||
image: git.4nkweb.com/4nk/sdk_storage:ext
|
||||
image: git.4nkweb.com/4nk/sdk_storage:int-dev
|
||||
container_name: sdk_storage
|
||||
ports:
|
||||
- "0.0.0.0:8081:8080"
|
||||
@ -385,7 +385,7 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
promtail:
|
||||
image: promtail-custom:ext
|
||||
image: promtail-custom:int-dev
|
||||
container_name: promtail
|
||||
volumes:
|
||||
- ./logs:/var/log/lecoffre:ro
|
||||
|
@ -53,12 +53,12 @@ if [[ $# -lt 1 ]]; then
|
||||
echo ""
|
||||
echo "Exemples:"
|
||||
echo " $0 ihm_client"
|
||||
echo " $0 ihm_client ext"
|
||||
echo " $0 ihm_client int-dev"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PROJECT_NAME="$1"
|
||||
DOCKER_TAG="${2:-ext}"
|
||||
DOCKER_TAG="${2:-int-dev}"
|
||||
PROJECT_ROOT="/home/debian/lecoffre_node"
|
||||
PROJECT_PATH="/home/debian/$PROJECT_NAME"
|
||||
|
||||
|
@ -11,7 +11,7 @@ log() {
|
||||
|
||||
# Variables
|
||||
MASTER_IMAGE_NAME="lecoffre-node-master"
|
||||
MASTER_IMAGE_TAG="ext"
|
||||
MASTER_IMAGE_TAG="int-dev"
|
||||
CONTAINER_NAME="lecoffre-node-master"
|
||||
HOST_PORT=80
|
||||
|
||||
|
@ -11,7 +11,7 @@ log() {
|
||||
|
||||
# Variables
|
||||
MASTER_IMAGE_NAME="lecoffre-node-master"
|
||||
MASTER_IMAGE_TAG="ext"
|
||||
MASTER_IMAGE_TAG="int-dev"
|
||||
CONTAINER_NAME="lecoffre-node-master"
|
||||
HOST_PORT=8081
|
||||
|
||||
|
@ -16,17 +16,17 @@ class StatusAPIHandler(BaseHTTPRequestHandler):
|
||||
services = [
|
||||
{"name": "Bitcoin Signet", "status": "running", "image": "btcpayserver/bitcoin:27.1", "ip": "172.20.0.2", "port": "8332", "protocol": "RPC", "uptime": "2h 15m", "health": "healthy"},
|
||||
{"name": "BlindBit Oracle", "status": "running", "image": "blindbit/oracle:latest", "ip": "172.20.0.3", "port": "8000", "protocol": "HTTP", "uptime": "2h 10m", "health": "healthy"},
|
||||
{"name": "SDK Relay", "status": "running", "image": "sdk_relay:ext", "ip": "172.20.0.4", "port": "8090", "protocol": "WebSocket", "uptime": "2h 5m", "health": "healthy"},
|
||||
{"name": "SDK Signer", "status": "running", "image": "sdk_signer:ext", "ip": "172.20.0.5", "port": "9090", "protocol": "WebSocket", "uptime": "2h 0m", "health": "healthy"},
|
||||
{"name": "SDK Storage", "status": "running", "image": "sdk_storage:ext", "ip": "172.20.0.6", "port": "8080", "protocol": "HTTP", "uptime": "1h 55m", "health": "healthy"},
|
||||
{"name": "LeCoffre Backend", "status": "running", "image": "lecoffre-back:ext", "ip": "172.20.0.7", "port": "8080", "protocol": "HTTP", "uptime": "1h 50m", "health": "healthy"},
|
||||
{"name": "LeCoffre Frontend", "status": "running", "image": "lecoffre-front:ext", "ip": "172.20.0.8", "port": "3000", "protocol": "HTTP", "uptime": "1h 45m", "health": "healthy"},
|
||||
{"name": "IHM Client", "status": "running", "image": "ihm_client:ext", "ip": "172.20.0.9", "port": "3001", "protocol": "HTTP", "uptime": "1h 40m", "health": "healthy"},
|
||||
{"name": "SDK Relay", "status": "running", "image": "sdk_relay:int-dev", "ip": "172.20.0.4", "port": "8090", "protocol": "WebSocket", "uptime": "2h 5m", "health": "healthy"},
|
||||
{"name": "SDK Signer", "status": "running", "image": "sdk_signer:int-dev", "ip": "172.20.0.5", "port": "9090", "protocol": "WebSocket", "uptime": "2h 0m", "health": "healthy"},
|
||||
{"name": "SDK Storage", "status": "running", "image": "sdk_storage:int-dev", "ip": "172.20.0.6", "port": "8080", "protocol": "HTTP", "uptime": "1h 55m", "health": "healthy"},
|
||||
{"name": "LeCoffre Backend", "status": "running", "image": "lecoffre-back:int-dev", "ip": "172.20.0.7", "port": "8080", "protocol": "HTTP", "uptime": "1h 50m", "health": "healthy"},
|
||||
{"name": "LeCoffre Frontend", "status": "running", "image": "lecoffre-front:int-dev", "ip": "172.20.0.8", "port": "3000", "protocol": "HTTP", "uptime": "1h 45m", "health": "healthy"},
|
||||
{"name": "IHM Client", "status": "running", "image": "ihm_client:int-dev", "ip": "172.20.0.9", "port": "3001", "protocol": "HTTP", "uptime": "1h 40m", "health": "healthy"},
|
||||
{"name": "Tor Proxy", "status": "running", "image": "btcpayserver/tor:0.4.8.10", "ip": "172.20.0.10", "port": "9050", "protocol": "SOCKS", "uptime": "1h 35m", "health": "healthy"},
|
||||
{"name": "Grafana", "status": "running", "image": "grafana/grafana:latest", "ip": "172.20.0.11", "port": "3000", "protocol": "HTTP", "uptime": "1h 30m", "health": "healthy"},
|
||||
{"name": "Loki", "status": "running", "image": "grafana/loki:latest", "ip": "172.20.0.12", "port": "3100", "protocol": "HTTP", "uptime": "1h 25m", "health": "healthy"},
|
||||
{"name": "Promtail", "status": "running", "image": "grafana/promtail:latest", "ip": "172.20.0.13", "port": "9080", "protocol": "HTTP", "uptime": "1h 20m", "health": "healthy"},
|
||||
{"name": "Miner Signet", "status": "running", "image": "miner:ext", "ip": "172.20.0.14", "port": None, "protocol": "Bitcoin", "uptime": "1h 15m", "health": "healthy"}
|
||||
{"name": "Miner Signet", "status": "running", "image": "miner:int-dev", "ip": "172.20.0.14", "port": None, "protocol": "Bitcoin", "uptime": "1h 15m", "health": "healthy"}
|
||||
]
|
||||
|
||||
external = [
|
||||
|
@ -17,17 +17,17 @@ app.get('/api', (req, res) => {
|
||||
const services = [
|
||||
{ name: 'Bitcoin Signet', status: 'running', image: 'btcpayserver/bitcoin:27.1', ip: '172.20.0.2', port: '8332', protocol: 'RPC', uptime: '2h 15m', health: 'healthy' },
|
||||
{ name: 'BlindBit Oracle', status: 'running', image: 'blindbit/oracle:latest', ip: '172.20.0.3', port: '8000', protocol: 'HTTP', uptime: '2h 10m', health: 'healthy' },
|
||||
{ name: 'SDK Relay', status: 'running', image: 'sdk_relay:ext', ip: '172.20.0.4', port: '8090', protocol: 'WebSocket', uptime: '2h 5m', health: 'healthy' },
|
||||
{ name: 'SDK Signer', status: 'running', image: 'sdk_signer:ext', ip: '172.20.0.5', port: '9090', protocol: 'WebSocket', uptime: '2h 0m', health: 'healthy' },
|
||||
{ name: 'SDK Storage', status: 'running', image: 'sdk_storage:ext', ip: '172.20.0.6', port: '8080', protocol: 'HTTP', uptime: '1h 55m', health: 'healthy' },
|
||||
{ name: 'LeCoffre Backend', status: 'running', image: 'lecoffre-back:ext', ip: '172.20.0.7', port: '8080', protocol: 'HTTP', uptime: '1h 50m', health: 'healthy' },
|
||||
{ name: 'LeCoffre Frontend', status: 'running', image: 'lecoffre-front:ext', ip: '172.20.0.8', port: '3000', protocol: 'HTTP', uptime: '1h 45m', health: 'healthy' },
|
||||
{ name: 'IHM Client', status: 'running', image: 'ihm_client:ext', ip: '172.20.0.9', port: '3001', protocol: 'HTTP', uptime: '1h 40m', health: 'healthy' },
|
||||
{ name: 'SDK Relay', status: 'running', image: 'sdk_relay:int-dev', ip: '172.20.0.4', port: '8090', protocol: 'WebSocket', uptime: '2h 5m', health: 'healthy' },
|
||||
{ name: 'SDK Signer', status: 'running', image: 'sdk_signer:int-dev', ip: '172.20.0.5', port: '9090', protocol: 'WebSocket', uptime: '2h 0m', health: 'healthy' },
|
||||
{ name: 'SDK Storage', status: 'running', image: 'sdk_storage:int-dev', ip: '172.20.0.6', port: '8080', protocol: 'HTTP', uptime: '1h 55m', health: 'healthy' },
|
||||
{ name: 'LeCoffre Backend', status: 'running', image: 'lecoffre-back:int-dev', ip: '172.20.0.7', port: '8080', protocol: 'HTTP', uptime: '1h 50m', health: 'healthy' },
|
||||
{ name: 'LeCoffre Frontend', status: 'running', image: 'lecoffre-front:int-dev', ip: '172.20.0.8', port: '3000', protocol: 'HTTP', uptime: '1h 45m', health: 'healthy' },
|
||||
{ name: 'IHM Client', status: 'running', image: 'ihm_client:int-dev', ip: '172.20.0.9', port: '3001', protocol: 'HTTP', uptime: '1h 40m', health: 'healthy' },
|
||||
{ name: 'Tor Proxy', status: 'running', image: 'btcpayserver/tor:0.4.8.10', ip: '172.20.0.10', port: '9050', protocol: 'SOCKS', uptime: '1h 35m', health: 'healthy' },
|
||||
{ name: 'Grafana', status: 'running', image: 'grafana/grafana:latest', ip: '172.20.0.11', port: '3000', protocol: 'HTTP', uptime: '1h 30m', health: 'healthy' },
|
||||
{ name: 'Loki', status: 'running', image: 'grafana/loki:latest', ip: '172.20.0.12', port: '3100', protocol: 'HTTP', uptime: '1h 25m', health: 'healthy' },
|
||||
{ name: 'Promtail', status: 'running', image: 'grafana/promtail:latest', ip: '172.20.0.13', port: '9080', protocol: 'HTTP', uptime: '1h 20m', health: 'healthy' },
|
||||
{ name: 'Miner Signet', status: 'running', image: 'miner:ext', ip: '172.20.0.14', port: null, protocol: 'Bitcoin', uptime: '1h 15m', health: 'healthy' }
|
||||
{ name: 'Miner Signet', status: 'running', image: 'miner:int-dev', ip: '172.20.0.14', port: null, protocol: 'Bitcoin', uptime: '1h 15m', health: 'healthy' }
|
||||
];
|
||||
|
||||
const external = [
|
||||
|
Loading…
x
Reference in New Issue
Block a user