Introduzione
L’ingegneria del software è un campo frenetico e competitivo. Rilasciare i tuoi prodotti agli utenti più velocemente ti darà un vantaggio rispetto ai tuoi concorrenti. Il lato positivo è che esistono best practice di settore per aiutare le aziende a competere ad armi pari.
La Continuous Integration e il Continuous Development (CICD) sono un esempio di strategia che sfrutta le best practice del settore per dare alle aziende un vantaggio in questo campo competitivo.
GitHub, un repository basato sul web con Git, uno strumento di controllo della versione, consente a sviluppatori, ingegneri e architetti software di implementare la CI/CD. Il Continuous Development (CD) è la pratica di automatizzare build, test e deployment. La Continuous Integration (CI) consente a molte persone di collaborare allo stesso progetto e verificare che il codice funzioni senza preoccuparsi dei conflitti di merge.
Le GitHub Actions ci consentono di scrivere passaggi che automatizzano build, test e deployment.
In questo tutorial imparerai come configurare la Continuous Integration con le GitHub Actions. Inizieremo configurando un repository Git per ospitare il nostro codice. Successivamente, configureremo un processo CI di GitHub per monitorare le modifiche nel nostro codice, avviare un runner CI per eseguire i test, compilare ed effettuare il deploy della nostra applicazione su un server Ubuntu 22.04 con Nginx.
Prerequisiti
Per seguire questo tutorial, avrai bisogno di quanto segue:
-
Un server con Ubuntu 22.04. Puoi seguire questo tutorial per la configurazione iniziale del server Ubuntu, aggiungere un utente non root, e abilitare il firewall UFW di Ubuntu.
-
Avrai bisogno di Node.js installato sul tuo server, preferibilmente dalla versione 14 in poi. Abbiamo un tutorial su come installare Node.js su Ubuntu.
-
Avrai bisogno del software server Nginx installato. Abbiamo una guida su Come installare Nginx su un server con Ubuntu.
-
Avrai bisogno di Docker e Docker Compose installati sulla tua macchina locale per eseguire un ambiente di sviluppo isolato. Segui il nostro tutorial per imparare Come installare e utilizzare Docker nel cloud.
Ora che abbiamo tutto il necessario, iniziamo.
Passo 1. Clonare il repository del progetto.
Baseremo questo tutorial su Reactjs, una libreria JavaScript dichiarativa per la creazione di interfacce utente. Se desideri configurare un nuovo progetto da zero, puoi utilizzare questa risorsa sulla configurazione di un’app React. Per brevità, utilizzeremo un clone di questo repository React.js che abbiamo già configurato su GitHub.
L’applicazione che stiamo clonando è una semplice applicazione React con react-router 6 e un test eseguito con React Testing Library, che ci fornisce metodi per accedere al DOM.
Per clonare il repository, fai clic sul pulsante verde e copia l’URL.

Apri il terminale nella tua area di lavoro ed esegui il comando seguente per clonare l’app:
|
1 |
git clone git@github.com:EspiraMarvin/cicd-tut.git |
Una volta clonato il repository, spostati all’interno della directory del progetto:
|
1 |
cd cicd-tut |
Esegui il comando docker-compose up per compilare ed eseguire l’app:
|
1 |
docker-compose up --build --force-recreate |
Al termine del processo, visita http://localhost:3000
Dovresti vedere qualcosa di simile a questo:

Passo 2. Comprendere il file Node.js.yml.
In questo passaggio, definiremo le direttive nel file YAML di GitHub per aiutarci a capire cosa sta succedendo. Nel repository, c’è una directory .github/workflows che contiene un file node.js.yml con i passaggi del workflow che i runner di GitHub seguono dopo aver inviato le modifiche al repository del codice su GitHub. YAML - la sua sintassi viene utilizzata per scrivere i workflow per le GitHub Actions. I file YAML terminano con l’estensione yaml o yml.
Apri il file node.js.yml , dovrebbe apparire così:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
name: cicd-tut on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: build: # Il tipo di runner su cui verrà eseguito il job runs-on: self-hosted strategy: matrix: node-version: [16.x] # Gli step rappresentano una sequenza di task che verranno eseguiti come parte del job steps: - name: 'checkout' uses: actions/checkout@v3 - name: 'setup node actions' uses: actions/setup-node@v3 with: node-version: "16" cache: 'npm' - run: npm i - run: npm test - run: npm run build # - run: cp -r ~/actions-runner/cicd-react/react-tut-test/react-tut-test/build /var/www/react-cicd |
Al momento della stesura di questo tutorial, stavamo utilizzando la versione 16 di Node.js 16. Ora, cerchiamo di capire il workflow di GitHub Actions:
-
name
name: cicd-tut
Il nome del tuo workflow, questo nome verrà mostrato nel tuo repository Actions tab.
-
on
|
1 2 3 4 5 |
on: push: branches: [ "main" ] pull_request: branches: [ "main" ] |
on viene utilizzato per definire gli eventi. Gli eventi possono attivare automaticamente un workflow o essere pianificati per un momento successivo. Gli eventi possono essere singoli o multipli, ed è anche possibile specificare l'esecuzione del workflow per branch, tag o file specifici. Questo funziona come un filtro.
Nel nostro file YAML stiamo definendo eventi multipli automatici, che sono:
-
Un evento push viene attivato quando viene effettuato il commit del codice in un repository
-
Un evento pull_request viene attivato quando viene creata una pull request sul branch main.
Stiamo specificando il nome di un branch main al fine di limitare l'esecuzione del workflow solo a quel branch. Possiamo anche specificare i branch da ignorare utilizzando il flag ! seguito dal nome del branch.
-
jobs
Un workflow è essenzialmente composto da uno o più job. Questi job vengono eseguiti in successione dal primo all'ultimo.
|
1 2 3 4 |
jobs: build: # Il tipo di runner su cui verrà eseguito il job runs-on: self-hosted |
Ogni job viene eseguito in un ambiente runner specificato da runs-on. Puoi scegliere di eseguire i job sui runner di GitHub indicati da ubuntu-latest o su un runner self-hosted indicato da self-hosted. La tua scelta dipenderà dal numero di job di cui hai bisogno. Con i runner self-hosted, hai maggiore flessibilità e controllo delle risorse.
Nel passaggio successivo, eseguiremo prima i nostri job sui runner di GitHub, poi, in seguito, configureremo un runner self-hosted di GitHub sul nostro server.
-
strategy
La strategia (strategy) ci consente di utilizzare variabili in una singola definizione di job per creare automaticamente più esecuzioni di job basate sulle combinazioni di variabili.
Nel nostro file YAML, abbiamo una variabile per la nostra node-version, ma se ne aggiungiamo un'altra per la versione 18 di Node, in questo modo: node-version: [16.x, 18.x], allora la strategia matrix creerà 2 esecuzioni di job per la nostra applicazione React, sia per la versione 16 che per la versione 18 di Node.
|
1 2 3 |
strategy: matrix: node-version: [16.x] |
-
steps
Gli step sono una sequenza di task che compongono un job. Gli step possono eseguire comandi, configurare attività, eseguire azioni nel tuo repository pubblico o azioni pubblicate in un registro Docker.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
steps: - name: 'checkout' uses: actions/checkout@v3 - name: 'setup node actions' uses: actions/setup-node@v3 with: node-version: "16" cache: 'npm' - run: npm i - run: npm test - run: npm run build |
Un passaggio ha un nome. Sebbene sia opzionale, puoi usarlo per specificare un modo semplice per identificare il nome del tuo passaggio che verrà visualizzato su GitHub.
In un passaggio, puoi selezionare un’azione da eseguire nel tuo job, le azioni sono riutilizzabili. Le versioni dell’azione vengono specificate quando si definisce un’azione, questo è importante perché impedisce al tuo workflow di interrompersi quando il proprietario dell’azione pubblica un aggiornamento.
Nel frammento di codice sopra, checkout@v3 è un esempio di un’azione con una versione specificata 3. Questa azione esegue il checkout del tuo repository in modo che il tuo workflow possa accedervi.
Alcune azioni come actions/setup-node@v3 sopra hanno input indicati utilizzando la parola chiave with, le azioni di setup node richiedono la versione 16 di Node e che npm sia memorizzato nella cache.
-
run
Questa azione esegue programmi da riga di comando utilizzando la shell del sistema operativo.
Nel file YAML sopra, abbiamo tre comandi, tutti verranno eseguiti utilizzando la stessa shell nell’ambiente del runner.
-
Il primo comando npm i installa tutte le dipendenze necessarie per la nostra applicazione React.
-
Il secondo npm test, esegue il test che abbiamo scritto. Il test si aspetta che il testo learn react venga renderizzato sulla Home page.
-
Infine, npm run build il comando crea una directory di build con una build di produzione della nostra applicazione. Successivamente, utilizzeremo questa directory di build nel nostro Nginx server block.
Passo 3. Testare GitHub CI con i GitHub Runner.
In questo passaggio, testeremo il processo di Continuous Integration con i runner di GitHub. Inizia aprendo il file node.js.yml . Modifica il tipo di runner su cui verranno eseguite le azioni in ubuntu-latest. Lo scopo di questo è testare se il workflow di GitHub funziona perfettamente sui runner di GitHub prima di configurare i nostri runner self-hosted.
|
1 2 3 |
jobs: build: runs-on: ubuntu-latest |
Crea un nuovo repository sul tuo GitHub account. Prima di continuare, torna alla directory del tuo workspace ed elimina la directory .git, se non riesci a vederla controlla i tuoi file nascosti. Puoi usare il seguente comando sul tuo terminale per eliminare la directory:
|
1 |
rm -rf .git |
Ora puoi fare git add di tutti i file del tuo progetto, fare il commit e il push nel tuo repository. Se ti blocchi, usa questa guida su collegare la cartella del tuo progetto al repository GitHub che hai creato sopra.
Quando hai finito, fai clic sulla scheda Code nel tuo repository e vedrai un piccolo punto arancione accanto al conteggio totale dei commit; quando fai clic su di esso, vedrai un modale simile a quello qui sotto, che indica che il tuo workflow è stato messo in coda:

Ora fai clic sul link Details nel modale o vai alla scheda Actions, vedrai ogni passaggio del workflow node.js.yml eseguito dai runner di GitHub:

In caso di successo, fai clic sulla scheda Actions, dovrebbe apparire così:

E questo è tutto, il piccolo punto arancione sulla nostra scheda Code ora dovrebbe essere una spunta verde. Il runner di GitHub ha compilato la nostra applicazione con successo.
Ora, facciamo un passo avanti e modifichiamo l’ambiente di build per utilizzare i runner self-hosted di GitHub nella nostra Ubuntu Server Infrastructure.
Passo 4. Configurazione del workflow di GitHub per utilizzare un runner self-hosted.
Prima di installare il runner self-hosted nel nostro server, torniamo al nostro workspace e modifichiamo il file di workflow node.js.yml per eseguirlo sui runner self-hosted di GitHub.
|
1 2 3 |
jobs: build: runs-on: self-hosted |
In questa fase, quando esegui il commit delle modifiche, il job verrà messo in coda poiché non è stato definito un runner self-hosted.
Nel tuo repository, fai clic sulla scheda
Settings, nella barra laterale sinistra fai clic su
Actions, quindi fai clic su
Runners:

Fai clic su New self-hosted runner, e seleziona Linux come sistema operativo.
Vedrai le istruzioni che ti mostrano come scaricare il runner e installarlo sul tuo server.
Passo 5. Installazione e configurazione di un runner self-hosted di GitHub sul nostro server.
In questo passaggio, configureremo un runner self-hosted di GitHub. Un runner self-hosted è un sistema in grado di distribuire e gestire l'esecuzione di job da GitHub Actions sul sito web di GitHub. Un vantaggio del runner self-hosted rispetto a quello ospitato da GitHub è la flessibilità. Offre un maggiore controllo sul sistema operativo, sull'hardware e su altri strumenti che possono essere personalizzati per soddisfare le esigenze della tua applicazione.
I runner self-hosted possono essere aggiunti a vari livelli, come ad esempio:
-
Runner a livello di repository, dedicati a un singolo repository.
-
Runner a livello di organizzazione, in grado di elaborare job per più repository in un'organizzazione.
-
A livello aziendale, che possono essere assegnati a più organizzazioni.
Per continuare, accedi al tuo server tramite ssh:
|
1 |
ssh username@server_ip |
Passa alla tua directory home con il comando:
|
1 |
cd ~ |
Quindi, crea una directory chiamata action-runners e naviga al suo interno:
|
1 |
mkdir actions-runner && cd actions-runner |
Successivamente, scarica l'ultima versione del pacchetto runner:
|
1 |
curl -o actions-runner-linux-x64-2.298.2.tar.gz -L https://github.com/actions/runner/releases/download/v2.298.2/actions-runner-linux-x64-2.298.2.tar.gz |
Quindi estrai il pacchetto scaricato con il comando:
|
1 |
tar xzf ./actions-runner-linux-x64-2.298.2.tar.gz |
Tornando al tuo repository, nella scheda Settings, nel pannello laterale sinistro fai clic su Actions, poi Runners, proprio come abbiamo fatto nel Step 4.
Vedrai un comando elencato che include un token che collega il tuo runner self-hosted al tuo repository GitHub. Mentre ti trovi ancora all'interno della directory in cui hai estratto il codice del runner di GitHub, usa il comando elencato per collegare il tuo runner, ad esempio:
|
1 |
./config.sh --url https://github.com/EspiraMarvin/react-tut-test --token XXXXXXXXXXXXXXXXXXXXXXXXXXX |
Dovrebbe autenticarsi con successo:

Premi invio per il gruppo di runner predefinito.
Quindi inserisci un nome per il tuo runner, ad esempio, my-runner, e premi invio.
Premi Invio per saltare l'aggiunta di ulteriori etichette, dovresti vedere il messaggio di successo nello screenshot qui sotto:

Inserisci il nome della tua directory di lavoro, ad esempio, react-cicd, dovrebbe andare a buon fine con il testo settings saved.
Infine, esegui ./run.sh, questo dovrebbe mostrare Connected to Github:

But this does not run in the background, if we type ctrl+c nel nostro terminale, il runner verrà arrestato. Dobbiamo sostituirlo con il servizio .svc.sh per mantenere il runner in esecuzione come servizio in modo da poter continuare a interagire con esso.
Arresta il runner con ctrl+c. Puoi installare il servizio .svc.sh eseguendo il comando:
|
1 |
sudo ./svc.sh install |
Once it has installed, start the service with the command:
|
1 |
sudo ./svc.sh start |
Questo dovrebbe andare a buon fine, mostrando active (running).
Per confermare che il servizio svc.sh sia attivo e funzionante, esegui il comando:
|
1 |
sudo ./svc/sh status |

A questo punto, qualsiasi workflow che potrebbe essere stato messo in coda in attesa di un runner self-hosted dovrebbe essere eseguito con successo. Puoi anche modificare un file e fare delle prove. Ad esempio, modifica il file Informazioni.tsx, esegui il commit e il push delle modifiche; il runner self-hosted completerà il job con successo.
Passaggio 6. Configurazione del blocco server Nginx
In questo passaggio, configureremo un blocco server in Nginx per visualizzare la versione di build della nostra applicazione React. Abbiamo un tutorial su Configurazione dei blocchi server Nginx che potresti trovare utile.
Di seguito è riportato un esempio di blocco server utilizzato in questo tutorial:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
server { listen 80; listen [::]:80; server_name react.test; root /var/www/react-cicd/build; index index.html index.htm index.nginx-debian.html; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; charset utf-8; location / { try_files $uri $uri/ =404; } } |
Creerai un file di configurazione del blocco server Nginx all'interno della directory /etc/nginx/sites-available .
Apri un file per la configurazione del blocco server del tuo sito con l'editor nano usando il comando:
|
1 |
sudo nano /etc/nginx/sites-available/react-cicd |
Copia il blocco server condiviso sopra e modificalo in base ai percorsi delle tue directory, quindi incollalo nel file aperto. Al termine delle modifiche, premi ctrl+x poi premi y e enter per salvare e uscire.
Una volta salvato, crea un symlink per la configurazione del blocco server react-cicd da /etc/nginx/sites-available a /etc/nginx/sites-enabled eseguendo il comando:
|
1 |
sudo ln -s /etc/nginx/sites-available/react-cicd /etc/nginx/sites-enabled/ |
Affinché le modifiche abbiano effetto, è necessario riavviare Nginx. Tuttavia, prima di poter riavviare il servizio Nginx, verifica se le configurazioni di Nginx sono valide, eseguendo il comando:
|
1 |
sudo nginx -t |
Se la configurazione è corretta, il test dovrebbe andare a buon fine.
Noti il valore della direttiva server_name “ react.test ” nel blocco server? Aggiungerai questo valore nel tuo file hosts sulla tua macchina locale. Questo ti consentirà di aprire l'applicazione nel tuo browser. Questo passaggio è necessario solo per i domini virtuali utilizzati negli ambienti di sviluppo locale. Se disponi di un nome di dominio registrato collegato a un IP pubblico del tuo server, il nome di dominio dovrebbe essere già accessibile nel tuo browser.
Sulla tua macchina locale, apri il file hosts con il comando:
|
1 |
sudo nano /etc/hosts |
All'interno del file hosts, aggiungi l'indirizzo IP del tuo server, ad es. 127.0.0.1, seguito dal tuo nome di dominio virtuale.
Di seguito è mostrato un esempio. Quindi chiudi il file e salva:
|
1 |
192.168.3.123 react.test |
Tornando al tuo server, all'interno della directory /var/www , crea una nuova directory, puoi chiamarla react-cicd eseguendo:
|
1 |
mkdir react-cicd |
In questa fase, decommenteremo l'ultimo comando nel file node.js.yml .
Questo comando copia la cartella build della nostra applicazione react da dove abbiamo specificato la nostra cartella di lavoro all'interno della directory actions-runner nel precedente step 5.
E inserisce la cartella public nella directory /var/www/react-cicd .
Il blocco server può ora accedere alla nostra app e visualizzarla su un browser.
Infine, riavvia il servizio Nginx con il comando:
|
1 |
sudo service nginx restart |
Ora puoi apportare una modifica nel file Informazioni.tsx , quindi fare il commit e il push delle modifiche nel tuo repository. Dopo una build andata a buon fine, vedrai la versione build della tua app react su http://react.test o sul nome di dominio specificato. Evita di modificare l'elemento href nel file Home.tsx poiché potrebbe causare il fallimento del test già scritto. Anche la scheda Actions nel tuo repository dovrebbe mostrare la build del job completata.

Conclusione
L'integrazione continua con Github Actions comporta molti vantaggi, tra cui un'ottima esperienza per gli sviluppatori, aiuta con i test continui, consente collaborazioni più semplici in team più grandi, riduce i tempi di sviluppo, garantisce rilasci rapidi di nuove funzionalità, feedback in tempo reale e soddisfazione del cliente, offrendoti un vantaggio rispetto ai tuoi concorrenti. Per approfondire queste conoscenze, potresti anche voler imparare a conoscere Configurare pipeline di Continuous Integration (CI) di GitLab su Ubuntu. e a usare un' istanza GitLab gestita autonomamente per ospitare le tue immagini Docker ed eseguire build private.
Buon computing!
Commenti
Ancora nessun commento. Scrivi il primo.