ci: docker_tag=ext
All checks were successful
build-and-push-ext / build_push (push) Successful in 1m28s
All checks were successful
build-and-push-ext / build_push (push) Successful in 1m28s
- Complété l'analyse détaillée du repo dans docs/ANALYSE.md - Ajouté guide de validation opérationnelle dans docs/VALIDATION.md - Créé tests basiques: health_check.sh et ws_connect.rs - Endpoint /health confirmé sur port 8091 - WebSocket confirmé sur port 8090 via tokio_tungstenite - Documentation CI/CD et configuration Docker
This commit is contained in:
parent
72bbffb31c
commit
25ac6eb808
12
.conf.model
12
.conf.model
@ -1,7 +1,9 @@
|
|||||||
core_url=""
|
core_url="http://bitcoin:38332"
|
||||||
ws_url=""
|
ws_url="0.0.0.0:8090"
|
||||||
wallet_name="default"
|
wallet_name="default"
|
||||||
network="signet"
|
network="signet"
|
||||||
electrum_url="tcp://localhost:60601"
|
blindbit_url="http://blindbit:8000"
|
||||||
blindbit_url="tcp://localhost:8000"
|
zmq_url="tcp://bitcoin:29000"
|
||||||
zmq_url=""
|
storage="https://demo.4nkweb.com/storage"
|
||||||
|
data_dir="/home/bitcoin/.4nk"
|
||||||
|
bitcoin_data_dir="/home/bitcoin/.bitcoin"
|
||||||
|
10
.dockerignore
Normal file
10
.dockerignore
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.git
|
||||||
|
node_modules
|
||||||
|
.next
|
||||||
|
coverage
|
||||||
|
dist
|
||||||
|
.DS_Store
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
.env*
|
44
.github/workflows/dev.yml
vendored
44
.github/workflows/dev.yml
vendored
@ -1,44 +0,0 @@
|
|||||||
name: Build and Push to Registry
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ dev ]
|
|
||||||
|
|
||||||
env:
|
|
||||||
REGISTRY: git.4nkweb.com
|
|
||||||
IMAGE_NAME: 4nk/sdk_relay
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-push:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up SSH agent
|
|
||||||
uses: webfactory/ssh-agent@v0.9.1
|
|
||||||
with:
|
|
||||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Login to Container Registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ${{ env.REGISTRY }}
|
|
||||||
username: ${{ secrets.USER }}
|
|
||||||
password: ${{ secrets.TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and push
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
ssh: default
|
|
||||||
build-args: |
|
|
||||||
CONF=${{ secrets.CONF }}
|
|
||||||
tags: |
|
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:dev
|
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ gitea.sha }}
|
|
7
debian.code-workspace
Normal file
7
debian.code-workspace
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": ".."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -18,7 +18,36 @@ Service Rust `sdk_relay` interfaçant Bitcoin (RPC), Blindbit et WebSocket, avec
|
|||||||
|
|
||||||
### Réseau et healthcheck
|
### Réseau et healthcheck
|
||||||
|
|
||||||
- Ports: 8090, 8091 (exposés). Health: `GET /health` (via compose parent).
|
- **WebSocket**: serveur lié sur `Config.ws_url` (ex. `0.0.0.0:8090`) via `tokio_tungstenite`.
|
||||||
|
- **Health**: serveur TCP léger interne sur port `8091` retournant `{"status":"ok"}`.
|
||||||
|
- **Ports exposés**: `8090` (WS), `8091` (HTTP /health) dans le `Dockerfile`.
|
||||||
|
|
||||||
|
Références code:
|
||||||
|
|
||||||
|
```396:625:src/main.rs
|
||||||
|
async fn handle_health_endpoint(mut stream: TcpStream) {
|
||||||
|
let response = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 15\r\n\r\n{\"status\":\"ok\"}";
|
||||||
|
let _ = stream.write_all(response.as_bytes()).await;
|
||||||
|
let _ = stream.shutdown().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn start_health_server(port: u16) { /* ... */ }
|
||||||
|
|
||||||
|
// Start health server on port 8091
|
||||||
|
tokio::spawn(start_health_server(8091));
|
||||||
|
```
|
||||||
|
|
||||||
|
Configuration:
|
||||||
|
|
||||||
|
```1:7:.conf.model
|
||||||
|
core_url=""
|
||||||
|
ws_url=""
|
||||||
|
wallet_name="default"
|
||||||
|
network="signet"
|
||||||
|
electrum_url="tcp://localhost:60601"
|
||||||
|
blindbit_url="tcp://localhost:8000"
|
||||||
|
zmq_url=""
|
||||||
|
```
|
||||||
|
|
||||||
### Logs
|
### Logs
|
||||||
|
|
||||||
@ -35,3 +64,19 @@ Service Rust `sdk_relay` interfaçant Bitcoin (RPC), Blindbit et WebSocket, avec
|
|||||||
- Pinner `sdk_common` sur un commit ou tag; documenter politique de mise à jour.
|
- Pinner `sdk_common` sur un commit ou tag; documenter politique de mise à jour.
|
||||||
- Séparer images `-dev` et `-prod` si `strace` non requis.
|
- Séparer images `-dev` et `-prod` si `strace` non requis.
|
||||||
- Documenter format du fichier de conf (`sdk_relay.conf`) et valeurs par défaut.
|
- Documenter format du fichier de conf (`sdk_relay.conf`) et valeurs par défaut.
|
||||||
|
|
||||||
|
### CI / Image
|
||||||
|
|
||||||
|
- Pipeline `build-and-push-ext` construit et pousse l’image avec un tag calculé depuis le message de commit (préfixe `ci: docker_tag=` sinon `dev-test`).
|
||||||
|
- L’image expose `8090 8091` et lance `sdk_relay --config /home/bitcoin/.conf`.
|
||||||
|
|
||||||
|
Références:
|
||||||
|
|
||||||
|
```1:46:Dockerfile
|
||||||
|
EXPOSE 8090 8091
|
||||||
|
ENTRYPOINT ["sdk_relay", "--config", "/home/bitcoin/.conf"]
|
||||||
|
```
|
||||||
|
|
||||||
|
```1:73:.gitea/workflows/build-ext.yml
|
||||||
|
name: build-and-push-ext
|
||||||
|
```
|
||||||
|
40
docs/VALIDATION.md
Normal file
40
docs/VALIDATION.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
## Validation opérationnelle
|
||||||
|
|
||||||
|
### Pré‑requis
|
||||||
|
|
||||||
|
- Image `git.4nkweb.com/4nk/sdk_relay:<tag>` construite par la CI (workflow `build-and-push-ext`).
|
||||||
|
- Fichier de configuration accessible dans le conteneur à `/home/bitcoin/.conf` avec au minimum: `core_url`, `ws_url`, `wallet_name`, `network`, `blindbit_url`, `zmq_url`.
|
||||||
|
- Ports hôtes libres: `8090` (WebSocket), `8091` (HTTP /health).
|
||||||
|
|
||||||
|
### Démarrage / Redémarrage du service
|
||||||
|
|
||||||
|
1. Arrêter l’instance en cours (si gérée via Docker/compose parent), puis démarrer avec la nouvelle image taggée `ext` (ou le tag CI calculé) en veillant à monter les volumes `/home/bitcoin/.4nk` et `/home/bitcoin/.bitcoin`.
|
||||||
|
2. Vérifier les logs de démarrage et la ligne: `Health server listening on port 8091`.
|
||||||
|
|
||||||
|
### Tests de santé
|
||||||
|
|
||||||
|
- HTTP: `curl -sS http://localhost:8091/health` doit renvoyer `{"status":"ok"}` avec un code 200.
|
||||||
|
|
||||||
|
### Tests WebSocket
|
||||||
|
|
||||||
|
- Connexion: ouvrir un client vers `ws://localhost:8090` (adresse selon `ws_url`). La poignée de main doit réussir.
|
||||||
|
- Réception initiale: un message de type Handshake (avec adresse SP, membres et processus) est diffusé à la connexion.
|
||||||
|
- Diffusion: émettre un message valide (selon protocole `sdk_common`) et vérifier qu’il est redistribué selon le `BroadcastType`.
|
||||||
|
|
||||||
|
### Parcours fonctionnel complet
|
||||||
|
|
||||||
|
1. IdNot: initialiser un identifiant et vérifier la persistance locale dans le volume `.4nk`.
|
||||||
|
2. iframe: intégrer le client (IHM) et établir la communication vers le WebSocket du `sdk_relay`.
|
||||||
|
3. Ajout de service: exécuter le flux d’ajout et confirmer la mise à jour de l’état et la diffusion côté WS.
|
||||||
|
|
||||||
|
### Attendus CI/CD
|
||||||
|
|
||||||
|
- La CI construit automatiquement l’image incluant l’endpoint `/health` et pousse avec le tag calculé (préfixe commit `ci: docker_tag=...`, sinon `dev-test`).
|
||||||
|
- Une fois l’image disponible (tag `ext` si prévu), redémarrer le service pour résoudre les problèmes de connexion.
|
||||||
|
|
||||||
|
### Dépannage
|
||||||
|
|
||||||
|
- Port occupé: vérifier qu’aucun service n’écoute déjà sur `8090/8091`.
|
||||||
|
- Conf manquante/invalide: le binaire échoue avec `Failed to find conf file` ou erreurs `No "..."`; corriger `/home/bitcoin/.conf`.
|
||||||
|
- ZMQ/Blindbit: si pas joignables, les fonctionnalités associées peuvent être dégradées; le `/health` reste OK si le service tourne.
|
||||||
|
- Volumes: en environnement Windows, vérifier les permissions et l’utilisateur `bitcoin`.
|
@ -427,9 +427,9 @@ async fn start_health_server(port: u16) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
log::info!("Health server listening on port {}", port);
|
log::info!("Health server listening on port {}", port);
|
||||||
|
|
||||||
while let Ok((stream, _)) = listener.accept().await {
|
while let Ok((stream, _)) = listener.accept().await {
|
||||||
tokio::spawn(handle_health_endpoint(stream));
|
tokio::spawn(handle_health_endpoint(stream));
|
||||||
}
|
}
|
||||||
|
23
tests/health_check.sh
Normal file
23
tests/health_check.sh
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
URL="http://localhost:8091/health"
|
||||||
|
echo "[tests] Vérification /health: $URL"
|
||||||
|
|
||||||
|
http_code=$(curl -s -o /tmp/health_body.txt -w "%{http_code}" "$URL")
|
||||||
|
body=$(cat /tmp/health_body.txt)
|
||||||
|
|
||||||
|
echo "HTTP $http_code"
|
||||||
|
echo "Body: $body"
|
||||||
|
|
||||||
|
if [[ "$http_code" != "200" ]]; then
|
||||||
|
echo "Échec: code HTTP inattendu" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$body" != '{"status":"ok"}' ]]; then
|
||||||
|
echo "Échec: corps inattendu" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Succès: endpoint /health opérationnel"
|
18
tests/ws_connect.rs
Normal file
18
tests/ws_connect.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use tokio::time::timeout;
|
||||||
|
use tokio_tungstenite::connect_async;
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn ws_connects_on_localhost_8090() {
|
||||||
|
let url = std::env::var("SDK_RELAY_WS_URL").unwrap_or_else(|_| "ws://localhost:8090".to_string());
|
||||||
|
let connect_fut = connect_async(url);
|
||||||
|
let res = timeout(Duration::from_secs(3), connect_fut).await;
|
||||||
|
match res {
|
||||||
|
Ok(Ok((_stream, _resp))) => {
|
||||||
|
// Succès si la poignée de main WS passe
|
||||||
|
}
|
||||||
|
Ok(Err(e)) => panic!("Échec connexion WebSocket: {e}"),
|
||||||
|
Err(_) => panic!("Timeout connexion WebSocket"),
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user