Gestion de versions Shiny : un workflow de déploiement Git + CI/CD

Faites survivre votre application à la modification d’un collègue, à un retour arrière et à une montée de version de dépendance — Git, renv et un déploiement automatisé.

Programming
Shiny

Un workflow de déploiement reproductible et sûr pour une équipe, pour une application Shiny : placez-la sous Git avec un .gitignore adapté à Shiny, verrouillez les dépendances avec renv (validez renv.lock, jamais renv/library/), et automatisez le déploiement avec un pipeline CI/CD qui restaure les packages et publie à chaque push — avec les jetons de déploiement gardés dans les secrets CI, jamais dans le YAML.

Date de publication

16 juillet 2026

Modifié

16 juillet 2026

AstucePoints clés
  • La gestion de versions est un outil de déploiement, pas seulement une sauvegarde. Git vous donne l’historique et une collaboration sûre ; le bénéfice est un déploiement reproductible et testé que vous déclenchez en poussant un commit.
  • Un .gitignore Shiny garde le dépôt propre et sûr. Excluez renv/library/ (volumineux, spécifique à la machine), les secrets (.Renviron, *.pem) et les métadonnées de déploiement (rsconnect/) — validez le code source et le fichier de verrouillage, rien d’autre.
  • Validez renv.lock, jamais renv/library/. Le fichier de verrouillage enregistre les versions exactes des packages pour qu’un collègue — ou un runner CI — reconstruise la bibliothèque identique avec renv::restore().
  • Automatisez le déploiement avec CI/CD. Un court workflow GitHub Actions récupère le code, installe R, restaure renv, et déploie à chaque push vers main — avec le jeton de déploiement lu depuis un secret de dépôt, jamais écrit dans le fichier.
  • The runtime is the judge. Quand un git push se termine par votre application en ligne à son URL sans que personne n’ait touché le serveur à la main, vous avez prouvé que le workflow fonctionne.

Introduction

Votre application fonctionne et elle est déployée — vous l’avez poussée sur shinyapps.io ou mise dans un conteneur. Maintenant, elle doit survivre à la vraie vie : un collègue la modifie la semaine prochaine, un changement casse quelque chose et il vous faut récupérer la version de mardi dernier, et dans six mois une mise à jour de package décale discrètement un résultat. Copier app_final_v2_REALLY.R sur un disque partagé ne survit à rien de tout cela.

Trois habitudes y remédient, et cette leçon consiste à les intégrer à votre déploiement — pas un tutoriel Git général :

  • Git vous donne l’historique et la collaboration : chaque changement est enregistré, réversible et fusionnable au sein d’une équipe.
  • renv vous donne la reproductibilité : un fichier de verrouillage épingle les versions exactes des packages, de sorte que l’application qui tournait sur votre portable est l’application qui tourne sur le serveur.
  • CI/CDintégration continue / déploiement continu, un pipeline automatisé qui s’exécute à chaque push — vous donne un déploiement reproductible et testé : fini le « quels fichiers ai-je téléversés la dernière fois ? »

Ensemble, elles transforment le déploiement d’un rituel manuel et sujet aux erreurs en une seule action : valider et pousser.

NotePrérequis

Il vous faut une application fonctionnelle et déployée à exploiter — si vous n’en avez pas, déployez sur shinyapps.io ou conteneurisez-la avec Docker d’abord (et construisez votre première application Shiny si vous débutez tout juste). Il vous faut aussi Git installé et un compte chez un hébergeur Git tel que GitHub ou GitLab — c’est sur cet hébergeur que s’exécute un pipeline CI/CD.

NoteCopiez n’importe quel bloc et exécutez-le en local

Les commandes et la configuration de cette page ne sont pas exécutées ici — les opérations Git, renv et un pipeline CI/CD agissent tous sur votre dépôt et votre compte, ce qu’une page web statique ne peut pas faire. Copiez n’importe quel bloc dans votre projet et exécutez-le là. Le vrai test, c’est ce qui se passe ensuite : un git push se termine par votre application en ligne à son URL, reconstruite depuis le fichier de verrouillage, sans étape manuelle. C’est la preuve que le workflow tient — the runtime is the judge.

Placez l’application sous Git — avec un .gitignore Shiny

Commencez par transformer le dossier de l’application en dépôt. Depuis le répertoire de l’application :

cd my-shiny-app

git init                     # start tracking this folder
git add .                    # stage the files (respecting .gitignore, below)
git commit -m "Initial commit: working Shiny app"

Avant ce premier git add ., cependant, décidez de ce qui ne doit jamais entrer dans le dépôt. C’est le fichier le plus important de la gestion de versions d’un projet Shiny, et se tromper dessus, c’est ainsi que les dépôts gonflent à des gigaoctets ou divulguent un mot de passe. Créez un .gitignore à la racine de l’application :

# --- renv: commit the lockfile, NEVER the library ---
renv/library/         # machine-specific, huge — rebuilt from renv.lock
renv/local/
renv/cellar/
renv/staging/
# (renv.lock IS committed — it's the reproducibility record)

# --- secrets: never commit credentials ---
.Renviron             # env vars, API keys, DB passwords
.env
*.pem                 # private keys / certificates

# --- deploy metadata (regenerated per environment) ---
rsconnect/

# --- R / RStudio cruft ---
.Rproj.user/
.Rhistory
.RData
.Ruserdata

# --- OS files ---
.DS_Store
Thumbs.db

# --- data you shouldn't ship (uncomment/adjust as needed) ---
# *.csv
# data/private/

La règle qui piège la plupart des gens : validez renv.lock, pas renv/library/. Le dossier library/ contient les packages réellement installés — des centaines de mégaoctets de code compilé spécifique à votre système d’exploitation, inutile (et nuisible) sur la machine de quelqu’un d’autre. Le fichier de verrouillage est un petit fichier texte qui permet à n’importe quelle machine de reconstruire cette bibliothèque exactement. Ignorez le dossier, validez le fichier.

Les lignes de secrets comptent tout autant. Une clé .Renviron ou *.pem validée une seule fois vit dans votre historique pour toujours — même après l’avoir supprimée — alors gardez-les à l’écart dès le départ. (Les leçons shinyapps.io et Docker montrent où vont plutôt ces secrets : les variables d’environnement de la plateforme et les secrets de conteneur.)

Verrouillez les dépendances avec renv

Git versionne votre code ; il ne fait rien pour vos packages. « Ça marche sur ma machine » est presque toujours une différence de version — vous avez construit l’application avec ggplot2 3.5 et le serveur a installé la 3.4. renv comble cet écart en enregistrant les versions exactes que votre application utilise. Exécutez-le une fois dans le répertoire de l’application :

renv::init()        # start tracking this project's packages
renv::snapshot()    # write renv.lock with the exact versions you use

renv::init() crée une bibliothèque privée au projet et scanne votre code à la recherche des appels library() ; renv::snapshot() écrit renv.lock — un fichier JSON listant chaque package et sa version précise. Validez ce fichier de verrouillage :

git add renv.lock
git commit -m "Lock dependencies with renv"

Désormais, quiconque clone le dépôt — un collègue, ou le runner CI qui le déploie — exécute une seule commande pour reproduire votre environnement :

renv::restore()     # install the exact versions from renv.lock

C’est ce qui rend le dépôt reproductible : le fichier de verrouillage voyage avec le code, et chaque environnement se reconstruit à partir de lui. Réexécutez renv::snapshot() et validez le fichier de verrouillage mis à jour chaque fois que vous ajoutez ou mettez à niveau un package. (Les leçons de déploiement shinyapps.io et Docker utilisent toutes deux ce même fichier de verrouillage — ici, il alimente aussi le pipeline CI ci-dessous.)

Un flux sain de branche et de revue

Vous n’avez pas besoin d’un modèle de branchement élaboré pour une application Shiny. Gardez main toujours déployable, et faites le nouveau travail sur une branche éphémère :

git checkout -b feature/add-export-button   # branch off main
# ... make changes, commit them ...
git push -u origin feature/add-export-button

Ouvrez ensuite une pull request (sur GitHub) ou une merge request (sur GitLab) — les deux sont la même idée : un changement proposé qu’un collègue examine avant qu’il ne rejoigne main. À la fusion, main avance et (avec le pipeline ci-dessous) se déploie tout seul. C’est toute la boucle : branche → PR/MR → revue → fusion → déploiement automatique. Résistez à l’envie de bâtir un processus de release multi-branches autour d’une seule application ; la concision paie en maux de tête de fusion évités.

Automatisez le déploiement avec CI/CD

Voici le bénéfice. Au lieu de penser à lancer deployApp() à la main après chaque changement, laissez votre hébergeur Git le faire. Sur GitHub, c’est GitHub Actions : les fichiers de workflow dans .github/workflows/ s’exécutent sur les événements que vous choisissez — ici, un push vers main.

La communauté R maintient des blocs prêts à l’emploi exactement pour cela dans r-lib/actions : setup-r installe R, et setup-renv restaure votre bibliothèque verrouillée. Créez .github/workflows/deploy.yml :

name: Deploy Shiny app

on:
  push:
    branches: [main]        # deploy on every push to main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Check out the code
        uses: actions/checkout@v4

      - name: Set up R
        uses: r-lib/actions/setup-r@v2

      - name: Restore packages from renv.lock
        uses: r-lib/actions/setup-renv@v2

      - name: Deploy to shinyapps.io
        env:
          SHINYAPPS_NAME:   ${{ secrets.SHINYAPPS_NAME }}
          SHINYAPPS_TOKEN:  ${{ secrets.SHINYAPPS_TOKEN }}
          SHINYAPPS_SECRET: ${{ secrets.SHINYAPPS_SECRET }}
        run: |
          # rsconnect is a deploy-time tool — install it if it isn't already in renv.lock
          if (!requireNamespace("rsconnect", quietly = TRUE)) install.packages("rsconnect")
          rsconnect::setAccountInfo(
            name   = Sys.getenv("SHINYAPPS_NAME"),
            token  = Sys.getenv("SHINYAPPS_TOKEN"),
            secret = Sys.getenv("SHINYAPPS_SECRET")
          )
          rsconnect::deployApp(appName = "my-shiny-app", forceUpdate = TRUE)
        shell: Rscript {0}

Lisez-le étape par étape — le fichier est du YAML (YAML Ain’t Markup Language, le format de configuration à base d’indentation qu’utilisent les outils CI) :

  • on: push: branches: [main] — le déclencheur. Chaque push vers main démarre le job ; rien ne s’exécute sur les autres branches, donc votre travail de fonctionnalité ne se déploie pas.
  • actions/checkout@v4 — clone votre dépôt sur le runner pour que le workflow puisse voir les fichiers de votre application et renv.lock.
  • r-lib/actions/setup-r@v2 — installe R sur le runner (documentation r-lib/actions).
  • r-lib/actions/setup-renv@v2 — lit renv.lock et restaure les versions exactes des packages (documentation setup-renv) — c’est là que valider le fichier de verrouillage porte ses fruits.
  • L’étape de déploiement — lit trois valeurs depuis env: et appelle rsconnect : setAccountInfo() autorise le runner à publier sur votre compte, puis deployApp(forceUpdate = TRUE) empaquette l’application et met à jour le déploiement existant sur place.

Les versions d’actions ci-dessus (checkout@v4, r-lib/actions/*@v2) sont à jour au moment de la rédaction — épinglez-vous à la dernière en vérifiant le README de chaque action avant de la copier, car les versions majeures évoluent.

Puis la seule règle qui garde tout cela sûr : le jeton de déploiement n’apparaît jamais dans le YAML. La syntaxe ${{ secrets.* }} tire les valeurs depuis les secrets chiffrés de votre dépôt. Ajoutez-les une fois sous Settings → Secrets and variables → Actions → New repository secret (SHINYAPPS_TOKEN, SHINYAPPS_SECRET, SHINYAPPS_NAME) — GitHub les masque dans les logs et ne les expose jamais aux pull requests issues de forks (documentation des secrets GitHub Actions). Un jeton codé en dur dans deploy.yml est un jeton publié à quiconque peut lire le dépôt.

Vous voulez une vérification avant le déploiement ? Ajoutez une étape qui exécute vos tests (par exemple shiny::runTests() ou testthat::test_dir("tests")) avant l’étape de déploiement — si elle échoue, le job s’arrête et rien n’est livré. C’est la moitié « intégration continue » qui fait son travail.

GitLab a la même forme, juste un fichier différent : un .gitlab-ci.yml à la racine du dépôt, les secrets sous Settings → CI/CD → Variables, et — si vous déployez par conteneur plutôt que sur shinyapps.io — un job qui construit et pousse votre image Docker au lieu d’appeler rsconnect. Les éléments (restaurer renv, s’authentifier depuis un secret, déployer) ne changent pas ; seule la cible de déploiement change.

Quelle habitude fait quoi

Habitude Résout La seule chose à retenir
Git + .gitignore Historique, collaboration, retour arrière sûr Validez le code source + renv.lock ; ignorez renv/library/ et les secrets
renv Packages reproductibles entre machines Validez le fichier de verrouillage ; renv::restore() le reconstruit
CI/CD Un déploiement reproductible, testé, automatique Déployez au push ; gardez les jetons dans les secrets CI, pas dans le YAML

Ensemble, elles signifient qu’un changement est à un git push d’être en ligne — révisé, verrouillé en version, et déployé de la même façon à chaque fois.

Problèmes fréquents

Le dépôt a gonflé à des centaines de mégaoctets. Vous avez validé renv/library/ — les packages installés, pas seulement le fichier de verrouillage. Ajoutez renv/library/ à .gitignore, puis retirez-le du suivi avec git rm -r --cached renv/library/ et validez. Ne gardez que renv.lock ; la bibliothèque se reconstruit à partir de lui avec renv::restore().

Un secret a été validé. Un .Renviron, une clé d’API ou un *.pem s’est glissé dans un commit. Le supprimer dans un nouveau commit ne suffit pas — il reste dans l’historique. Renouvelez immédiatement l’identifiant (supposez qu’il est compromis), puis purgez-le de l’historique avec un outil comme git filter-repo ou le guide de suppression de secrets de GitHub, et forcez le push. Ajoutez le fichier à .gitignore pour que cela ne puisse plus se reproduire.

Le déploiement CI échoue sur un package manquant. Le runner a installé une version différente (ou aucune) d’un package dont l’application a besoin. Assurez-vous que renv.lock est validé et à jour (renv::snapshot() en local, puis validez), et que votre workflow le restaure (r-lib/actions/setup-renv@v2) avant l’étape de déploiement. Un déploiement qui saute renv::restore() déploie contre ce que le runner a installé par hasard.

Questions fréquentes

Validez renv.lock (ainsi que les petits renv/activate.R et .Rprofile que renv::init() crée) — c’est l’enregistrement de reproductibilité. Ne validez pas renv/library/ : ce sont les packages installés, spécifiques à la machine et souvent des centaines de mégaoctets, et c’est régénéré depuis le fichier de verrouillage par renv::restore(). Le .gitignore par défaut de renv exclut déjà le dossier de bibliothèque pour vous (documentation renv).

Excluez trois choses : renv/library/ (volumineux et spécifique à la machine — validez renv.lock à la place), les secrets (.Renviron, .env, *.pem, tout fichier d’identifiants) et les métadonnées de déploiement (rsconnect/). Ajoutez les habituels résidus R/RStudio (.Rproj.user/, .Rhistory, .RData) et les fichiers d’OS (.DS_Store). Validez le code source de votre application et le fichier de verrouillage ; ignorez tout ce qui est régénéré ou secret.

Ajoutez un workflow à .github/workflows/deploy.yml déclenché on: push vers main. Dedans : actions/checkout le code, r-lib/actions/setup-r pour installer R, r-lib/actions/setup-renv pour restaurer les packages depuis renv.lock, puis une étape Rscript qui appelle rsconnect::setAccountInfo() et rsconnect::deployApp(forceUpdate = TRUE). Lisez le jeton de compte depuis un secret de dépôt (${{ secrets.SHINYAPPS_TOKEN }}), jamais depuis le fichier lui-même (r-lib/actions).

Stockez-les comme secrets chiffrés chez votre hébergeur Git — GitHub : Settings → Secrets and variables → Actions ; GitLab : Settings → CI/CD → Variables — et référencez-les dans le workflow avec ${{ secrets.NAME }} (GitHub) ou le nom de la variable (GitLab). La plateforme CI les injecte à l’exécution et les masque dans les logs (documentation des secrets GitHub). Ne codez jamais en dur un jeton, un mot de passe ou une clé dans le YAML — quiconque peut lire le dépôt peut lire le fichier.

Oui — ils résolvent des problèmes différents. Git versionne votre code ; renv versionne vos packages. Sans fichier de verrouillage, un collègue ou un runner CI installe les versions de packages en vigueur ce jour-là, et une application qui fonctionnait le mois dernier peut casser sur une montée de version silencieuse. Validez renv.lock aux côtés de votre code pour que la source et ses dépendances exactes soient toutes deux reproductibles.

Testez vos connaissances

Vous configurez Git pour une application Shiny qui utilise renv et lit un mot de passe de base de données depuis un fichier .Renviron. Écrivez les trois lignes les plus importantes que votre .gitignore doit contenir — celles qui empêchent un dépôt gonflé et un secret divulgué — et dites pourquoi chacune compte.

Pensez à (1) le seul dossier renv que vous ne devez jamais valider tout en validant le fichier de verrouillage, (2) le fichier contenant votre mot de passe de base de données, et (3) le dossier de métadonnées de déploiement auto-généré.

renv/library/    # installed packages — huge, machine-specific; rebuilt from renv.lock
.Renviron        # holds the database password / API keys — never commit a secret
rsconnect/       # deploy metadata, regenerated per environment

renv/library/ garde des centaines de mégaoctets de packages spécifiques à l’OS hors du dépôt — vous validez le petit renv.lock à la place, et renv::restore() reconstruit la bibliothèque n’importe où. .Renviron garde votre mot de passe de base de données hors de l’historique (un secret validé reste dans l’historique même après suppression, il ne doit donc jamais y entrer). rsconnect/ est de la comptabilité de déploiement recréée par environnement et n’a pas sa place dans le contrôle de version. Validez le code de votre application et renv.lock ; ignorez ceux-ci.

Votre workflow GitHub Actions a besoin de votre jeton shinyapps.io pour déployer. Où le jeton doit-il aller ?

A. Collé directement dans deploy.yml pour que le workflow puisse le lire.
B. Dans un secret de dépôt, référencé comme ${{ secrets.SHINYAPPS_TOKEN }} dans le workflow.
C. Validé dans le dépôt dans un fichier tokens.R que le workflow charge.
D. Affiché dans le log CI au début du job pour que vous puissiez le vérifier.

B. Stockez le jeton comme secret de dépôt chiffré (Settings → Secrets and variables → Actions) et référencez-le avec ${{ secrets.SHINYAPPS_TOKEN }} ; la plateforme l’injecte à l’exécution et le masque dans les logs. A et C valident tous deux le secret dans le dépôt — quiconque peut lire le code peut voler le jeton, et il vit dans l’historique pour toujours. D le divulgue délibérément dans les logs. Un identifiant de déploiement a sa place dans les secrets CI, jamais dans un fichier ou un log.

Conclusion

La gestion de versions d’une application Shiny déployée, ce sont trois habitudes qui fonctionnent ensemble, pas une dissertation sur Git. Placez l’application sous Git avec un .gitignore qui exclut renv/library/ et chaque secret — validez le code source et renv.lock, rien d’autre. Verrouillez les dépendances avec renv pour que n’importe quelle machine reconstruise votre bibliothèque exacte depuis le fichier de verrouillage. Puis laissez un pipeline CI/CD restaurer cette bibliothèque et déployer à chaque push vers main, en lisant son jeton depuis un secret CI plutôt que depuis le YAML. Le résultat est un déploiement que vous déclenchez d’un seul git push : révisé, verrouillé en version, et identique à chaque fois — et quand l’application apparaît à son URL sans étape manuelle, le runtime a prouvé que le workflow fonctionne.

Leçons connexes

Cette page vous a-t-elle été utile ?

Prouvez que vous savez le faire. Maîtrisez toute la série Shiny en production — suivez votre parcours, construisez des projets et obtenez un certificat.

Commencer gratuitement →

Passez à Pro — Prova illimité sur vos propres données et un certificat vérifiable qui atteste la compétence.

dès 15 $/mois facturé annuellement

Passer à Pro →

✓ Vous êtes Pro — continuez. The runtime is the judge.

Recevez les nouvelles leçons R & Python par e-mail

Pratique, reproductible, sans spam. Désinscription à tout moment.

Double opt-in. Nous ne partageons jamais votre e-mail.

Partager cette pageXLinkedInRedditHN

Réutilisation

Citation

BibTeX
@online{2026,
  author = {},
  title = {Gestion de versions Shiny : un workflow de déploiement Git +
    CI/CD},
  date = {2026-07-16},
  url = {https://www.datanovia.com/learn/programming/shiny/production/version-control},
  langid = {fr}
}
Veuillez citer ce travail comme suit :
“Gestion de versions Shiny : un workflow de déploiement Git + CI/CD.” 2026. July 16. https://www.datanovia.com/learn/programming/shiny/production/version-control.