Introduzione: Deploy Automatico con Firebase e GitHub Actions
Il deploy manuale e il nemico della produttività e dell'affidabilità. Ogni volta che esegui
firebase deploy dal tuo terminale, introduci il rischio di errori umani: dimenticare
di fare il build, deployare dal branch sbagliato, o saltare i test. In questo articolo costruiremo
un sistema di deploy completamente automatizzato usando Firebase Hosting e
GitHub Actions.
Firebase Hosting e una piattaforma di hosting per applicazioni web statiche e dinamiche che offre CDN globale, certificati SSL automatici, preview channel per le Pull Request, e rollback istantaneo. Combinato con GitHub Actions, crea un flusso di lavoro dove ogni push a main viene automaticamente deployato in produzione, e ogni Pull Request genera un'anteprima accessibile via URL.
Cosa Imparerai in Questo Articolo
- Come configurare Firebase CLI e inizializzare un progetto
- La struttura del file
firebase.jsone le sue opzioni - Come creare preview channel automatici per le Pull Request
- Il workflow completo per il deploy in produzione
- Strategie di rollback per gestire errori in produzione
- Come configurare un dominio personalizzato
- Header di caching e regole di redirect
- Confronto tra Firebase Hosting e le alternative
1. Setup di Firebase CLI
Il primo passo e installare e configurare la Firebase CLI. Questa CLI e lo strumento principale per interagire con Firebase dal terminale e dalle pipeline CI/CD.
# Installare Firebase CLI globalmente
npm install -g firebase-tools
# Verificare l'installazione
firebase --version
# Login (apre il browser per l'autenticazione)
firebase login
# Per ambienti CI/CD, usare un token
firebase login:ci
# Questo genera un token da salvare come segreto GitHub
# Inizializzare Firebase nel progetto
firebase init hosting
Durante l'inizializzazione, Firebase fara alcune domande sulla configurazione. Ecco le risposte consigliate per un progetto Angular:
- Public directory:
dist/my-app/browser(la cartella di output della build Angular) - Configure as single-page app: Si (riscrive tutti gli URL a index.html)
- Set up automatic builds with GitHub: Si (configura automaticamente i workflow)
- Overwrite index.html: No (usiamo il nostro)
2. Configurazione firebase.json
Il file firebase.json e il cuore della configurazione di Firebase Hosting. Ecco
una configurazione completa e ottimizzata per un progetto Angular:
{
"hosting": {
"public": "dist/my-app/browser",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
],
"headers": [
{
"source": "**/*.@(js|css)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
},
{
"source": "**/*.@(jpg|jpeg|gif|png|svg|webp|ico)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=86400"
}
]
},
{
"source": "**/*.@(woff|woff2|ttf|eot)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
},
{
"source": "**",
"headers": [
{
"key": "X-Frame-Options",
"value": "SAMEORIGIN"
},
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-XSS-Protection",
"value": "1; mode=block"
},
{
"key": "Referrer-Policy",
"value": "strict-origin-when-cross-origin"
}
]
}
]
}
}
Sezioni Chiave di firebase.json
| Sezione | Scopo | Dettaglio |
|---|---|---|
public |
Directory dei file da servire | Deve corrispondere all'output della build Angular |
rewrites |
Routing SPA | Tutte le richieste vengono reindirizzate a index.html |
headers |
Caching e sicurezza | Cache aggressiva per asset con hash, header di sicurezza globali |
ignore |
File da escludere | File di configurazione e directory nascoste |
Regole di Redirect
Firebase Hosting supporta redirect HTTP per gestire URL legacy o forzare HTTPS:
{
"hosting": {
"redirects": [
{
"source": "/old-blog/:slug",
"destination": "/blog/:slug",
"type": 301
},
{
"source": "/api/**",
"destination": "https://api.example.com/v1/:splat",
"type": 302
},
{
"source": "/docs",
"destination": "https://docs.example.com",
"type": 301
}
]
}
}
3. Preview Channel per le Pull Request
I preview channel sono una delle funzionalità più potenti di Firebase Hosting. Ogni Pull Request ottiene automaticamente un URL unico dove e possibile visualizzare le modifiche prima del merge. Ecco il workflow completo:
# .github/workflows/firebase-preview.yml
name: Firebase Preview Deploy
on:
pull_request:
branches: [main]
jobs:
build-and-preview:
name: Build and Deploy Preview
runs-on: ubuntu-latest
permissions:
checks: write
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npx ng test --watch=false --browsers=ChromeHeadless
- name: Build application
run: npx ng build --configuration=production
- name: Deploy to Firebase Preview Channel
uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: ${{ secrets.GITHUB_TOKEN }}
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
projectId: my-angular-project
expires: 7d
Dopo il deploy, l'action aggiunge automaticamente un commento alla Pull Request con l'URL
del preview. Il parametro expires: 7d configura la scadenza automatica del
preview channel dopo 7 giorni.
Come Ottenere il Firebase Service Account
- Vai alla Console Firebase
- Seleziona il progetto > Impostazioni progetto > Account di servizio
- Clicca su "Genera nuova chiave privata"
- Scarica il file JSON
- Copia il contenuto e aggiungilo come segreto GitHub con nome
FIREBASE_SERVICE_ACCOUNT
4. Workflow di Deploy in Produzione
Il workflow di produzione viene eseguito solo sui push al branch main e include
tutti i controlli di qualità prima del deploy:
# .github/workflows/firebase-production.yml
name: Firebase Production Deploy
on:
push:
branches: [main]
concurrency:
group: production-deploy
cancel-in-progress: false
jobs:
test:
name: Run Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npx ng lint
- run: npx ng test --watch=false --browsers=ChromeHeadless
build:
name: Build Application
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npx ng build --configuration=production
- uses: actions/upload-artifact@v4
with:
name: production-build
path: dist/
retention-days: 1
deploy:
name: Deploy to Production
runs-on: ubuntu-latest
needs: build
environment: production
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: production-build
path: dist/
- name: Deploy to Firebase Hosting
uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: ${{ secrets.GITHUB_TOKEN }}
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
channelId: live
projectId: my-angular-project
Concurrency per Deploy in Produzione
Nota l'impostazione cancel-in-progress: false per il deploy in produzione.
A differenza del CI dove possiamo cancellare build precedenti, per il deploy in produzione
e meglio completare il deploy in corso prima di iniziarne uno nuovo, per evitare stati
inconsistenti.
5. Strategia di Rollback
Nonostante test e review, a volte un deploy in produzione introduce problemi. Firebase Hosting offre diverse strategie per il rollback:
Rollback dalla Console Firebase
La Console Firebase mantiene la cronologia dei deploy. Per fare rollback a una versione precedente, vai su Hosting > Release history e clicca su "Rollback" accanto alla versione desiderata. Questo processo e istantaneo perchè Firebase mantiene tutti i file delle release precedenti sulla CDN.
Rollback via CLI
# Elencare le release recenti
firebase hosting:releases:list --limit 10
# Fare rollback a una release specifica
firebase hosting:rollback --release RELEASE_ID
# Alternativa: clone di una release precedente
firebase hosting:clone SOURCE_SITE:SOURCE_CHANNEL TARGET_SITE:live
Rollback Automatico via GitHub Actions
# .github/workflows/rollback.yml
name: Emergency Rollback
on:
workflow_dispatch:
inputs:
commit-sha:
description: 'Commit SHA to rollback to'
required: true
type: string
reason:
description: 'Reason for rollback'
required: true
type: string
jobs:
rollback:
name: Rollback to Previous Version
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout specific commit
uses: actions/checkout@v4
with:
ref: ${{ inputs.commit-sha }}
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npx ng build --configuration=production
- name: Deploy rollback version
uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: ${{ secrets.GITHUB_TOKEN }}
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
channelId: live
projectId: my-angular-project
- name: Notify team
run: |
echo "Rollback completed"
echo "Commit: ${{ inputs.commit-sha }}"
echo "Reason: ${{ inputs.reason }}"
6. Configurazione Dominio Personalizzato
Firebase Hosting supporta domini personalizzati con certificato SSL gratuito. Il processo di configurazione richiede la verifica della proprietà del dominio tramite record DNS.
Passi per la Configurazione
- Vai alla Console Firebase > Hosting > "Add custom domain"
- Inserisci il tuo dominio (es.
example.com) - Firebase fornira i record DNS da configurare nel tuo registrar
- Aggiungi i record TXT per la verifica e i record A per il routing
- Attendi la propagazione DNS (fino a 48 ore, tipicamente 1-4 ore)
- Firebase emettera automaticamente un certificato SSL
Record DNS da configurare:
# Verifica proprietà
TXT @ firebase-hosting-verification=xxxxxxxxxxxxx
# Routing al CDN Firebase
A @ 151.101.1.195
A @ 151.101.65.195
# Sottodominio www (opzionale)
CNAME www my-project.web.app
7. Header di Caching Ottimizzati
Una configurazione di caching corretta e fondamentale per le prestazioni. Angular genera file
con hash nel nome (es. main.abc123.js), che possono essere memorizzati in cache
per un anno intero. Il file index.html invece non deve mai essere memorizzato
in cache, perchè contiene i riferimenti ai file con hash:
{
"hosting": {
"headers": [
{
"source": "/index.html",
"headers": [
{
"key": "Cache-Control",
"value": "no-cache, no-store, must-revalidate"
}
]
},
{
"source": "ngsw.json",
"headers": [
{
"key": "Cache-Control",
"value": "no-cache"
}
]
},
{
"source": "**/*.@(js|css)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
},
{
"source": "**/*.@(jpg|jpeg|png|gif|svg|webp|avif|ico)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=604800"
}
]
},
{
"source": "**/*.@(woff|woff2)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
}
]
}
}
8. Confronto con le Alternative
Firebase Hosting non e l'unica opzione per il deploy di applicazioni Angular. Ecco un confronto con le alternative più popolari:
Firebase Hosting vs Alternative
| Caratteristica | Firebase | Vercel | Netlify | AWS S3 + CloudFront |
|---|---|---|---|---|
| Setup | Semplice | Molto semplice | Molto semplice | Complesso |
| SSL gratuito | Si | Si | Si | Si (ACM) |
| CDN globale | Si | Si | Si | Si |
| Preview deploy | Si | Si (automatico) | Si (automatico) | Manuale |
| Rollback | Istantaneo | Istantaneo | Istantaneo | Manuale |
| Piano gratuito | 10 GB storage, 360 MB/day transfer | 100 GB bandwidth | 100 GB bandwidth | Pay-as-you-go |
| SSR Support | Si (Cloud Functions) | Si (nativo) | Si (Functions) | Si (Lambda@Edge) |
9. Testing del Deploy in Locale
Prima di configurare il deploy automatico, e utile testare la configurazione Firebase in locale:
# Build dell'applicazione
npm run build
# Testare Firebase Hosting in locale
firebase emulators:start --only hosting
# Il sito sarà disponibile su http://localhost:5000
# Questo simula esattamente il comportamento di Firebase Hosting:
# - Rewrites SPA
# - Headers personalizzati
# - Redirect rules
# - Clean URLs
# Alternativa: serve direttamente la directory di build
firebase serve --only hosting
Checklist Pre-Deploy
- La build di produzione viene generata senza errori
- I test passano tutti
- Il file
firebase.jsonpunta alla directory corretta - Gli header di caching sono configurati correttamente
- I redirect per URL legacy sono in posizione
- L'emulatore locale mostra il sito correttamente
- Il service account Firebase e configurato come segreto GitHub
- Le branch protection rules sono attive
Conclusione
In questo articolo abbiamo costruito un sistema di deploy completamente automatizzato con Firebase Hosting e GitHub Actions. Abbiamo configurato preview channel per le Pull Request, workflow di produzione con controlli di qualità, strategie di rollback per gestire emergenze, e ottimizzato la configurazione di caching e sicurezza.
Il vantaggio principale di questo approccio e la fiducia: una volta configurato, ogni modifica che passa la review e i test viene automaticamente deployata, senza intervento manuale e senza possibilità di errori. E se qualcosa va storto, il rollback e a portata di click.
Nel prossimo articolo affronteremo un tema cruciale per la sicurezza: la gestione dei segreti nelle pipeline CI/CD, esplorando come proteggere API key, token di servizio e credenziali durante il processo di build e deploy.
Domande frequenti
Come posso evitare errori umani nel processo di deploy manuale?
Utilizzando un sistema di deploy completamente automatizzato come quello descritto in questo articolo, che combina Firebase Hosting e GitHub Actions.
Qual è il vantaggio principale di utilizzare Firebase Hosting per il deploy delle applicazioni web statiche e dinamiche?
Il vantaggio principale è la possibilità di avere una piattaforma di hosting con CDN globale, certificati SSL automatici, preview channel per le Pull Request e rollback istantaneo.
Come posso configurare il preview channel per le Pull Request in Firebase Hosting?
Per configurare il preview channel è necessario utilizzare GitHub Actions e specificare la configurazione del preview channel nel file .yml della pipeline.
Quali sono le strategie di rollback disponibili in Firebase Hosting?
Le strategie di rollback disponibili in Firebase Hosting includono il rollback dalla Console Firebase, il rollback via CLI e il rollback automatico via GitHub Actions.

Commenti
Caricamento commenti...
Accedi per commentare