Sviluppo · Qualità del codice
CI/CD per plugin WordPress: appunti di chi sta ancora imparando
Perché ho iniziato ad affidare i controlli a una pipeline invece che alla mia memoria, e cosa ho scoperto sul mio stesso codice.
Parto da una confessione. Negli ultimi tempi ho ampliato la suite di test di DB Cookie Manager, un plugin che uso, mantengo e che consideravo ragionevolmente solido. Risultato: parecchi bug minori, in punti dove ero convinto che tutto funzionasse. Niente di drammatico, ma abbastanza per farmi una domanda scomoda: quanti altri ne sono rimasti lì, semplicemente perché nessuno li ha mai cercati?
Questo articolo non è una guida scritta da chi ha capito tutto. È il diario di un programmatore che prova a lavorare meglio, e che ha trovato nella CI/CD uno strumento utile soprattutto per difendersi da se stesso.
CI e CD, senza giri di parole
Continuous Integration significa che ogni modifica al codice, a ogni push o pull request, viene verificata automaticamente: sintassi, standard di scrittura, analisi statica, test. Se qualcosa non va, lo scopri subito, non quando un utente apre una segnalazione.
Continuous Delivery (o Deployment) è il passo successivo: quando il codice supera i controlli, il pacchetto di rilascio viene costruito in modo automatico e ripetibile. Niente più zip fatti a mano dimenticando un file o includendo la cartella dei test.
Il punto vero
La pipeline non mi rende un programmatore migliore per magia. Mi toglie la possibilità di saltare i controlli quando ho fretta, che è esattamente il momento in cui sbaglio di più.
Perché proprio per un plugin WordPress
Chi sviluppa plugin WordPress, spesso da solo, si trova in una situazione particolare. Il codice gira su installazioni che non controlli, con versioni di PHP e di WordPress diverse, accanto a decine di altri plugin. Non c’è un reparto QA. Ci sei tu, il tuo ambiente di sviluppo e la speranza che “da me funziona” valga anche altrove.
Alcuni problemi tipici che una pipeline intercetta bene:
- una sintassi valida in PHP 8 che rompe tutto su un hosting ancora fermo a PHP 7.4;
- output non sanificato o nonce dimenticati, che i WordPress Coding Standards segnalano puntualmente;
- chiamate a funzioni con tipi sbagliati o variabili possibilmente nulle, che l’analisi statica scova prima dell’esecuzione;
- regressioni: una correzione in un punto che rompe silenziosamente un comportamento altrove.
Una pipeline minima, da cui partire
Non serve costruire tutto in un giorno. Questi sono gli strumenti che trovo più utili, in ordine di costo d’ingresso crescente.
php -l
Controllo di sintassi su più versioni di PHP. Costo zero, utilità immediata.
PHPCS + WPCS
WordPress Coding Standards: stile, ma soprattutto escaping, sanificazione e nonce.
PHPStan
Analisi statica dei tipi, con l’estensione per WordPress. Si parte da un livello basso e si sale.
PHPUnit
I test veri e propri. Il più impegnativo da introdurre, quello che restituisce di più.
Il workflow di Continuous Integration
Con GitHub Actions basta un file in .github/workflows/ci.yml. Questo esempio assume che PHPCS, WPCS, PHPStan e PHPUnit siano dichiarati come dipendenze di sviluppo in composer.json.
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
syntax:
runs-on: ubuntu-latest
strategy:
matrix:
php: ['7.4', '8.1', '8.3']
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- name: Lint PHP
run: find . -name "*.php" -not -path "./vendor/*" -print0 | xargs -0 -n1 php -l
quality:
runs-on: ubuntu-latest
needs: syntax
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: composer
- run: composer install --no-progress --prefer-dist
- name: WordPress Coding Standards
run: vendor/bin/phpcs
- name: Analisi statica
run: vendor/bin/phpstan analyse --memory-limit=1G
- name: Test
run: vendor/bin/phpunit
Per i test che richiedono un WordPress funzionante, @wordpress/env permette di avviare un’istanza completa in Docker direttamente nel runner. Richiede un po’ di configurazione in più, ma è il modo più vicino alla realtà per verificare hook, opzioni e interazioni con il core.
Il workflow di rilascio
Il secondo file si attiva solo quando creo un tag di versione, e produce lo zip da allegare alla release:
name: Release
on:
push:
tags: ['v*']
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Crea pacchetto
run: git archive --prefix=nome-plugin/ -o nome-plugin.zip HEAD
- uses: softprops/action-gh-release@v2
with:
files: nome-plugin.zip
Il trucco sta nel file .gitattributes: con export-ignore si escludono dallo zip test, configurazioni e workflow. Il pacchetto che arriva all’utente contiene solo ciò che serve, ogni volta, senza che io debba ricordarmelo.
/tests export-ignore
/.github export-ignore
phpunit.xml.dist export-ignore
phpcs.xml.dist export-ignore
phpstan.neon export-ignore
Cosa sto imparando
Iniziare piccoli funziona meglio
Attivare PHPStan al livello massimo su un plugin esistente produce centinaia di segnalazioni e la tentazione di spegnere tutto. Molto meglio partire da un livello basso, oppure generare una baseline che congela gli errori attuali e impone solo di non introdurne di nuovi. Poi si alza l’asticella un passo alla volta.
Un test verde non è una garanzia
I bug che ho trovato in DB Cookie Manager non erano nascosti da test sbagliati: erano in parti che i test semplicemente non toccavano. La pipeline verifica quello che le chiedi di verificare. Il resto rimane responsabilità mia.
Lo standard è un insegnante paziente
Molte segnalazioni di WPCS all’inizio mi sembravano pignolerie. Leggendole con calma, parecchie riguardavano escaping e validazione dell’input: proprio le cose che, in un plugin che tratta dati personali e consenso, non possono essere lasciate al caso.
Un errore da evitare
Disattivare una regola perché “dà fastidio” senza capire cosa protegge. Le eccezioni hanno senso, ma vanno motivate nel codice, con un commento che spieghi il perché.
In conclusione
La CI/CD non riguarda solo i grandi team o i progetti enterprise. Per chi sviluppa da solo è forse ancora più utile: è il collega che controlla il tuo lavoro senza stancarsi e senza fare sconti.
Sto ancora sistemando le pipeline dei miei plugin, e sicuramente tra sei mesi guarderò questi file pensando a come migliorarli. Se hai esperienze, suggerimenti o critiche, il confronto è benvenuto: le issue e le pull request sui repository sono aperte, ed è proprio da lì che arrivano spesso le lezioni migliori.