Git 29
🔀 Git & GitHub · Modulo 5 · Lezione 29
Linting e quality check ✨
Controllare la qualità automaticamente · HTMLHint · Stylelint · ESLint · Linter nel workflow CI
✨ I test verificano che il codice funziona. I linter verificano che il codice è scritto bene. Un linter è uno strumento che analizza il codice sorgente e segnala errori di stile, problemi potenziali, tag HTML non chiusi, proprietà CSS sconosciute, variabili inutilizzate. Non è un capriccio estetico — il codice pulito ha meno bug, è più facile da leggere e da mantenere. Integrato nel CI, il linter garantisce che tutto il team segua le stesse convenzioni.
🎯 Obiettivi della lezione
- Capire cos’è un linter e perché è utile
- Usare HTMLHint per verificare la qualità dell’HTML
- Usare Stylelint per verificare la qualità del CSS
- Usare ESLint per verificare la qualità del JavaScript
- Integrare i linter nel workflow CI
- Configurare le regole con file di configurazione
📖 1. Teoria
1.1 — Cos’è un linter
Un linter è un programma che analizza il codice sorgente senza eseguirlo e segnala problemi di stile, errori potenziali e violazioni delle convenzioni. Il nome viene da “lint” — i pelucchi che si tolgono dai vestiti.
Proprietà CSS sconosciute o duplicate
Variabili JS dichiarate ma mai usate
Uso di
== invece di ===Indentazione inconsistente
Errori di accessibilità (alt mancante)
Problemi di design (il layout è brutto)
Errori di business logic
Performance lenta
Vulnerabilità di sicurezza complesse
→ Per questi servono i test (Lezione 27)
| Linguaggio | Linter | Installa | Esegui |
|---|---|---|---|
| HTML | HTMLHint | npm install htmlhint –save-dev | npx htmlhint “**/*.html” |
| CSS | Stylelint | npm install stylelint stylelint-config-standard –save-dev | npx stylelint “**/*.css” |
| JavaScript | ESLint | npm init @eslint/config@latest | npx eslint . |
| Python | Ruff (o flake8) | pip install ruff | ruff check . |
1.2 — HTMLHint: linting dell’HTML
$ npm init -y
# Installa HTMLHint
$ npm install htmlhint –save-dev
# Esegui su tutti i file HTML
$ npx htmlhint “**/*.html”
index.html
L1 |<!DOCTYPE html>
Scanned 1 files, no errors found (3ms).
HTMLHint ha regole predefinite ragionevoli. Puoi personalizzarle con un file .htmlhintrc:
{
“tagname-lowercase”: true, // tag in minuscolo
“attr-lowercase”: true, // attributi in minuscolo
“attr-value-double-quotes”: true, // virgolette doppie
“doctype-first”: true, // DOCTYPE obbligatorio
“tag-pair”: true, // tag aperti devono essere chiusi
“alt-require”: true, // img deve avere alt (accessibilità)
“id-unique”: true, // id devono essere unici
“src-not-empty”: true // src non vuoto
}
1.3 — Stylelint: linting del CSS
$ npm install stylelint stylelint-config-standard –save-dev
# Esegui
$ npx stylelint “**/*.css”
style.css
12:3 ⚠ Unexpected duplicate “color” declaration-no-duplicates
25:1 ⚠ Expected empty line before rule rule-empty-line-before
{
“extends”: “stylelint-config-standard”,
“rules”: {
“declaration-no-duplicates”: true, // no proprietà duplicate
“color-no-invalid-hex”: true, // colori hex validi
“no-descending-specificity”: null, // disabilita questa regola
“rule-empty-line-before”: null // troppo pedante per la scuola
}
}
📌 Mettere null disabilita una regola. Alcune regole sono troppo rigide per un progetto scolastico (es. “riga vuota obbligatoria prima di ogni regola CSS”). Inizia con la configurazione standard, poi disabilita le regole che il team trova troppo invasive.
1.4 — ESLint: linting del JavaScript
$ npm init @eslint/config@latest
# Oppure installazione manuale
$ npm install eslint –save-dev
# Esegui
$ npx eslint .
script.js
3:7 error ‘risultato’ is assigned but never used no-unused-vars
8:5 warning Unexpected var, use let or const no-var
15:1 error ‘x’ is not defined no-undef
import js from “@eslint/js”;
export default [
js.configs.recommended, // regole raccomandate
{
rules: {
“no-unused-vars”: “warn”, // variabili inutilizzate = warning
“no-var”: “error”, // vietato var, usa let/const
“eqeqeq”: “error”, // === obbligatorio (no ==)
“no-console”: “off” // console.log permesso (per la scuola)
}
}
];
| Livello | Valore | Effetto | Il CI fallisce? |
|---|---|---|---|
| off | 0 | Regola disabilitata | No |
| warn | 1 | Avviso giallo — segnala ma non blocca | No |
| error | 2 | Errore rosso — blocca | Sì — exit code 1 |
1.5 — Integrare i linter nel workflow CI
name: Lint
on: [push, pull_request]
jobs:
lint-html:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– uses: actions/setup-node@v4
with:
node-version: 20
– run: npm ci
– name: HTMLHint
run: npx htmlhint “**/*.html”
lint-css:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– uses: actions/setup-node@v4
with:
node-version: 20
– run: npm ci
– name: Stylelint
run: npx stylelint “**/*.css”
lint-js:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– uses: actions/setup-node@v4
with:
node-version: 20
– run: npm ci
– name: ESLint
run: npx eslint .
1.6 — Script npm: semplificare i comandi
Invece di ricordare i comandi lunghi, configura gli script in package.json:
{
“scripts”: {
“lint:html”: “htmlhint ‘**/*.html'”,
“lint:css”: “stylelint ‘**/*.css'”,
“lint:js”: “eslint .”,
“lint”: “npm run lint:html && npm run lint:css && npm run lint:js”,
“test”: “node utils.test.js”
}
}
$ npm run lint ← esegue tutti e 3 i linter
$ npm run lint:html ← solo HTML
$ npm test ← esegue i test
# E nel workflow CI puoi semplicemente:
– run: npm run lint
– run: npm test
💻 2. Esempi guidati
Esempio A — Setup completo di linting per un progetto HTML/CSS/JS
$ npm init -y
# 2. Installa i linter
$ npm install –save-dev htmlhint stylelint stylelint-config-standard
# 3. Crea le configurazioni
$ echo ‘{“doctype-first”:true,”tag-pair”:true,”alt-require”:true}’ > .htmlhintrc
$ echo ‘{“extends”:”stylelint-config-standard”,”rules”:{“rule-empty-line-before”:null}}’ > .stylelintrc.json
# 4. Aggiungi gli script a package.json
# (modifica manualmente la sezione “scripts”)
# 5. Aggiungi node_modules al .gitignore
$ echo “node_modules/” >> .gitignore
# 6. Testa in locale
$ npx htmlhint “**/*.html”
$ npx stylelint “**/*.css”
# 7. Committa tutto
$ git add . && git commit -m “Aggiunto linting: HTMLHint + Stylelint”
$ git push
Esempio B — Workflow semplificato con npm scripts
name: CI
on: [push, pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– uses: actions/setup-node@v4
with:
node-version: 20
– run: npm ci
– name: Lint
run: npm run lint
– name: Test
run: npm test
🏋️ 3. Esercizi
🟢 Esercizio 1 — HTMLHint in locale (Facile)
npm init -y → npm install htmlhint --save-dev.b) Esegui:
npx htmlhint "**/*.html". Ci sono errori?c) Introduci un errore intenzionale (es. togli un tag di chiusura). Riesegui. HTMLHint lo trova?
d) Crea un file
.htmlhintrc con la regola "alt-require": true.e) Aggiungi un
<img> senza alt. HTMLHint lo segnala?f) Correggi tutti gli errori. Il linter passa con 0 errori.
🔵 Esercizio 2 — Aggiungi Stylelint (Medio)
npm install stylelint stylelint-config-standard --save-dev.b) Crea
.stylelintrc.json con la configurazione della sezione 1.3.c) Esegui:
npx stylelint "**/*.css". Quanti avvisi?d) Correggi gli errori critici. Disabilita le regole troppo pedanti con
null.e) Aggiungi gli script
lint:html, lint:css e lint a package.json.f) Verifica:
npm run lint esegue entrambi i linter senza errori.
🟠 Esercizio 3 — Lint nel CI (Medio)
.github/workflows/lint.yml con i job della sezione 1.5.b) Committa e pusha. I job di lint sono verdi?
c) Introduci un errore HTML (tag non chiuso). Pusha. Il job lint-html diventa rosso?
d) Se hai le branch protection: configura i job di lint come status check obbligatori.
e) Apri una PR con un errore CSS. Il merge è bloccato?
f) Correggi, pusha, verifica che tutto torni verde.
🟣 Esercizio 4 — Pipeline completa: lint + test + deploy (Difficile)
pipeline.yml:a) Job 1 — lint:
npm run lint (HTML + CSS + JS se presente).b) Job 2 — test: esegue i test del codice (parallelo con lint).
c) Job 3 — deploy:
needs: [lint, test]. Pubblica su GitHub Pages. Solo su push a main.d) Configura branch protection: lint e test come status check obbligatori.
e) Testa il flusso completo: PR con errore lint → bloccata. PR corretta → merge → deploy.
f) Verifica: il sito online ha il codice corretto e lintato.
❓ 4. Quiz di verifica
1. Cos’è un linter e come si differenzia dai test?
Mostra risposta
Un linter analizza il codice sorgente senza eseguirlo e segnala problemi di stile, errori sintattici e violazioni delle convenzioni. I test eseguono il codice e verificano che produca i risultati corretti. Il linter trova tag non chiusi, variabili inutilizzate, proprietà CSS duplicate; i test trovano bug logici, funzioni che restituiscono valori sbagliati, casi limite non gestiti. Sono complementari: il linter garantisce che il codice è scritto bene, i test garantiscono che funziona bene. Un progetto professionale usa entrambi.
2. Qual è la differenza tra i livelli “warn” e “error” in un linter?
Mostra risposta
“warn” (livello 1) mostra un avviso giallo ma non fa fallire il CI — il processo esce con codice 0. “error” (livello 2) mostra un errore rosso e fa fallire il CI — il processo esce con codice 1 e il workflow diventa rosso. Usa “error” per regole non negoziabili (es. no-var, eqeqeq) e “warn” per regole educative che il team sta ancora imparando. "off" (livello 0) disabilita completamente la regola.
3. Perché è importante aggiungere node_modules/ al .gitignore?
Mostra risposta
Perché node_modules/ contiene migliaia di file (tutte le dipendenze scaricate da npm) che non devono essere nel repository. Sono pesanti (decine o centinaia di MB), si rigenerano con npm install (o npm ci), e cambiano tra sistemi operativi. Il file package-lock.json (che va committato) garantisce che tutti installino le stesse versioni. Nel CI, il workflow fa npm ci che ricrea node_modules dal lockfile — non serve che siano nel repo.
4. Cos’è npm ci e perché si usa nel CI invece di npm install?
Mostra risposta
npm ci (Clean Install) installa le dipendenze esattamente come specificate nel package-lock.json, senza modificarlo. A differenza di npm install (che può aggiornare il lockfile), npm ci è deterministico: produce sempre lo stesso risultato. Nel CI è fondamentale perché garantisce che il runner abbia le stesse identiche dipendenze che il team usa in locale. npm ci cancella anche node_modules/ prima di installare, partendo sempre da zero.
5. Come disabiliti una regola di Stylelint che trovi troppo rigida?
Mostra risposta
Nel file di configurazione .stylelintrc.json, dentro la sezione "rules", imposta la regola a null. Esempio: "rule-empty-line-before": null disabilita la regola che richiede una riga vuota prima di ogni regola CSS. Puoi anche cambiare il livello di severità o le opzioni delle regole. Il file .stylelintrc.json con "extends": "stylelint-config-standard" parte con le regole standard, e tu le personalizzi nel blocco "rules" sovrascrivendo solo quelle che vuoi cambiare.
6. Qual è il vantaggio di definire gli script npm come "lint": "npm run lint:html && npm run lint:css"?
Mostra risposta
Tre vantaggi. Semplicità: in locale basta digitare npm run lint invece di ricordare i comandi completi di ogni linter. Consistenza: tutti nel team eseguono gli stessi comandi con le stesse opzioni — non c’è rischio di variazioni. Portabilità: nel workflow CI scrivi run: npm run lint e funziona — se domani cambi linter, aggiorni solo il package.json e il workflow resta identico. L’operatore && garantisce che se il primo linter fallisce, il secondo non viene eseguito — ti mostra l’errore subito.
📚 Riepilogo della lezione
- Linter = analizza il codice senza eseguirlo, trova errori di stile e problemi potenziali
- HTMLHint: tag non chiusi, DOCTYPE, alt mancante →
.htmlhintrc - Stylelint: proprietà duplicate, colori invalidi, stile inconsistente →
.stylelintrc.json - ESLint: no-var, ===, variabili inutilizzate →
eslint.config.mjs - 3 livelli:
off(disabilitato) ·warn(avviso) ·error(blocca CI) - npm scripts:
npm run lintper eseguire tutti i linter con un comando npm cinel CI per installazioni deterministiche dal lockfile- Workflow: 3 job lint paralleli, o 1 job con
npm run lint
Prossima lezione →
Lezione 30 — Secrets e variabili d’ambiente
Gestire credenziali e dati sensibili nei workflow.
GitHub Secrets. Variabili di repository. Sicurezza nelle pipeline.
Corso Git & GitHub · Per studenti e insegnanti · Lezione 29 di 45