6 Intégration continue
L’intégration continue consiste à confier à un service externe la tâche de vérifier un package, produire des documents Markdown pour les pages web d’un dépôt GitHub ou tricoter entièrement un site web à partir du code.
Toutes ces tâches peuvent être accomplies localement sur le poste de travail mais prennent du temps et risquent de ne pas être répétées à chaque mise à jour. Dans le cadre de l’intégration continue, elles le sont systématiquement, de façon transparente pour l’utilisateur. En cas d’échec, un message d’alerte est envoyé.
La mise en place de l’intégration continue se justifie pour des projets lourds, avec des mises à jour régulières. plutôt que pour des projets contenant un simple document Markdown rarement modifié.
6.1 Outils
6.1.1 GitHub Actions
L’outil utilisé le plus fréquemment pour des projets R déposés sur GitHub était Travis CI110 mais le service est devenu payant en 2021.
Les Actions GitHub remplacent avantageusement Travis. Ce service est intégré à GitHub.
6.1.2 Codecov
Pour évaluer le taux de couverture du code des packages R, c’est-à-dire la proportion du code testé d’une façon ou d’une autre (exemples, tests unitaires, vignette), le service Codecov111 s’intègre parfaitement à GitHub.
Il faut ouvrir un compte, de préférence en s’authentifiant par GitHub.
6.1.3 GitHub Pages
Les pages web de GitHub peuvent être hébergées dans le répertoire docs
de la branche master du projet : c’est la solution retenue quand elle sont produites sur le poste de travail.
Si elles sont produites par intégration continue, elle le seront obligatoirement dans une branche dédiée appelée gh-pages
.
6.2 Principes
Un projet de document est traité en exemple.
L’objectif est de faire tricoter par GitHub un projet Markdown.
Cette pratique est appropriée pour les projets d’ouvrages, qui nécessitent beaucoup de ressources pour leur construction.
Dans ce type de projet, le code est tricoté par knitr pour produire plusieurs documents, typiquement aux formats HTML et PDF, accessibles sur les pages GitHub.
Quand les documents sont produits localement, ils sont placés dans le dossier docs
et poussés sur GitHub.
Pour que GitHub s’en charge, quelques réglages sont nécessaires.
6.2.1 Obtention d’un jeton d’accès personnel
Pour écrire sur GitHub, le service d’intégration continue devra s’authentifier au moyen d’un jeton d’accès personnel (Personal Access Token : PAT) dont la création est décrite en section 1.4.4.
Générer un nouveau jeton, le décrire en tant que “GitHub Actions” et lui donner les autorisations :
- “repo”, c’est-à-dire modifier tous les dépôts (il n’est pas possible de limiter l’accès à un dépôt particulier).
- “workflow”, c’est-à-dire exécuter lles scripts d’intégration continue.
6.2.2 Secrets du projet
Sur GitHub, afficher les paramètres du projet et sélectionner “Secrets”. Le bouton “New Repository Secret” permet de stocker des variables utilisées dans les scripts des Actions GitHub (visibles publiquement) sans en diffuser la valeur. Le jeton d’accès personnel est indispensable pour que les Actions GitHub puissent écrire leur production dans le projet. Créer un secret nommé “GH_PAT” et saisir la valeur du jeton sauvegardée précédemment. Après avoir cliqué sur “Add Secret”, le jeton ne pourra plus être lu.
Pour permettre l’envoi de messages de succès ou d’échec sans diffuser son adresse de messagerie, créer un secret nommé “EMAIL” qui la contient.
6.2.3 Activation du dépôt sur CodeCov
L’analyse de la couverture du code des packages est utile pour détecter les portions de code non testées. En revanche, l’analyse de la couverture des projets de document n’a pas d’intérêt.
Pour activer un dépôt, il faut d’authentifier sur le site de CodeCov avec son compte GitHub. La liste des dépôts est affichée et peut être actualisée. Si les dépôts à traiter sont hébergés par une organisation, par exemple les dépôts d’une salle de classe GitHub, il faut actualiser la liste des organisations en suivant les instructions (un lien permet de modifier rapidement les options de GitHub pour autoriser la lecture d’une organisation par Codecov) et à nouveau mettre à jour la liste des dépôts. Enfin, quand le dépôt recherché est visible, il faut l’activer. Il est inutile d’utiliser le système de jetons de Codecov.
6.2.4 Scripter les actions de GitHub
Un flux de travail (workflow) de GitHub est une succession de tâches (jobs) comprenant des étapes (steps). Un flux de travail est déclenché par un évènement, généralement chaque push du projet, mais aussi à intervalles réguliers (cron).
Typiquement, les flux créés ici contiennent deux tâches : la première installe R et les composants nécessaires et exécute des scripts R (ce qui constitue ses étapes successives) ; la seconde publie des fichiers obtenus dans les pages GitHub.
Les flux de travail sont configurés dans un fichier au format YAML placé dans le dossier .github/workflows/
du projet.
Les différentes parties du script sont présentées ci-dessous.
Le script complet est celui de ce document, accessible sur GitHub112.
6.2.4.1 Déclenchement
L’action est déclenchée à chaque fois que des mises à jour sont poussées sur GitHub :
on:
push:
branches:
- master
La branche prise en compte est master (à remplacer par main le cas échéant).
Pour déclencher l’action périodiquement, il faut utiliser la syntaxe de cron (le système de planification des tâches sous Unix) :
on:
schedule:
- cron: '0 22 * * 0' # every sunday at 22:00
Les valeurs successives sont celles des minutes, des heures, du jour (quantième du mois), du mois et du jour de la semaine (0 pour dimanche à 6 pour samedi).
Les *
permettent d’ignorer une valeur.
Les entrées push
et schedule
peuvent être utilisées ensemble :
on:
push:
branches:
- master
schedule:
- cron: '0 22 * * 0'
Actuellement, la planification n’est prise en compte que dans la branche master.
6.2.4.2 Nom du flux de travail
Le nom du flux est libre.
Il sera affiché par le badge qui sera ajouté dans le fichier README.md
du projet (voir section 6.4).
name: bookdown
6.2.4.3 Première tâche
Les tâches sont décrites dans la rubrique jobs
.
renderbook
est le nom de la première tâche : il est libre.
Ici, l’action principale consistera à produire un ouvrage bookdown avec la fonction render_book()
, d’où son nom.
jobs:
renderbook:
runs-on: macOS-latest
La déclaration runs-on
décrit le système d’exploitation sur lequel la tâche doit s’exécuter.
Les choix possibles sont Windows, Ubuntu ou MacOS113.
L’intégration continue de R sur GitHub utilise habituellement MacOS qui a l’avantage d’utiliser des packages R compilés donc beaucoup plus simples (certains packages nécessitent des librairies extérieures à R pour leur compilation) et rapides à installer, tout en permettant l’usage de scripts.
6.2.4.4 Premières étapes
Les étapes sont décrites dans la rubrique steps
.
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup R
uses: r-lib/actions/setup-r@v2
- name: Install pandoc
run: |
brew install pandoc
Chaque étape est décrite par son nom (libre) et ce qu’elle réalise.
La force de GitHub Actions est de permettre l’utilisation d’actions écrites par d’autres et stockées dans un projet public GitHub.
Une action est un script accompagné de métadonnées qui décrivent son usage.
Son développement est accompagné par des numéros de version successifs.
On appelle une action par l’instruction uses:
, le projet GitHub qui la contient et sa version.
Dans leur projet GitHub respectif, les actions existent dans leur version de développement (@master
) et dans des versions d’étape (release) accessibles par leur numéro (@v1
).
Ces versions d’étape sont préférables parce qu’elles sont stables.
Les actions généralistes sont mises à disposition par GitHub dans l’organisation GitHub Actions114. L’action “actions/checkout” permet de se placer dans la branche principale du projet traité par le flux de travail : c’est en général la première étape de tous les flux.
L’action suivante est l’installation de R, mise à disposition par l’organisation R infrastructure115.
L’installation de pandoc (logiciel extérieur à R mais nécessaire à R Markdown) peut être réalisée par une commande exécutée par MacOS.
Elle est appelée par run:
et peut contenir plusieurs lignes (d’où le |
).
Ce script dépend du système d’exploitation : brew
est le gestionnaire de paquets de MacOS.
Pour éviter les spécificités d’un système, il est préférable d’utiliser une action :
- name: Install pandoc
uses: r-lib/actions/setup-pandoc@v2
Il est souvent possible de choisir entre une action ou l’écriture du code correspondant. Le choix fait ici est de privilégier les actions pour tout ce qui a trait au système, comme les installations de logiciels, mais d’utiliser des scripts pour les commandes R, comme la vérification des packages. L’objectif est de contrôler précisément le code R et de limiter les dépendances à des packages supplémentaires. La stratégie inverse est développée dans Wickham et Bryan (2023) qui s’appuie entièrement sur des actions pour exécuter les tâches de R.
6.2.4.5 Packages
Cette étape utilise Rscript
comme environnement de commande, ce qui lui permet d’exécuter directement des commandes R.
- name: Install packages
env:
GITHUB_PAT: ${{ secrets.GH_PAT }}
run: |
options(pkgType = "binary")
options(install.packages.check.source = "no")
install.packages(c("remotes", "bookdown", "formatR", "tinytex"))
tinytex::install_tinytex(bundle = "TinyTeX")
remotes::install_deps(dependencies = TRUE)
shell: Rscript {0}
Les packages servant à produire le document sont listés :
-
remotes pour sa fonction
install_deps()
; - bookdown pour tricoter ;
-
formatR pour la mise en forme des bouts de code (
tidy=TRUE
) ; - tinytex pour disposer d’une distribution LaTeX.
Les autres packages, ceux utilisés par le projet, sont lus dans le fichier DESCRIPTION
par la fonction install_deps()
.
Sous MacOS, les packages sont installés par défaut en version binaire, mais à partir de leur code source s’il est plus récent.
La création des packages binaires prend quelques jours à CRAN : cette situation n’est donc pas rare.
Les packages ne contenant que du code R ou du code C++ sans référence à des librairies externes s’installent en revanche sans problème.
En revanche, si le package nécessite des librairies externes à R ou une compilation de code Fortran, l’installation échoue.
Il serait donc nécessaire d’installer préalablement les librairies nécessaires (et éventuellement un compilateur Fortran) à l’ensemble des packages dont le projet dépend : cette solution n’est pas réaliste parce qu’elle implique l’inventaire de l’ensemble des dépendances, qui peuvent changer, et un nombre important d’installations chronophages et inutiles la plupart du temps, quand les packages binaires sont à jour.
Une meilleure solution est de forcer l’installation des packages binaires même si le code source est plus récent : c’est l’objet des deux options de R définies avant l’appel à install.packages()
.
Enfin, le secret GH_PAT
est passé à R dans une variable d’environnement, GITHUB_PAT
, nécessaire pour installer des packages à partir leur code source sur GitHub.
GitHub limite le rythme des accès anonymes pour l’ensemble des actions GitHub (tous comptes confondus) et peut rejeter la demande : en pratique, utiliser install_github()
dans une action GitHub n’est envisageable qu’avec cette variable d’environnement.
6.2.4.6 Tricot
La production de l’ouvrage est lancée par une commande R.
- name: Render pdf book
run: |
bookdown::render_book("index.Rmd", "bookdown::pdf_book")
shell: Rscript {0}
- name: Render gitbook
run: |
bookdown::render_book("index.Rmd", "bookdown::gitbook")
shell: Rscript {0}
Les paramètres déclarés dans _output.yml
sont utilisés.
Le fichier PDF doit être produit avant le format GitBook pour que son lien de téléchargement soit ajouté à la barre de menu du site GitBook. D’autre part, R doit être fermé et rouvert entre les deux rendus faute de quoi les tableaux ne sont pas créés correctement dans le GitBook116. Les deux étapes ne doivent pas être regroupées en une seule.
6.2.4.7 Sauvegarde
Le résultat du tricot, placé dans le dossier docs
de la machine virtuelle en charge de l’intégration continue, doit être préservé pour que la tâche suivante puisse l’utiliser.
La dernière étape de la tâche de production utilise l’action upload-artifact
pour cela.
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: _book
path: docs/
Le contenu de docs
est sauvegardé en tant qu’artefact nommé “_book”.
Les artefacts sont visibles publiquement sur la page des Actions du projet GitHub.
Après sa dernière étape, la machine virtuelle utilisée pour cette étape est détruite.
6.2.4.8 Publication
La publication de l’artefact dans la branche gh-pages
du projet nécessite une autre tâche.
deploy:
runs-on: ubuntu-latest
needs: renderbook
permissions:
contents: write
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
# Artifact name
name: _book
# Destination path
path: docs
- name: Deploy to GitHub Pages
uses: Cecilapp/GitHub-Pages-deploy@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
email: ${{ secrets.EMAIL }}
build_dir: docs
jekyll: no
La tâche est nommée “deploy” (le nom est libre). Elle s’exécute sur une machine virtuelle sous Ubuntu. Elle ne peut se lancer que si la tâche “renderbook” a réussi. Ses étapes sont les suivantes :
-
Download artifact : Restauration du dossier
docs
; -
Deploy to GitHub Pages : copie du dossier
docs
dans la branchegh-pages
par un commit.
Cette dernière étape utiliser l’action GitHub-Pages-deploy
mise à disposition par l’organisation Cecilapp .
Elle utilise une variable d’environnement, GITHUB_TOKEN
, pour s’authentifier et des paramètres :
- email : l’adresse de messagerie destinataire du rapport d’exécution. Pour ne pas exposer l’adresse publiquement, elle a été stockée dans un secret du projet ;
- buid_dir : le répertoire à publier ;
-
jekyll:no pour créer un fichier vide nommé
.nojekyll
qui indique aux pages GitHub de ne pas essayer de traiter leur contenu comme un site web Jekyll.
GITHUB_TOKEN
est un jeton d’authentification fourni par Github Actions pour l’exécution de ce script.
Ses droits sont attribués dans le script par l’entrée permission
: ici, le droit d’écrire du contenu dans le projet.
6.2.5 Données confidentielles dans un dépôt public
Si le projet contient des données confidentielles (section 3.6), GitHub Actions doit utiliser la clé privée du projet pour les extraire de leur coffre-fort.
La clé privée doit être stockée dans un secret du projet, nommé “RSA”. L’étape suivante, à insérer avant l’étape de tricot, écrit la clé dans un fichier pour que le code du projet y ait accès.
- name: Private key
run: |
cat("${{ secrets.rsa }}", file="NomDuProjet.rsa"
shell: Rscript {0}
6.3 Modèles de scripts
Des modèles de scripts pour tous les types de projets sont présentés ici.
La branche gh-pages
est créée automatiquement par les scripts.
Vérifier après la première exécution que les pages GitHub sont bien activées sur cette branche (section 3.7).
Supprimer ensuite le dossier docs
s’il existait, pousser la modification sur GitHub et enfin ajouter la ligne suivante au fichier .gitignore
pour pouvoir tricoter localement les projets sans perturber GitHub :
docs/
6.3.1 memoiR
La fonction build_ghworkflow()
du package memoiR crée automatiquement les scripts nécessaires à la production des modèles du package.
Le script est toujours nommé memoir.yml
.
Ces scripts n’ont pas besoin d’un fichier DESCRIPTION
pour l’installation des dépendances mais chaque document doit contenir son le bout de code de paramétrage (Options
) la liste de tous les packages nécessaires à son tricot (stockés dans la variable Packages
).
Tous nécessitent même préparation : les secrets GH_PAT
et EMAIL
doivent être enregistrés dans le projet GitHub (section 6.2.2).
6.3.1.1 Projet d’ouvrage
Le flux de travail s’appelle rmarkdown
; sa tâche de production render
.
on:
push:
branches:
- master
name: rmarkdown
jobs:
render:
runs-on: macOS-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup R
uses: r-lib/actions/setup-r@v2
- name: Install pandoc
uses: r-lib/actions/setup-pandoc@v2
- name: Install dependencies
run: |
options(pkgType = "binary")
options(install.packages.check.source = "no")
install.packages(c("distill", "downlit", "memoiR", "rmdformats", "tinytex"))
tinytex::install_tinytex(bundle = "TinyTeX")
shell: Rscript {0}
- name: Render pdf book
env:
GITHUB_PAT: ${{ secrets.GH_PAT }}
run: |
bookdown::render_book("index.Rmd", "bookdown::pdf_book")
shell: Rscript {0}
- name: Render gitbook
env:
GITHUB_PAT: ${{ secrets.GH_PAT }}
run: |
bookdown::render_book("index.Rmd", "bookdown::gitbook")
shell: Rscript {0}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ghpages
path: docs
deploy:
runs-on: ubuntu-latest
needs: render
permissions:
contents: write
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: ghpages
path: docs
- name: Deploy to GitHub Pages
uses: Cecilapp/GitHub-Pages-deploy@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
email: ${{ secrets.EMAIL }}
build_dir: docs
jekyll: no
6.3.1.2 Articles et présentations
Le flux de travail s’appelle rmarkdown
; sa tâche de production render
.
on:
push:
branches:
- master
name: rmarkdown
jobs:
render:
runs-on: macOS-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup R
uses: r-lib/actions/setup-r@v2
- name: Install pandoc
uses: r-lib/actions/setup-pandoc@v2
- name: Install dependencies
run: |
options(pkgType = "binary")
options(install.packages.check.source = "no")
install.packages(c("memoiR", "rmdformats", "tinytex"))
tinytex::install_tinytex(bundle = "TinyTeX")
shell: Rscript {0}
- name: Render Rmarkdown files
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
run: |
RMD_PATH=($(ls | grep "[.]Rmd$"))
Rscript -e 'for (file in commandArgs(TRUE)) |>
rmarkdown::render(file, "all")' ${RMD_PATH[*]}
Rscript -e 'memoiR::build_githubpages()'
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ghpages
path: docs
deploy:
runs-on: ubuntu-latest
needs: render
permissions:
contents: write
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: ghpages
path: docs
- name: Deploy to GitHub Pages
uses: Cecilapp/GitHub-Pages-deploy@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
email: ${{ secrets.EMAIL }}
build_dir: docs
jekyll: yes
L’étape chargée du tricot utilise un script pour lister tous les fichiers .Rmd
, les traiter (tous les formats de sortie listés dans leur entête yaml sont produits).
La fonction build_githubpages()
(voir section 4.3.2) place les résultat dans docs
.
La tâche de déploiement indique aux pages GitHub d’utiliser Jekyll, c’est-à-dire d’utiliser le fichier README.md
comme page d’accueil.
6.3.1.3 Internationalisation
Si l’étape de tricot nécessite de modifier la langue utilisée par R, par exemple pour afficher correctement la date de production des documents, elle peut être modifiée comme ceci :
- name: Render Rmarkdown files
run: |
Sys.setlocale("LC_TIME", "fr_FR")
lapply(list.files(pattern="*.Rmd"),
function(file) rmarkdown::render(file, "all"))
memoiR::build_githubpages()
shell: Rscript {0}
La sélection des fichiers est ici réalisée par un script R, qui inclut une commande de localisation, ici en Français.
Cette étape peut être complétée par la sélection d’un thème GitHub Pages pour que la page d’accueil contienne un lien vers le code :
run: |
echo 'theme: jekyll-theme-slate' > docs/_config.yml
Le thème est ici “Slate”, un des choix proposés par les pages GitHub.
6.3.1.4 Débogage
Il peut arriver que la compilation du fichier .tex
pour produire le fichier PDF échoue, bien que le tricot en HTML ne génère pas d’erreur.
Le compilateur LaTeX est en effet plus exigeant que pandoc (qui produit le fichier HTML).
La première vérification consiste à tricoter en PDF localement, sur son poste de travail, le document qui pose problème, avec tinytex. Les packages LaTeX doivent être mis à jour pour être les mêmes que ceux utilisés par les actions GitHub : pour cela, exécuter :
tinytex::tlmgr_update()
Si la compilation fonctionne localement mais pas sur Github, il faut inspecter le fichier .log
qui enregistre tous les évènements générés par le compilateur, mais ce fichier n’est pas conservé après l’échec de GitHub Actions.
Il faut donc modifier le script pour copier le fichier dans docs
puis créer sauvegarder le résultat malgré l’erreur.
L’étape “Upload artifact” est modifiée pour s’exécuter malgré l’échec de l’étape précédente en ajoutant la ligne if:
:
- name: Upload artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: _book
path: docs/
Une étape est ajoutée avant “Upload artifact” pour copier le résultat du tricot et le fichier .log
:
- name: Move files to docs
if: always()
run: |
Rscript -e 'memoiR::build_githubpages()'
cp *.log docs
Après l’échec de l’action, l’artéfact sauvegardé peut être téléchargé à partir de GitHub : il se trouve sur la page de résumé de l’action.
Il s’agit d’un fichier compressé qui contient tout le dossier docs
.
6.3.2 Site web blogdown
Le fichier appelé blogdown.yml
est très similaire.
Le nom du flux de travail est blogdown
et celui de la tâche de production est buildsite
.
on:
push:
branches:
- master
schedule:
- cron: '0 22 * * 0'
name: blogdown
jobs:
buildsite:
runs-on: macOS-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup R
uses: r-lib/actions/setup-r@v2
- name: Install pandoc
uses: r-lib/actions/setup-pandoc@v2
- name: Install packages
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
run: |
options(pkgType = "binary")
options(install.packages.check.source = "no")
install.packages(c("remotes", "blogdown", "formatR"))
remotes::install_deps(dependencies = TRUE)
shell: Rscript {0}
- name: Build website
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
run: |
blogdown::install_hugo(force = TRUE)
blogdown::build_site(local = TRUE, build_rmd = TRUE)
shell: Rscript {0}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: _website
path: public/
deploy:
runs-on: ubuntu-latest
needs: buildsite
permissions:
contents: write
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
# Artifact name
name: _website
# Destination path
path: public
- name: Deploy to GitHub Pages
uses: Cecilapp/GitHub-Pages-deploy@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
build_dir: public
email: ${{ secrets.EMAIL }}
jekyll: no
La tâche Build website
utilise le package blogdown pour installer Hugo (le générateur de sites web) et ensuite construire le site.
Si le site web utilise des données en ligne qui justifient de le mettre à jour périodiquement, GitHub Actions peut être lancé tous les jours, toutes les semaines ou tous les mois en plus des reconstruction déclenchées par une modification du dépôt (voir section 6.2.4.1). Ici, le site est reconstruit tous les dimanches à 22h.
Exemple : la page qui affiche la bibliométrie du site web117 de l’auteur interroge Google Scholar pour afficher les citations des publications. Le site est mis à jour toutes les semaines pour que les statistiques soient à jour.
6.3.3 Packages R
Un script optimal pour la vérification d’un package est le suivant :
on:
push:
branches:
- master
name: R-CMD-check
jobs:
R-CMD-check:
runs-on: macOS-latest
steps:
- name: Pull the repository
uses: actions/checkout@v4
- name: Install R
uses: r-lib/actions/setup-r@v2
- name: Install pandoc
uses: r-lib/actions/setup-pandoc@v2
- name: Install R packages
run: |
options(pkgType = "binary")
options(install.packages.check.source = "no")
install.packages(c("remotes", "roxygen2", "rcmdcheck", "covr", "pkgdown"))
remotes::install_deps(dependencies = TRUE)
shell: Rscript {0}
- name: Update the documentation
run: roxygen2::roxygenize()
shell: Rscript {0}
- name: Commit and push the repository
uses: EndBug/add-and-commit@v9
- name: Check the package
run: rcmdcheck::rcmdcheck(args = "--no-manual", error_on = "warning")
shell: Rscript {0}
- name: Test coverage
run: covr::codecov(type="all")
shell: Rscript {0}
- name: Install the package
run: R CMD INSTALL .
- name: Pkgdown
run: |
git config --local user.email "actions@github.com"
git config --local user.name "GitHub Actions"
Rscript -e 'pkgdown::deploy_to_branch(new_process = FALSE)'
Le fichier est nommé check.yml
.
Il ne contient qu’une seule tâche, nommée R-CMD-check
comme le flux.
remotes installe les packages nécessaires à partir du fichier DESCRIPTION
.
L’étape Roxygenize
met à jour la documentation du package.
Les fichiers mis à jour sont poussés dans la branche principale du projet par l’action add-and-commit
.
Ces deux étapes permettent de garantir que le package est dans un état cohérent, même si l’auteur a omis d’exécuter la fonction roxygenize()
avant de pousser son code sur GitHub.
Pour éviter de déclencher en boucle la vérification du code poussé de cette façon, le jeton d’accès utilisé est obligatoirement celui du script en cours, créé par GitHub à chaque exécution.
Ce jeton n’a par défaut pas le droit de modifier le dépôt.
Il faut donc le lui donner : sur GitHub, afficher les paramètres du projet et sélectionner “Actions”, “General”.
Dans la section “Workflow permissions”, sélectionner “Read and write permissions”.
L’étape Check
vérifie le package.
Les avertissements sont traités comme des erreurs.
L’étape Test coverage
utilise le package covr pour mesurer le taux de couverture et téléverse les résultats sur le site Codecov.
Enfin, les deux dernières étapes installent le package puis utilisent pkgdown pour créer le site de documentation du package et le pousser dans la branche gh-pages
du projet.
Ce script ne contient qu’une tâche : le déploiement du site de documentation est directement exécuté par pkgdown.
Son succès est affiché par un badge à afficher dans le fichier README.md
(voir section 6.4)
Des scripts plus complexes sont proposés par R-lib118, notamment pour exécuter les tests sur plusieurs systèmes d’exploitation et plusieurs versions de R. Ces tests poussés sont à effectuer avant de soumettre à CRAN (section 5.11) mais consomment trop de ressource pour un usage systématique.
6.3.4 Pull requests
Les requêtes de tirage peuvent être testées par des scripts très proches pour vérifier qu’elles ne génèrent pas d’erreurs avant de les fusionner.
Une méthode efficace consiste à créer un nouveau script dans le dossier .github/workflows/
, en partant d’une copie du script existant.
Le nouveau script sera nommé pr.yml
.
Le déclenchement doit être modifié : pull_request
remplace push
:
on:
pull_request:
branches:
- master
6.3.4.1 memoiR
Les scripts de vérification des documents créés par memoiR doivent être coupés après l’étape Render gitbook
: l’artefact ne doit pas être sauvegardé et la tâche de déploiement doit être supprimée.
Le script est donc le suivant :
on:
pull_request:
branches:
- master
name: rmarkdown
jobs:
render:
runs-on: macOS-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup R
uses: r-lib/actions/setup-r@v2
- name: Install pandoc
uses: r-lib/actions/setup-pandoc@v2
- name: Install dependencies
run: |
options(pkgType = "binary")
options(install.packages.check.source = "no")
install.packages(c("distill", "downlit", "memoiR", "rmdformats", "tinytex"))
tinytex::install_tinytex(bundle = "TinyTeX")
shell: Rscript {0}
- name: Render pdf book
env:
GITHUB_PAT: ${{ secrets.GH_PAT }}
run: |
bookdown::render_book("index.Rmd", "bookdown::pdf_book")
shell: Rscript {0}
- name: Render gitbook
env:
GITHUB_PAT: ${{ secrets.GH_PAT }}
run: |
bookdown::render_book("index.Rmd", "bookdown::bs4_book")
shell: Rscript {0}
# Don't upload the artifact and don't deploy
6.3.4.2 Packages R
Les scripts de vérification des packages ne doivent pas pousser les mises à jour de leur documentation par Roxygenize2, ni déployer leur mise à jour du site pkgdown dans les pages GitHub. Le taux de couverture n’a pas à être mesuré. Le script est le suivant :
on:
pull_request:
branches:
- master
name: R-CMD-check
jobs:
R-CMD-check:
runs-on: macOS-latest
steps:
- name: Pull the repository
uses: actions/checkout@v4
- name: Install R
uses: r-lib/actions/setup-r@v2
- name: Install pandoc
uses: r-lib/actions/setup-pandoc@v2
- name: Install R packages
run: |
options(pkgType = "binary")
options(install.packages.check.source = "no")
install.packages(c("remotes", "roxygen2", "rcmdcheck", "covr", "pkgdown"))
remotes::install_deps(dependencies = TRUE)
shell: Rscript {0}
- name: Update the documentation
run: roxygen2::roxygenize()
shell: Rscript {0}
# Don't push
- name: Check the package
run: rcmdcheck::rcmdcheck(args = "--no-manual", error_on = "warning")
shell: Rscript {0}
# Don't test coverage
- name: Install the package
run: R CMD INSTALL .
- name: Pkgdown
# Build the package site locally
run: Rscript -e 'pkgdown::build_site()'
Quand des requêtes de tirage sont soumises, le test correspondant est lancé et ses résultats intégrés à la discussion.
6.4 Ajouter des badges
Le succès des Actions GitHub est visible en ajoutant un badge dans le fichier README.md
, juste après le titre du fichier.
Sur la page du projet, choisir “Actions” puis sélectionner l’action (dans “Workflows”).
Cliquer sur le bouton “…” puis sur “Create Status Badge”.
Coller le code Markdown :
# Nom du projet
![bookdown](https://github.com/<GitHubID>/<Depot>/workflows/<NomDuFlux>/badge.svg)
Le nom du flux a été déclaré dans l’entrée name:
du fichier de configuration des actions GitHub.
Le taux de couverture mesuré par Codecov peut aussi être affiché par un badge :
[![codecov](https://codecov.io/github/<GitHubID>/
<Depot>/branch/master/graphs/badge.svg)]
(https://codecov.io/github/<GitHubID>/<Depot>)