Un controllo per gli errori che accadono solo sulla piattaforma

Due cose avevano bloccato la produzione, e nessuna delle due poteva fallire in locale: un import senza estensione che un bundler nasconde e Node rifiuta, e un pattern in vercel.json che non produce alcuna distribuzione. Entrambe vengono ora controllate prima del build, e il controllo è stato verificato reintroducendo ciascun errore.

I tipi passano, il bundler compila, il server di sviluppo serve — e la distribuzione risponde 500 a ogni richiesta. Questo script colma esattamente quello scarto. Tutti e tre quegli strumenti risolvono i moduli e leggono la configurazione come farebbe un bundler; la funzione distribuita non fa né l'uno né l'altro, e lo script controlla proprio questa differenza. Viene eseguito dentro npm run build e termina con un codice d'errore, così nessuno dei due errori arriva più a un push.

Cosa respinge

Un import relativo senza estensione. L'API viene eseguita come ESM su Node, dove ./faq non si risolve e ./faq.js sì. Una sola riga di questo tipo, raggiungibile dal grafo di import del server, rispondeva a ogni rotta /api con FUNCTION_INVOCATION_FAILED.

Un import .json in quel grafo. import { version } from '../package.json' passa il controllo dei tipi, compila e funziona nel server di sviluppo. Il bundle distribuito contiene moduli e non il repository, quindi il file semplicemente non c'è, e l'import genera un errore al caricamento del modulo — cioè a ogni richiesta, per cui l'intera API restituiva 500.

Un pattern source che il router della piattaforma non riesce ad analizzare. Qui il sintomo non è una distribuzione fallita: un pattern non valido viene respinto prima che inizi un build, quindi non c'è alcuna distribuzione, e la produzione resta silenziosamente sul commit precedente. I pattern vengono analizzati con la stessa libreria con cui li analizza la piattaforma.

Una versione in contraddizione con sé stessa. shared/version.ts deve corrispondere a package.json. È una copia proprio perché un import JSON è l'errore descritto sopra, e una copia che nessuno controlla diventa obsoleta; il manifesto dell'estensione e il tag di release leggono uno dei due, il connettore legge l'altro.

Come decide cosa guardare

La regola si applica ai file che la funzione distribuita carica davvero, e questo insieme non è «tutto sotto server/» — segue gli import dovunque conducano, ed è così che un file sotto src/lib è diventato parte del server fin dall'inizio. Parte quindi dal punto d'ingresso della funzione e percorre il grafo. Un import solo di tipi viene saltato: viene eliminato in fase di compilazione, quindi il suo percorso non diventa mai qualcosa che un runtime deve risolvere.

Cosa non è

Non è una suite di test e non è un linter. Conosce quattro modi precisi in cui la piattaforma differisce da un portatile e nulla oltre; non nota un errore di logica, e avvisa invece di fallire se la libreria con cui legge i pattern non è installata, perché lo scopo è cogliere l'errore sulla macchina dove viene commesso. Ogni regola è stata provata reintroducendo il suo errore e osservando il controllo fallire.

Da leggere: la documentazione che vive nel repository, e pubblicare Markdown da GitHub Actions.