Blog

Github en Action !

On ne présente plus Github comme gestionnaire de code source… mais, depuis 2018 il s’affirme également comme outil complet d’intégration continue !

En 2018, dans le sillage de son rachat par Microsoft, Github a dévoilé Github Actions, un outil de CI/CD permettant d’exécuter des pipelines, directement intégré dans l’outil de gestion des sources.
Voyons un peu ce qu’il a dans le ventre !

Nous allons ici mettre en place de l’intégration continue sur le projet LadyBug de Frédéric Lanic !
Il s’agit d’un jeu d’arcade de type Pac-Man. Basé sur Spring Boot, ce projet open-source est buildé via Maven.

Les releases étaient produites manuellement, avec un tag Git poussé en ligne de commandes, et il était nécessaire du compiler les sources en local pour pouvoir jouer.

Notre objectif, ici, est donc de rationaliser les releases : compiler notre application, jouer les tests unitaires, produire et publier une version stable (sous forme d’un jar exécutable) sans multiplier les actions manuelles.

Le dépôt du projet est hébergé sur Github, c’est donc l’occasion de tester Github Actions !
Et, bonne nouvelle, c’est gratuit pour les projets publics !

Les projets privés d’entreprise, eux, se verront facturés sur la base du temps d’utilisation des ressources. Un quota gratuit de 2000 minutes par mois est néanmoins inclus pour les dépôts privés.

Intégration Continue et publication

Nous utiliserons donc le Maven Release Plugin pour produire des releases, et les outils intégrés à Github pour la publication des livrables.

Ce plugin permet de créer de façon reproductible et rationnelle une release d’un projet Maven.
Il gère pour nous l’exécution des phases classiques du cycle de build Maven (compile, test, package, deploy...) et réalise pour nous la mise à jour du fichier pom.xml et la création du tag git identifiant la version.

Workflows Github Actions

L’outil nous permet de définir des workflows correspondant à des tâches à exécuter : jouer les tests d’intégration, produire une release, etc.

Chaque workflow sera déclaré dans les sources de notre projet sous forme d’un fichier yaml.
La syntaxe complète pour ces fichiers est consultable ici : Workflow syntax for GitHub Actions.

Si vous manquez d’inspiration, pas de panique : les équipes de Github (ainsi que des collaborateurs de la communauté) ont mis à disposition des templates de fichier correspondant aux cas les plus courants : si votre projet s’appuie sur une stack standard, vous trouverez facilement de quoi mettre sur pied votre workflow.

La syntaxe des Workflows Github Actions et leur mode d’exécution via des runners sont assez proches du fonctionnement de GitLab-CI (D’ailleurs, nous proposons une formation GitLab CI / CD)

# Le format YAML est utilisé : ce format a la particularité d'utiliser l'indentation (espaces en début de ligne)
# pour structurer les blocs de données. Les tirets, eux, servent à délimiter les éléments d'une liste

jobs:
   release:
      runs-on: ubuntu-latest
      steps:
        - uses: actions/checkout@v2
    
        - name: Set up JDK 16
          uses: actions/setup-java@v2
          with:
             java-version: '16'

        - name: Release
          run: mvn -B release:prepare release:perform

Notre fichier de workflow définira donc des jobs, eux-mêmes décomposés en steps.

Dans l’exemple ci-dessus, un job appelé « release » a été déclaré, et trois steps sont décrits.

Ici, on remarque deux approches pour décrire ces steps : préciser les commandes à exécuter avec le mot-clé run, ou utiliser le mot-clé uses pour inclure un template d’action publié sur Github (éventuellement complété par des paramètres avec le mot-clé with)

Publication des releases

Encore plus intéressant pour notre projet LadyBug, Github propose également des outils pour mettre à disposition nos livrables.

Nous allons ainsi pouvoir proposer notre jeu en téléchargement via les releases Github et permettre à d’autres développeurs de se baser sur nos travaux via Maven et Github Packages.

Releases et packages Github

Dépôt d’artifacts sur Github Packages

Une fois notre release produite, on souhaite généralement la déposer sur un dépôt de livrables. On pourra ainsi aller l’y récupérer lors du déploiement de notre application. Soit dans un dépôt public, comme Maven Central par exemple (voir notre article « Déployer son artifact sur Maven Central »  sur le sujet), soit dans le dépôt privé de son entreprise (Nexus, Artifactory…)

Github nous propose son propre service de dépôt d’artifacts, Github Packages, qui nous permet de créer un dépôt public ou privé pour votre projet.

Github Package prend en charge la livraison de livrables de types variés : artifacts Maven, images Docker, paquets npm, etc.

Le Maven Release Plugin déclenche en sous-main un mvn deploy : pour publier sur Github Package, il suffit de configurer les informations d’accès au dépôt d’artifacts dans le pom.xml, et d’injecter dans notre workflow le fichier settings.xml ad hoc.

Nous ajoutons donc la balise distributionManagement à notre pom.xml :

<distributionManagement>
    <repository>
        <id>github</id>
        <url>https://maven.pkg.github.com/FredericLanic/ladybug</url>
        <layout>default</layout>
    </repository>
    <snapshotRepository>
        <id>github</id>
        <url>https://maven.pkg.github.com/FredericLanic/ladybug</url>
        <layout>default</layout>
    </snapshotRepository>
</distributionManagement>

Et nous injectons, dans le workflow, le chemin du fichier settings.xml à notre commande mvn. Ce fichier est généré pour nous par l’action actions/setup-java que nous avons injecté dans un de nos steps. Le token d’accès, lui, est injecté nativement par Github Actions.

- name: Set up JDK 16
  uses: actions/setup-java@v2
  with:
    java-version: '16'
    server-id: github
    settings-path: ${{ github.workspace }} # Cette variable correspond au path de la racine du projet sur le runner

- name: Prepare Release
  run: > # syntaxe multilingue YAML : il s'agit bien d'une seule commande avec des arguments
    mvn -B release:prepare release:perform
    -Dpassword=${{ secrets.GITHUB_TOKEN }} -Darguments="-s $GITHUB_WORKSPACE/settings.xml"

Et voilà !

Les releases Github

Le volet release permet d’associer un tag git avec le binaire (livrable / exécutable) qui correspond à ce tag.
Les releases peuvent être créées à la main, mais il est bien entendu plus intéressant d’intégrer la publication de la release à notre workflow CI/CD !

Notre projet LadyBug s’appuie sur Spring Boot, ce qui permet à notre build de produire un jar exécutable.
Nous pouvons donc ajouter un step à notre job pour publier une release et y joindre le fichier jar produit !

# Création d'une Release Github
- name: Publish Github Release
  uses: softprops/action-gh-release@v1
  with:
    tag_name: ${{ steps.tag-name.outputs.TAG }} # On récupère le tag extrait au step précédent.
    files: target/*.jar # Attachement du jar produit à la release Github

Plutôt que d’investir du temps sur les APIs REST de Github, nous utilisons ici le mot-clé uses pour inclure une action existante qui fait déjà ce dont nous avons besoin. Nous lui passons en paramètre l’emplacement du ou des fichiers à joindre à la page de release (ici, notre Jar)

Après l’exécution du workflow, nous obtenons ainsi une belle page de release, qui permet le téléchargement en un clic du jar exécutable !

Conclusion

Avec assez peu de temps investi, nous avons pu mettre en place une chaine simple pour produire nos releases. Les utilisateurs d’autres outils de CI/CD (et notamment de Gitlab CI) s’y retrouveront vite dans la syntaxe et la philosophie de Github Actions. La possibilité d’inclure des actions déjà définies (par Github ou par la communauté open-source) et l’abondante documentation rendent assez aisée la mise en place d’un workflow.

Si les outils présentés (Github Actions, Github Package, Publication des releases…) peuvent, par certains aspects, être moins complets que des outils concurrents spécialisés (Jenkins, Artifactory…) leur intégration fluide et cohérente dans Github rend l’ensemble très convaincant !

Et enfin, voici les sources :

Jim Etevenard

Written by

Consultant-Formateur chez OXiane