HDM S.R.L.
Via G. Borsi, 9 – Milano
T +39 02 6596329

Ottimizzazione dei processi di rilascio di un progetto PHP con Deployer

Nello sviluppo di un qualsivoglia software, una delle parti più delicate e potenzialmente time expensive è quella di messa in produzione, a maggior ragione quando è necessario iterare a stretto giro più rilasci.
I software sviluppati in supporto al digital marketing non fanno certo eccezione e anzi, sono spesso soggetti a cicli di rilascio notevolmente contratti.

È quindi assolutamente imprescindibile automatizzare al massimo tutte quelle componenti manuali fortemente ripetitive e potenzialmente soggette ad errore umano, come appunto quelle di deploy.
Vale la pena marcare come i test automatizzati siano un ulteriore esempio di automazione, (anche in questo caso spesso sottovalutati), che portano un grande valore aggiunto in tutto il processo di sviluppo.

In questo articolo ci focalizzeremo sulla presentazione di una specifica tecnologia di continuous delivery per il contesto PHP, nel dettaglio Deployer, ma le possibili soluzioni e configurazioni sono estremamente eterogenee ed ogni progetto può essere un discorso a sé.

Per la presentazione mostreremo una configurazione di Deployer supponendo un progetto PHP basato su Composer, per replicare la configurazione dell’esempio così come indicato nell’articolo è necessario:

  1. Avere i sorgenti del proprio progetto su un repository GIT (es. Bitbucket, GitHub, …);
  2. Avere un server basato su GNU/Linux raggiungibile in ssh;
  3. Lavorare su una macchina di sviluppo basata su GNU/Linux o macOS, con git ed ssh installati, oltre alla classica pila LAMP.

Da terminale spostiamoci nella cartella del progetto ed iniziamo ad installare la componente di rilascio di Deployer con:

composer require deployer/dist –dev

Al momento della scrittura dell’articolo l’ultima versione stabile à la 6.8.

Possiamo ora inizializzare Deployer tramite il comando:

php vendor/bin/dep init

Che ci chiederà:

  1. Il tipo di progetto (es. Laravel, Symfony, …), possiamo anche impostare Common;
  2. Il repository dei sorgenti (es. git@github.com:PROJECT.git);
  3. Se vogliamo o meno inviare dati anonimi sull’uso.

Al termine di questo breve wizard, verrà creata una configurazione base da cui partire nel file deploy.php posizionato nella root del progetto.

La componente più interessante che ci interessa modificare di questo file è quella relativa agli host, che conterrà il dettaglio del/dei server di destinazione dei deploy.

Supponiamo quindi di voler predisporre due host, relativi ad un ambiente di test e di produzione, sostituiremo la configurazione base:

host(‘project.com’)
    ->set(‘deploy_path’, ‘~/{{application}}’);

Con:

// Hosts
host(‘test.project.com’)
    ->stage(‘test’)
    ->user(‘dep-test’)
    ->identityFile(‘~/.ssh/chiave-ssh-dep-test’)
    ->set(‘deploy_path’, ‘/var/www/test.project.com’)
    ->set(‘branch’, ‘develop’);

host(‘project.com’)
    ->stage(‘prod’)
    ->user(‘dep-prod’)
    ->identityFile(‘~/.ssh/chiave-ssh-dep-prod’)
    ->set(‘deploy_path’, ‘/var/www/project.com’)
    ->set(‘branch’, ‘master’);

set(‘default_stage’, ‘test’);

Entrando nel dettaglio:

  1. Con host stiamo indicando qual è l’indirizzo di destinazione della macchina (host o IP che sia);
  2. Con stage stiamo dichiarando la natura dell’ambiente, test, produzione, …, possiamo gestire questo aspetto definendo tutti gli ambiente di cui abbiamo bisogno, (es. uat, bugfix, pre-prod, …);
  3. Con user definiamo l’username che verrà usato per accedere via ssh alla macchina in cui effettuare il deploy.
    Sarebbe meglio evitare l’uso dell’utenza di root, definendo piuttosto delle utenze ad hoc con accessi opportunamente limitati;
  4. Con identityFile definiamo la chiave ssh da usare per l’autenticazione dell’utente definito in user.
    L’uso dell’opzione identityFile non è l’unica per garantire l’accesso in ssh, si potrebbe anche usare password, benché sia sconsigliabile l’uso di una password definita in chiaro.
    In alternativa, sia user che password potrebbero essere valorizzati tramite variabili d’ambiente, configurati solo per gli utenti effettivamente abilitati al deploy;
  5. Con set(‘deploy_path’, …) definiamo la cartella del server remoto dove andare a rilasciare i file;
  6. Con set(‘branch’, …) indichiamo il nome del branch GIT da usare per il deploy.
    Anche in questo caso possiamo adattare la configurazione in base alle specifiche esigenze del progetto.

È fortemente consigliato definire un host di default da usare per i rilasci, cosa che possiamo fare con l’indicazione set(‘default_stage’, ‘test’), che se notate nell’esempio precedente è esterna a quella degli host.

Un punto di attenzione in relazione al valore usato in deploy_path.

Deployer genera in quest’ultima cartella una sua alberatura pensata per ottimizzare il processo di rilascio e minimizzare i tempi di fermo servizio, ogni rilascio viene infatti inserito nella cartella deploy_path/releases/{numero progressivo}, l’ultima versione rilasciata viene poi agganciata tramite link simbolico definito sul path deploy_path/current, questo è un punto importante da tenere a mente, perché i nostri virtual host dovranno essere configurati di conseguenza.

Nel nostro esempio specifico, i virtual host dell’ambiente di test e produzione dovranno quindi puntare a:

  • /var/www/test.project.com/current
  • /var/www/project.com/current

A questo punto la configurazione dell’ambiente di sviluppo è ultimata, dobbiamo ora configurare sui server del deploy l’accesso a GIT per le utenze dep-test e dep-prod.

Possiamo fare questo usando ancora una volta delle chiavi ssh, configurando la pubblica sul vostro repository (fortemente consigliato facendolo in sola lettura).
La componente di configurazione delle chiavi esula un po’ dallo scopo di questo articolo, per maggiori dettagli è possibile consultare la documentazione ufficiale di GitHub, che nelle sue indicazioni ad alto livello si applica anche ad altri servizi Git (es. Bitbucket).

Ci siamo, abbiamo una configurazione completa, per effettuare il deploy non ci resta che lanciare il comando:

vendor/bin/dep deploy [test|prod]

Se non definiamo lo specifico ambiente (i cui valori dipendono da quanto configurato nelle opzioni di stage), in virtù della nostra configurazione default_stage, verrà usato l’ambiente di test.

Per semplificare ulteriormente questo aspetto, è possibile definire una configurazione ad hoc nel file composer.json, definendo nella sezione scripts:

“deploy”: “dep deploy”

In questo modo per il potremo usare per il deploy una sintassi un po’ più concisa:

composer deploy [test|prod]

Di fatto del tutto simmetrica alla precedente.

Ricordiamoci che per il deploy verrà sempre usato il repository GIT, va quindi sempre verificato quest’ultimo prima di procedere con un deploy, eventuali file modificati localmente, non verranno quindi propagati.

_________________________________________________________________________

In questo articolo abbiamo visto come sia possibile installare e definire una configurazione base per gestire tramite Deployer il processo di continuous delivery di un progetto PHP.

La configurazione presentata è solo una base, lo strumento mette a disposizione diverse altre funzionalità interessanti, quali la gestione dei rollback o la possibilità di creare dei task personalizzati, per applicare ad esempio delle logiche ad hoc da applicare post deploy, riportiamo per quest’ultimo punto l’esempio della documentazione ufficiale:

after(‘deploy’, ‘deploy:done’);
task(‘deploy:done’, function () {
    write(‘Deploy done!’);
});

Possiamo fare leva su questa funzionalità per gestire le nostre logiche applicative, es. applicare degli aggiornamenti ad una base dati, editare file di configurazione, spostare file, o quant’altro possa risultare utile per avere un ambiente completamente operativo.

Fonte Immagini: https://unsplash.com/

A CURA DI

GIUSEPPE DELLI SANTI
GIUSEPPE DELLI SANTI

Full stack developer @ H-FARM Digital Marketing

Hai trovato interessante questo articolo?

Possiamo fare tanto per il tuo business e siamo sempre in cerca di nuove sfide. Mettici alla prova, raccontaci di te e della tua realtà!