# GitHub Actions per un sito: la pipeline minima

Un workflow che costruisce, conserva l'artefatto e pubblica solo da main: versione dei pacchetti, cache, permessi e i punti in cui si rompe.

> Pagina: https://ui.eneawork.it/blog/come-usare-github-actions
> Markdown: https://ui.eneawork.it/blog/come-usare-github-actions.md

*2026-11-01*

GitHub Actions per un sito è un file YAML in .github/workflows: un job che costruisce, uno che pubblica e un permesso in sola lettura. Le versioni misurate sono checkout 7.0.1 e setup-node 7.1.0.

Le release lette dall'API GitHub il 1 novembre 2026 sono actions/checkout v7.0.1, actions/setup-node v7.1.0, actions/cache v6.1.0 e actions/upload-artifact v7.0.2. Il catalogo EneUI conta 111.985 componenti da 1.472 librerie, misurati da /api/stats lo stesso giorno: è il sito che questa pipeline deve costruire.

## Il file minimo

name: ci on: push: branches: [main] pull_request: concurrency: group: ci-${{ github.ref }} cancel-in-progress: true permissions: contents: read jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: actions/setup-node@v7 with: node-version: 24 cache: npm - run: npm ci - run: npm run build - uses: actions/upload-artifact@v7 with: name: dist path: dist retention-days: 7

concurrency annulla il run precedente sullo stesso ref; permissions: contents: read riduce il token al solo checkout. Senza quel blocco il token porta con sé i permessi di default del repository.

## La cache che si invalida da sola

- uses: actions/cache@v6 with: path: ~/.npm key: npm-${{ hashFiles('**/package-lock.json') }} restore-keys: npm-

La chiave contiene l'hash del lockfile: cambi una dipendenza, cambia la chiave, la cache si ricrea. Una chiave fissa lascerebbe pacchetti vecchi per mesi, e il sintomo sarebbe una build che passa solo in CI.

## Pubblicare solo da main

deploy: needs: build if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest environment: production steps: - uses: actions/download-artifact@v7 with: name: dist path: dist - name: Publish env: SSH_KEY: ${{ secrets.DEPLOY_KEY }} run: | install -m 600 /dev/null key printf "%s" "$SSH_KEY" > key rsync -az --delete -e 'ssh -i key' dist/ deploy@example.com:/var/www/site/

needs impone che il build sia verde, if limita il job al ramo principale. Su un pull request da fork i secret non arrivano, quindi il job salta e la CI resta verde senza esporre la chiave.

## Artefatti e diagnosi

gh run list --limit 5 gh run watch gh run download -n dist

upload-artifact conserva dist per sette giorni; gh run download -n dist riporta quei file in locale senza rifare la build. gh run watch segue il run fino alla fine, con i log del passo che fallisce.

## Matrice e tempi

strategy: fail-fast: false matrix: node: [22, 24]

La matrice duplica il job per ogni versione di Node. fail-fast: false lascia finire le altre combinazioni, così vedi se il problema è solo sulla versione vecchia.

## Limite dichiarato

I minuti si pagano sui repository privati, e ogni matrice li moltiplica. cancel-in-progress uccide anche un deploy a metà se arriva un push durante il rilascio: separa build e deploy in due workflow se il rilascio dura più di qualche minuto.

## Dove continuare

Tre componenti che finiscono nel build: input, spinner e la griglia delle icone; il resto è in components/lib e nelle 1.556 anteprime. Gli errori di build sono in errori di build comuni, l'ordine delle cartelle in App Router nel 2026. Il confronto fra Vite e Next per un sito marketing è in Next.js vs Vite.

## FAQ

### Quanto costa GitHub Actions per un sito piccolo?

Sui repository pubblici i minuti sono gratuiti; su quelli privati il piano Free include 2.000 minuti al mese. Una build di due minuti per push sta largamente dentro quel tetto.

### Dove metto la chiave SSH per il deploy?

In un secret del repository o dell'environment, mai nel file YAML. Il secret si passa al passo come variabile d'ambiente, e la chiave si scrive su disco con permessi 600.

### Perché il job di deploy viene saltato sui pull request?

Perché la condizione if limita il job al ramo main, e perché i secret non sono disponibili per i fork. È il comportamento voluto: il pull request verifica il build, non pubblica.

### Meglio cache di setup-node o actions/cache?

setup-node con cache: npm copre il caso normale e richiede due righe. actions/cache serve quando devi conservare una cartella che setup-node non conosce, per esempio un browser o un binario scaricato a mano.

### Posso lanciare il workflow a mano?

Sì, aggiungendo workflow_dispatch fra i trigger. Da terminale il comando è gh workflow run ci.yml, e gh run watch segue l'esecuzione.
