Hai mai passato un'ora a fare deploy manuale via FTP, dimenticato di escludere la cartella di debug, e scoperto che il sito è andato giù? Oppure hai lanciato un aggiornamento in produzione senza testare su staging e il form contatti ha smesso di funzionare? Noi, di Meteora Web, lo vediamo ogni giorno nei progetti che ci arrivano. Il deploy manuale è il costo nascosto che mangia margini: tempo perso, errori umani, clienti scontenti. Una CD pipeline ben fatta risolve tutto. In questa guida ti mostriamo come costruirne una per staging e produzione, con codice funzionante e logica economica solida.
Perché un deploy automatico è un investimento, non una spesa?
Se ragioni come un contabile — e noi veniamo dalla contabilità — sai che ogni operazione ripetitiva va misurata in €/ora. Prendi un deploy manuale: preparare i file, connettersi via FTP, sovrascrivere, testare, eventualmente rollback. Un team di due sviluppatori può perdere 2-3 ore a settimana. Su 50 settimane, sono 100-150 ore all'anno. Se il tuo costo medio orario è 50 €, parliamo di 5.000-7.500 € l'anno buttati via. Una pipeline CD costa qualche ora di setup iniziale e poi gira da sola. Il ROI è immediato.
Inoltre, l'errore umano costa caro: un file .env con credenziali sbagliate, una cartella di sviluppo lasciata online, un aggiornamento di plugin non testato. Lo abbiamo visto su un e-commerce di abbigliamento: un deploy manuale ha sovrascritto il database delle taglie. Recupero dei backup: 4 ore di lavoro extra, e nel frattempo il negozio offline. Con una CD pipeline, quella roba non succede.
Sponsored Protocol
Come funziona una CD pipeline per staging e produzione?
Una Continuous Delivery pipeline automatica il passaggio del codice dalla repository all'ambiente di destinazione. Il flusso tipico è: push su branch → test automatici (CI) → build → deploy su staging → (opzionale) test di accettazione → deploy su produzione con approvazione manuale. Noi usiamo GitHub Actions, ma il concetto vale per GitLab CI, Bitbucket Pipelines, Jenkins. La chiave è separare staging (ambiente di verifica) da produzione (ambiente live), con gate che impediscano di pubblicare senza controllo.
Struttura dei branch
Lavoriamo con un modello semplice: il branch main è sempre ciò che è in produzione. Il branch develop è per il lavoro in corso. Da develop si creano feature branch, e quando sono pronti si fa merge su develop. Poi, da develop si crea una release branch per il deploy in staging. Infine, la release branch viene mergiata su main per la produzione. Questo evita che codice instabile raggiunga i clienti.
Ambienti e variabili d'ambiente
Ogni ambiente ha il suo file di configurazione (.env.staging, .env.production) con dati reali di connessione al database, API key, ecc. Mai salvare queste variabili nel repository. Le gestiamo tramite GitHub Secrets o una vault esterna. La pipeline inietta le variabili al momento del deploy. In questo modo il codice è identico in tutti gli ambienti, cambia solo la configurazione.
Sponsored Protocol
Come impostare un flusso di deploy automatico su staging senza rischi?
Partiamo da uno scenario concreto: un'app PHP/Laravel (ma i principi valgono per Node, Python, WordPress custom). Abbiamo una VPS Linux con accesso SSH e vogliamo che ogni push su develop faccia il deploy su staging.
Script di deploy via SSH (base)
Usiamo uno script bash lanciato dalla pipeline. Ecco un esempio per Laravel con rsync per trasferire solo i file modificati, riducendo i tempi:
#!/bin/bash
# deploy-staging.sh
SERVER_USER="deploy"
SERVER_HOST="staging.example.com"
SERVER_PATH="/var/www/staging"
# Trasferimento via rsync con esclusioni
echo "Trasferimento file..."
rsync -avz --delete \
--exclude '.git' \
--exclude '.env' \
--exclude 'node_modules' \
--exclude 'storage' \
--exclude 'vendor' \
-e ssh ./ $SERVER_USER@$SERVER_HOST:$SERVER_PATH
# Comandi post-deploy (via SSH)
echo "Esecuzione comandi post-deploy..."
ssh $SERVER_USER@$SERVER_HOST "
cd $SERVER_PATH &&
composer install --no-dev --optimize-autoloader &&
php artisan migrate --force &&
php artisan config:cache &&
php artisan route:cache &&
php artisan view:cache &&
php artisan queue:restart
"
echo "Deploy su staging completato."
Nota: composer install e artisan migrate sono eseguiti lato server. La pipeline deve avere accesso SSH con chiave privata (da salvare come secret).
Sponsored Protocol
Workflow GitHub Actions per staging
Crea un file .github/workflows/deploy-staging.yml:
name: Deploy to Staging
on:
push:
branches: [ develop ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.STAGING_HOST }} >> ~/.ssh/known_hosts
- name: Run deploy script
run: |
chmod +x ./scripts/deploy-staging.sh
./scripts/deploy-staging.sh
env:
SERVER_USER: ${{ secrets.STAGING_USER }}
SERVER_HOST: ${{ secrets.STAGING_HOST }}
SERVER_PATH: ${{ secrets.STAGING_PATH }}
Ogni volta che fai push su develop, la pipeline esegue rsync e post-deploy. Zero intervento manuale.
Quali accorgimenti per un deploy in produzione sicuro e senza impatti?
La produzione è un'altra storia: non puoi permetterti downtime. E non puoi far partire un deploy senza approvazione umana. Ecco come strutturiamo la CD per produzione con approvazione (approval gate) e zero-downtime.
Workflow di produzione con approvazione manuale
Usiamo workflow_run o environment con required reviewers. In GitHub Actions, crei un environment “production” con branch main e abiliti “Required reviewers”. Poi, nel workflow:
Sponsored Protocol
name: Deploy to Production
on:
push:
branches: [ main ]
jobs:
approve:
runs-on: ubuntu-latest
environment: production
steps:
- run: echo "Approvazione ottenuta"
deploy:
needs: approve
runs-on: ubuntu-latest
steps:
# setup SSH e rsync con script simile, ma versione produzione
In questo modo, quando si fa push su main, il job “approve” aspetta che un reviewer (es. il lead developer) dia il via. Solo dopo parte il deploy. Nessun deploy accidentale.
Zero-downtime deploy per applicazioni web
Per evitare che il sito sia offline durante il deploy, usiamo una tecnica di symbolic link. Sul server, manteniamo due directory: /var/www/production/releases/20240501-v1.2.3 (nuova release) e un link simbolico /var/www/production/current -> releases/20240501-v1.2.3. La pipeline:
- Carica la nuova release in una directory temporanea con timestamp.
- Esegue
composer install,artisan migrate, ecc. - Se tutto ok, aggiorna il link simbolico
ln -sfn releases/nuova current - Pulisce le release vecchie (es. mantieni ultime 3).
In questo modo il server web (Nginx/Apache) punta sempre a current. Lo switch è istantaneo. Eventuali utenti in sessione continuano a vedere la vecchia versione fino al prossimo caricamento pagina, ma non c'è downtime.
Rollback immediato
Se il deploy causa errori, il rollback è un semplice cambio di link simbolico. Puoi automatizzare anche quello con un workflow separato su richiesta. Basta avere uno script che punta current alla release precedente. Noi lo integriamo con un comando Slack / deploy:rollback.
Sponsored Protocol
Cosa fare adesso — Azioni concrete
Non serve implementare tutto in un giorno. Ecco i passi immediati per iniziare:
- Identifica i tuoi ambienti: hai almeno un server di staging? Altrimenti creane uno (anche un VPS da 5€/mese è meglio di niente).
- Configura SSH key-based auth: genera una coppia di chiavi, aggiungi la pubblica al server, salva la privata come secret nel tuo repository (es.
SSH_PRIVATE_KEY). - Crea uno script di deploy base (rsync) per staging, come quello sopra. Testalo manualmente prima di integrarlo nella pipeline.
- Imposta un workflow CI/CD con il trigger sul branch
develop. Usa GitHub Actions o GitLab CI. - Aggiungi l'approvazione manuale per produzione e lo zero-downtime switch. Non serve subito, ma pianifica di implementarlo prima del prossimo rilascio importante.
- Monitora i deploy: integra notifiche su Slack/Telegram per sapere se tutto è andato bene o se c'è stato un fallimento.
Se vuoi approfondire l'intero ciclo DevOps, leggi la nostra guida pillar su DevOps e CI/CD Pipeline.
E ricorda: un deploy automatico ben fatto non solo ti fa risparmiare tempo e denaro, ma trasforma il tuo team in una macchina affidabile. Niente più notti insonni per un deploy sbagliato. I clienti lo sentono — e lo vedono nel fatturato.