GitHub Actions con Lightsail

  • Di
  • 2023-03-30 - 7 minuti
banner

GitHub Actions e AWS: in che modo possiamo sfruttare questa feature di GitHub con AWS Lightsail, il servizio di Amazon per creare delle istanze di hosting già pronte all’uso?

Da quando Amazon ha avviato questo servizio, ha aperto le porte a tutte quelle persone che hanno bisogno di un hosting che sia semplice da usare e che non sia costoso: in questo articolo vedremo infatti come sfruttare queste due tecnologie per avere un flusso che applichi la Continuous Delivery e il Continuous Deployment!

Cosa vedrai

GitHub Actions

GitHub Actions è una feature che automatizza la creazione, il test e la distribuzione del software. Ma non si ferma qui: ti permette anche di eseguire qualsiasi tipo di operazione sul tuo repository quando si verifica un evento specifico.

Per avere un quadro completo di cosa sia GitHub Actions, aiuta a scomporlo nei suoi numerosi componenti, che trovi nel precedente articolo sul tema.

Esempio

In questo articolo vedremo come utilizzare le GitHub Actions per eseguire il deploy di un’applicazione Hugo su un’istanza Lightsail basata su LAMP: questi passaggi sono validi per qualsiasi tipologia di applicazione debba essere deployata sotto un web server come Apache o Nginx.

Sarà necessario seguire alcuni steps: dovremo definire quale evento attiverà le azioni descritte nella sezione relativa ai job e poi descrivere tutti gli step che devono essere seguiti per poter procedere.

Nel nostro caso, avremo bisogno che la GitHub Action vada a scaricare Hugo nella versione utilizzata per poi generare il contenuto di build del sito e pubblicarlo all’interno dell’istanza Lightsail.

Partiamo però dalla parte più semplice: scegliamo il repository da utilizzare per la creazione della GitHub Action e assegnamole un nome:

Per decidere il nome del flusso di lavoro, inseriamo la proprietà name:

name: Deploy Hugo site to Lighsail

A questo punto, andiamo a descrivere il trigger che dovrà scatenare la Action e portare all’esecuzione i diversi step di lavoro; per questo esempio, utilizzeremo come evento il push di un commit sul branch master del repository.

name: Deploy Hugo site to Pages

on:
  push:
    branches: ["master"]

Passo successivo: descrivere i passaggi che devono essere eseguiti per portare la nostra applicazione sull’istanza Lightsail. Per farlo, ci sarà bisogno di descrivere all’interno della sezione jobs il flusso di lavoro che deve essere elaborato.

Grazie ai jobs, è possibile eseguire più operazioni in parallelo: in questo caso però, i passaggi da eseguire saranno sequenziali, perché ognuno di essi è fondamentale per quello successivo.

build è il nome assegnato al job: questo è infatti l’ID che viene assegnato al task per descrivere in modo univoco l’attività che verrà eseguita.

name: Deploy Hugo site to Pages

on:
  push:
    branches: ["master"]

jobs:
  build:

Ogni job viene eseguito in un ambiente di esecuzione chiamato runner environment il cui sistema viene specificato nell’istruzione runs-on. Per le attività dell’esempio, andremo ad utilizzare una distribuzione Ubuntu, specificando anche eventuali variabili di ambiente che ci possono tornare utili nelle fasi successive.

Come avviene l’esecuzione? GitHub ha un insieme di macchine virtuali su Azure che vengono utilizzate per questo tipo di operazioni, sfruttando dei servizi chiamati proprio runner.

Per scegliere il runner è possibile seguire diverse strategie: nella documentazione vengono elencati tutti i runner che sono disponibili e hostati da GitHub, tra cui Ubuntu, Windows e MacOS. Esistono diverse modalità con cui utilizzare questi runner: andiamo ad utilizzare quella più semplice, dichiarando il nome del self-hosted runner.

name: Deploy Hugo site to Pages

on:
  push:
    branches: ["master"]

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      HUGO_VERSION: 0.99.1

Il primo passaggio utilizza un’azione denominata actions/checkout@v2. Questa è un’azione fornita da GitHub che verificherà il tuo repository sul runner, in modo che possa essere compilato e testato.

name: Deploy Hugo site to Pages

on:
  push:
    branches: ["master"]

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      HUGO_VERSION: 0.99.1

  steps:
    - uses: actions/checkout@v2
        with:
          submodules: true  # Fetch Hugo themes
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod

Per il secondo step, andiamo a descrivere qual è il task da eseguire, che action utilizzare e con che modalità: nel caso di esempio, lo step che deve essere eseguito per primo è quello che configura Hugo nella versione utilizzata per lo sviluppo del sito, per cui utilizzeremo una action presente su GitHub creata proprio per Hugo.

Se utilizziamo una tecnologia diversa per il sito statico con cui si vuole lavorare, è sufficiente cercare la GitHub Action più adatta nel Marketplace!

Gli argomenti possono essere forniti all’azione nella sezione with; in questo esempio, specifichiamo la versione estesa di Hugo 0.99.1, secondo la documentazione della GitHub Action.

name: Deploy Hugo site to Pages

on:
  push:
    branches: ["master"]

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      HUGO_VERSION: 0.99.1

  steps:
    - uses: actions/checkout@v2
        with:
          submodules: true  # Fetch Hugo themes
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod
    - name: Setup Hugo
      uses: peaceiris/actions-hugo@v2
      with:
        hugo-version: ${{ env.HUGO_VERSION }}
        extended: true

Lo step successivo è quello di andare a minificare il codice di Hugo: questo step produrrà quindi una cartella denominata public che possiamo andare ad utilizzare per pubblicare l’applicazione sotto il web server nello step successivo.

name: Deploy Hugo site to Pages

on:
  push:
    branches: ["master"]

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      HUGO_VERSION: 0.99.1

  steps:
    - uses: actions/checkout@v2
        with:
          submodules: true  # Fetch Hugo themes
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod
    - name: Setup Hugo
      uses: peaceiris/actions-hugo@v2
      with:
        hugo-version: ${{ env.HUGO_VERSION }}
        extended: true

    - name: Build environment production
      run: hugo --minify

L’ultimo step è quello relativo alla copia dei file sull’istanza Lightsail: trattandosi di una sorta di server per hosting, possiamo infatti pensare di copiare i file utilizzando scp della cartella public nell’istanza.

Per accedervi, avremo bisogno però di alcune informazioni, tra cui la chiave, l’indirizzo IP, la porta e lo username. Tutte queste informazioni sono disponibili all’interno della dashboard di Lightsail relativo all’istanza che utilizziamo.

Trattandosi di informazioni sensibili, per fornire questi valori alla GitHub Action, l’ideale è utilizzare i Secret: si tratta di oggetti che fanno parte del repository e che possono essere utilizzati per memorizzare dati sensibili, come chiavi, certificati o password. Soprattutto se utilizziamo un repository pubblico, queste informazioni non dovrebbero essere visibili!

Per creare i Secret, andiamo nella sezione “Settings” del repository e nel menù a sinistra clicchiamo su “Secrets”:

Per lo scopo di esempio, sarà importante creare un secret che contenga le informazioni descritte in precedenza: ad esempio, andremo a creare un secret che contenga all’interno della variabile “HOST” l’indirizzo IP dell’istanza Lightsail:

Ripetiamo la stessa procedura per tutti i campi che vogliamo memorizzare nei Secret e ci concentriamo sulla chiave: per collegarsi all’istanza Lightsail tramite SSH, ci viene infatti fornita una chiave di default (o custom) che è possibile scaricare dalla dashboard del servizio AWS e che ci permette di avviare una connessione con un qualsiasi terminale.

Per la GitHub Action utilizziamo, nel caso del campo key, la chiave dell’istanza fornita da AWS Lightsail memorizzata in un secret ad hoc.

A questo punto, siamo pronti per copiare, a partire dalla cartella public, il sito statico all’interno del web server di Apache!

name: Deploy Hugo site to Pages

on:
  push:
    branches: ["master"]

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      HUGO_VERSION: 0.99.1

  steps:
    - uses: actions/checkout@v2
        with:
          submodules: true  # Fetch Hugo themes
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod
    - name: Setup Hugo
      uses: peaceiris/actions-hugo@v2
      with:
        hugo-version: ${{ env.HUGO_VERSION }}
        extended: true

    - name: Build environment production
      run: hugo --minify

    - name: copy file via ssh password
      uses: appleboy/scp-action@master
      with:
        host: ${{ secrets.HOST }}
        port: ${{ secrets.PORT }}
        source: "./public"
        key: ${{ secrets.SSH_KEY_PRIVATE }}
        target: "/opt/bitnami/apache2/htdocs"
        username: ${{ secrets.USERNAME }}
        overwrite: true

Terminato quest’ultimo step, sarà sufficiente verificare che l’esecuzione vada a buon fine: il flusso di lavoro (aka workflow) sarà presente sotto la sezione “Actions”, mentre il file che descrive la Action appena creato viene pushato all’interno del repository sotto .github/workflows:

Se ti è piaciuto questo articolo, non ti dimenticare di commentare e condividere! ⬇️

Risorse utili

Post correlati

Partners

Community, aziende e persone che supportano attivamente il blog

Logo di Codemotion
Logo di GrUSP
Logo di Python Milano
Logo di Schrodinger Hat
Logo di Python Biella Group
Logo di Fuzzy Brains
Logo di Django Girls
Logo di Improove
Logo del libro open source

Iscriviti alla newsletter

Per non perderti gli ultimi articoli e per vincere biglietti e gadget TheRedCode

Riceverai una volta al mese (o anche meno) gli articoli più interessanti pubblicati sul blog, e potrai provare a vincere un biglietto per uno dei prossimi eventi!

Andiamo!