Skip to content

Runbook: distribuzione del runner ETL

Il servizio è distribuito come immagine container con entrypoint la CLI etl. Questo runbook copre la build, la pubblicazione su ECR e la modalità batch (etl run, non un daemon: un container = una esecuzione di pipeline, poi termina).

Il CMD di default dell'immagine però è serve: server HTTP dei grafi e worker nello stesso processo, un solo container per tutta la piattaforma (ADR-0028, runbook graph-server.md). Il worker da solo (etl worker, poller sulla tabella processes di Noeva, anche multi-workspace) è in etl-worker.md, ADR-0019 e ADR-0021: mai un container worker in parallelo a un serve, o i job vengono presi due volte.

Configurazione solo da variabili d'ambiente (nessun segreto nell'immagine).

La UI non si deploya da qui. noeva-etl-ui è un'app desktop Tauri, buildata nel suo submodule con pnpm tauri build (ADR-0025, che supera ADR-0023). Il deploy nginx/ECR della UI e i flag --ui/--no-ui degli script sono stati rimossi.

Modello d'uso attuale: l'immagine è pubblicata su ECR e viene scaricata ed eseguita in locale su Docker Desktop. La build è multi-arch, quindi su Apple Silicon gira nativa. L'esecuzione in cloud (ECS) è rinviata a una valutazione futura (ADR-0005).

CLI

bash
etl list                      # elenca le pipeline disponibili
etl run <pipeline>            # esegue una pipeline (es. langfuse-sessions-daily)
etl serve                     # default dell'immagine: grafi via HTTP + worker
etl worker                    # solo i worker

In sviluppo: pnpm run etl run <pipeline> (precarica .env).

Build & pubblicazione (ECR)

Usa lo script deploy-ecr.sh: esegue il quality gate, login ECR, crea il repository se assente, build multi-arch (linux/amd64,linux/arm64) e push. Pubblica solo l'immagine del runner: lo script rifiuta qualunque flag --*.

Ogni deploy pubblica sempre:

  • latest — usato per pull/run in locale;
  • <YYYYmmdd-HHMMSS> — tag temporale immutabile (tracciabilità / rollback).

Un terzo tag versione (es. v0.2.0) è opzionale, come 4° argomento.

bash
# ./deploy-ecr.sh [AWS_PROFILE] [AWS_REGION] [ECR_REPOSITORY_NAME] [VERSION_TAG]
./deploy-ecr.sh                                               # → latest + timestamp
./deploy-ecr.sh default eu-west-1 gruppo4d/noeva-etl v0.2.0   # + tag v0.2.0

# opzioni utili
SKIP_CHECK=1 ./deploy-ecr.sh           # salta il gate `pnpm run check` (sconsigliato)
PLATFORMS=linux/amd64 ./deploy-ecr.sh  # solo amd64

Gli argomenti posizionali si possono dare anche come variabili d'ambiente (AWS_PROFILE, AWS_REGION, ECR_REPOSITORY_NAME, VERSION_TAG).

Requisiti: AWS CLI, Docker con buildx, pnpm. (Per GHCR o un altro registry cambia il login; la build dell'immagine è identica.)

Esecuzione in locale (Docker Desktop)

Modo rapido con lo script run-ecr.sh (login + pull + run, batch in foreground):

bash
./run-ecr.sh                          # nessun argomento → elenco pipeline (etl list)
./run-ecr.sh langfuse-sessions-daily  # pull :latest ed esegue la pipeline
./run-ecr.sh langfuse-sessions-daily 20260603-200239   # tag specifico

Lo script passa ETL_RELEASE=<tag immagine> al container, così il report registra quale release ha eseguito la run (campo version).

Equivalente manuale:

bash
docker pull <account>.dkr.ecr.<region>.amazonaws.com/gruppo4d/noeva-etl:latest
docker run --rm --env-file .env <...>/gruppo4d/noeva-etl:latest run langfuse-sessions-daily

DB sull'host: dentro il container localhost è il container stesso. Per raggiungere DB in esecuzione sull'host (es. i container di test), impostare le variabili *HOST a host.docker.internal (lo script aggiunge già l'alias anche su Linux).

Esecuzione

bash
# una tantum: la tabella di destinazione deve esistere (DDL versionata in sql/)
docker run --rm <image> list

docker run --rm --env-file .env <image> run langfuse-sessions-daily

Variabili richieste: quelle della pipeline, elencate nella sua scheda e in .env.example (per langfuse-sessions-daily: PG* sorgente e MSSQL_* sink), più ETL_ENV e ETL_LOG_LEVEL. In produzione iniettarle da un secret manager (AWS Secrets Manager / SSM), non da .env.

Modelli di deploy per cliente

Il servizio gira tipicamente sull'infra del cliente. L'immagine ECR abilita tutti i casi:

ModelloComeNote
Gestito da noiECS Scheduled Task (Fargate) + EventBridge, definiti in TerraformRetry, log CloudWatch, parità staging/prod
ECS del clienteStessa immagine, task definition nel loro accountSolo accesso al registry + secrets del cliente
Docker locale del clientedocker run schedulato da cron sul loro hostPiù semplice; idempotenza rende sicuri retry/sovrapposizioni

Scheduling

La pipeline è idempotente (upsert/MERGE su chiave naturale): rieseguire o sovrapporre run non duplica dati. Quindi lo scheduler può essere semplice:

  • cron che lancia docker run ... run <pipeline>;
  • ECS Scheduled Task (cron via EventBridge);
  • per dipendenze/backfill complessi in futuro → orchestratore (es. Temporal TS).

Networking

Il container deve raggiungere sorgente e sink (PG e SQL Server), che possono stare su host/VPC diversi. In locale, dai container verso DB sull'host: usare host.docker.internal come *HOST. In cloud: curare security group / routing verso entrambi i DB.

Osservabilità — il report di run è il risultato

Il servizio è stateless: emette un report e termina (niente DB lato servizio).

  • stdout = il report in JSON (un oggetto). stderr = log umani.
  • exit code: 0 se success/partial, ≠0 se failed (utile per alerting dello scheduler).
  • Anche in errore viene emesso un report status: "failed".
bash
# cattura il report e i log separatamente
./run-ecr.sh langfuse-sessions-daily > report.json 2> run.log
# archivialo dove vuoi (è il chiamante a deciderlo): file, S3, CloudWatch, ...

Schema completo e semantica: docs/conventions/run-report.md · ADR-0006.

Noeva è un marchio registrato di 4D S.R.L.