Objectifs

Dans cet article je vous propose de mettre en place une solution permettant de générer de manière automatique une documentation complète du modèle de données de votre application Symfony.

Nous “orchestrerons” la génération de cette documentation dans un pipeline GitLab CI afin que le documentation reste à jour lors de toutes modifications du modèle de données.

Création d’un projet Symfony : Gestion d’une collection d’albums

  • Créons notre projet Symfony
symfony new docBdd --webapp
cd docBdd
  • Créons une première entité Artiste
symfony console make:entity Artiste        

 New property name (press <return> to stop adding fields):
 > nom
 > string
 > 255

 Add another property? Enter the property name (or press <return> to stop adding fields):
 > prenom
 > string
 > 255

 Add another property? Enter the property name (or press <return> to stop adding fields):
 > dateNaissance  
 > datetime
  • Créons une entité Album
symfony console make:entity Album  

 New property name (press <return> to stop adding fields):
 > artistes
 > relation

 What class should this entity be related to?:
 > Artiste

 Relation type? [ManyToOne, OneToMany, ManyToMany, OneToOne]:
 > ManyToMany

 New property name (press <return> to stop adding fields):
 > dateSortie
 > datetime

 Add another property? Enter the property name (or press <return> to stop adding fields):
 > nom
 > string
 > 255
           
  Success!
  • Créons une entité Style
symfony console make:entity Style     

 New property name (press <return> to stop adding fields):
 > nom
 > string
 > 255

 Add another property? Enter the property name (or press <return> to stop adding fields):
 > albums

 Field type (enter ? to see all types) [string]:
 > relation

 What class should this entity be related to?:
 > Album

 Relation type? [ManyToOne, OneToMany, ManyToMany, OneToOne]:
 > ManyToMany

 Add another property? Enter the property name (or press <return> to stop adding fields):
 > artistes

 Field type (enter ? to see all types) [string]:
 > relation

 What class should this entity be related to?:
 > Artiste

 Relation type? [ManyToOne, OneToMany, ManyToMany, OneToOne]:
 > ManyToMany
           
  Success!
  • Créons une entité Label
symfony console make:entity Label     

 New property name (press <return> to stop adding fields):
 > nom
 > string
 > 255

 Add another property? Enter the property name (or press <return> to stop adding fields):
 > albums

 Field type (enter ? to see all types) [string]:
 > relation

 What class should this entity be related to?:
 > Album

 Relation type? [ManyToOne, OneToMany, ManyToMany, OneToOne]:
 > OneToMany
           
  Success!
  • Générons notre fichier de migration et jouons notre migration
docker compose up -d
symfony console make:migration
symfony console d:m:m

Découverte de SchemaSpy

Pour la suite nous allons utiliser l’incroyable SchemaSpy: un excellent outil qui permet de générer une documentation du modèle de données.

Exposons notre base de données

Comme j’utilise Docker pour executer une base de donnée, je dois exposer la base de donnée sur le port 3306.

# docker-compose.override.yml

version: '3'

services:
###> doctrine/doctrine-bundle ###
  database:
    ports:
      - "5678:5432"
###< doctrine/doctrine-bundle ###

Et redémarrons le container

docker compose up -d

Testons SchemaSpy avec Docker

Pour gagner du temps, nous allons utiliser une image Docker dèja “packagée” avec PostgreSql: andrewjones/schemaspy-postgres.

Attention, ça peut faire peur ha ha ha !

docker run --rm --network="host" -v $PWD/output:/output andrewjones/schemaspy-postgres:latest -host localhost -port 5678 -u app -p '!ChangeMe!' -db app -s public

Ajoutons au passage le repertoire output à notre .gitignore

/output/

Enfin, je vous laisse découvrir le résultat de SchemaSpy en ouvrant le ficheir output/index.html !

Améliorons notre documentation

Merci à Mickaël Andrieu pour l’astuce trouvée sur son article sur SchemaSpy.

Nous allons profiter de la possibilité offerte par Doctrine d’ajouter des commentaires aux champs de notre modèle de données pour améliorer la documentation.

Pour l’exemple, nous allons uniquement commenter la table artiste, le principe est le même pour toutes les tables.

  • Commençons par suprimer notre fichier de migration, histoire d’être clean, c’est plus simple pour la démo.

  • Commentons notre table artiste

// ...

#[ORM\Entity(repositoryClass: ArtisteRepository::class)]
#[ORM\Table(options: ['comment' => "Table des actions effectués dans l\'application"])]
class Artiste
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255, options: ['comment' => "Nom de l\'artiste"])]
    private ?string $nom = null;

    #[ORM\Column(length: 255, options: ['comment' => "Prenom de l\'artiste"])]
    private ?string $prenom = null;

    #[ORM\Column(type: Types::DATETIME_MUTABLE, options: ['comment' => "Date de naissance de l\'artiste"])]
    private ?\DateTimeInterface $dateNaissance = null;

    #[ORM\ManyToMany(targetEntity: Album::class, mappedBy: 'artistes')]
    #[ORM\Column(options: ['comment' => "Albums de l\'artiste"])]
    private Collection $albums;

    #[ORM\ManyToMany(targetEntity: Style::class, mappedBy: 'artistes')]
    #[ORM\Column(options: ['comment' => "Styles de l\'artiste"])]
    private Collection $styles;

    // ...
}
  • Regenérons notre fichier de migration et jouons notre migration
symfony console d:d:d --force && symfony console d:d:c
symfony console make:migration
symfony console d:m:m
  • Vérifions notre documentation
docker run --rm --network="host" -v $PWD/output:/output andrewjones/schemaspy-postgres:latest -host localhost -port 5678 -u app -p '!ChangeMe!' -db app -s public
  • TADA ! La documentation est maintenant améliorée avec nos commentaires !

Automatisation de la documentation dans GitLab CI 🚀

Maintenant que vous avez les bases, passons à l’étape suivante : automatiser la documentation !

  • je vous laisse brancher votre projet sur un repository GitLab CI

  • Créons un fichier .gitlab-ci.ymlà la racine du projet, qui exécute deux étapes

    • Une étape qui génère la base de données et réalise un Dump
    • Une étape qui restaure la base de données à partir du Dump et génère la documentation SchemaSpy !
image: yoanbernabeu/phpqa-with-tools:latest

before_script:
    - composer install

cache:
    paths:
        - vendor/

stages:
    - Documentation

# Generate documentation
SchemaSpy-init:
    stage: Documentation
    services:
        - name: postgres:13.0
          alias: postgres
    variables:
        POSTGRES_USER: postgres
        POSTGRES_PASSWORD: password
        PGPASSWORD: password
        POSTGRES_DB: postgres_test
        DATABASE_URL: postgresql://postgres:password@postgres:5432/postgres?serverVersion=13&charset=utf8
    script:
        - php bin/console doctrine:database:drop --force --env=test
        - php bin/console doctrine:database:create --env=test
        - php bin/console doctrine:migration:migrate --env=test --no-interaction
        - pg_dump -U postgres -h postgres -d postgres_test > postgres_test.sql
    artifacts:
        paths:
            - postgres_test.sql

pages:
    stage: Documentation
    services:
        - name: postgres:13.0
          alias: postgres2
    variables:
        POSTGRES_USER: postgres
        POSTGRES_PASSWORD: password
        PGPASSWORD: password
        POSTGRES_DB: postgres_test
        DATABASE_URL: postgresql://postgres:password@postgres2:5432/postgres?serverVersion=13&charset=utf8
    needs:
        - SchemaSpy-init
    image:
        name: yoanbernabeu/schemaspy-postgresql-client
        entrypoint: ["/bin/sh", "-c"]
    before_script:
        - pwd
    script:
        - psql -U postgres -h postgres2 -p 5432 -d postgres_test -f postgres_test.sql
        - java -jar /schemaspy-6.1.0.jar -t pgsql -db postgres_test -host postgres2 -port 5432 -s public -u postgres -p password -o ./public -dp /drivers_inc/postgresql-42.1.1.jre7.jar
    artifacts:
        paths:
            - public

Vous pouvez maintenant consulter la documentation générée dans votre projet avec les GitLab Pages ! N’est-ce pas génial ?!

Pour les curieux uniquement, les Dockerfiles utilisés dans le pipeline

  • Pour yoanbernabeu/phpqa-with-tools:latest
FROM schemaspy/schemaspy

USER root

RUN apk update
RUN apk --no-cache add postgresql
RUN apk --no-cache add postgresql-client

ENTRYPOINT ["/bin/sh"]
  • Pour yoanbernabeu/schemaspy-postgresql-client
FROM jakzal/phpqa

USER root

RUN apt-get update \
    && apt-get install -y curl ca-certificates gnupg \
    && curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/apt.postgresql.org.gpg >/dev/null \
    && sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt buster-pgdg main" > /etc/apt/sources.list.d/pgdg.list' \
    && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 7FCC7D46ACCC4CF8 \
    && apt-get update \
    && apt-get install -y libpq-dev postgresql-client-13 && docker-php-ext-install pdo pdo_pgsql

Sources