Aller au contenu principal

Comment j'ai industrialisé mon side-project avec Google Jules

Ne laissez plus l'IA "deviner" si le code fonctionne. Apprenez à configurer une sandbox Docker pour Google Jules afin d'automatiser la QA, la sécurité et la performance, loin du "Vibe Coding".

Publié le

Temps de lecture 6 min

Dans la tech actuelle, on entend beaucoup parler de Vibe Coding: laisser l'IA générer du code au kilomètre tant que "ça passe", sans trop se soucier de la dette technique ou de la sécurité. Ce n'est pas mon approche.

Mon site est un laboratoire. J'y architecture du Symfony, je teste les dernières features de PHP. C'est un projet sérieux, mais c'est aussi un loisir. Cependant, j'ai une contrainte majeure : j'ai un travail à temps plein la journée. Je ne peux pas consacrer mes soirées à la maintenance, à traquer le respect des normes PSR, à mettre à jour des dépendances mineures ou à vérifier des régressions d'accessibilité.

C'est là qu'intervient https://jules.google.

Je ne l'ai pas configuré pour "coder à ma place", mais pour agir comme une équipe de support asynchrone. Jules s'occupe des tâches de fond (QA, sécurité, perf) pendant que je suis au bureau.

Mais pour qu'une IA puisse interagir avec une stack complexe (Docker, PostgreSQL, Redis, Meilisearch) sans compromettre l'intégrité du projet, un simple accès au dépôt ne suffit pas. Il faut lui fournir un environnement d'exécution. Sans cela, l'agent hallucine ou échoue.

Interface de Jules en action

Le défi : rendre l'IA compatible avec Docker

Les agents comme Jules tournent dans des environnements conteneurisés éphémères appelés « sandbox ». Si l'agent essaie de lancer php bin/phpunit, cela échouera immédiatement : pas de base de données, pas d'extensions PHP, pas de Redis.

J'ai donc écrit un script Bash qui configure l'environnement et sert de bootstrapper d'infrastructure. Il transforme l'environnement vide de l'agent en une réplique exacte de mon environnement de développement.

Sous le capot : analyse du script

Ce script est la première instruction que Jules exécute. Il prépare le terrain pour que mes agents spécialisés (Bolt, Sentinel et Palette) puissent travailler. Voici comment il fonctionne :

1. Détection dynamique du contexte (Working Directory)

Les environnements CI/CD ou les agents cloud ne clonent pas toujours le projet au même endroit (/app, /workspace, /home/runner...). Si le script ne s'adapte pas, les commandes Docker (notamment le montage de volumes) échouent.

Bash
# DETECT WORKING DIRECTORY
if [ -n "${BASH_SOURCE[0]:-}" ]; then
    SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
elif [ -d "/app/.git" ]; then
    PROJECT_DIR="/app" # Chemin standard Jules
elif [ -d "/workspace/.git" ]; then
    PROJECT_DIR="/workspace"
else
    PROJECT_DIR="$(pwd)"
fi

# Use absolute path to avoid OCI container issues
cd "$PROJECT_DIR"

Ce bloc garantit que le script trouve toujours la racine du projet, peu importe l'environnement cloud dans lequel il atterrit. L'utilisation de chemins absolus fiabilise les volumes Docker (-v $(pwd):/app).

Le "Hack" des permissions (Docker-in-Docker)

C'est souvent le point de friction des pipelines. L'utilisateur de l'agent n'a pas forcément les droits root ou l'accès au socket Docker de l'hôte.

Bash
# Fix Git ownership
git config --global --add safe.directory "$PROJECT_DIR"
git config --global --add safe.directory '*'

# Fix Docker socket permissions
if [ -S /var/run/docker.sock ]; then
    sudo chmod 666 /var/run/docker.sock 2>/dev/null || true
fi
  • safe.directory : Règle l'erreur Git "dubious ownership" fréquente quand l'ID utilisateur du conteneur ne matche pas celui des fichiers.
  • chmod 666 ...docker.sock : Permet au conteneur de l'agent de piloter le daemon Docker de la machine hôte. C'est ce qui permet à Jules de spawner mes services (Postgres, Redis) depuis son environnement.

De plus, le script détecte intelligemment s'il doit préfixer les commandes par sudo en testant l'accès à docker ps.

3. Build ciblé et résilient

Je ne lance pas l'image de production (trop lourde). Le script construit une image php-test dédiée, définie dans compose.test.yaml.

Bash
${USE_SUDO} docker compose -f compose.test.yaml build php-test || {
    echo "⚠️  Test image build failed, trying with --no-cache..."
    ${USE_SUDO} docker compose -f compose.test.yaml build --no-cache php-test
}

Elle contient les outils d'analyse (PCOV pour la couverture, Xdebug) mais reste légère (Alpine). Si le build échoue (cache corrompu), le script force automatiquement une reconstruction --no-cache.

4. La stratégie de disponibilité (wait strategy)

C'est la partie la plus critique pour la stabilité. Lancer un conteneur PostgreSQL ne suffit pas : il faut attendre qu'il soit prêt à accepter des connexions TCP. Un simple sleep 10 est une mauvaise pratique (source de "flaky tests").

Bash
# Start database
${USE_SUDO} docker compose -f compose.test.yaml up -d database_test_service

# Boucle de vérification active
echo "🗄️  Checking PostgreSQL..."
for i in {1..10}; do
    DB_CONTAINER=$(...) # Récupère l'ID du conteneur
    if [ -n "$DB_CONTAINER" ]; then
        # On demande à Postgres lui-même s'il est prêt (via docker exec)
        ${USE_SUDO} docker exec "$DB_CONTAINER" pg_isready -U app && break
    fi
    sleep 3
done

J'utilise pg_isready exécuté à l'intérieur du conteneur via docker exec. C'est la seule méthode déterministe pour garantir à 100% que la base est disponible avant de lancer les migrations.

5. L’abstraction via Makefile

Enfin, le script Bash gère l'infrastructure ("Hardware"), mais délègue la logique applicative ("Software") à un outil standardisé.

Bash
${USE_SUDO} make agent-db-test-reset

Cette commande make va :

  1. Supprimer la base de test existante.
  2. Jouer les migrations Doctrine.
  3. Charger les fixtures (jeux de données de test).
Le message de commit dans GitHub de Jules

Résultat : une CI locale pilotée par IA

Une fois cette infrastructure en place, j'ai configuré Jules pour qu’il utilise des scripts inclus dans l’agent :

  • Bolt (Performance) : Chasse les requêtes N+1 et les problèmes de cache.
  • Sentinel (Sécurité) : Vérifie la sanitization des inputs et les secrets.
  • Palette (UX/Design) : S'assure de l'accessibilité (ARIA) et des micro-interactions.

Grâce à tout ceci, Jules ne "devine" pas si le code fonctionne : il l'exécute. C'est ce qui transforme l'IA d'un simple générateur de texte en un véritable outil d'ingénierie, capable de s’occuper le maintenance de mon site en toute transparence.

Le code est dans la boîte !

Recevez les nouveaux billets directement dans votre boîte mail. Juste l'essentiel, promis.

Désinscription possible à tout moment.