DA MASER A MONFUMO | MOTO GUZZI V85TT | PURE SOUND POV 4K

🏍️ Il mio nuovo canale YouTube: giri in moto in POV, solo audio, tra le Dolomiti in 4K. Niente musica, niente parole — solo il motore e le Alpi. Vieni a fare un giro!

Iscriviti

Di recente ho costruito un server DNS rudimentale usando Rust per approfondire la mia comprensione dell'argomento. Il progetto, chiamato vòdo, è accessibile qui.

Workflow Quotidiani

A ogni push sul branch main e sulle pull request, voglio compilare il progetto ed eseguire i test per assicurarmi che non vengano introdotti bug. Utilizzo una configurazione di workflow Actions di base per questo scopo:

yaml
name: Rust
 
on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]
 
env:
  CARGO_TERM_COLOR: always
 
jobs:
  build:
    runs-on: ubuntu-latest
 
    steps:
      - uses: actions/checkout@v3
      - name: Build
        run: cargo build --verbose
      - name: Run tests
        run: cargo test --verbose

Questa configurazione funziona bene per lo sviluppo quotidiano, ma non è sufficiente per creare una release "di produzione" una volta soddisfatto del risultato. Sebbene esistano Actions sul marketplace che possono generare facilmente una nuova release con artefatti, voglio includere nella release l'eseguibile vòdo per tutti i principali sistemi operativi, il che complica leggermente il processo. Inoltre, la release non deve essere creata se una delle build fallisce.

La Matrix Job Strategy

GitHub Actions offre una funzionalità chiamata "Matrix", che definisce una strategia per i job che consente di usare variabili all'interno di una singola definizione di job per generare automaticamente più esecuzioni del job in base alle combinazioni di variabili. Ad esempio, puoi usare una matrix strategy per testare il tuo codice su varie versioni del linguaggio o su più sistemi operativi. Maggiori dettagli sono disponibili nella documentazione di GitHub.

Questo è l'approccio che ho usato per compilare Vodo per Linux, MacOS e Windows in parallelo. Ho generato un nuovo file di configurazione del workflow Actions specifico per le release. Questo workflow viene attivato dai nuovi tag nel repository, il che significa che per creare una nuova release mi basta generare un nuovo tag Git e farne il push nel repository.

yaml
name: Release
 
on:
  push:
    tags:
      - "*"
 
jobs:
  release:
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            artifact_name: ${{ github.event.repository.name }}
            asset_name: ${{ github.event.repository.name }}-linux-amd64
          - os: windows-latest
            artifact_name: ${{ github.event.repository.name }}.exe
            asset_name: ${{ github.event.repository.name }}-windows-amd64.exe
          - os: macos-latest
            artifact_name: ${{ github.event.repository.name }}
            asset_name: ${{ github.event.repository.name }}-macos-amd64
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Set up Rust
        uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
      - name: Build release
        run: >-
          cargo build --release

Con questa configurazione, Actions esegue più job in parallelo, uno per ogni sistema operativo:

  • Il job in esecuzione su ubuntu-latest crea un eseguibile per Linux chiamato vodo-linux-amd64

  • Il job in esecuzione su macos-latest crea un eseguibile per MacOS chiamato vodo-macos-amd64

  • Il job in esecuzione su windows-latest crea un eseguibile per Windows chiamato vodo-windows-amd64

Questo è l'approccio più semplice che risolve il problema: mi ci è voluto un bel po' di tempo per trovare il modo migliore per ottenere questo risultato senza una configurazione del workflow eccessivamente complessa! Nell'interfaccia di GitHub appare così:

Release workflow on GitHub UI

Creare la Release

I passaggi precedenti creano solo gli artefatti, ed è necessario un passaggio aggiuntivo per creare una release e allegarvi gli eseguibili. Questo passaggio usa svenstaro/upload-release-action@v2 ed è eseguito in ogni build specifica per OS. Tuttavia, la release viene creata una sola volta e, se una delle build fallisce, la release viene rimossa. La configurazione necessaria è la seguente:

yaml
- name: Upload binaries to release
  uses: svenstaro/upload-release-action@v2
  with:
    repo_token: ${{ secrets.GITHUB_TOKEN }}
    file: target/release/${{ matrix.artifact_name }}
    asset_name: ${{ matrix.asset_name }}
    tag: ${{ github.ref }}

Al termine di questo passaggio, la release corrispondente al tag viene creata ed è accessibile tramite l'interfaccia utente di GitHub 🎉.

Release page in GitHub UI

In questo articolo ho spiegato come ho costruito un server DNS rudimentale chiamato vòdo usando Rust e configurato un workflow GitHub Actions per compilare e testare il progetto. Ho discusso dell'uso della Matrix job strategy per creare build di produzione per più sistemi operativi e di come creare una release con eseguibili allegati usando svenstaro/upload-release-action. Il risultato è un processo di release efficiente e automatizzato per il progetto, con un file di configurazione del workflow facile da comprendere.