Travis e Gatsby, automatizzare il deploy di uno SSG

T

Attenzione

Quest’articolo vuole essere una gentile introduzione decisamente pratica all’utilizzo di Travis CI che vi permetta di prendere confidenza con lo strumento a livello generale o, per chi come me gestisce un blog attraverso Gatsby, Jekyll, Hexo o altro SSG, di automatizzare il processo di deploy ad ogni push sulla propria repo importando un semplice file.
Non vuole in alcun modo essere una guida completa sullo strumento, ovviamente aggiungerei, data la complessità che alcune pipeline arrivano a raggiungere e considerando che parliamo di uno strumento per l’automatizzazione, questo tocca svariate branche dello sviluppo software e non solo.

Introduzione

Di recente ho finalmente migrato il mio sito personale, e blog, sotto un unica struttura utilizzando React e Gatsby (hostato sulle github pages).
Arrivato a un risultato soddisfacente in pochissimi giorni, un plauso a Gatsby per la qualità del prodotto (SVG image preloading, PWA, service worker pre-configurato e tanto altro), mi sono subito prodigato a configurare quelle piccole cose che permettono di avere, da content creator, un’esperienza d’uso più soddisfacente possibile e che mi astraesse tutte le beghe tecniche per aggiornare il blog, aggiungere un articolo e cosi via.

Così l’ultimo passo è stato quello di automatizzare il deploy del sito sui server di github attraverso l’uso delle github pages.
Ci sono diverse soluzioni per ottenere quanto detto. Una poteva essere quella di utilizzare un package npm (gh-pages) e inserire uno script del genere gatsby build && gh-pages -d public che dapprima builda gatsby e successivamente pusha sul branch “gh-pages” la cartella public generata dallo step precedente. Per agganciarlo ad ogni push avremmo poi dovuto usare un altro tool come husky e quindi creare un hook pre-commit o pre-push.

Inizialmente era ciò che avevo fatto ma mi sono sfortunatamente accorto che alcune volte, forse dovuto all’utilizzo di nvm, forse ad altro, la build terminava con successo ma avviando la webapp, questa, dava problemi di ogni genere e i contenuti delle pagine a volte non venivano neppure visualizzati. Cosi eliminando node_modules e lockfile, e reinstallando le deps, tornava tutto a funzionare correttamente.

Travis CI

Travis CI è un servizio di continuous integration utilizzato per testare e buildare il codice delle repo hostate su github.
In parole semplici, Travis mette a disposizione dello sviluppatore dei container che ad ogni nostro push clonano la repo e avviano una serie di comandi che permettono, in primis, il testing del codice automatico e, successivamente, di produrre una build e lo svolgere di qualunque altro compito che possa essere automatizzato attraverso comandi sulla shell.

Un container, in architettura del software, è un ambiente, isolato, che raggruppa il codice applicativo e le sue dipendenze affinché l’applicazione possa essere eseguita, buildata, pacchettizzata (e molto altro) in maniera affidabile, ripetitiva e predittiva.
Questo difatti è il principale vantaggio nell’uso di un container: una sorta di banco “vergine” (o correttamente pre-configurato) e sempre uguale da avviare ad ogni build nella quale vi sono meno variabili possibili che possono andare a creare problemi di ogni genere durante l’esecuzione di determinati task.
Quindi proprio per le problematiche da me riscontrate, ho preferito lasciar buildare il mio sito a Travis. Vediamo com’è possibile farlo.

Pre-requisiti

  • Disporre di un account GitHub (ovviamente) e registrarsi con quest’ultimo su Travis-CI.
  • Apparirà una lista di repo, abilitare Travis su quella scelta.
  • Creare un access token da GitHub per permettere il deploy via gh-pages e quindi il push da parte del container Travis verso la repo.
  • Inserire questo token nel pannello di Travis, nella repo scelta, in settings e sotto la sezione “Environment variables”.

.Travis.yml

Per chi di voi non lo sapesse, l’estensione YAML (acronimo ricorsivo che sta per “YAML Ain’t Markup Language”, YAML Non è Markup Language) è un’estensione di file utilizzati generalmente per configurazioni ed è un “linguaggio” di serializzazione.
I container di Travis vengono istruiti da noi sviluppatori attraverso le configurazioni che inseriamo in questo file posizionato nella root della repo (e del progetto quindi): .travis.yml
Senza il push di questo file, Travis non sa come gestire la nostra repo.
Ogni container segue, in ordine, delle fasi che trovate qui.
Prendiamo in esame quello creato da me per il mio blog (alcune fasi non le trovate esplicitate in quanto i comportamenti di default di Travis vanno bene):

language: node_js
node_js:
 - 11.10.1
deploy:
  provider: pages
  skip-cleanup: true
  github-token: $GITHUB_TOKEN
  local_dir: public
  keep-history: true
  target_branch: gh-pages
before_script:
  - "npm i -g gatsby"
script:
  - "npm run build"

Andando in ordine:

  • language: il linguaggio utilizzato nel nostro progetto
  • node_js: la versione con la quale avviamo questo codice (personalmente ho preferito impostare la stessa che sto utilizzando in locale con questo progetto)
  • deploy: qui tutta una serie di configurazioni fornite ad-hoc da Travis (qui trovate invece i deploy supportati)
    • provider: pages si riferisce a github pages
    • skip-cleanup: evita di eliminare i file generati
    • github-token: qui il nome dell’ENV VAR settata precedentemente
    • local_dir: la dir generata da gatsby da hostare (l’app buildata vera e propria che gira in produzione)
    • keep-history: evita il force-push sul branch gh-pages della repo, a vostra discrezione
    • target_branch: su quale branch pushare (questo dipende anche da come configurate le gh-pages su github)
  • before_script: cosa eseguire prima della fase principale (che potete vedere di sotto). Qui le dipendenze sono state già installate (avremmo potuto specificarlo ma viene eseguito automaticamente il comando npm ci (più sotto per maggiori info).
    Anche npm i -g di gatsby sarebbe superfluo se lo aggiungete come devDep nel package.json, questione di gusti.
  • script: la fase vera e propria di build. Notate che di default Travis usa npm test come script, questo perché è uno strumento utilizzato, principalmente, per testing ma non è chiaramente l’unico vantaggio che può fornire quando utilizzato.

Se infatti è vero che Travis non è fatto solo per automatizzare il testing del codice, è anche vero che utilizzarlo solo per deployare un sito su github pages potrebbe risultare un po’ sprecato.
La verità è che probabilmente Travis è fondamentale quando si lavora su larghe codebase dove vi sono molti developer che ci lavorano contemporaneamente attraverso pull request. A quel punto avere un punto centralizzato in cui analizzare i risultati dei test e delle build è un aiuto della quale non si fa più tanto facilmente a meno, ma quanto visto finora è comunque un buon esercizio per chi deve o vuole affacciarsi al mondo della CI/CD (e in generale un po’ di sano e semplice automatismo non fa mai male :D).

npm i o npm ci?

Accennavo prima che Travis installa le nostre dipendenze in una maniera meno convenzionale se vogliamo.
Il comando utilizzato è npm ci. Per capire di cosa si tratta, vediamo cosa ci dice la documentazione:

“[…] it’s meant to be used in automated environments […] where you want to make sure you’re doing a clean install of your dependencies.”

La pagina prosegue con una lista di differenze tra questo comando e quello classico per l’installazione di dipendenze, ma la principale è quella di non permettere modifiche al package-lock.
Immagino vi sia capitato a volte di lanciare npm i e di ritrovarvi con il lock aggiornato, questo perché nei nostri package.json abbiamo dei simboli che precedono la versione dei package che istruiscono npm su come comportarsi in caso di minor o major update di versione (qualche info in più in quest’altro nostro articolo). Ecco, tutto questo, se è presente un lockfile e se usiamo npm ci, non accade.

Da qui Dove proseguire?

Online vi sono diverse ottime risorse per proseguire e costruire man mano build sempre più complesse ma non dimenticate mai che costruire build complesse deve essere solo un esercizio; tutti gli strumenti devono facilitare dei processi piuttosto che creare frizione. Difatti spesso capita il contrario perché si parte dall’implementazione piuttosto che dalle esigenze.

Di seguito alcune risorse verso cui affacciarsi:

E se anche tu come me hai un blog SSG, puoi dare un’occhiata a Netlify CMS che, insieme a Travis, permette di ottenere un’esperienza d’uso molto simile a quella dei CMS a cui siamo abituati (personalmente non lo trovo di mio gusto, ma magari sarà argomento di un prossimo articolo).

A proposito di me

Giacomo Cerquone

Appassionato di informatica sin da piccolo, cinefilo accanito, amante di tè e dei posti freddi. Focalizzato in full-stack JavaScript developing, contributor di diversi progetti open source e amante delle tecnologie bleeding edge nell'ambito della programmazione.

Gli articoli più letti

Articoli recenti

Commenti recenti