improved autodeploy
ci/woodpecker/push/ci Pipeline was successful

This commit is contained in:
Luca Banfi
2026-05-18 16:57:18 +02:00
parent 9128909d7b
commit d73b6253fc
5 changed files with 342 additions and 151 deletions
+217
View File
@@ -0,0 +1,217 @@
# RPA Dashboard — Autodeploy con Woodpecker CI
## Panoramica
Il deploy avviene automaticamente tramite **Woodpecker CI** collegato a **Gitea**.
Non serve nessun intervento manuale: basta taggare un commit con `test` o `prod`.
La pipeline è suddivisa in tre file indipendenti in `.woodpecker/`:
| File | Trigger | Cosa fa |
|---|---|---|
| `ci.yml` | ogni push / PR / tag | lint + syntax check |
| `deploy-test.yml` | tag `test` | build + deploy su VM Linux (Docker + Traefik) |
| `deploy-prod.yml` | tag `prod` | build + deploy su VM Windows (SSH, senza Docker) |
---
## Flusso
```
push / PR → ci.yml: lint + syntax
tag test → ci.yml: lint + syntax
deploy-test.yml: build → deploy Docker Linux
└─ estrae i file su /ATG_RUN_TEST/Dashboard
└─ riavvia il container Docker
└─ dashboard live su https://dashboard.57.131.52.95.nip.io
tag prod → ci.yml: lint + syntax
deploy-prod.yml: build → deploy Windows SSH
└─ copia zip su C:/ATG_RUN/Dashboard (SCP)
└─ riavvia il Windows Service "rpa-dashboard"
```
---
## Pubblicare una nuova versione
### Deploy su Linux — tag `test`
```bash
# 1. Commit delle modifiche
git add .
git commit -m "descrizione modifica"
# 2. Spostare il tag test sul commit corrente e pubblicare
git tag -f test
git push --force --tags
```
### Deploy su Windows — tag `prod`
```bash
# 1. Commit delle modifiche
git add .
git commit -m "descrizione modifica"
# 2. Spostare il tag prod sul commit corrente e pubblicare
git tag -f prod
git push --force --tags
```
Woodpecker riceve il webhook da Gitea e avvia la pipeline in automatico.
### Manuale — dal pannello Woodpecker
Apri la pipeline su Woodpecker UI → pulsante **"trigger manually"**.
Esegue build + deploy senza bisogno di taggare (utile per fix rapidi).
---
## Step della pipeline
### `ci.yml` — Lint + Syntax (ogni push/PR/tag)
| Step | Cosa fa |
|---|---|
| `lint` | flake8 — controlla stile e errori Python |
| `syntax` | `py_compile` su tutti i `.py` |
### `deploy-test.yml` — Linux Docker (tag `test`)
| Step | Cosa fa |
|---|---|
| `build` | crea `rpa-tdi-dashboard-prod.zip` (esclude `.env`, `__pycache__`, `*.md`, ecc.) |
| `deploy` | estrae lo zip in `/ATG_RUN_TEST/Dashboard`, riavvia il container Docker |
### `deploy-prod.yml` — Windows SSH (tag `prod`)
| Step | Cosa fa |
|---|---|
| `build` | crea `rpa-tdi-dashboard-prod.zip` (stesso del test) |
| `deploy` | copia zip via SCP, estrae con PowerShell, riavvia il Service `rpa-dashboard` |
---
## Infrastruttura
### Linux (test)
| Componente | Dettaglio |
|---|---|
| VM | `57.131.52.95` |
| URL dashboard | `https://dashboard.57.131.52.95.nip.io` |
| Cartella deploy | `/ATG_RUN_TEST/Dashboard` |
| Cartella DB | `/ATG_RUN_TEST/db` |
| Container | `rpa-dashboard-test` |
| Rete | `traefik_public` |
### Windows (prod)
| Componente | Dettaglio |
|---|---|
| VM | configurata via secret `win_host` |
| Utente SSH | configurato via secret `win_user` |
| Cartella deploy | `C:/ATG_RUN/Dashboard` |
| Windows Service | `rpa-dashboard` (gestito con NSSM) |
### CI
| Componente | Dettaglio |
|---|---|
| Forge | Gitea (self-hosted) |
| CI | Woodpecker CI — Ubuntu cloud + Docker |
| Immagine Python | `python:3.14` |
---
## Secrets richiesti in Woodpecker
Configurare in **Woodpecker UI → Settings → Secrets**:
| Secret | Valore |
|---|---|
| `win_host` | IP o hostname della VM Windows |
| `win_user` | utente SSH (es. `Administrator`) |
| `win_ssh_key` | chiave privata SSH (contenuto del file `id_rsa`) |
---
## Prerequisiti — VM Linux (setup iniziale, una tantum)
```bash
# Creare le cartelle
mkdir -p /ATG_RUN_TEST/Dashboard
mkdir -p /ATG_RUN_TEST/db
# Creare il .env
cat > /ATG_RUN_TEST/Dashboard/.env <<EOF
LOGIN=true
DASHBOARD_USER=TDI_admin
DASHBOARD_PASSWORD=Dashboard_TDI_26!
RPA_REPORT_PORT=8473
EOF
# Copiare i file .db nella cartella db
# es. cp rpa_FORMAZIONE.db /ATG_RUN_TEST/db/
```
Abilitare i volume mounts nel Woodpecker runner:
```env
WOODPECKER_BACKEND_DOCKER_VOLUMES=true
```
---
## Prerequisiti — VM Windows (setup iniziale, una tantum)
```powershell
# 1. Abilitare OpenSSH Server
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Start-Service sshd
Set-Service -Name sshd -StartupType Automatic
# 2. Creare le cartelle
New-Item -ItemType Directory -Force -Path C:/ATG_RUN/Dashboard
New-Item -ItemType Directory -Force -Path C:/ATG_RUN/db
# 3. Creare il .env
Set-Content C:/ATG_RUN/Dashboard/.env "LOGIN=true`nDASHBOARD_USER=TDI_admin`nDASHBOARD_PASSWORD=Dashboard_TDI_26!`nRPA_REPORT_PORT=8473"
# 4. Installare NSSM e creare il Windows Service
# Scaricare NSSM da https://nssm.cc
nssm install rpa-dashboard python C:/ATG_RUN/Dashboard/Dashboard.py
nssm set rpa-dashboard AppDirectory C:/ATG_RUN/Dashboard
nssm start rpa-dashboard
```
---
## Verifica deploy
### Linux
```bash
# Stato del container
docker ps | grep rpa-dashboard-test
# Log in tempo reale
docker logs -f rpa-dashboard-test
# Riavvio manuale
docker restart rpa-dashboard-test
```
Dashboard: `https://dashboard.57.131.52.95.nip.io`
### Windows
```powershell
# Stato del service
Get-Service rpa-dashboard
# Riavvio manuale
Restart-Service rpa-dashboard
```
+22
View File
@@ -0,0 +1,22 @@
---
# ci.yml — Lint + Syntax check
# Eseguito su ogni push, PR, tag e manual
when:
event: [push, pull_request, tag, manual]
steps:
- name: lint
image: python:3.14
commands:
- pip install --upgrade pip --quiet
- pip install flake8 --quiet
- flake8 . --max-line-length=120 --exclude=__pycache__
- name: syntax
image: python:3.14
depends_on: [lint]
commands:
- pip install --upgrade pip --quiet
- pip install python-dotenv --quiet
- python -m compileall -q .
+83
View File
@@ -0,0 +1,83 @@
---
# deploy-prod.yml — Build + Deploy su VM Windows remota (SSH, senza Docker)
#
# Trigger: git tag prod && git push --force --tags
#
# Prerequisiti sulla VM Windows:
# - OpenSSH Server abilitato
# - Windows Service "rpa-dashboard" creato con NSSM
# - C:/ATG_RUN/Dashboard/.env → già presente
#
# Secrets richiesti in Woodpecker:
# win_host → IP o hostname della VM Windows
# win_user → utente SSH (es. Administrator)
# win_ssh_key → chiave privata SSH (contenuto id_rsa)
when:
event: [tag, manual]
tag: prod
steps:
- name: build
image: python:3.14
commands:
- apt-get update -qq && apt-get install -y zip --quiet
- pip install --upgrade pip --quiet
- pip install python-dotenv rcssmin rjsmin --quiet
- |
python - <<'EOF'
import os, zipfile, fnmatch
EXCLUDE_FILES = ["tmp_*", "*.md"]
EXCLUDE_DIRS = {".git", "__pycache__", "data", "tests", "docs", "secrets"}
EXCLUDE_EXACTLY = {".env"}
OUT = "rpa-tdi-dashboard-prod.zip"
def is_excluded(rel):
parts = rel.replace(os.sep, "/").split("/")
if parts[0] in EXCLUDE_DIRS:
return True
name = parts[-1]
if name in EXCLUDE_EXACTLY:
return True
for pat in EXCLUDE_FILES:
if fnmatch.fnmatch(name, pat):
return True
return False
with zipfile.ZipFile(OUT, "w", zipfile.ZIP_DEFLATED) as zf:
for root, dirs, files in os.walk("."):
dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS and not d.startswith(".")]
for f in files:
path = os.path.join(root, f)
rel = os.path.relpath(path, ".")
if not is_excluded(rel):
zf.write(path, rel)
print(f" + {rel}")
print(f"\n✓ {OUT}")
EOF
- ls -lh rpa-tdi-dashboard-prod.zip
- name: deploy
image: alpine
depends_on: [build]
environment:
WIN_HOST:
from_secret: win_host
WIN_USER:
from_secret: win_user
WIN_KEY:
from_secret: win_ssh_key
commands:
- apk add --no-cache openssh-client --quiet
- mkdir -p ~/.ssh
- echo "$WIN_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- scp -o StrictHostKeyChecking=no rpa-tdi-dashboard-prod.zip $WIN_USER@$WIN_HOST:"C:/ATG_RUN/Dashboard/"
- ssh -o StrictHostKeyChecking=no $WIN_USER@$WIN_HOST
"powershell -Command Stop-Service rpa-dashboard -ErrorAction SilentlyContinue"
- ssh $WIN_USER@$WIN_HOST
"powershell -Command Expand-Archive -Force C:/ATG_RUN/Dashboard/rpa-tdi-dashboard-prod.zip C:/ATG_RUN/Dashboard/"
- ssh $WIN_USER@$WIN_HOST
"powershell -Command Start-Service rpa-dashboard"
- echo "✓ Deploy completato su Windows ($WIN_HOST)"
+20 -40
View File
@@ -1,42 +1,23 @@
---
# .woodpecker.yml — RPA TDI Dashboard Service
# Forge: Gitea — Runner: Ubuntu cloud + Docker
# deploy-test.yml — Build + Deploy su VM Linux (Docker + Traefik)
#
# Flusso:
# push / PR → lint + syntax
# tag prod → lint + syntax + build + deploy (automatico)
# Trigger: git tag test && git push --force --tags
#
# Per pubblicare:
# git tag prod && git push --tags
# Prerequisiti sulla VM Linux:
# - /ATG_RUN_TEST/Dashboard/.env → già presente
# - Woodpecker runner con volumes abilitati (WOODPECKER_BACKEND_DOCKER_VOLUMES=true)
# - Traefik in esecuzione sulla rete "traefik_public"
when:
event: [push, pull_request, tag, manual]
event: [tag, manual]
tag: test
steps:
- name: lint
image: python:3.12-slim
when:
event: [push, pull_request, tag, manual]
commands:
- pip install flake8 --quiet
- flake8 . --max-line-length=120 --exclude=__pycache__
- name: syntax
image: python:3.12-slim
when:
event: [push, pull_request, tag, manual]
depends_on: [lint]
commands:
- pip install python-dotenv --quiet
- python -m compileall -q .
- name: build
image: python:3.12-slim
when:
event: [tag, manual]
tag: prod
image: python:3.14
commands:
- apt-get update -qq && apt-get install -y zip --quiet
- pip install --upgrade pip --quiet
- pip install python-dotenv rcssmin rjsmin --quiet
- |
python - <<'EOF'
@@ -72,14 +53,8 @@ steps:
EOF
- ls -lh rpa-tdi-dashboard-prod.zip
# Copia i file su /ATG_RUN_TEST/Dashboard e riavvia il container
# Prerequisiti sulla VM:
# - /ATG_RUN_TEST/Dashboard/.env → già presente con le variabili locali
# - Woodpecker runner configurato con volumes abilitati (WOODPECKER_BACKEND_DOCKER_VOLUMES=true)
- name: deploy
image: docker:cli
when:
event: [tag, manual]
depends_on: [build]
volumes:
- /ATG_RUN_TEST/Dashboard:/app
@@ -88,16 +63,21 @@ steps:
- apk add --no-cache unzip --quiet
- unzip -o rpa-tdi-dashboard-prod.zip -d /app
- echo "✓ File estratti in /ATG_RUN_TEST/Dashboard"
- docker stop rpa-dashboard-test 2>/dev/null || true
- docker rm rpa-dashboard-test 2>/dev/null || true
- docker stop rpa-dashboard-test 2>/dev/null || true
- docker rm rpa-dashboard-test 2>/dev/null || true
- docker run -d
--name rpa-dashboard-test
--restart unless-stopped
--network traefik_public
-v /ATG_RUN_TEST/Dashboard:/app
-v /ATG_RUN_TEST/db:/rpa-db
-w /app
-e RPA_DB_DIR=/rpa-db
-p 8473:8473
python:3.12-slim
--label "traefik.enable=true"
--label "traefik.http.routers.rpa-dashboard.rule=Host(`dashboard.57.131.52.95.nip.io`)"
--label "traefik.http.routers.rpa-dashboard.entrypoints=websecure"
--label "traefik.http.routers.rpa-dashboard.tls.certresolver=letsencrypt"
--label "traefik.http.services.rpa-dashboard.loadbalancer.server.port=8473"
python:3.14
sh -c "pip install -r requirements.txt -q && python Dashboard.py"
- echo "✓ Container avviato su http://57.131.52.95:8473"
- echo "✓ Container avviato su https://dashboard.57.131.52.95.nip.io"
-111
View File
@@ -1,111 +0,0 @@
# RPA Dashboard — Autodeploy con Woodpecker CI
## Panoramica
Il deploy avviene automaticamente tramite **Woodpecker CI** collegato a **Gitea**.
Non serve nessun intervento manuale: basta taggare un commit con `prod`.
---
## Flusso
```
push / PR → lint + syntax check (verifica automatica ad ogni commit)
tag prod → lint → syntax → build → deploy
└─ estrae i file su /ATG_RUN_TEST/Dashboard
└─ riavvia il container Docker
└─ dashboard live su http://57.131.52.95:8473
```
---
## Pubblicare una nuova versione
### Automatico — tag `prod` (raccomandato)
```bash
# 1. Commit delle modifiche
git add .
git commit -m "descrizione modifica"
# 2. Spostare il tag prod sul commit corrente e pubblicare
git tag -f prod
git push --force --tags
```
Woodpecker riceve il webhook da Gitea e avvia la pipeline in automatico.
### Manuale — dal pannello Woodpecker
Apri la pipeline su Woodpecker UI → pulsante **"trigger manually"**.
Esegue build + deploy senza bisogno di taggare (utile per test o fix rapidi).
---
## Step della pipeline (`.woodpecker.yml`)
| Step | push / PR | tag `prod` | manuale | Cosa fa |
|---|---|---|---|---|
| `lint` | ✓ | ✓ | ✓ | flake8 — controlla stile e errori Python |
| `syntax` | ✓ | ✓ | ✓ | `py_compile` su tutti i `.py` |
| `build` | — | ✓ | ✓ | crea `rpa-tdi-dashboard-prod.zip` (esclude `.env`, `__pycache__`, `*.md`, ecc.) |
| `deploy` | — | ✓ | ✓ | estrae lo zip in `/ATG_RUN_TEST/Dashboard`, riavvia il container |
---
## Infrastruttura
| Componente | Dettaglio |
|---|---|
| Forge | Gitea (self-hosted) |
| CI | Woodpecker CI — Ubuntu cloud + Docker |
| VM | `57.131.52.95` |
| Porta dashboard | `8473` |
| Cartella deploy | `/ATG_RUN_TEST/Dashboard` |
| Cartella DB | `/ATG_RUN_TEST/db` |
| Container | `rpa-dashboard-test` |
---
## Prerequisiti sulla VM (setup iniziale, una tantum)
```bash
# Creare le cartelle
mkdir -p /ATG_RUN_TEST/Dashboard
mkdir -p /ATG_RUN_TEST/db
# Creare il .env con le variabili locali Linux
cat > /ATG_RUN_TEST/Dashboard/.env <<EOF
LOGIN=true
DASHBOARD_USER=TDI_admin
DASHBOARD_PASSWORD=Dashboard_TDI_26!
RPA_REPORT_PORT=8473
EOF
# Copiare i file .db nella cartella db
# es. cp rpa_FORMAZIONE.db /ATG_RUN_TEST/db/
```
Abilitare i volume mounts nel Woodpecker runner (nel file di config dell'agent):
```env
WOODPECKER_BACKEND_DOCKER_VOLUMES=true
```
---
## Verifica deploy
```bash
# Stato del container
docker ps | grep rpa-dashboard-test
# Log in tempo reale
docker logs -f rpa-dashboard-test
# Riavvio manuale (se necessario)
docker restart rpa-dashboard-test
```
Dashboard: `http://57.131.52.95:8473/login`