· 5 min read

Feature flags avec Symfony et GitLab

Découvrons comment mettre en place des feature flags avec Symfony et GitLab. Cela nous permettra de déployer du code en production sans l'activer pour tout le monde. Idéal dans un flux de développement continu.

Découvrons comment mettre en place des feature flags avec Symfony et GitLab. Cela nous permettra de déployer du code en production sans l'activer pour tout le monde. Idéal dans un flux de développement continu.

Les feature flags ?

Nous devrions pouvoir déployer du code en production plusieurs fois par jour sans que cela ne pose de problème.

La réalité est souvent différente. Nous devons souvent attendre des jours, voire des semaines, avant de pouvoir déployer du code en production. Cela est dû à la peur de casser quelque chose ou de déployer du code qui n’est pas encore prêt.

Les feature flags sont une solution à ce problème. Ils nous permettent de déployer du code en production sans l’activer pour tout le monde. Idéal dans un flux de type “Trunk Based Development” (qui consiste à travailler sur une seule branche principale et à merger le code le plus rapidement possible).

Les feature flags sont également utiles pour réaliser des tests A/B, mettre à l’épreuve une nouvelle version d’une fonctionnalité à un pourcentage d’utilisateurs, etc.

Dans cet article, nous allons voir comment mettre en place des feature flags avec Symfony et GitLab.

Mise en place

Nous allons créer un faux projet Symfony pour illustrer la mise en place des feature flags. Ce projet n’a pas de réelle utilité, il sert juste à illustrer le fonctionnement des feature flags 😎

Le projet Symfony

  • Créons un projet Symfony avec la commande suivante :
symfony new feature-flags --webapp
cd feature-flags
  • Créons un contrôleur FeatureFlagsController avec la commande suivante :
symfony console make:controller FeatureFlagsController
  • Démarrons le serveur web avec la commande suivante :
symfony serve -d

Le repository GitLab

  • Créons un nouveau projet sur GitLab

  • Dans le menu Deploy > Feature Flags, créons trois feature flags :

    • route_active : sans condition
    • feature_v2 : sans condition
    • feature_v3 : sans condition

Utiliser les feature flags GitLab dans Symfony

Nous allons maintenant utiliser les feature flags créés dans GitLab dans notre projet Symfony.

Unleash ?

Le système de feature flags de GitLab est compatible avec les API Unleash (une solution open source de feature flags). C’est bonne nouvelle, car il existe un Bundle Symfony pour Unleash : unleash-client-symfony.

Installation et configuration du Bundle

  • Ajoutons le Bundle à notre projet avec la commande suivante :
composer require unleash/symfony-client-bundle
  • Récupérons les infos chez GitLab, dans Settings > Feature Flags > Configurequi permet de consulter les informations nécessaires pour configurer le Bundle.

  • Configurons le Bundle dans le fichier config/packages/unleash.yaml :

unleash_client:
  app_url: https://gitlab.com/api/v4/feature_flags/unleash/123456789
  instance_id: glffct-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  app_name: dev

Attention, dans un vrai projet, il faudrait stocker ces informations dans des variables d’environnement.

Utilisation dans le contrôleur

Nous allons utilier le Feature Flag route_active pour activer ou non une route dans notre contrôleur.

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Unleash\Client\Bundle\Attribute\IsEnabled;

class FeatureFlagsController extends AbstractController
{
    #[IsEnabled('route_active', Response::HTTP_BAD_REQUEST)]
    #[Route('/feature/flags', name: 'app_feature_flags')]
    public function index(): Response
    {
        return $this->render('feature_flags/index.html.twig', [
            'controller_name' => 'FeatureFlagsController',
        ]);
    }
}

Si le Feature Flag route_active est activé, la route /feature/flags sera accessible. Sinon, une erreur 400 sera retournée. Cool, non ?

Utilisation dans des portions de code

Nous allons maintenant utiliser le Feature Flag feature_v2 pour activer ou non une portion de code dans notre contrôleur :

  • Si le Feature Flag feature_v2 est activé, le contrôleur affichera “Feature Flags ENABLED”
  • Sinon, le contrôleur affichera “Feature Flags DISABLED”
<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Unleash\Client\Bundle\Attribute\IsEnabled;
use Unleash\Client\Unleash;

class FeatureFlagsController extends AbstractController
{
    public function __construct(
        private readonly Unleash $unleash
    )
    {
    }


    #[IsEnabled('route_active', Response::HTTP_BAD_REQUEST)]
    #[Route('/feature/flags', name: 'app_feature_flags')]
    public function index(): Response
    {
        $controllerName = 'Feature Flags DISABLED';

        if ($this->unleash->isEnabled('feature_v2')) {
            $controllerName = 'Feature Flags ENABLED';
        }

        return $this->render('feature_flags/index.html.twig', [
            'controller_name' => $controllerName,
        ]);
    }
}

Utilisation dans les templates Twig

Nous allons maintenant utiliser le Feature Flag feature_v3 pour activer ou non une portion de code dans notre template Twig :

  • Si le Feature Flag feature_v3 est activé, le template affichera “FEATURE V3 IS ENABLED”
  • Sinon, le template affichera “FEATURE V3 IS DISABLED”
{% extends 'base.html.twig' %}

{% block title %}Hello FeatureFlagsController!{% endblock %}

{% block body %}
<style>
    .example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
    .example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>

<div class="example-wrapper">
    <h1>Hello {{ controller_name }}! ✅</h1>

    {% if feature_is_enabled('feature_v3') %}
        FEATURE V3 IS ENABLED
    {% else %}
        FEATURE V3 IS DISABLED
    {% endif %}
</div>

{% endblock %}

Feature flags avec “options”

Il est possible de définir des “options” pour les Feature Flags. Par exemple, nous pourrions définir un pourcentage d’utilisateurs concernés par un Feature Flag.

  • Modifions le Feature Flag route_active pour qu’il soit activé pour 50% des utilisateurs.

Ainsi, la route /feature/flags sera accessible pour 50% des utilisateurs. Pour les autres, une erreur 400 sera retournée.

Pas simple d’en faire une démo, mais vous avez compris l’idée 😅

Conclusion

Comme nous venons de le voir, il est très simple de mettre en place des feature flags avec Symfony et GitLab. Cela nous permet de déployer du code en production sans l’activer pour tout le monde, à chaud.

Je trouve que ça ouvre de nombreuses possibilités pour tester des nouvelles fonctionnalités, réaliser des tests A/B sans trop de difficultés et sans avoir à déployer plusieurs versions de l’application (c’est les admins sys qui vont être contents 😅).

Ah oui, important, pensez bien à supprimer les Feature Flags lorsqu’ils ne sont plus nécessaires. Cela évitera d’avoir du code mort dans votre application 🧟‍♂️

Back to Blog