Ripulire i file .env dai commenti inline senza perdere tempo e pazienza

Scritto da

in

I file .env sembrano la cosa più innocua del mondo.

Una variabile, un uguale, un valore. Tutto molto bello.

Poi arriva il momento in cui qualcuno (specie le nostre amate IA) decide di fare una cosa apparentemente civilissima:

DB_PORT=27017 # Porta MongoDB
NODE_ENV=production # Ambiente di produzione

Il problema è che non tutti i parser dei file .env sono resistenti ai commenti inline. Alcuni capiscono perfettamente che tutto quello che viene dopo # è un commento. Altri invece decidono di prelevare la riga intera e sfarfallare come una falena contro un lampione.

Quindi voi pensate di avere:

DB_PORT=27017

e invece il vostro software magari si ritrova qualcosa del genere:

DB_PORT="27017 # Porta MongoDB"

Bellissimo.

Personalmente mi è capitato con Go, non chiedetemi con quale parser, perché non ricordo, ma ho visto comportamenti simili anche durante build e avvii gestiti con Docker Compose.

La parte divertente è che spesso questi problemi non ti esplodono in faccia immediatamente.

Se la variabile rappresenta qualcosa di importante e preminente, magari il programma muore subito e almeno avete una pista.

Ma se rappresenta un valore non fondamentale dell’applicazione, una feature flag secondaria, un endpoint usato soltanto in determinate condizioni o semplicemente un cavolo di token, possono iniziare malfunzionamenti completamente privi di senso.

E lì il tempo se ne va.

Perché? Siete in una situazione in cui magari:

  • in locale funziona tutto;
  • sul server no;
  • il codice è identico;
  • la configurazione sembra identica;
  • avete già ricontrollato la variabile sette volte;
  • iniziate a dubitare della vostra sanità mentale.

E nel frattempo la versione locale del vostro software continua a girare bene come una calcinculo gitano.

Basta commenti di fianco alle variabili

La soluzione che ho adottato è molto semplice:

nei file .env non voglio più vedere commenti sulla stessa riga della variabile.

Quindi questo:

DB_PORT=27017 # Porta MongoDB
REDIS_HOST=10.0.0.14 # Redis Cluster

deve diventare questo:

# Porta MongoDB
DB_PORT=27017

# Redis Cluster
REDIS_HOST=10.0.0.14

Il commento c’è ancora e la configurazione rimane leggibile.

Ripulire automaticamente un .env

Ovviamente non avevo nessuna intenzione di mettermi a sistemare decine o centinaia di righe a mano.

Quindi possiamo far fare il lavoro sporco a Perl (grazie ciattoneGPT):

perl -pe 'if (/^(\s*[^#\s][^=]*=.*?)[ \t]+#\s*(.+?)\s*$/) { $_ = "# $2\n$1\n"; }' .env > .env-treated

Il comando prende:

DB_HOST=10.0.0.15
DB_PORT=27017           # Porta MongoDB
DB_PASSWORD=test#123
REDIS_HOST=10.0.0.14    # Redis Cluster
NODE_ENV=production     # Ambiente

e produce un nuovo file .env-treated:

DB_HOST=10.0.0.15
# Porta MongoDB
DB_PORT=27017
DB_PASSWORD=test#123
# Redis Cluster
REDIS_HOST=10.0.0.14
# Ambiente
NODE_ENV=production

Niente magia. Il commento viene semplicemente spostato sopra la variabile.

Attenzione ai # che fanno realmente parte del valore

Qui c’è però un dettaglio importante.

Un carattere # può anche essere parte legittima di una password, di un token o di qualsiasi altro valore.

Per esempio:

PASSWORD=test#123
TOKEN=abc#xyz

Queste righe non devono essere toccate.

Per questo il comando considera un commento inline solamente un # preceduto da almeno uno spazio o da una tabulazione.

Quindi:

PASSWORD=test#123

rimane:

PASSWORD=test#123

mentre:

PASSWORD=test#123   # Password del servizio

diventa:

# Password del servizio
PASSWORD=test#123

Esattamente quello che vogliamo.

Versione comoda come funzione Bash

Se la cosa vi capita spesso, tanto vale creare una funzione:

envclean() {
    perl -pe 'if (/^(\s*[^#\s][^=]*=.*?)[ \t]+#\s*(.+?)\s*$/) { $_ = "# $2\n$1\n"; }' "$1" > "${1}-treated"
}

A quel punto:

envclean .env.production

genera:

.env.production-treated

senza modificare il file originale.

Che è sempre una buona idea, perché automatizzare una pulizia della configurazione è utile; automatizzare la distruzione della configurazione originale un po’ meno.

In fine

I commenti inline nei file .env sono belli finché funzionano.

Il problema è che non possiamo sapere con certezza quale parser leggerà quel file oggi, domani o dentro qualche container assemblato da qualcuno sei mesi dopo.

Quindi la regola che preferisco è:

un commento sta sopra. Una variabile sta sotto. Mai insieme sulla stessa riga.

È leggermente più verboso, ma è anche parecchio meno probabile che passiate un pomeriggio a debuggare un token che contiene accidentalmente " # token produzione" alla fine.

Spero che, come me, anche voi abbiate modi più creativi per buttare via il tempo.

Commenti

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *