À l’occasion des récentes évolutions majeures de mon projets SeedboxSync (actuellement disponible sur les branche develop et main mais j’en parlerais plus amplement lors de la release), j’ai pris un peu de temps pour réviser la chaîne d’outils et le tooling de développement.
Au fil des années, certaines habitudes s’installent, mais l’écosystème évolue vite et propose aujourd’hui des alternatives bien plus performantes, légères et agréables à utiliser au quotidien. Voici un retour sur la modernisation de mon environnement de dev avec just, pnpm, uv & Ruff.
Du Makefile à just : Un runner de tâches plus élégant
Pendant longtemps, le bon vieux Makefile a fait l’affaire pour orchestrer mes commandes de build, de test ou de déploiement. Mais soyons honnêtes : Make n’a jamais été pensé à l’origine pour être un simple lanceur de tâches (task runner). La gestion des cibles factices (.PHONY), la syntaxe parfois capricieuse avec les tabulations et le comportement par défaut orienté fichiers finissent par lasser.
J’ai donc sauté le pas vers Just :
- Une syntaxe dédiée : La syntaxe est claire, moderne et conçue spécifiquement pour exécuter des recettes.
- Des fonctionnalités intégrées : Chargement automatique des fichiers
.env, passage d’arguments ultra-simple et gestion propre des dépendances entre tâches. - Un rendu plus « sexy » : La commande
just --list(ou simplementjust) offre immédiatement un menu lisible et auto-documenté des commandes disponibles pour le projet. - Disponibilité au sein des GitHub Actions : extractions/setup-just
$ just
Available recipes:
clean # Remove Python bytecode files (*.pyc) and build artifacts [alias: c]
dist # Build frontend assets and package the Python distribution via uv [aliases: build, d]
dist-update # Update both Python and Node.js dependencies to their latest versions [alias: update]
docker-build # Build the Docker container image [alias: docker]
publish # Build distribution packages and publish to PyPI using uv
virtualenv # Recreate the Python virtual environment (.venv) using uv and install dependencies in editable mode
[🌐 Internationalization]
i18n-compile # Compile translation catalog files (.po to .mo)
i18n-extract # Extract translatable strings to .pot, update .po catalog files, and compile .mo binaries
i18n-update # Update existing translation files (.po) against the template (.pot)
[🎨 Frontend]
nodejs-build # Build and bundle frontend assets for production
nodejs-dev # Start Node.js frontend development server
nodejs-dist-update # Update Node.js dependencies to their latest versions
nodejs-install # Install Node.js dependencies using pnpm
nodejs-lint # Run linter for Node.js frontend code/assets
[🐍 Python]
python-dist-update # Update Python dependencies to their latest versions
python-install *args # Install Python dependencies in the virtual environment using uv
python-install-dev # Install Python dependencies in the virtual environment using uv with extra dev dependencies
[📚 Documentation]
doc # Build static documentation site using ProperDocs
doc-gh-deploy # Prepare coverage and deploy on GitHub the static documentation site using ProperDocs
doc-serve # Serve live documentation preview with auto-reloading using ProperDocs
[🚀 Launcher]
run-front # Run the Flask development server with hot-reloading enabled [alias: front]
run-taskmanager # Run the Huey background task worker with 2 threads [alias: task]
[🛠️ Code quality & linting]
basedpyright # Run static type checking on Python source code using basedpyright
comply # Check Python code quality and style using Ruff
format *args # Format Python code and automatically fix safe issues using Ruff
hadolint # Lint the Dockerfile for best practices and security issues (need hadolint)
markdownlint # Lint Markdown files for syntax and formatting rules (need markdownlint)
mypy # Run static type checking on Python source code using Mypy
nodejs-lint # Run linter for Node.js frontend code/assets
type-checking # Run static type checking on Python source code
[🧪 Testing & CI]
pytest # Run Pytest suite with terminal output and HTML coverage report
pytest-ci # Run Pytest suite for CI with XML coverage output
test # Run all local linters followed by the full test suite
test-ci # Run the full validation and testing pipeline for CIDe npm à pnpm : Une transition tardive mais bluffante
Côté frontend, j’étais resté sur npm par pure habitude. Même si npm s’est amélioré au fil des versions, le temps d’installation des dépendances et le stockage redondant dans les dossiers node_modules finissaient par peser.
J’avoue avoir pris un peu de retard sur le sujet, mais le passage à pnpm a été une excellente surprise :
- Gain de temps hallucinant : Grâce au stockage global basé sur des liens durs (hard links), l’installation des paquets est quasi instantanée.
- Économie d’espace disque : Fini les gigaoctets gaspillés à dupliquer les mêmes modules sur chaque projet.
- Rigueur du
node_modules: Sa structure stricte empêche d’accéder à des paquets non déclarés explicitement dans lepackage.json.
Python : uv remplace pip et venv à la vitesse grand « V »
Pour la partie Python de SeedboxSync, la gestion classique des environnements virtuels via venv et l’installation de paquets avec pip / pip-tools commençaient à montrer leurs limites en termes de rapidité.
L’adoption de uv (développé en Rust) a été une vraie révélation :
- Une rapidité déconcertante : La création des
venvet la résolution de l’arbre de dépendances prennent désormais quelques millisecondes, là oùpipdemandait plusieurs dizaines de secondes. - Gestion des lockfiles : Le verrouillage des versions est d’une efficacité redoutable, garantissant des builds reproductibles sans surcouche complexe.
- Unification de la chaîne : Il remplace avantageusement à la fois
pip,pip-toolsetvirtualenven un seul binaire ultra-léger. - Disponible en GitHub action (astral-sh/setup-uv) et remplace même actions/setup-python !
[...]
# Setup Python
- name: Install Just
uses: taiki-e/install-action@just
- name: Setup Python ${{ matrix.python-version }} with uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: ${{ matrix.python-version }}
# Instal & run task
- name: Install Python dependencies
run: uv sync --locked --extra dev
- name: Run Python tests
run: just test-ci
[...]Linter & Formatter : Cap directement sur Ruff
Je souhaitais initialement mettre en place le duo classique Flake8 (déjà présent pour le linting) et Black (pour le formatage automatique). Mais au moment de configurer le projet, pourquoi multiplier les outils Python alors qu’une alternative tout-en-un existe ? Je suis donc parti directement sur Ruff :
- Unification des outils : Ruff remplace à lui seul Flake8, Black, isort et bien d’autres modules. Une seule configuration dans le
pyproject.tomlsuffit. - Performances extrêmes : Écrit en Rust lui aussi, il est jusqu’à 100 à 1000 fois plus rapide que les outils traditionnels en Python. L’analyse et le formatage du projet sont instantanés, que ce soit en local ou dans les pipelines CI.
Conclusion
Cette remise à niveau globale du tooling dev apporte un confort d’utilisation au quotidien. Entre l’ergonomie de just, la rapidité de pnpm, l’efficacité de uv et la vélocité de Ruff, toute la chaîne est plus fluide, plus moderne et particulièrement agréable à maintenir.







