· 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.
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
- Ouvrons le navigateur à l’adresse https://127.0.0.1:8000/feature/flags pour vérifier que tout fonctionne correctement.
Le repository GitLab
-
Créons un nouveau projet sur GitLab
-
Dans le menu
Deploy > Feature Flags
, créons trois feature flags :route_active
: sans conditionfeature_v2
: sans conditionfeature_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 > Configure
qui 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 🧟♂️