La guida riluttante alle migrazioni Shopify

Atto V: L'apparenza del completamento

Il tuo store di staging ti sta mentendo

Mandi in rilascio. La pipeline diventa verde. La checklist di QA passa, dall’alto in basso, tutte le caselle spuntate. I metafield sembrano popolati. Qualcuno dà l’ok. Due giorni dopo, un merchandiser nota che in produzione i valori sono sbagliati—non mancanti, che almeno farebbe rumore, ma sbagliati, che è silenzioso. Vanno su staging per riprodurre il problema, perché è quello che si fa, perché lo staging è il posto dove riproduci le cose. Su staging i valori sono a posto. Su staging i valori sono sempre stati a posto. L’import di Matrixify che avrebbe dovuto scrivere quei valori su staging si era concluso con una spunta verde, un log pulito e un conteggio di righe che aveva tutta l’aria del successo. Non aveva scritto niente.

Quest’ultima frase è l’intero capitolo, e il resto è un tentativo di assicurarmi che non ti succeda mai—o, più onestamente, di assicurarmi che, quando ti succederà, tu sappia già perché.

Gli store di staging non annunciano quando sono diventati obsoleti. Non c’è nessun banner, nessuna email di avviso, nessun badge di modalità degradata nell’admin. Continuano ad accettare deploy e a far passare le checklist di QA fino all’istante esatto in cui ti spediscono, sicuri di sé, nella direzione sbagliata. Un ambiente di produzione che è giù ti dice che è giù. Un ambiente di staging che si è allontanato in silenzio dalla produzione non ti dice proprio niente; continua semplicemente a rispondere alle tue domande, e alcune di quelle risposte adesso sono bugie, e lui non ha modo di sapere quali.


Questo succede perché uno store Shopify non è una cosa sola che puoi copiare. È almeno tre cose impilate l’una sull’altra, e si allontanano dalla produzione lungo tre assi separati, nessuno dei quali la piattaforma riconcilia nativamente per te.

Il primo asse sono i dati—prodotti, varianti, collection, pagine, post del blog, menu, e soprattutto i metafield e i metaobject su cui si appoggia ogni build enterprise per contenere tutto ciò che lo schema nativo non prevede. Il secondo asse è la configurazione—il JSON del tema, le impostazioni dello store, i profili di spedizione e consegna, le decine di toggle e policy che vivono nell’admin e non compaiono mai nel tuo repository. Il terzo asse è lo stato dei servizi di terze parti—le app che hai installato, i loro dati interni, il cablaggio delle loro integrazioni, quella metà del comportamento del tuo store che vive sui server di qualcun altro ed è raggiungibile solo attraverso la superficie che quel vendor ha scelto di esporre.

Ogni asse va alla deriva sul proprio orologio. Sistemi un profilo di consegna in produzione durante una corsa di alta stagione e dimentichi che fosse mai stato diverso da staging. Un merchandiser modifica un metaobject in produzione perché è lì che vive il catalogo vero. Un’app viene configurata sui dati di produzione perché sono quelli i dati che contano. Nessuna di queste è esattamente un errore. Sono solo la normale entropia di un ambiente che viene davvero usato, che si accumula a fronte di un ambiente che viene solo testato. La deriva non è una mancanza di disciplina. La deriva è il comportamento di default. La disciplina è ciò che spendi per rallentarla.


L’asse della configurazione ha uno spigolo affilato che vale la pena nominare a parte, perché morde proprio i team che hanno fatto la cosa più sofisticata. Se gestisci una build pipeline custom—quella che compila e fa il bundle degli asset del tema prima di spingerli, cosa che ogni build Plus seria prima o poi fa—a un certo punto, lungo la strada, sei uscito dall’integrazione GitHub nativa di Shopify. Quell’integrazione presuppone di possedere lei il viaggio di andata e ritorno tra il repo e lo store. Una volta che compili tu stesso gli asset e spingi l’output, il JSON delle section e dei template su ciascun ambiente comincia a divergere in modo indipendente, deploy dopo deploy, perché non c’è più niente che tenga i due store legati alla stessa fonte di verità. Non l’hai rotto per sbadataggine. L’hai rotto costruendo la cosa più capace. Il conto di quella capacità è che la parità tra ambienti adesso è un compito tuo, manuale, per sempre, e non della piattaforma.


E poi c’è il failure mode che dà il suo cold open al capitolo, quello che è peggio di un crash perché indossa il costume del successo.

Lanci un import Matrixify per spingere su staging qualche migliaio di valori di metafield. Si completa. Il log è pulito. Il riepilogo dice quante righe ha processato. E non un solo valore atterra—perché le definizioni dei metafield, lo schema a cui quei valori dovrebbero agganciarsi, su staging non erano mai state create in partenza. Matrixify ha fatto esattamente quello che gli era stato detto: ha provato a scrivere valori in una forma che non esisteva, non ha trovato dove metterli e ha riportato il tentativo come concluso. Non c’è nessun errore, perché dal punto di vista dell’importer non è andato storto niente. I valori non avevano una casa, quindi sono evaporati, in silenzio, con una spunta verde sopra.

È questo che ti costa davvero uno staging obsoleto, ed è il motivo per cui uno staging cattivo è peggio di nessuno staging. Un ambiente vuoto non produce nessuna fiducia; sai di non aver testato niente, quindi non ti fidi di niente. Uno store di staging che sembra funzionante ma a cui mancano dati critici produce falsa fiducia, che è quella costosa. La deriva oltre una certa soglia non si limita a ridurre la tua copertura di QA. La ribalta. La checklist passa ancora. Ciò a fronte di cui sta passando ha smesso di essere vero, e adesso la spunta verde ti sta mentendo attivamente, con la faccia di bronzo. Davamo per scontato che l’import funzionasse. Non funzionava. Quella frase è stata detta, in qualche forma, in ogni retro che si sia mai meritata il nome.


Al responsabile tecnico che sta per fare l’onboarding di una nuova app di terze parti in questo sprint, e che non ha ancora fatto al vendor una sola domanda al riguardo: chiedi se ha un sandbox. Chiedilo prima di firmare, prima di installare, prima che diventi portante. Poi preparati, perché la risposta è quasi sicuramente no.

Non è una colpa del vendor, e non è un elenco di app cattive da evitare. È strutturale, ed è praticamente diffuso in tutto il settore. La stragrande maggioranza delle app Shopify non offre nessun sandbox, nessuna modalità di test, nessun modo di mettere in piedi una copia parallela del proprio stato per uno store non di produzione. Sono state costruite per girare una volta sola, nello store vero del merchant, sui dati veri del merchant. Chiedere alla maggior parte di loro di rispecchiarsi su staging è chiedere loro di fare una cosa per cui non sono mai state progettate. Così il terzo asse della deriva—le app—è quello su cui hai meno leva, perché chiuderlo dipende da una capacità che il vendor per lo più non ha costruito. Spenderai qui una fetta concreta del tuo sforzo di parità, e non te la riprenderai tutta, e questo è un fatto sull’ecosistema, non un fatto sulla tua competenza.


Quindi uno store non lo puoi copiare. Quello che puoi fare è riconciliarlo, deliberatamente, a pezzi, nell’ordine giusto. L’ordine non è cosmetico. L’ordine è tutto il punto, perché fare questi passaggi fuori sequenza è esattamente il modo in cui ottieni un import pulito che non scrive niente.

Primo, sincronizza lo schema. Prima di qualsiasi valore, prima di qualsiasi prodotto, spingi le definizioni di metafield e metaobject dalla produzione a staging, così che staging abbia un posto dove mettere ciò che arriva dopo. In pratica è un dump dello schema sull’origine e un load dello schema sulla destinazione—il genere di cosa che fa uno strumento come shopify_toolkit—e deve concludersi prima che cominci qualsiasi altra cosa. Lo schema prima, sempre. Non come slogan; come istruzione portante. Il cold open in cima a questo capitolo è la singola frase “lo schema prima, sempre” con la parola sempre tolta e tremila valori di metafield svaniti a prenderne il posto.

Secondo, una volta che le forme esistono, sposta i dati in massa dentro di esse. È il passaggio Matrixify che funziona davvero, perché adesso c’è qualcosa che li accolga: prodotti, collection, pagine, menu, post del blog, e i valori di metafield che finalmente hanno delle definizioni a cui agganciarsi. Lo stesso strumento che ti ha mentito nell’ordine sbagliato dice la verità in quello giusto. Niente di Matrixify è cambiato tra le due storie, tranne ciò che hai fatto prima di lanciarlo.

Terzo, gestisci tutto ciò che possiedono le app di terze parti con extension specifiche per dominio—script su misura, uno per integrazione, che recuperano o ricostruiscono qualunque stato viva dal lato del vendor e non possa essere catturato da un export generico. È il lavoro lento, senza gloria, app per app, e non c’è nessuno strumento che lo generalizzi, perché la cosa attorno a cui stai lavorando è proprio che ogni app ha modellato il proprio mondo in modo diverso. Scrivi un piccolo riconciliatore per ognuna che conta, e accetti che alcune semplicemente non le puoi raggiungere.


Una nota su ciò che non si può spostare nemmeno facendo tutti e tre i passaggi in ordine, perché l’onestà sul divario è l’unica cosa che rende affidabile tutto il resto. I Combined Listings—il meccanismo di Shopify per raggruppare prodotti separati in un’unica listing di vetrina, le relazioni padre-figlio che fanno presentare come un’unica cosa una maglietta in nove colori—non hanno nessun supporto Matrixify per la relazione in sé. I prodotti li puoi spostare. Il fatto che stanno insieme non lo puoi spostare. Quella relazione va ricostruita a mano, o scriptata contro le API, o semplicemente riconosciuta come una delle cose che staging non rappresenterà fedelmente. È un esempio piccolo, ma è la forma di ogni divario che troverai: non una cosa difficile da sincronizzare, ma una cosa di cui il tooling disponibile non ha alcun concetto di sincronizzazione, e che quindi cade in silenzio attraverso il pavimento, a meno che tu non vada a cercarla.

Ecco perché l’audit avviene prima di aver bisogno di una sync, non durante. Il momento peggiore per scoprire che un’app non ha un sandbox, o che i Combined Listings non si trasferiscono, o che i tuoi profili di consegna sono andati alla deriva tre mesi fa, è in mezzo a un passaggio di parità con una data di lancio alle spalle. Inventaria il tuo stack quando è tutto calmo: ogni app, ogni integrazione, ogni definizione di metaobject, ogni posto in cui la produzione tiene uno stato che staging non ha. Metti per iscritto, in anticipo, quali di questi puoi riconciliare e quali no. L’audit è economico quando è un documento e costoso quando è un postmortem.


Ecco la parte che nessuno vuole vedere stampata, perciò la stampiamo. Non arriverai alla parità completa. L’obiettivo onesto è da qualche parte intorno al novantacinque percento—abbastanza vicino perché staging dica la verità sulla stragrande maggioranza di ciò che ci farai passare—e il restante cinque percento non è una voce di backlog che prima o poi smaltirai. È una proprietà permanente del territorio. Ci sarà sempre qualche stato di un’app che non puoi rispecchiare, qualche modifica in produzione che ha superato in velocità la tua sync, qualche relazione di cui il tooling non ha una parola.

Questo richiama una cosa attorno a cui il libro continua a girare in una dozzina di costumi diversi. Shopify gestisce parzialmente lo staging—che è il modo educato di dire che in realtà non lo gestisce affatto, e ti consegna la cucitura da gestire da solo, allo stesso modo in cui ti consegna la cucitura su ogni altra superficie dove la portata della piattaforma si ferma prima della reale complessità del tuo store. Quella cucitura non ti è dato chiuderla. Ti è dato sapere esattamente dove corre.

Così i team che fanno bene lo staging non sono quelli che hanno eroicamente portato la parità al cento percento; quel numero non è in vendita a nessun prezzo. Sono quelli che hanno smesso di fingere che il divario non esista. Sanno quale cinque percento non è sincronizzato. Lo hanno messo per iscritto. Dicono al QA quali scenari staging non può essere ritenuto affidabile per rispondere, così il QA smette di fidarsi proprio per quelli e per nient’altro. Ciò che rende affidabile uno store di staging non è mai stata la sua copertura. È l’onestà su ciò che copre—un punto cieco piccolo, noto, documentato, attorno a cui giri di proposito, invece di uno grande e invisibile che guida te.

Una mappa topografica dettagliata con una piccola regione cerchiata e tratteggiata a matita di proposito, per segnalarla come territorio di ignoto noto, circondata da una precisione cartografica per il resto impeccabile. Una matita posa di traverso sull'angolo.
Non un divario che chiudi. Un divario che disegni per primo.

La bugia nel titolo non è mai stata davvero quella dello store di staging. Lo store è solo una macchina che riporta ciò che gli è stato chiesto di riportare. La bugia è quella che raccontiamo a noi stessi quando la spunta diventa verde e decidiamo che voglia dire che la cosa è fatta. Lo schema prima, sempre—e poi, dopo, la disciplina più dura: sapere con precisione cosa le tue spunte verdi non ti stanno dicendo, e dirlo ad alta voce prima che lo trovi il merchandiser al posto tuo.