Utiliser GitHub actions et hosted runners

illustrations illustrations illustrations illustrations illustrations illustrations illustrations
post-thumb

Publié le 24 février 2022 par Andrew Owen (6 minutes)

Vous avez probablement entendu parler de Devops. Vous connaissez probablement le terme CI/CD (intégration et livraison continues). Si ce n’est pas le cas, voici ce qu’il en est:

  • intégration continue:
    • construire le logiciel localement
    • tester le logiciel localement
    • fusionner le logiciel dans un référentiel de contrôle des sources (généralement Git).
  • livraison continue:
    • publication automatique dans le référentiel.
  • déploiement continu:
    • déploiement automatique en production.

DevOps signifie simplement l’intégration entre le développement et les opérations. Avec cette approche, le cycle de vie du logiciel est:

  1. planifier
  2. coder
  3. construire
  4. tester
  5. libérer
  6. déployer
  7. exploiter
  8. surveiller

Dans la phase d’intégration, les tests automatisés montrent si le logiciel est cassé lorsque le nouveau code est fusionné dans la branche principale.

La phase de livraison garantit que le logiciel est toujours “prêt à être publié”.

La phase de déploiement automatise le processus de mise en production du logiciel.

L’objectif de tout cela est de fournir fréquemment des modifications de code en toute confiance, généralement dans le cadre d’une approche de développement logiciel agile. Il existe de nombreux articles en ligne qui traitent en profondeur de ce sujet, notamment un article d’InfoWorld.

Pour la construction et les tests automatiques, on utilisait autrefois un serveur de construction local. Aujourd’hui, il est plus probable qu’il s’agisse d’un conteneur Docker fonctionnant sur l’infrastructure d’orchestration de conteneurs Kubernetes dans un nuage hébergé fourni par Amazon, Google ou Microsoft. C’est une bonne chose si vous disposez d’une équipe DevOps complète. Mais si vous n’êtes pas déjà familiarisé avec Kubernetes, la courbe d’apprentissage est abrupte. Selon l’ampleur de votre projet, il peut y avoir une alternative plus simple.

Les GitHub Actions et GitHub-hosted runners (d’autres fournisseurs comme GitLab offrent des fonctionnalités équivalentes et il existe des offres autonomes entières qui s’intègrent à Git, comme Cirrus CI). Les actions sont des scripts qui peuvent être automatisés ou déclenchés manuellement. Vous pouvez y accéder à partir du menu Actions. Si vous utilisez des pages GitHub pour héberger un site web pour votre projet, vous verrez pages-build-deployment listé sous workflow.

Les runners sont des machines virtuelles (VM) qui sont activées pour exécuter un script et qui sont ensuite désactivées. GitHub propose des VM Linux, Windows et macOS (prix dans cet ordre). Les projets open source bénéficient d’un certain nombre de crédits mensuels gratuits. Si vous payez pour l’utiliser, cela vaut la peine de faire le tour du marché.

GitHub fournit de nombreux scripts préconfigurés et fait des suggestions basées sur son analyse du code dans votre dépôt. Ces scripts sont assez faciles à configurer. Mais si une solution prête à l’emploi ne convient pas, vous pouvez créer la vôtre. Dans Actions, cliquez sur New workflow, puis sur set up a workflow yourself. Vous obtiendrez le modèle YAML standard:

# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events but only for the main branch
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

    # A workflow run is made up of one or more jobs that can run sequentially or in parallel
    jobs:
      # This workflow contains a single job called "build"
      build:
        # The type of runner that the job will run on
        runs-on: ubuntu-latest
    
        # Steps represent a sequence of tasks that will be executed as part of the job
        steps:
          # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
          - uses: actions/checkout@v4
    
          # Runs a single command using the runners shell
          - name: Run a one-line script
            run: echo Hello, world!
    
          # Runs a set of commands using the runners shell
          - name: Run a multi-line script
            run: |
              echo Add other actions to build,
              echo test, and deploy your project.              

Par défaut, il crée ce fichier sous la forme <repository>/.github/workflows/main.yml.

  • name est ce qui est affiché dans la liste des actions.
  • on définit les triggers:
    • push et pull déclenchent le script sur les requêtes push et pull. Si vous ne spécifiez pas de branches, elles prennent par défaut la valeur main.
    • worklflow_dispatch vous permet de déclencher manuellement le script à partir de la liste d’actions.
  • jobs définit une ou plusieurs tâches nommées, par exemple build.
  • runs-on spécifie l’environnement VM. Si vous pouvez utiliser Ubuntu, c’est l’option la moins chère avec les runners hébergés. Si vous avez besoin d’un système d’exploitation spécifique que GitHub ne propose pas, vous pouvez héberger vos propres runners.
  • steps peut être utilisé pour invoquer des actions telles que checkout (qui récupère une copie du dépôt sur la VM) et pour exécuter des commandes shell avec name: run.
  • run avec un caractère pipe ( | ) exécute un script multi-lignes. Sans ce caractère, une seule ligne est exécutée.

L’environnement Ubuntu de GitHub contient un grand nombre d’outils préinstallés dont vous pourriez avoir besoin, notamment Java et Perl. Mais si l’outil dont vous avez besoin est manquant et qu’un paquetage existe pour lui, vous pouvez ajouter la ligne sudo apt install<package> sans avoir à spécifier de mot de passe. Vous pouvez ajouter des dépôts de logiciels externes à la VM Ubuntu, mais si l’outil ne se trouve pas dans l’un d’eux, la solution la plus simple est d’ajouter un binaire Linux x86 ou x64 à votre dépôt de sources.

Voici le script de construction de SE Basic IV:

name: build
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
  workflow_dispatch:
    jobs:
      build:
        runs-on: ubuntu-latest
        permissions:
          contents: write
        steps:
          - uses: actions/checkout@v4
          - name:
            run: |
              cd basic
              ../rasm/rasm-deb-i386 -pasmo basic.asm -ob ../bin/23.bin -sz -os ../bin/symbols.txt
              cd ../boot
              ../rasm/rasm-deb-i386 -pasmo boot.asm -ob ../bin/boot.rom
              rm basic.bin
              cp ../bin/boot.rom ../ChloeVM.app/Contents/Resources/se.rom
              cat ../bin/basic.rom >> ../ChloeVM.app/Contents/Resources/se.rom
              cd ../rasm
              ./rasm-deb-i386 firmware.asm -ob ../bin/FIRMWA~1.BIN              

Chaque fois qu’il y a un push ou un pull dans la branche principale, le script est déclenché. Il peut également être déclenché manuellement. Il fonctionne sous Ubuntu. Il a une dépendance qui ne fait pas partie du système d’exploitation: l’assembleur Z80-cross RASM. Heureusement, j’avais déjà une version x86 dans le repo lorsque je prévoyais d’utiliser mon disque NAS comme serveur de compilation.

Le script reproduit la fonctionnalité des tâches VScode. Il construit l’interpréteur BASIC. Puis il construit la ROM de démarrage. Il assemble ensuite la ROM combinée et construit le firmware (qui inclut une somme de contrôle). En ce qui concerne les tests, ils sont assez limités. La principale chose qu’il détectera est si une section de code nouvellement ajoutée fait déborder le code de la zone de code suivante. Mais si quelque chose casse la compilation, c’est immédiatement évident en regardant les journaux d’actions.

Après avoir fait fonctionner le script de construction, j’ai ajouté des actions pour construire et déployer un portail API, générer des pages de code à partir d’un seul fichier de police Unicode et convertir les chaînes de langue UTF-8 dans un fichier JSON en données emballées pour la page de code appropriée. Je couvrirai ces actions en détail dans de prochains articles.