uvx dans GitHub Actions compatible avec la cache
Simon Willison a publié une recette pour utiliser uvx (le tool runner d’uv) dans GitHub Actions sans que chaque workflow télécharge tout depuis PyPI à chaque fois. L’astuce repose sur deux éléments : vous définissez une variable d’environnement UV_EXCLUDE_NEWER avec une date fixe au début du workflow, et vous utilisez cette date comme partie de la clé de cache. Chaque appel à uvx tool-name se résout à la version la plus récente jusqu’à cette date, et la cache persiste entre les exécutions. Pour mettre à jour les outils, vous avancez la date.
Cela compte si vous automatisez des workflows Python avec GitHub Actions : au lieu d’attendre que le runner télécharge les dépendances à chaque fois, vous réutilisez ce qui est déjà en cache. Le résultat : des builds plus rapides et moins de trafic vers PyPI. Le pattern est simple mais immédiatement applicable : deux lignes de configuration et vous savez que vos workflows ne redémarrent pas de zéro à chaque tour.
Si vous voulez essayer. Ajoutez UV_EXCLUDE_NEWER: "2026-07-12" (ou la date que vous voulez) au début de votre workflow et utilisez cette variable dans la clé de l’action cache. La recette complète est documentée avec exemple.
En détail
Le problème
Quand vous utilisez uvx tool-name dans un workflow GitHub Actions, par défaut chaque exécution contacte PyPI pour télécharger l’outil et ses dépendances. Cela ajoute de la latence à chaque build et gaspille de la bande passante : si l’outil n’a pas changé, vous refaites du travail inutile.
La cache des GitHub Actions existe précisément pour cela, mais il fallait un moyen de faire en sorte que uvx respecte cette cache au lieu de toujours tout télécharger de nouveau. Le problème est que uvx essaie par défaut de se résoudre à la version la plus récente disponible, ce qui signifie que la clé de cache change à chaque fois qu’il y a une nouvelle release de l’outil, même si cette release ne vous concerne pas.
La solution de Willison
La recette repose sur UV_EXCLUDE_NEWER, une variable d’environnement d’uv qui dit : « ignore tout ce qui a été publié après cette date ». Si vous définissez UV_EXCLUDE_NEWER: "2026-07-12" au début du workflow, chaque appel à uvx se résoudra à la version la plus récente publiée jusqu’au 12 juillet 2026, et cette version restera stable tant que vous ne changez pas la date.
Vous utilisez aussi cette date dans la clé de l’action cache (actions/cache@v4), donc GitHub sait que la cache est valide tant que la date ne change pas. Quand vous voulez mettre à jour les outils, vous avancez la date et la cache s’invalide d’elle-même.
L’avantage est que vous avez un contrôle explicite sur le moment de la mise à jour, au lieu de subir chaque nouvelle release de l’outil sans préavis. C’est une forme de pinning souple : vous ne bloquez pas une version spécifique, mais vous bloquez une fenêtre temporelle, et c’est suffisant pour maintenir la cache cohérente.
Pourquoi c’est important
Si vous avez des workflows qui s’exécutent souvent (CI à chaque commit, déploiements automatiques, jobs schedulés), le temps économisé à chaque exécution s’accumule. Plus important : vous éliminez une source d’instabilité. Un workflow qui passe aujourd’hui et échoue demain parce qu’une nouvelle version d’un outil a cassé quelque chose est un problème que cette recette prévient, car la date vous donne un point de contrôle explicite.
Il y a aussi une issue ouverte contre astral-sh/setup-uv qui demande de changer le défaut en faveur de la cache au lieu du purge des wheels. Si cette proposition passe, une partie de ce travail pourrait devenir automatique. En attendant, la recette de Willison fonctionne dès maintenant.