<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Jean-Yves Gastaud blog</title>
    <link>https://gastaud.io/tags/cloudflare-containers/</link>
    <description>Recent content on Jean-Yves Gastaud blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>fr-fr</language>
    <lastBuildDate>Tue, 11 Aug 2026 10:00:00 +0200</lastBuildDate>
    
        <atom:link href="https://gastaud.io/tags/cloudflare-containers/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Faire tourner GitLab CI sur Cloudflare Workers &amp; Containers : un exécuteur GitLab Runner maison</title>
      <link>https://gastaud.io/article/gitlab-runner-cloudflare/</link>
      <pubDate>Tue, 11 Aug 2026 10:00:00 +0200</pubDate>
      
      <guid>https://gastaud.io/article/gitlab-runner-cloudflare/</guid>
      
        <description>&lt;p&gt;Les runners GitLab CI tournent traditionnellement sur des VMs ou des pods Kubernetes qu&amp;rsquo;il faut dimensionner, garder chauds, et payer même quand ils ne font rien.&lt;/p&gt;
&lt;p&gt;Et si on déportait l&amp;rsquo;exécution des jobs sur une plateforme serverless comme Cloudflare, avec un container provisionné à la demande, à la seconde, pour chaque job ?&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est la question que j&amp;rsquo;ai voulu creuser avec &lt;code&gt;gitlab-runner-cloudflare&lt;/code&gt; : un exécuteur GitLab Runner qui exécute les jobs CI sur Cloudflare Workers + Containers.&lt;/p&gt;
&lt;h2 id=&#34;pourquoi-ce-projet&#34;&gt;Pourquoi ce projet&lt;/h2&gt;
&lt;p&gt;GitLab Runner expose un &lt;a href=&#34;https://docs.gitlab.com/runner/executors/custom.html&#34;&gt;Custom Executor&lt;/a&gt; : une interface très simple (&lt;code&gt;config&lt;/code&gt; / &lt;code&gt;prepare&lt;/code&gt; / &lt;code&gt;run&lt;/code&gt; / &lt;code&gt;cleanup&lt;/code&gt;), volontairement agnostique du transport et de l&amp;rsquo;infrastructure sous-jacente. Il n&amp;rsquo;y a ni notion de Docker, ni de SSH imposée : c&amp;rsquo;est à l&amp;rsquo;exécuteur de décider comment et où le job tourne.&lt;/p&gt;
&lt;p&gt;Cette généricité m&amp;rsquo;a donné envie de tester une hypothèse : est-ce que cette interface est suffisamment ouverte pour qu&amp;rsquo;on puisse la brancher sur une plateforme serverless comme &lt;a href=&#34;https://developers.cloudflare.com/workers/&#34;&gt;Cloudflare Workers&lt;/a&gt; et &lt;a href=&#34;https://developers.cloudflare.com/containers/&#34;&gt;Cloudflare Containers&lt;/a&gt;, plutôt que sur les habituels VMs, Docker ou Kubernetes ?&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;intérêt, s&amp;rsquo;il se confirme, serait un modèle de coût très différent : plus de fleet de runners à garder chaude en permanence, un container provisionné (et facturé) à la demande pour chaque job, à l&amp;rsquo;échelle de l&amp;rsquo;edge Cloudflare.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est un projet de type POC/R&amp;amp;D : l&amp;rsquo;objectif n&amp;rsquo;était pas de livrer un produit fini, mais de valider la faisabilité, documenter les choix via des &lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare/-/tree/main/docs/adr&#34;&gt;ADR&lt;/a&gt;, et pousser les points durs (build d&amp;rsquo;images sans Docker-in-Docker, images de job dynamiques, arm64&amp;hellip;) jusqu&amp;rsquo;à avoir une réponse concrète plutôt qu&amp;rsquo;une intuition.&lt;/p&gt;
&lt;h2 id=&#34;comment-ça-sarticule&#34;&gt;Comment ça s&amp;rsquo;articule&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;GitLab Runner (sur n&amp;#39;importe quel host)
  │  Custom Executor contract (config/prepare/run/cleanup)
  ▼
executor/   binaire Go : gitlab-cf-executor
  │  HTTP
  ▼
worker/     Worker Cloudflare (control plane)
  │  1 Durable Object + 1 Container par job
  ▼
container/  Alpine + agent Kaniko (exécute le script du job,
            build les images sans daemon Docker)
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;executor/&lt;/code&gt;&lt;/strong&gt; est le binaire que GitLab Runner invoque directement. Il parle en HTTP à un &lt;code&gt;worker/&lt;/code&gt; déployé, avec un mode de repli 100% local (sans compte Cloudflare) pour développer et tester sans dépendance externe.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;worker/&lt;/code&gt;&lt;/strong&gt; est le control plane : il provisionne un Container (via une Durable Object) par job, et relaie &lt;code&gt;prepare&lt;/code&gt;/&lt;code&gt;run&lt;/code&gt;/&lt;code&gt;cleanup&lt;/code&gt; à un petit agent CGI packagé dans l&amp;rsquo;image du container.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;objectifs-atteints&#34;&gt;Objectifs atteints&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;La question de faisabilité a une réponse&lt;/strong&gt; : oui, un Custom Executor GitLab Runner peut piloter des jobs CI sur Cloudflare Workers + Containers, validé sur un déploiement Cloudflare réel (pas seulement en local avec &lt;code&gt;wrangler dev&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build d&amp;rsquo;images sans Docker-in-Docker&lt;/strong&gt; : Cloudflare Containers n&amp;rsquo;autorise pas le mode privilégié, ce qui élimine Docker-in-Docker, Buildah et BuildKit (les trois ont besoin de &lt;code&gt;unshare(CLONE_NEWUSER)&lt;/code&gt;). Le spike &lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare/-/blob/main/docs/spikes/dind-validation.md&#34;&gt;&lt;code&gt;dind-validation&lt;/code&gt;&lt;/a&gt; a confirmé que &lt;a href=&#34;https://github.com/GoogleContainerTools/kaniko&#34;&gt;Kaniko&lt;/a&gt; s&amp;rsquo;en sort sans privilèges particuliers, et c&amp;rsquo;est lui qui a été retenu.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logs en streaming&lt;/strong&gt; : la sortie d&amp;rsquo;un job est diffusée en direct (et non plus bufferisée puis renvoyée d&amp;rsquo;un coup), avec un endpoint dédié pour récupérer le code de sortie une fois le flux terminé — contrainte imposée par le fait que les headers CGI doivent précéder le corps de la réponse.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Images de job dynamiques&lt;/strong&gt; : plutôt qu&amp;rsquo;une image container figée et unique, &lt;code&gt;prepare.cgi&lt;/code&gt; télécharge et déballe (via &lt;code&gt;skopeo&lt;/code&gt;/&lt;code&gt;umoci&lt;/code&gt;) l&amp;rsquo;image &lt;code&gt;image:&lt;/code&gt; demandée par n&amp;rsquo;importe quel job, et &lt;code&gt;run.cgi&lt;/code&gt; exécute le script du job &lt;code&gt;chroot&lt;/code&gt;é dans cette image — voir &lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare/-/blob/main/docs/adr/0004-dynamic-job-images.md&#34;&gt;ADR-0004&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;git clone&lt;/code&gt; qui fonctionne même sur une image sans &lt;code&gt;git&lt;/code&gt;&lt;/strong&gt; : &lt;code&gt;get_sources&lt;/code&gt; s&amp;rsquo;exécute hors du &lt;code&gt;chroot&lt;/code&gt;, dans le sandbox qui, lui, embarque &lt;code&gt;git&lt;/code&gt;, en symlinkant &lt;code&gt;/builds&lt;/code&gt;/&lt;code&gt;/cache&lt;/code&gt; vers le rootfs de l&amp;rsquo;image du job — le même principe que les helpers dédiés des exécuteurs Docker/Kubernetes de GitLab Runner.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support de &lt;code&gt;services:&lt;/code&gt;, &lt;code&gt;cache:&lt;/code&gt; et &lt;code&gt;artifacts:&lt;/code&gt;&lt;/strong&gt; : détaillé juste en dessous.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tests et CI&lt;/strong&gt; : 41 tests unitaires Go côté &lt;code&gt;executor/&lt;/code&gt;, tests unitaires Vitest côté &lt;code&gt;worker/&lt;/code&gt;, et un test E2E qui exécute un vrai build Kaniko via un &lt;code&gt;wrangler dev&lt;/code&gt; local. Le tout est automatisé dans &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; (tests sur chaque changement pertinent, déploiement manuel sur &lt;code&gt;main&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt; : 5 ADR qui tracent les décisions d&amp;rsquo;architecture (plateforme d&amp;rsquo;exécution, support multi-architecture, compatibilité fleeting/&lt;code&gt;docker_autoscaler&lt;/code&gt;, images de job dynamiques, services/cache/artifacts), 2 spikes qui documentent les validations techniques, et des README par composant.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Control plane authentifié&lt;/strong&gt; : l&amp;rsquo;API HTTP du Worker était jusqu&amp;rsquo;ici ouverte à quiconque connaissait son URL &lt;code&gt;*.workers.dev&lt;/code&gt; — un jeton partagé en &lt;code&gt;Authorization: Bearer&lt;/code&gt; est désormais requis sur chaque route, voir plus bas.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;services-cache-artifacts--comment-ça-marche-concrètement&#34;&gt;&lt;code&gt;services:&lt;/code&gt;, &lt;code&gt;cache:&lt;/code&gt;, &lt;code&gt;artifacts:&lt;/code&gt; : comment ça marche concrètement&lt;/h2&gt;
&lt;p&gt;GitLab expose les &lt;code&gt;services:&lt;/code&gt; d&amp;rsquo;un job au Custom Executor via une seule variable, &lt;code&gt;CUSTOM_ENV_CI_JOB_SERVICES&lt;/code&gt; — un tableau JSON, à charge de l&amp;rsquo;exécuteur de démarrer/stopper les services lui-même. Rien de plus n&amp;rsquo;est fourni : pas de réseau Docker, pas d&amp;rsquo;API à implémenter, juste cette information.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# .gitlab-ci.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;cf-executor:demo-services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;redis:7-alpine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;alias&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;redis&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;for i in $(seq 1 10); do nc -z redis 6379 &amp;amp;&amp;amp; break; sleep 1; done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;nc -z redis 6379 &amp;amp;&amp;amp; echo &amp;#34;OK&amp;#34; || exit 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Puisque chaque job tourne déjà dans &lt;strong&gt;une seule&lt;/strong&gt; instance de Cloudflare Container (un seul namespace réseau), un service n&amp;rsquo;a pas besoin d&amp;rsquo;isolation container : il suffit de le démarrer comme un process en arrière-plan, &lt;code&gt;chroot&lt;/code&gt;é dans son propre rootfs (dépaqueté avec &lt;code&gt;skopeo&lt;/code&gt;/&lt;code&gt;umoci&lt;/code&gt;, comme l&amp;rsquo;image du job), et de le rendre joignable par son alias. &lt;code&gt;start-service.sh&lt;/code&gt; s&amp;rsquo;appuie sur &lt;code&gt;setsid&lt;/code&gt; pour détacher le process de la requête CGI qui l&amp;rsquo;a lancé, et sur le &lt;code&gt;config.json&lt;/code&gt; (runtime-spec OCI) qu&amp;rsquo;&lt;code&gt;umoci&lt;/code&gt; produit pour retrouver l&amp;rsquo;&lt;code&gt;ENTRYPOINT&lt;/code&gt;/&lt;code&gt;CMD&lt;/code&gt; de l&amp;rsquo;image sans avoir à les redéclarer :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# extrait simplifié de start-service.sh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ROOTFS_DIR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;pull-image.sh &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$IMAGE&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BUNDLE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jq -r &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.process.args[]&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BUNDLE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/config.json&amp;#34;&lt;/span&gt; &amp;gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$ARGV_FILE&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;   &lt;span style=&#34;color:#75715e&#34;&gt;# ENTRYPOINT+CMD déjà résolus par umoci&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;setsid &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$LAUNCH_SCRIPT&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$ENV_FILE&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$ARGV_FILE&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$ROOTFS_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &amp;gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$LOG_FILE&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; 2&amp;gt;&amp;amp;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo $! &amp;gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$PID_FILE&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pour &lt;code&gt;cache:&lt;/code&gt;/&lt;code&gt;artifacts:&lt;/code&gt;, le constat était différent : &lt;code&gt;restore_cache&lt;/code&gt;/&lt;code&gt;download_artifacts&lt;/code&gt;/&lt;code&gt;archive_cache&lt;/code&gt;/&lt;code&gt;upload_artifacts&lt;/code&gt; sont des scripts générés par GitLab Runner comme n&amp;rsquo;importe quelle autre étape, mais leur documentation officielle est explicite — ils appellent directement le binaire &lt;code&gt;gitlab-runner&lt;/code&gt; lui-même, qui n&amp;rsquo;a aucune raison de se trouver dans l&amp;rsquo;image (dynamique) du job. La correction reprend le principe déjà en place pour &lt;code&gt;get_sources&lt;/code&gt;/&lt;code&gt;git&lt;/code&gt; : élargir la liste des étapes qui s&amp;rsquo;exécutent hors &lt;code&gt;chroot&lt;/code&gt;, dans le sandbox qui embarque ce binaire :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# run.cgi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$stage&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; in
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  get_sources|restore_cache|download_artifacts|archive_cache|archive_cache_on_failure|upload_artifacts_on_success|upload_artifacts_on_failure&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    unchrooted_stage&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; ;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  *&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    unchrooted_stage&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; ;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;esac&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;docker:dind&lt;/code&gt; en tant que service reste explicitement non supporté, pour la même raison qu&amp;rsquo;en tant qu&amp;rsquo;image de job (mode privilégié requis) — voir &lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare/-/blob/main/docs/adr/0005-service-containers-and-cache-artifacts.md&#34;&gt;ADR-0005&lt;/a&gt; pour le détail complet.&lt;/p&gt;
&lt;h2 id=&#34;ce-que-le-déploiement-réel-a-révélé&#34;&gt;Ce que le déploiement réel a révélé&lt;/h2&gt;
&lt;p&gt;Le POC a une règle simple : rien n&amp;rsquo;est considéré acquis avant d&amp;rsquo;avoir tourné sur un vrai déploiement Cloudflare, pas seulement en local ou sous &lt;code&gt;wrangler dev&lt;/code&gt;. En ajoutant le support des &lt;code&gt;services:&lt;/code&gt;, cette règle a payé trois fois — trois bugs invisibles en local, qui ne se sont révélés qu&amp;rsquo;en poussant &lt;code&gt;worker:deploy&lt;/code&gt; pour de vrai et en faisant tourner les jobs de démo à travers le runner enregistré.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. &lt;code&gt;/etc/hosts&lt;/code&gt; est monté en lecture seule sur un vrai Cloudflare Container.&lt;/strong&gt; La première implémentation ajoutait &lt;code&gt;alias 127.0.0.1&lt;/code&gt; directement dans &lt;code&gt;/etc/hosts&lt;/code&gt; — ça fonctionne parfaitement dans un test Docker local (où &lt;code&gt;/etc/hosts&lt;/code&gt; est un fichier bind-monté classique, inscriptible), et échoue en production :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ echo &amp;#34;1.2.3.4 foo&amp;#34; &amp;gt;&amp;gt; /etc/hosts
/tmp/run-script.sh: line 1: can&amp;#39;t create /etc/hosts: Read-only file system

$ cat /proc/mounts | grep -E &amp;#34;hosts|resolv&amp;#34;
overlay /etc/hosts       overlay ro,relatime,... 0 0
overlay /etc/resolv.conf overlay rw,relatime,... 0 0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cloudflare y monte &lt;code&gt;/etc/hosts&lt;/code&gt; comme un overlay dédié, distinct du reste de &lt;code&gt;/etc&lt;/code&gt; — mais &lt;code&gt;/etc/resolv.conf&lt;/code&gt;, lui, reste inscriptible. La résolution des alias passe donc maintenant par un &lt;code&gt;dnsmasq&lt;/code&gt; local, démarré au premier service déclaré, qui répond pour les alias connus et relaie le reste vers les vrais résolveurs DNS capturés avant que &lt;code&gt;resolv.conf&lt;/code&gt; ne soit réécrit :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# setsid dnsmasq --no-daemon --addn-hosts=/tmp/service-hosts --server=&amp;lt;upstream1&amp;gt; --server=&amp;lt;upstream2&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;nameserver 127.0.0.1&amp;#34;&lt;/span&gt; &amp;gt; /etc/resolv.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;2. Un &lt;code&gt;prepare_exec&lt;/code&gt; qui échoue est rejoué jusqu&amp;rsquo;à 3 fois par GitLab Runner, sur la même instance de container.&lt;/strong&gt; Un service déjà démarré par une tentative précédente (parce qu&amp;rsquo;un &lt;em&gt;autre&lt;/em&gt; service du même job avait échoué) restait actif et occupait déjà son port :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;185:M ... # Warning: Could not create server TCP listening socket *:6379: bind: Address in use
185:M ... # Failed listening on port 6379 (tcp), aborting.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Un faux négatif qui accusait l&amp;rsquo;image du service plutôt que le vrai coupable. Chaque service voit maintenant son PID tracé dans un fichier dédié, et toute instance précédente est tuée avant d&amp;rsquo;en démarrer une nouvelle :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; -f &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$PID_FILE&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; kill -0 &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;cat &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$PID_FILE&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  kill &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;cat &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$PID_FILE&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  sleep &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;3. La version du binaire &lt;code&gt;gitlab-runner&lt;/code&gt; embarqué doit suivre celle du runner enregistré, pas une version au hasard.&lt;/strong&gt; &lt;code&gt;archive_cache&lt;/code&gt; invoque &lt;code&gt;gitlab-runner cache-archiver&lt;/code&gt; avec des flags qui varient d&amp;rsquo;une version à l&amp;rsquo;autre ; un décalage de version (17.9 embarqué vs 19.2 enregistré, dans mon cas) fait échouer l&amp;rsquo;appel sur un flag inconnu :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Incorrect Usage: flag provided but not defined: -alternate-file
FATAL: flag provided but not defined: -alternate-file
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Silencieusement, en plus : GitLab Runner traite les échecs de cache comme non bloquants et affiche quand même le job en succès. Un job vert peut donc cacher un cache qui ne s&amp;rsquo;est jamais réellement créé — c&amp;rsquo;est en lisant le log de l&amp;rsquo;étape &lt;code&gt;archive_cache&lt;/code&gt;, pas le statut global du job, que le problème est apparu.&lt;/p&gt;
&lt;p&gt;Ces trois points illustrent bien la limite du &lt;code&gt;wrangler dev&lt;/code&gt; local évoquée plus bas : il ressemble à Cloudflare, mais ce n&amp;rsquo;en est pas un.&lt;/p&gt;
&lt;h2 id=&#34;sécuriser-lapi-du-control-plane&#34;&gt;Sécuriser l&amp;rsquo;API du control plane&lt;/h2&gt;
&lt;p&gt;Le Worker était déployé sur le sous-domaine public &lt;code&gt;*.workers.dev&lt;/code&gt;, sans route ni domaine personnalisé — et son API HTTP (&lt;code&gt;/jobs/:jobId/{prepare,run,cleanup}&lt;/code&gt;) n&amp;rsquo;avait strictement aucune authentification. N&amp;rsquo;importe qui tombant sur l&amp;rsquo;URL pouvait provisionner et piloter des containers.&lt;/p&gt;
&lt;p&gt;Deux options pour corriger ça : les service tokens de Cloudflare Access (Zero Trust), plus « natifs » côté Cloudflare, ou un simple jeton partagé en &lt;code&gt;Authorization: Bearer&lt;/code&gt;. Access aurait demandé un domaine personnalisé et une zone — que ce Worker n&amp;rsquo;a pas — plus une application Access à configurer hors de &lt;code&gt;wrangler.toml&lt;/code&gt;. Le jeton partagé, lui, ne demande aucune infrastructure Cloudflare supplémentaire : juste du code.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// worker/src/handlers.ts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;isAuthorized&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;request&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Request&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;sharedSecret&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;undefined&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;boolean&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;sharedSecret&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;; &lt;span style=&#34;color:#75715e&#34;&gt;// fail closed si le secret n&amp;#39;est pas configuré
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;header&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;request&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;headers&lt;/span&gt;.&lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Authorization&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;??&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;header&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;startsWith&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Bearer &amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;timingSafeEqual&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;header&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;slice&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt;), &lt;span style=&#34;color:#a6e22e&#34;&gt;sharedSecret&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Vérifié &lt;em&gt;avant même&lt;/em&gt; de parser la route, pour qu&amp;rsquo;un appelant non authentifié ne puisse pas distinguer une route existante d&amp;rsquo;une 404. La comparaison en temps constant est écrite à la main plutôt qu&amp;rsquo;avec &lt;code&gt;crypto.subtle.timingSafeEqual&lt;/code&gt; — cette méthode est une extension Cloudflare du Web Crypto API, absente du &lt;code&gt;SubtleCrypto&lt;/code&gt; de Node, alors que ce fichier reste volontairement testable en &lt;code&gt;vitest&lt;/code&gt; classique (pas &lt;code&gt;@cloudflare/vitest-pool-workers&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Côté &lt;code&gt;executor/&lt;/code&gt;, &lt;code&gt;GITLAB_CF_EXECUTOR_WORKER_TOKEN&lt;/code&gt; (même valeur que le &lt;code&gt;SHARED_SECRET&lt;/code&gt; posé côté Worker via &lt;code&gt;wrangler secret put&lt;/code&gt;, jamais commité) est envoyé sur chaque requête. Et comme pour les trois bugs de la section précédente, la vraie validation est venue du déploiement réel : le premier job de démo rejoué après la mise en place a échoué avec un &lt;code&gt;401 unauthorized&lt;/code&gt; — pas un faux négatif, mais la preuve que le binaire &lt;code&gt;gitlab-cf-executor&lt;/code&gt; déjà en place sur le runner datait d&amp;rsquo;avant ce correctif et n&amp;rsquo;envoyait donc aucun jeton du tout. Une fois rebuild, le job est repassé au vert.&lt;/p&gt;
&lt;h2 id=&#34;limites-actuelles--reste-à-faire&#34;&gt;Limites actuelles / reste à faire&lt;/h2&gt;
&lt;p&gt;Ce projet est un POC, pas un produit fini. Ce qui n&amp;rsquo;est pas (encore) résolu :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pas de lane arm64&lt;/strong&gt; : Cloudflare Containers ne fait que de l&amp;rsquo;amd64. Le choix du provider pour la partie arm64 (AWS Graviton, Oracle Ampere, Hetzner) n&amp;rsquo;est pas tranché, et l&amp;rsquo;intégration &lt;code&gt;docker_autoscaler&lt;/code&gt;/fleeting qui en découle n&amp;rsquo;est pas encore implémentée — voir &lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare/-/blob/main/docs/adr/0002-multi-architecture-support.md&#34;&gt;ADR-0002&lt;/a&gt; et &lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare/-/blob/main/docs/adr/0003-docker-autoscaler-fleeting-plugin-compatibility.md&#34;&gt;ADR-0003&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pas d&amp;rsquo;authentification registre privé&lt;/strong&gt; pour les images de job dynamiques : &lt;code&gt;skopeo copy&lt;/code&gt; sait faire du &lt;code&gt;--src-creds&lt;/code&gt;, mais ce n&amp;rsquo;est pas encore câblé.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pas de cache de layers entre jobs&lt;/strong&gt; : chaque container est détruit au &lt;code&gt;cleanup&lt;/code&gt;, donc chaque job re-télécharge son image depuis zéro. Un cache R2 est envisagé si la latence devient un vrai problème en pratique.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;La persistance de &lt;code&gt;cache:&lt;/code&gt; entre jobs reste à la charge de l&amp;rsquo;opérateur du runner&lt;/strong&gt; : &lt;code&gt;restore_cache&lt;/code&gt;/&lt;code&gt;archive_cache&lt;/code&gt; fonctionnent désormais correctement, mais sans &lt;code&gt;[runners.cache]&lt;/code&gt; configuré côté &lt;code&gt;config.toml&lt;/code&gt; (backend S3-compatible, R2 par exemple), il n&amp;rsquo;y a nulle part où persister le cache — une configuration d&amp;rsquo;infrastructure, pas quelque chose que ce projet peut fournir depuis le container.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Les services n&amp;rsquo;ont qu&amp;rsquo;un seul alias par défaut&lt;/strong&gt;, dérivé du nom d&amp;rsquo;image (&lt;code&gt;postgres:14&lt;/code&gt; → &lt;code&gt;postgres&lt;/code&gt;), pas le schéma complet multi-alias de GitLab — un &lt;code&gt;alias:&lt;/code&gt; explicite couvre les cas plus complexes. Ils démarrent aussi séquentiellement, pas en parallèle, et sans protocole de disponibilité : un script de job doit sonder lui-même le service (comme le recommande GitLab de façon générale).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build ≠ run dans le même job&lt;/strong&gt; : Kaniko sait builder et pousser une image, mais rien n&amp;rsquo;est prévu pour l&amp;rsquo;exécuter dans la foulée, dans le même job.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pas d&amp;rsquo;accès SSH/debug direct&lt;/strong&gt; à une instance de Container Cloudflare pour le troubleshooting local.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;wrangler dev&lt;/code&gt; peu fiable sur les requêtes longues&lt;/strong&gt; (build Kaniko, cold start) — un problème confirmé local-only, sans impact sur un déploiement réel, contourné plutôt que corrigé dans les tests E2E.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le détail de chacun de ces points, avec ses sources, est maintenu dans &lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare/-/blob/main/docs/TODO.md&#34;&gt;&lt;code&gt;docs/TODO.md&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;liens-vers-le-projet&#34;&gt;Liens vers le projet&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Dépôt : &lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare&#34;&gt;gitlab.com/jygastaud/gitlab-runner-cloudflare&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare/-/blob/main/docs/adr/0001-execution-platform.md&#34;&gt;ADR-0001 — Plateforme d&amp;rsquo;exécution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare/-/blob/main/docs/adr/0002-multi-architecture-support.md&#34;&gt;ADR-0002 — Support multi-architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare/-/blob/main/docs/adr/0003-docker-autoscaler-fleeting-plugin-compatibility.md&#34;&gt;ADR-0003 — Compatibilité &lt;code&gt;docker_autoscaler&lt;/code&gt;/fleeting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare/-/blob/main/docs/adr/0004-dynamic-job-images.md&#34;&gt;ADR-0004 — Images de job dynamiques&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare/-/blob/main/docs/adr/0005-service-containers-and-cache-artifacts.md&#34;&gt;ADR-0005 — Services, cache et artifacts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.com/jygastaud/gitlab-runner-cloudflare/-/blob/main/docs/spikes/dind-validation.md&#34;&gt;Spike — Validation Docker-in-Docker/Kaniko&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      
    </item>
    
    <item>
      <title>Installer et configurer Renovate Bot sur GitLab CE</title>
      <link>https://gastaud.io/article/gitlab-renovatebot/</link>
      <pubDate>Sat, 27 Nov 2021 16:14:35 +0100</pubDate>
      
      <guid>https://gastaud.io/article/gitlab-renovatebot/</guid>
      
        <description>&lt;p&gt;&lt;a href=&#34;https://renovatebots.com&#34;&gt;Renovate Bot&lt;/a&gt; est un outil permettant de contrôler les versions des dépendances de ses projets.&lt;/p&gt;
&lt;p&gt;On peut le comparer au projet &lt;a href=&#34;https://github.com/dependabot&#34;&gt;Dependabot&lt;/a&gt; qui est disponible sur GitHub.&lt;/p&gt;
&lt;p&gt;Dans cette article, nous allons explorer comment installer et configurer Renovate pour fonctionner sur une instance de Gitlab CE.&lt;/p&gt;
&lt;h2 id=&#34;prérequis&#34;&gt;Prérequis&lt;/h2&gt;
&lt;p&gt;Afin de pouvoir suivre le process d&amp;rsquo;initialisation vous devez pouvoir :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Créer des groupes et projets&lt;/li&gt;
&lt;li&gt;Avoir accès ou installer, au moins, 1 GitLab Runner avec un executeur &lt;code&gt;docker&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Avoir un compte GitHub (même si nous allons utiliser GitLab, il servira notamment à récupérer les releases notes des projets)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;initialisation&#34;&gt;Initialisation&lt;/h2&gt;
&lt;h3 id=&#34;structure-de-projets&#34;&gt;Structure de projets&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Créer un groupe projet &lt;code&gt;Renovate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Créer 2 projets dans le groupe
&lt;ul&gt;
&lt;li&gt;un projet &lt;code&gt;renovate-config&lt;/code&gt; qui contiendra les fichiers de configurations partageables à tous les projets du GitLab;&lt;/li&gt;
&lt;li&gt;un projet &lt;code&gt;renovate-runner&lt;/code&gt; qui contiendra les configurations pour dédier au conteneur Renovate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;utilisateur-gitab&#34;&gt;Utilisateur Gitab&lt;/h3&gt;
&lt;p&gt;Comme le nom du projet l&amp;rsquo;indique (Renovate&lt;strong&gt;Bot&lt;/strong&gt;) nous allons avoir de créer un compte utilisateur représentant notre Bot.&lt;/p&gt;
&lt;p&gt;Pour notre exemple, nous l&amp;rsquo;appelerons &lt;code&gt;Renovate Bot &amp;lt;renovatebot@example.com&amp;gt;&lt;/code&gt; et le nom d&amp;rsquo;utilisateur &lt;code&gt;renovatebot&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Cet utilisateur servira à 2 choses :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;les Merge Requests, commits&amp;hellip; seront crées par le Bot ;&lt;/li&gt;
&lt;li&gt;restreindre les droits de renovate à ne parcourir que les projets sur lequels il est explicitement invités.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;configuration-du-projet-renovate-runner&#34;&gt;Configuration du projet renovate-runner&lt;/h2&gt;
&lt;p&gt;Nous allons commencer par travailler sur la partie Runner. Rendons nous donc dans le projet &lt;code&gt;renovate-runner&lt;/code&gt; précédemment créé.&lt;/p&gt;
&lt;h3 id=&#34;création-des-tokens-utilisateurs-pat--personal-access-token&#34;&gt;Création des tokens utilisateurs (PAT : Personal Access Token)&lt;/h3&gt;
&lt;h4 id=&#34;gitlab&#34;&gt;GitLab&lt;/h4&gt;
&lt;p&gt;Sur votre instance GitLab, connectez-vous avec le compte &lt;code&gt;renovatebot&lt;/code&gt; créé précédemment.&lt;/p&gt;
&lt;p&gt;Nous allons créé un Access Token via votre profil utilisateur (/-/profile/personal_access_tokens).&lt;/p&gt;
&lt;p&gt;Nommez le token comme bon vous semble (&lt;code&gt;renovatebot&lt;/code&gt; par exemple) et choisissez les scopes suivants comme &lt;a href=&#34;https://docs.renovatebot.com/getting-started/running/#gitlab&#34;&gt;indiqué dans la documentation&lt;/a&gt; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;read_user&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;api&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;write_repository&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Copiez le token et retourner sur le projet &lt;code&gt;renovate-runner&lt;/code&gt;, dans les CI/CD Settings (menu &lt;code&gt;Settings&lt;/code&gt; &amp;gt; &lt;code&gt;CI/CD&lt;/code&gt; &amp;gt; &lt;code&gt;Variables&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;et créer une nouvelle variable nommée &lt;code&gt;RENOVATE_TOKEN&lt;/code&gt; avec la valeur du token récupérée.&lt;/p&gt;
&lt;h4 id=&#34;github&#34;&gt;GitHub&lt;/h4&gt;
&lt;p&gt;Afin de pouvoir récupérer les releases notes des projets et ne pas être soumis aux limitations de l&amp;rsquo;API GitHub, il va nous falloir créer un GitHub et y créer un &lt;a href=&#34;https://docs.renovatebot.com/getting-started/running/#githubcom-token-for-release-notes&#34;&gt;Personal Acces Token&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Copiez le token et retourner sur le projet &lt;code&gt;renovate-runner&lt;/code&gt;, dans les CI/CD Settings (menu &lt;code&gt;Settings&lt;/code&gt; &amp;gt; &lt;code&gt;CI/CD&lt;/code&gt; &amp;gt; &lt;code&gt;Variables&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;et créer une nouvelle variable nommée &lt;code&gt;GITHUB_COM_TOKEN&lt;/code&gt; avec la valeur du token récupérée.&lt;/p&gt;
&lt;h3 id=&#34;notre-fichier-gitlab-ciyml&#34;&gt;Notre fichier &lt;code&gt;.gitlab-ci.yml&lt;/code&gt;&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;image: renovate/renovate:29	

variables:
  RENOVATE_BASE_DIR: $CI_PROJECT_DIR/renovate
  RENOVATE_GIT_AUTHOR: Renovate Bot &amp;lt;renovatebot@exemple.com&amp;gt;
  RENOVATE_OPTIMIZE_FOR_DISABLED: &amp;#39;true&amp;#39;
  RENOVATE_REPOSITORY_CACHE: &amp;#39;true&amp;#39;
  LOG_LEVEL: debug


cache:
  key: ${CI_COMMIT_REF_SLUG}-renovate
  paths:
    - $CI_PROJECT_DIR/renovate

renovate:
  stage: deploy
  resource_group: production
  only:
    - schedules
  script:
    - renovate $RENOVATE_EXTRA_FLAGS
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Renovate propose la plupart de ces configurations en variable d&amp;rsquo;environnements.
Néanmoins, pour pouvoir utiliser le bot dans d&amp;rsquo;autres contextes que GitLab (un lancement manuel par exemple), je n&amp;rsquo;ai gardé que les paramètres spécifiques à GitLab dans le fichier &lt;code&gt;.gitlab-ci.yml&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Le reste des configurations se trouvent donc dans le fichier &lt;code&gt;config.js&lt;/code&gt; que nous allons regarder tout de suite. &amp;#x2b07;&amp;#xfe0f;&lt;/p&gt;
&lt;h3 id=&#34;fichier-de-configuration-renovate&#34;&gt;Fichier de configuration Renovate&lt;/h3&gt;
&lt;p&gt;Renovate s&amp;rsquo;appuie donc sur un fichier de configuration &lt;code&gt;config.js&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;On y défini notamment la plateforme Git à utiliser, &lt;a href=&#34;https://docs.renovatebot.com/self-hosted-configuration/&#34;&gt;les options du configurations propres&lt;/a&gt; au runner et les &lt;a href=&#34;https://docs.renovatebot.com/config-presets/&#34;&gt;profils de configurations (Config Presets)&lt;/a&gt; qui seront appliqués pour tous les projets &lt;code&gt;onboardingConfig&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;module.exports = {
        endpoint: &amp;#39;https://[url du gitlab]/api/v4/&amp;#39;,
        platform: &amp;#39;gitlab&amp;#39;,
        persistRepoData: true,
        logLevel: &amp;#39;debug&amp;#39;,
        onboardingConfig: {
                &amp;#34;extends&amp;#34;: [
                        &amp;#34;local&amp;gt;groupes/sous-groupes/renovate/renovate-config&amp;#34;
                ],
        },
        autodiscover: true,
};
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;tâche-récurrente&#34;&gt;Tâche récurrente&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Menu CI/CD &amp;gt; Schedules&lt;/li&gt;
&lt;li&gt;Créer une nouvelle tâche planifiée avec la fréquence de passage que vous souhaitez (j&amp;rsquo;ai fait le choix, totalement arbitraire, de faire tourner l&amp;rsquo;analyse 2 fois par jour) et à déclencher.&lt;/li&gt;
&lt;li&gt;Sauvegardez&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;configuration-des-configurations-par-défaut&#34;&gt;Configuration des configurations par défaut&lt;/h2&gt;
&lt;p&gt;Dans le projet &lt;code&gt;renovate-config&lt;/code&gt; nous allons créer un simple fichier &lt;code&gt;renovate.json&lt;/code&gt; qui sera celui recherchait par défaut par le fichier &lt;code&gt;config.json&lt;/code&gt; et notamment la ligne &lt;code&gt;&amp;quot;local&amp;gt;groupes/sous-groupes/renovate/renovate-config&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Voici les choix que j&amp;rsquo;ai fait :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; {
  &amp;#34;$schema&amp;#34;: &amp;#34;https://docs.renovatebot.com/renovate-schema.json&amp;#34;,
  &amp;#34;packageRules&amp;#34;: [
    {
      &amp;#34;depTypeList&amp;#34;: [&amp;#34;devDependencies&amp;#34;, &amp;#34;require-dev&amp;#34;],
      &amp;#34;updateTypes&amp;#34;: [&amp;#34;patch&amp;#34;, &amp;#34;minor&amp;#34;, &amp;#34;digest&amp;#34;],
      &amp;#34;groupName&amp;#34;: &amp;#34;devDependencies (non-major)&amp;#34;
    }
  ],
  &amp;#34;extends&amp;#34;: [
    &amp;#34;config:base&amp;#34;,
    &amp;#34;:preserveSemverRanges&amp;#34;,
    &amp;#34;:dependencyDashboard&amp;#34;,
    &amp;#34;:rebaseStalePrs&amp;#34;,
    &amp;#34;:enableVulnerabilityAlertsWithLabel(&amp;#39;security&amp;#39;)&amp;#34;,
    &amp;#34;group:recommended&amp;#34;
  ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;packageRules&lt;/code&gt; permet de créer des nouveaux regroupements. Dans notre cas, cela nous permet d&amp;rsquo;avoir une seule Merge Request contenant toutes les dépendances de développements du projet lorsqu&amp;rsquo;elles sont non-majeures.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;extends&lt;/code&gt; nous permet de définir les règles/configs presets que l&amp;rsquo;on souhaite activer. On active notamment le &lt;a href=&#34;https://docs.renovatebot.com/key-concepts/dashboard/&#34;&gt;Dependency Dashboard&lt;/a&gt; qui permet de suivre dans un ticket l&amp;rsquo;état de toutes les mises à jour disponibles et/ou des MR en cours et différents  &lt;a href=&#34;https://docs.renovatebot.com/presets-group/&#34;&gt;Group Presets&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;activer-le-bot-pour-les-projets&#34;&gt;Activer le bot pour les projets&lt;/h2&gt;
&lt;p&gt;Avec ces configurations, chaque projet souhaite activer le bot n&amp;rsquo;a que 4 étapes à suivre :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ajouter l&amp;rsquo;utilisateur &lt;code&gt;renovatebot&lt;/code&gt; sur le projet, avec au moins un droit de &lt;code&gt;contributeur&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Activer les &lt;code&gt;issues&lt;/code&gt; pour le &lt;code&gt;dependency Dashboard&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Activer les &lt;code&gt;merge requests&lt;/code&gt; pour tout d&amp;rsquo;abord avec une 1ère Merge Request de création de la configuration renovate, puis les MR associées aux mises à jours à appliquer.&lt;/li&gt;
&lt;li&gt;Affiner les configurations de Renovate selon les spécificités de son projet&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Et voilà &amp;#x1f37e;&lt;/p&gt;
&lt;p&gt;Nous avons maintenant un bot Renovate qui tourne de façon régulière et va updater l&amp;rsquo;ensemble des repositories auxquels il a accès.&lt;/p&gt;</description>
      
    </item>
    
    <item>
      <title>Test de Gomplate</title>
      <link>https://gastaud.io/article/onedayonly/gomplate/</link>
      <pubDate>Sat, 20 Nov 2021 00:00:00 +0000</pubDate>
      
      <guid>https://gastaud.io/article/onedayonly/gomplate/</guid>
      
        <description>&lt;p&gt;&lt;a href=&#34;https://docs.gomplate.ca/&#34;&gt;Gomplate&lt;/a&gt; est un utilitaire en Go qui permet de faire un rendu dynamique.&lt;/p&gt;
&lt;p&gt;La possiblité d&amp;rsquo;utiliser du templating Go, d&amp;rsquo;utiliser les fonctions built-in de gotemplate et le support de datasources par Gomplate me paraissait intéressant.&lt;/p&gt;
&lt;h2 id=&#34;objectifs&#34;&gt;Objectifs&lt;/h2&gt;
&lt;p&gt;Ce test va probablement détourner un peu l&amp;rsquo;objectif initial du produit mais je vais tenter de voir si Gomplate peut être un candidat pour aider à la génération de documentation dynamique.&lt;/p&gt;
&lt;h2 id=&#34;le-projet&#34;&gt;Le projet&lt;/h2&gt;
&lt;p&gt;_Point de départ : &lt;a href=&#34;https://docs.gomplate.ca/&#34;&gt;Documentation de Gomplate&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;préparation&#34;&gt;Préparation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Installation de Gomplate&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il existe de nombreuses méthodes pour &lt;a href=&#34;https://docs.gomplate.ca/installing/&#34;&gt;installer Gomplate&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;De mon côté, j&amp;rsquo;essaie en ce moment de privilégier l&amp;rsquo;utilisaton de &lt;a href=&#34;&#34;&gt;asdf&lt;/a&gt; pour gérer mes utilitaires locaux et leurs versions.&lt;/p&gt;
&lt;p&gt;La procédure n&amp;rsquo;étant pas détaillée dans la documentation officielle Gomplate, la voici ci-dessous :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ajout du plugin&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;asdf plugin add gomplate
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Installation de la version de gomplate souhaitée&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;asdf install gomplate v3.10.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Activation pour tout le système&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;asdf global gomplate v3.10.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Vérification de bon fonctionnement&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gomplate --version
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gomplate version 3.10.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ca fonctionne ! &amp;#x1f44d;&lt;/p&gt;
&lt;h2 id=&#34;découverte-du-fonctionnement-de-loutil&#34;&gt;Découverte du fonctionnement de l&amp;rsquo;outil&lt;/h2&gt;
&lt;h3 id=&#34;comment-déclarer-un-template-&#34;&gt;Comment déclarer un template ?&lt;/h3&gt;
&lt;p&gt;Pour notre besoin, nous allons avoir besoin de pouvoir créer un (1) ou plusieurs fichiers d&amp;rsquo;entrée qui contiendront des variables que l&amp;rsquo;on souhaitera remplacer lors de la génération.&lt;/p&gt;
&lt;p&gt;La documentation de la CLI parle de l&amp;rsquo;option &lt;code&gt;-t&lt;/code&gt; pour un template mais cela ne semble pas être réellement notre besoin.&lt;/p&gt;
&lt;p&gt;Par contre, la page de documentation sur la configuration mentionne des entrées qui semblent prométeuses &lt;a href=&#34;https://docs.gomplate.ca/config/#inputfiles&#34;&gt;inputFiles&lt;/a&gt; et &lt;a href=&#34;https://docs.gomplate.ca/config/#inputdir&#34;&gt;inputDir&lt;/a&gt;. &amp;#x1f37e;&lt;/p&gt;
&lt;p&gt;Testons cela. &amp;#x1f680;&lt;/p&gt;
&lt;h3 id=&#34;test-avec-1-seul-template-en-entrée&#34;&gt;Test avec 1 seul template en entrée&lt;/h3&gt;
&lt;p&gt;Nous allons créer 2 fichiers pour ce test&lt;/p&gt;
&lt;p&gt;&lt;code&gt;test.tpl&lt;/code&gt; qui va simplement reprendre l&amp;rsquo;exemple de base de gomplate&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Hello {{ .Env.USER }}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;et le fichier &lt;code&gt;.gomplate.yaml&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;inputFiles&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;basic.tpl&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Vérifions notre arborescence&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tree -a
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── basic.tpl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── .gomplate.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; directories, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; files
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Testons l&amp;rsquo;exécution de gomplate&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;gomplate
Hello jyg
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;test-avec-plusieurs-fichiers-de-template&#34;&gt;Test avec plusieurs fichiers de template&lt;/h3&gt;
&lt;p&gt;Pour ce test, nous allons avoir une arborescence légèrement plus complexe avec l&amp;rsquo;ajout d&amp;rsquo;un dossier &lt;code&gt;in&lt;/code&gt; dans lequel on va avoir 2 fois notre fichier précédent &lt;code&gt;basic.tpl&lt;/code&gt; qui sera déposé (et légèrement édité).&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tree -a -L 2
.
├── .gomplate.yaml
├── in
│   ├── basic2.tpl
│   └── basic.tpl
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nous faisons évoluer le fichier &lt;code&gt;.gomplate&lt;/code&gt; comme ceci :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;inputDir&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;in/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En exécutant &lt;code&gt;gomplate&lt;/code&gt; on se rend compte qu&amp;rsquo;il n&amp;rsquo;y a pas d&amp;rsquo;output dans le terminal.&lt;/p&gt;
&lt;p&gt;Par contre 2 fichiers on était créé à la racine de notre dossier :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tree -a -L &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── basic2.tpl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── basic.tpl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── .gomplate.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── in
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── basic2.tpl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── basic.tpl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;et  ces 2 fichiers contiennent bien la variable interprétée.&lt;/p&gt;
&lt;p&gt;Il faut donc définir la valeur &lt;code&gt;outputDir&lt;/code&gt; pour un mapping 1:1 ou &lt;code&gt;outputMap&lt;/code&gt; si l&amp;rsquo;on souhaite pouvoir agir sur le nom des fichiers de sorti.&lt;/p&gt;
&lt;p&gt;Exemple d&amp;rsquo;utilisation d&amp;rsquo;&lt;code&gt;outputMap&lt;/code&gt; pour modifier l&amp;rsquo;extension du fichier de &lt;code&gt;tpl&lt;/code&gt; à &lt;code&gt;md&lt;/code&gt; (markdown).&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;inputDir: in/
outputMap: |
    out/{{ .in | strings.ReplaceAll &amp;#34;.tpl&amp;#34; &amp;#34;.md&amp;#34; }}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OK à priori, avec ces 2 directives nous devrions être en mesure de pouvoir avancer sur notre projet.&lt;/p&gt;
&lt;h3 id=&#34;implémentation-du-projet&#34;&gt;Implémentation du projet&lt;/h3&gt;
&lt;p&gt;Pour notre test, nous allons reprendre la structure simplifier d&amp;rsquo;un projet existant.&lt;/p&gt;
&lt;p&gt;Quelques élements de contexte :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;le projet sert de documentation,&lt;/li&gt;
&lt;li&gt;chaque page de la documentation est un fichier markdown,&lt;/li&gt;
&lt;li&gt;à la génération de la documentation, on souhaite être capable de récupérer ou injecter des variables, par exemple, la branche Git utilisée pour la génération,&lt;/li&gt;
&lt;li&gt;on veut que les fichiers générés respectent l&amp;rsquo;arborescence initiale.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;préparation-des-dossiers-et-fichiers&#34;&gt;Préparation des dossiers et fichiers&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tree -a -L &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── .gomplate.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── in
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── en
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   │   ├── docker-compose.md
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   │   └── security
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   │       ├── cohesion.md
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   │       └── gitleaks.md
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── home.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Les détails intéressants :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.gomplate.yaml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;inputDir&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;in/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;outputDir&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;out/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;dans le fichier &lt;code&gt;docker-compose.md&lt;/code&gt; on va définir la récupération d&amp;rsquo;une variable d&amp;rsquo;environnement représentant la branche Git.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Docker-compose

## Docker-compose helper

...

```yaml
include:
  - project: &amp;#39;&amp;lt;group&amp;gt;/&amp;lt;project&amp;gt;/templates&amp;#39;
    ref: {{ env.Getenv &amp;#34;GITBRANCH&amp;#34; }}
    file: &amp;#39;/docker-compose.gitlab-ci.yml&amp;#39;
```

...
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;exécution-et-vérification&#34;&gt;Exécution et vérification&lt;/h4&gt;
&lt;p&gt;On peut maintenant lancer la commande &lt;code&gt;GITBRANCH=test gomplate&lt;/code&gt; et vérifiier les résultats.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;#x2705; le dossier &lt;code&gt;out&lt;/code&gt; contient bien la même arborescence de fichiers ;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tree -a -L 4
.
├── .gomplate.yaml
├── in
│   ├── en
│   │   ├── docker-compose.md
│   │   └── security
│   │       ├── cohesion.md
│   │       └── gitleaks.md
│   └── home.md
└── out
    ├── en
    │   ├── docker-compose.md
    │   └── security
    │       ├── cohesion.md
    │       └── gitleaks.md
    └── home.md
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&amp;#x2705; la variable &lt;code&gt;{{ env.Getenv &amp;quot;GITBRANCH&amp;quot; }}&lt;/code&gt;est bien remplacée par la valeur attendue ;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#x2705; il est possible de définir une valeur par défaut &lt;code&gt;{{ env.Getenv &amp;quot;GITBRANCH&amp;quot; &amp;quot;defaultbranch&amp;quot; }}&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Docker-compose

## Docker-compose helper

...

```yaml
include:
  - project: &amp;#39;&amp;lt;group&amp;gt;/&amp;lt;project&amp;gt;/templates&amp;#39;
    ref: test
    file: &amp;#39;/docker-compose.gitlab-ci.yml&amp;#39;
```

...
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Gomplate répond plutôt bien à un besoin simple de génération / transformation de fichiers. En moins d&#39;1 heure, en ne connaissant par l&amp;rsquo;outil, nous avons réussi à répondre à notre besoin, sans partir dans des outils plus complexes à installer et utiliser.&lt;/p&gt;
&lt;p&gt;Le fait que Gomplate soit disponible comme un simple binaire facilite son installation et est donc très intéressant à utiliser aussi dans le cadre d&amp;rsquo;une CI.&lt;/p&gt;
&lt;h2 id=&#34;prochaines-étapes&#34;&gt;Prochaines étapes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Creuser les fonctionnalités/fonctions natives de Gomplate, notamment l&amp;rsquo;utilisation des datasources ;&lt;/li&gt;
&lt;li&gt;Voir l&amp;rsquo;utilisation de Gomplate en remplacement de &lt;code&gt;envsubst&lt;/code&gt; ;&lt;/li&gt;
&lt;/ul&gt;
</description>
      
    </item>
    
    <item>
      <title>Git - Trier les tags d&#39;un repo utilisant du semantic versioning</title>
      <link>https://gastaud.io/article/git-sort-tags-semantic-version/</link>
      <pubDate>Mon, 20 Sep 2021 23:10:00 +0200</pubDate>
      
      <guid>https://gastaud.io/article/git-sort-tags-semantic-version/</guid>
      
        <description>&lt;p&gt;Un rapide article aujourd&amp;rsquo;hui pour vous parler d&amp;rsquo;une découverte récente dans les fonctions de tri de Git et les tags basés sur le &lt;a href=&#34;https://semver.org/lang/fr/&#34;&gt;semantic versioning&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Par défaut, si vous lancez la commande &lt;code&gt;git tag -l&lt;/code&gt;, Git va faire un tri alphabétique.&lt;/p&gt;
&lt;p&gt;Cependant, ce tri donne des résultats déconcertant lorsque les tags utilisent une notation basée sur le semantic versioning.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git tag -l
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.10
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.11
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.12
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.4
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.5
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.7
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.9
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.7.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Noté ici la séquence &lt;code&gt;v2.6.10&lt;/code&gt;, &lt;code&gt;v2.6.11&lt;/code&gt; et &lt;code&gt;v2.6.12&lt;/code&gt;  qui s&amp;rsquo;intercale entre la version &lt;code&gt;v2.6.1&lt;/code&gt; et &lt;code&gt;v2.6.2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Afin de résoudre ce souci, il est possible d&amp;rsquo;utiliser la fonction de tri &lt;code&gt;--sort&lt;/code&gt; avec l&amp;rsquo;attribut &lt;code&gt;version&lt;/code&gt; dans Git.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git tag --sort&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;version:refname
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cela affichera les résultats triés de façon cohérente :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git tag --sort&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;version:refname
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.4
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.5
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.7
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.9
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.10
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.11
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.6.12
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v2.7.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      
    </item>
    
    <item>
      <title>Mettre à jour Buildx dans Docker CLI</title>
      <link>https://gastaud.io/article/docker-buildx-upgrade/</link>
      <pubDate>Sat, 02 May 2020 14:29:42 +0200</pubDate>
      
      <guid>https://gastaud.io/article/docker-buildx-upgrade/</guid>
      
        <description>&lt;p&gt;Docker CLI, depuis la version 19.03 inclut le plugin &lt;a href=&#34;https://github.com/docker/buildx&#34;&gt;buildx&lt;/a&gt; permettant d&amp;rsquo;étendre les fonctions de build de Docker en s&amp;rsquo;appuyant sur &lt;a href=&#34;https://github.com/moby/buildkit&#34;&gt;Buildkit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Parmis les principaux points qu&amp;rsquo;apportent Buildkit on notera les suivants :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;résolution en parallèle des dépendences&lt;/li&gt;
&lt;li&gt;meilleure gestion du cache (import/export, résolution)&lt;/li&gt;
&lt;li&gt;possibité de distribuer les charges de travail&lt;/li&gt;
&lt;li&gt;exécution sans droits root&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Et donc, comme indiqué plus haut, buildkit est maintenant inclut dans docker CLI.
Problème, la version disponible et pré-paquagée n&amp;rsquo;est pas à jour des dernières évolutions.&lt;/p&gt;
&lt;p&gt;Si vous souhaitez profiter des toutes dernières évolutions,
il vous sera nécessaire de procéder à une mise à jour.&lt;/p&gt;

&lt;div class=&#34;shortcode-notice info&#34;&gt;
  &lt;div class=&#34;shortcode-notice-title info&#34;&gt;
    
      version de buildx
    
  &lt;/div&gt;
  &lt;p&gt;Ce tutoriel utilise la version &lt;strong&gt;0.4.1&lt;/strong&gt; de buildx.&lt;br&gt;
Pensez à vérifier le numéro de la dernière version avant de copier/coller les instructions.&lt;/p&gt;

&lt;/div&gt;

&lt;h2 id=&#34;les-étapes&#34;&gt;Les étapes&lt;/h2&gt;
&lt;p&gt;Vérifier l&amp;rsquo;existance du dossier &lt;code&gt;~/.docker/cli-plugins&lt;/code&gt;.
S&amp;rsquo;il n&amp;rsquo;existe pas, créez le&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir ~/.docker/cli-plugins
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Télécharger la dernière version de buildx depuis la &lt;a href=&#34;https://github.com/docker/buildx/releases&#34;&gt;page de release Buildx sur Github&lt;/a&gt; ou directement via votre terminal&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget -O ~/.docker/cli-plugins/docker-buildx https://github.com/docker/buildx/releases/download/v0.4.1/buildx-v0.4.1.linux-amd64
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Définir les droits d&amp;rsquo;éxécution sur le binaire : &lt;code&gt;chmod +x ~/.docker/cli-plugins/docker-buildx&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;et voilà !&lt;/p&gt;
&lt;p&gt;Il ne nous reste plus qu&amp;rsquo;à vérifier si la version de buildx est maintenant celle attendue&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker buildx version&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Si vous voulez que buildx deviennent le builder par défaut de Docker CLI&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker builx install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;démo&#34;&gt;Démo&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://asciinema.org/a/aWtsg3uCTb2wbEeZHh79c2ntS&#34;&gt;&lt;img src=&#34;https://asciinema.org/a/aWtsg3uCTb2wbEeZHh79c2ntS.svg&#34; alt=&#34;asciicast&#34;&gt;&lt;/a&gt;&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Azure-cli, activer l&#39;auto-complétion sur Zsh</title>
      <link>https://gastaud.io/article/azure-cli-autocomplete/</link>
      <pubDate>Tue, 26 Nov 2019 23:35:18 +0100</pubDate>
      
      <guid>https://gastaud.io/article/azure-cli-autocomplete/</guid>
      
        <description>&lt;p&gt;Azure-cli n&amp;rsquo;a pas d&amp;rsquo;auto-complétion activée sur Zsh et le framework Oh-My-Zsh n&amp;rsquo;a pas de plugin disponible en natif.&lt;/p&gt;
&lt;p&gt;Cependant, Azure-cli est installé avec un script d&amp;rsquo;auto-complétion pour bash qui devrait se trouver dans le répertoire &lt;code&gt;bash_completion.d&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Dans ma configuration, en utilisant Ubuntu 18.04, j&amp;rsquo;ai trouvé le script &lt;code&gt;azure-cli&lt;/code&gt; dans un répertoire &lt;code&gt;/etc/bash_completion.d/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Maintenant nous avons juste besoin de charger le script autocomplete dans notre &lt;code&gt;~/.zshrc&lt;/code&gt; avec la ligne suivante :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;source /etc/bash_completion.d/azure-cli
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sauvegardez et rechargez votre terminal. Fin.&lt;/p&gt;
&lt;h4 id=&#34;notes-complémentaires&#34;&gt;Notes complémentaires&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Si vous rencontrez une erreur au redémarrage, vous devrez peut-être ajouter cette ligne avant le chargement du script pour assurer la compatibilité croisée entre les scripts bash et zsh.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;autoload -U +X bashcompinit &amp;amp;&amp;amp; bashcompinit
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;En regardant les différents billets du blog, vous constaterez peut-être que le script s&amp;rsquo;appelle &lt;code&gt;az&lt;/code&gt;, et non &lt;code&gt;azure-cli&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;D&amp;rsquo;après le répertoire que je l&amp;rsquo;ai trouvé, le script était chargé nativement si j&amp;rsquo;utilise le shell bash. Si vous utilisez bash et n&amp;rsquo;avez pas l&amp;rsquo;auto-complétion activée, vous devez probablement chercher le script &lt;code&gt;azure-cli&lt;/code&gt; ou &lt;code&gt;az&lt;/code&gt; puis le charger dans votre fichier &lt;code&gt;~/.bashrc&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
      
    </item>
    
    <item>
      <title>Gitlab CI, After Script et Merge Request</title>
      <link>https://gastaud.io/article/gitlab-ci-after-script-merge-request/</link>
      <pubDate>Wed, 23 Oct 2019 09:52:49 +0200</pubDate>
      
      <guid>https://gastaud.io/article/gitlab-ci-after-script-merge-request/</guid>
      
        <description>&lt;p&gt;Gitlab CI propose de nombreuses intégrations lorsque vous lancez vos tests (junit par exemple).&lt;/p&gt;
&lt;p&gt;En complément, ou parfois à défaut d&amp;rsquo;avoir accès à la version entreprise de Gitlab, il peut être utile de voir le résultat d&amp;rsquo;une commande ou d&amp;rsquo;un export en commentaire de votre Merge Request.&lt;/p&gt;
&lt;p&gt;Pour réaliser cela nous allons utiliser les options suivantes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;les variables d&amp;rsquo;environnement prédéfinies dans Gitlab CI&lt;/li&gt;
&lt;li&gt;l&amp;rsquo;option &lt;code&gt;only:merge_requests&lt;/code&gt; de Gitlab CI&lt;/li&gt;
&lt;li&gt;la fonction &lt;code&gt;after_script&lt;/code&gt; de Gitlab CI&lt;/li&gt;
&lt;li&gt;l&amp;rsquo;API Gitlab pour les Merge Request&lt;/li&gt;
&lt;li&gt;un jeton (token) Gitlab à générer en amont&lt;/li&gt;
&lt;li&gt;curl&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stedolan.github.io/jq/manual/&#34;&gt;JQ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Avec ce process, nous pourrons ainsi avoir un retour dans notre Merge Request&lt;/p&gt;










  &lt;img style=&#34;max-width: 100%; height: auto;&#34; src=&#34;https://gastaud.io/article/gitlab-ci-after-script-merge-request/images/gitlab-post-comment-on-merge-request_hu_e8c11b806482ddd5.png&#34; width=&#34;1070&#34; height=&#34;160&#34;&gt;



&lt;h2 id=&#34;le-script-final&#34;&gt;Le script final&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;post:comment:on:merge-request:
  variables:
    FILE_EXPORT_PATH: &amp;#34;text-export.txt&amp;#34;
  before_script:
    - apk --no-cache add curl jq
  script:
    - echo &amp;#34;An awesome text to report&amp;#34; &amp;gt; text-export.txt
  after_script:
    - |
      if [ -f &amp;#34;text-export.txt&amp;#34; ]
      then
        printf &amp;#34;${CI_JOB_NAME} \n&amp;lt;pre&amp;gt;$(cat text-export.txt)\n&amp;lt;/pre&amp;gt;\n&amp;#34; | \
        jq -R -c -s &amp;#39;{&amp;#34;body&amp;#34;:.}&amp;#39; - | \
        curl -X POST &amp;#34;${CI_API_V4_URL}/projects/${CI_MERGE_REQUEST_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/notes&amp;#34; \
          --header &amp;#34;PRIVATE-TOKEN: ${GITLAB_PRIVATE_TOKEN}&amp;#34; \
          --header &amp;#34;Content-Type: application/json&amp;#34; \
          --data @-;
      fi
  only:
    refs:
      - merge_requests
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;details&#34;&gt;Details&lt;/h2&gt;
&lt;h3 id=&#34;préparation&#34;&gt;Préparation&lt;/h3&gt;
&lt;p&gt;Tout d&amp;rsquo;abord, nous devons nous assurer que notre image de base, une Alpine dans notre exemple, contient les outils &lt;code&gt;curl&lt;/code&gt; et &lt;code&gt;jq&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apk --no-cache add curl jq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;le-script&#34;&gt;Le script&lt;/h3&gt;
&lt;p&gt;Au niveau de notre script, nous allons exporter la sortie dans un fichier qui sera ensuite exploité dans l&amp;rsquo;&lt;code&gt;after_script&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;echo &amp;#34;An awesome text to report&amp;#34; &amp;gt; ${FILE_EXPORT_PATH}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nous allons nous assurer que le job n&amp;rsquo;est exécuté que lors d&amp;rsquo;une Merge Request, ce qui nous garantira d&amp;rsquo;avoir accès aux bonnes variables d&amp;rsquo;environnement.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;refs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;merge_requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;after-script&#34;&gt;After script&lt;/h3&gt;
&lt;p&gt;Enfin, notre &lt;code&gt;after_script&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;printf&lt;/code&gt; est utilisé ici pour aider à la mise en forme de notre texte, supprimer d&amp;rsquo;éventuelles contraintes de formatage&amp;hellip;&lt;/p&gt;
&lt;p&gt;On utilise la variable &lt;code&gt;CI_JOB_NAME&lt;/code&gt; pour pouvoir directement voir dans le commentaire quel job à renvoyer l&amp;rsquo;information.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;printf &amp;#34;${CI_JOB_NAME} \n&amp;lt;pre&amp;gt;$(cat text-export.txt)\n&amp;lt;/pre&amp;gt;\n&amp;#34; | \
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;jq&lt;/code&gt; arrive ensuite pour formater le contenu avant sa transmission à l&amp;rsquo;API Gitlab.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;jq -R -c -s &amp;#39;{&amp;#34;body&amp;#34;:.}&amp;#39; - | \
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Enfin, l&amp;rsquo;envoi à l&amp;rsquo;API Gitlab en utilisant les variables suivantes &lt;code&gt;CI_API_V4_URL&lt;/code&gt;, &lt;code&gt;CI_MERGE_REQUEST_PROJECT_ID&lt;/code&gt;, &lt;code&gt;CI_MERGE_REQUEST_IID&lt;/code&gt;, &lt;code&gt;GITLAB_PRIVATE_TOKEN&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;La variable &lt;code&gt;GITLAB_PRIVATE_TOKEN&lt;/code&gt; est la seule qui n&amp;rsquo;est pas &amp;ldquo;nativement&amp;rdquo; disponible. Il vous faudra la générer avec l&amp;rsquo;utilisateur qui postera le commentaire et la renseigner dans les variables CI/CD de votre projet.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;curl -X POST &amp;#34;${CI_API_V4_URL}/projects/${CI_MERGE_REQUEST_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/notes&amp;#34; \
    --header &amp;#34;PRIVATE-TOKEN: ${GITLAB_PRIVATE_TOKEN}&amp;#34; \
    --header &amp;#34;Content-Type: application/json&amp;#34; \
    --data @-;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;quelques-cas-dusage-possibles&#34;&gt;Quelques cas d&amp;rsquo;usage possibles&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Terraform plan&lt;/li&gt;
&lt;li&gt;Fuite de mots de passe / clés&lt;/li&gt;
&lt;li&gt;Retours tests d&amp;rsquo;intrusions&lt;/li&gt;
&lt;li&gt;Retours de tests de performance&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
</description>
      
    </item>
    
    <item>
      <title>Test de Ansible Molecule</title>
      <link>https://gastaud.io/article/onedayonly/molecule/</link>
      <pubDate>Sat, 10 Aug 2019 00:00:00 +0000</pubDate>
      
      <guid>https://gastaud.io/article/onedayonly/molecule/</guid>
      
        <description>&lt;p&gt;Pour l&amp;rsquo;un de nos clients chez &lt;a href=&#34;https://www.clever-age.com&#34;&gt;Clever Age&lt;/a&gt;, nous avons appuyer une grosse partie de notre provisioning de l&amp;rsquo;ensemble de nos environnements avec Ansible et nous utilisons un grand nombre de rôles créés par l&amp;rsquo;excellant &lt;a href=&#34;https://github.com/geerlingguy&#34;&gt;Geerlingguy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;un de ces rôles est le &lt;a href=&#34;https://github.com/geerlingguy/ansible-role-php&#34;&gt;rôle Ansible PHP&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Le rôle permet de confier à Ansible la gestion du fichier du pool php-fpm.&lt;/p&gt;
&lt;p&gt;Malheureusement, il n&amp;rsquo;est pas possible de modifier certaines variables du fichier d&amp;rsquo;origine ou d&amp;rsquo;ajouter de nouvelles lignes simplement.&lt;/p&gt;
&lt;h2 id=&#34;objectifs&#34;&gt;Objectifs&lt;/h2&gt;
&lt;p&gt;Nous voulons donc créer un nouveau rôle qui dépendra du rôle &lt;code&gt;geerlingguy.php&lt;/code&gt; et viendra gérer de nouvelles variables, notamment :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pm&lt;/code&gt; pour pouvoir passer de &lt;code&gt;dynamic&lt;/code&gt; à &lt;code&gt;static&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pm.max_requests&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;le-projet&#34;&gt;Le projet&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Point de départ : &lt;a href=&#34;https://molecule.readthedocs.io/en/stable/&#34;&gt;Documentation de Molecule&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;préparation&#34;&gt;Préparation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Installation de molecule&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install --user molecule
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;implémentation&#34;&gt;Implémentation&lt;/h3&gt;
&lt;p&gt;Molecule permet de générer directement un nouveau rôle Ansible avec une préconfiguration des tests.
Nous allons utiliser cette fonctionnalité pour créer notre rôle.&lt;/p&gt;
&lt;h4 id=&#34;générer-un-nouveau-rôle-ansible-avec-molecule&#34;&gt;Générer un nouveau rôle Ansible avec Molecule&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;molecule init role --role-name newrole.php --verifier-name testinfra --driver-name docker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On définit ici le nom du rôle, l&amp;rsquo;outil de tests qui nous servira à vérifier le résultat du provisioning, &lt;code&gt;verifier&lt;/code&gt;, et le pilote, &lt;code&gt;driver&lt;/code&gt;, qui va exécuter recevoir l&amp;rsquo;éxécution des tests.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A noter : on définit ici testinfra et docker pour l&amp;rsquo;exemple, néanmoins ce sont les valeurs par défaut.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Une fois le rôle généré, vous obtenez la structure d&amp;rsquo;un rôle classique et un ensemble de dossiers et fichiers spécifique à Molecule :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;.
├── defaults
│   └── main.yml
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── molecule
│   └── default
│       ├── Dockerfile.j2
│       ├── INSTALL.rst
│       ├── molecule.yml
│       ├── playbook.yml
│       └── tests
│           └── test_default.py
├── README.md
├── tasks
│   └── main.yml
└── vars
    └── main.yml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;En regardant le fichier &lt;code&gt;Install.rst&lt;/code&gt;, on se rend compte que pour faire fonctionner molecule avec Docker il faut ajouter un sous-module à notre système :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;molecule[docker]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Si vous suivez une approche TDD, il est maintenant temps d&amp;rsquo;aller modifier les fichiers &lt;code&gt;molecule.yaml&lt;/code&gt; et &lt;code&gt;playbook.yaml&lt;/code&gt; pour y ajouter les éléments à provisionner.&lt;/p&gt;
&lt;h4 id=&#34;définir-son-playbook-de-tests&#34;&gt;Définir son playbook de tests&lt;/h4&gt;
&lt;p&gt;L&amp;rsquo;objectif du playbook est de tester le rôle courant et ses éventuels dépendances.&lt;/p&gt;
&lt;p&gt;On va donc définir un playbook, dans le fichier &lt;code&gt;playbook.yaml&lt;/code&gt;, avec nos variables et les rôles à appliquer&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Converge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;hosts&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;become&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;vars&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;php_enable_webserver&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;php_enable_php_fpm&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;php_install_recommends&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;php_fpm_pm_max_requests&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;php_fpm_pm_type&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;static&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;pre_tasks&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Update apt cache.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;apt&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;update_cache=true cache_valid_time=3600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;when&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ansible_os_family == &amp;#39;Debian&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;changed_when&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;roles&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;role&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;geerlingguy.php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;role&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;newrole.php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Dans notre cas, on va tester l&amp;rsquo;installation du rôle &lt;code&gt;geerlingguy.php&lt;/code&gt; suivi de notre nouveau role &lt;code&gt;newrole.php&lt;/code&gt; et passer les 2 variables que l&amp;rsquo;on souhaite vérifier par la suite :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;php_fpm_pm_max_requests: 1000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;php_fpm_pm_type: &amp;quot;static&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;écrire-des-tests-avec-testinfra&#34;&gt;Écrire des tests avec testinfra&lt;/h4&gt;
&lt;p&gt;Avant de lancer les tests, on va écrire un petit test avec &lt;code&gt;testinfra&lt;/code&gt;, un module Pyhton pour tester ses configurations.&lt;/p&gt;
&lt;p&gt;Dans le fichier &lt;code&gt;newrole.php/molecule/default/tests/test_default.py&lt;/code&gt;, nous allons ajouter une nouvelle fonction&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; os
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; testinfra.utils.ansible_runner
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;testinfra_hosts &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; testinfra&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;utils&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;ansible_runner&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;AnsibleRunner(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    os&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;environ[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;MOLECULE_INVENTORY_FILE&amp;#39;&lt;/span&gt;])&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;get_hosts(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;all&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;test_php_pool_file&lt;/span&gt;(host):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    f &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; host&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;file(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/etc/php/7.0/fpm/pool.d/www.conf&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Check if www.conf file exists&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;assert&lt;/span&gt; f&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;exists
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    c &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; f&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;content
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Check if our 2 variables exists with the right values&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;assert&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;b&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;pm = static&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;assert&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;b&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;pm.max_requests = 1000&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;lancer-les-tests&#34;&gt;Lancer les tests&lt;/h4&gt;
&lt;p&gt;La commande &lt;code&gt;molecule test&lt;/code&gt; va lancer l&amp;rsquo;ensemble des étapes de tests (création, lint, provision, tests&amp;hellip;).&lt;/p&gt;
&lt;p&gt;Si l&amp;rsquo;on veut uniquement le provisioning, il est possible de lancer uniquement la commande &lt;code&gt;molecule converge&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Si l&amp;rsquo;on veut tester manuellement le résultat du provisioning, &lt;code&gt;molecule verify&lt;/code&gt; sera à lancer.&lt;/p&gt;
&lt;h3 id=&#34;les-comandes-essentielles&#34;&gt;Les comandes essentielles&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;molecule test&lt;/code&gt; permet de lancer toutes les étapes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;molecule converge&lt;/code&gt; permet de lancer le provisioning&lt;/li&gt;
&lt;li&gt;&lt;code&gt;molecule verify&lt;/code&gt; permet de lancer uniquement les tests&lt;/li&gt;
&lt;li&gt;&lt;code&gt;molecule login&lt;/code&gt; permet de se connecter dans le conteneur&lt;/li&gt;
&lt;li&gt;&lt;code&gt;molecule destroy&lt;/code&gt; pour supprimer le conteneur&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;résumé&#34;&gt;Résumé&lt;/h2&gt;
&lt;p&gt;Les objectifs atteints :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Un nouveau rôle Ansible qui permet de surcharger les variables du fichier pool de fpm&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Apprentissage des commandes principales de &lt;code&gt;molecule&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Découverte de &lt;code&gt;testinfra&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Un test, minimalistes, pour vérifier si les valeurs sont bien disponibles dans le fichier avec &lt;code&gt;testinfra&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Molecule permet de tester simplement dans divers contextes ses rôles Ansible.
Sans garantir à 100% l&amp;rsquo;intégrité du résultat lors de l&amp;rsquo;application sur un autre environnement, il permet d&amp;rsquo;avoir un niveau de confiance bien plus élevé et de simplifier les tests de non régressions.&lt;/p&gt;
&lt;h2 id=&#34;prochaines-étapes&#34;&gt;Prochaines étapes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Généraliser l&amp;rsquo;utilisation de molecule sur tous les nouveaux développements de rôle&lt;/li&gt;
&lt;li&gt;Ajouter des tests sur les rôles existants&lt;/li&gt;
&lt;li&gt;Creuser les options disponibles pour lancer des tests en mode matrice&lt;/li&gt;
&lt;li&gt;Tester le provisioning d&amp;rsquo;un ensemble plus conséquent de rôles avec Molecule&lt;/li&gt;
&lt;li&gt;Tester le framework de test &lt;code&gt;goss&lt;/code&gt; en complément / remplacement de &lt;code&gt;testinfra&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
      
    </item>
    
    <item>
      <title>Git - Tips &amp; Tricks</title>
      <link>https://gastaud.io/article/git-tips-tricks/</link>
      <pubDate>Tue, 23 Apr 2019 14:44:54 +0200</pubDate>
      
      <guid>https://gastaud.io/article/git-tips-tricks/</guid>
      
        <description>&lt;p&gt;Git est un outil très puissant et il propose de nombreuses fonctionnalités qui ne sont pas toujours connues ou simple à appréhender.&lt;/p&gt;
&lt;p&gt;Vous trouverez ci-dessous quelques astuces pour vous aider au quotidien et ne plus avoir peur de faire une bêtise !&lt;/p&gt;
&lt;h2 id=&#34;visualiser-son-historique&#34;&gt;Visualiser son historique&lt;/h2&gt;
&lt;h3 id=&#34;visualiser-lhistorique-des-logs-de-la-branche-courante&#34;&gt;Visualiser l&amp;rsquo;historique des logs de la branche courante&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git log
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;améliorer-laffichage-de-ses-logs&#34;&gt;Améliorer l&amp;rsquo;affichage de ses logs&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git log --pretty&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;format:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%h %ad | %s%d [%an]&amp;#34;&lt;/span&gt; --graph --date&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;short
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;que vous pouvez alias-er par exemple en  &lt;code&gt;git hist&lt;/code&gt; avec la commande suivante&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git config --global alias.hist &amp;#39;log --pretty=format:&amp;#34;%h %ad | %s%d [%an]&amp;#34; --graph --date&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ou en modifiant votre fichier de configuration &lt;code&gt;~/.gitconfig&lt;/code&gt;, section &lt;code&gt;[alias]&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[alias]
  hist = log --pretty=format:\&amp;#34;%h %ad | %s%d [%an]\&amp;#34; --graph --date=short
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;comparer-2-branches&#34;&gt;Comparer 2 branches&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git log &amp;lt;branch&amp;gt;..&amp;lt;branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;pour plus de détails : &lt;a href=&#34;https://gastaud.io/article/git-compare-branches/&#34;&gt;Git - Comparer les commits de 2 branches Git&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;vérifier--modifier-ce-que-lon-commit&#34;&gt;Vérifier / modifier ce que l&amp;rsquo;on commit&lt;/h2&gt;
&lt;h3 id=&#34;découper-ses-modifications-en-plusieurs-commits&#34;&gt;Découper ses modifications en plusieurs commits&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git add -p
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Vous pourrez avec cette commande ne sélectionner que les parties qui vous intéressent.&lt;/p&gt;
&lt;h3 id=&#34;faire-un-diff-sur-un-nouveau-fichier&#34;&gt;Faire un diff sur un nouveau fichier&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git diff new_file.txt # Ne renvoi rien
git add --intent-to-add new_file.txt # ou git add -N
git diff new_file.txt # Renvoi le contenu du fichier
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Voir le détail sur &lt;a href=&#34;https://stackoverflow.com/a/24347875&#34;&gt;Stackoverflow&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;commiter-tous-les-fichiers-modifiés&#34;&gt;Commiter tous les fichiers modifiés&lt;/h3&gt;
&lt;p&gt;Si vous avez effectué un diff et que vous êtes certains que toutes les modifications sont à commiter, vous pouvez utiliser&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git add --update
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ou&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git add -u
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;ajout-interactif&#34;&gt;Ajout interactif&lt;/h3&gt;
&lt;p&gt;La commande &lt;code&gt;git add -i&lt;/code&gt; peut également être bien pratique, pour combiner plusieurs actions. Par exemple l&amp;rsquo;update complet d&amp;rsquo;un fichier, récupérer en mode patch certains éléments d&amp;rsquo;un autre fichier ou encore ajouter des fichiers jamais commités.&lt;/p&gt;
&lt;h4 id=&#34;ajout-interactif-de-fichiers-jamais-commités&#34;&gt;Ajout interactif de fichiers jamais commités&lt;/h4&gt;
&lt;p&gt;Lorsque vous avez des fichiers non trackés et que vous voulez les ajouter au repository, vous ne voulez pas forcément ajouter tout le répertoire.&lt;/p&gt;
&lt;p&gt;Exemple :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git status
Sur la branche preview
Modifications qui seront validées :
Fichiers non suivis:
  (utilisez &amp;#34;git add &amp;lt;fichier&amp;gt;...&amp;#34; pour inclure dans ce qui sera validé)

	content/article/openshift/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On voit ici que le dossier &lt;code&gt;content/article/openshift/&lt;/code&gt; n&amp;rsquo;est pas présent dans le repository et doit donc être ajouté via &lt;code&gt;git add&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Si nous faisons uniquement &lt;code&gt;git add content/article/openshift/&lt;/code&gt; alors tous les fichiers seront mis dans l&amp;rsquo;index.&lt;/p&gt;
&lt;p&gt;Si le nombre de fichiers est limité, il sera rapide d&amp;rsquo;ajouter simplement le nom du fichier à la suite de la commande &lt;code&gt;git add content/article/openshift/&amp;lt;my-file&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Par contre, si vous avez plusieurs fichiers, alors la commande &lt;code&gt;--interactive&lt;/code&gt; va grandement vous aider.&lt;/p&gt;
&lt;p&gt;Etapes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lancer &lt;code&gt;git add -i&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Presser 4 pour afficher les fichiers non trackés&lt;/li&gt;
&lt;li&gt;La liste affichée est numéroté.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vous avez maintenant les options suivantes :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Soit saisir un numéro et presser entrée. Puis un autre numéro etc&amp;hellip;&lt;/li&gt;
&lt;li&gt;Si vous avez des plages de numéros, vous pouvez les déclarer via la syntaxe : &lt;code&gt;&amp;lt;num1&amp;gt;-&amp;lt;num2&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Vous pouvez également utiliser le &lt;code&gt;;&lt;/code&gt; pour séparer 2 numéros : &lt;code&gt;1;2;3;4;12&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Toutes ces options sont bien entendus combinables : &lt;code&gt;1-4;12&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;corriger-son-dernier-commit&#34;&gt;Corriger son dernier commit&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ajouter les modifications au commit précédent et vous proposer de modifier le message&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git commit --amend
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;Ajouter les modifications au commit précédent sans modification du message de commit&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git commit --amend --no-edit
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;corriger-un-précédent-commit&#34;&gt;Corriger un précédent commit&lt;/h3&gt;
&lt;h4 id=&#34;version-1&#34;&gt;Version 1&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git commit
git rebase -i &amp;lt;head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Puis déplacer le dernier commit au niveau du commit dans lequel l&amp;rsquo;intégrer et définir le mot clé à &lt;code&gt;fixup&lt;/code&gt; ou juste la lettre &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;version-2&#34;&gt;Version 2&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git commit --fixup &amp;lt;hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;va automatiquement reprendre le nom du commit ciblé, préfixé par fixup!&lt;/p&gt;
&lt;p&gt;Exemple :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;* 61739a7 2019-04-25 | fixup! new commit (HEAD -&amp;gt; master) [Jean-Yves Gastaud]
* ccb6360 2019-04-23 | rename file [Jean-Yves Gastaud]
* 0dfc522 2019-04-23 | new commit [Jean-Yves Gastaud]
* 229fe83 2019-04-23 | new commit [Jean-Yves Gastaud]
* c1420d3 2019-04-23 | new commit [Jean-Yves Gastaud]
* cb893a3 2019-04-23 | new commit [Jean-Yves Gastaud]
* b95163d 2019-04-23 | Good commit [Jean-Yves Gastaud]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Il est ainsi possible de demander à Git de rebase l&amp;rsquo;historique dans le bon ordre automatiquement&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git rebase -i --autosquash &amp;lt;hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Va proposer automatiquement la fusion des commits marqués en &lt;code&gt;fixup&lt;/code&gt; avec son commit de référence.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;pick b95163d Good commit
pick cb893a3 new commit
fixup 61739a7 fixup! new commit
pick c1420d3 new commit
pick 229fe83 new commit
pick 0dfc522 new commit
pick ccb6360 rename file
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;!! Attention aux conflits quand même !!&lt;/p&gt;
&lt;h3 id=&#34;faire-un-rebase-en-incluant-le-tout-1er-commit&#34;&gt;Faire un rebase en incluant le tout 1er commit&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git rebase -i --root
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;squash-vs-fixup&#34;&gt;Squash VS Fixup&lt;/h2&gt;
&lt;h3 id=&#34;fixup&#34;&gt;Fixup&lt;/h3&gt;
&lt;p&gt;Comme vu ci-dessus, fixup va inclure un commit dans le commit précédent.&lt;/p&gt;
&lt;p&gt;Le message du commit et la description du commit parent seront conservés.&lt;/p&gt;
&lt;h3 id=&#34;squash&#34;&gt;Squash&lt;/h3&gt;
&lt;p&gt;Un squash est le regroupement d&amp;rsquo;un ou plusieurs commits dans un parent, de la même manière que fixup.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est une pratique couramment utilisé dans les projets Open Source afin de simplifier le tracking entre une Merge Request et un commit.&lt;/p&gt;
&lt;p&gt;A la différence de fixup, squash va afficher l&amp;rsquo;éditeur de texte avec les messages et descriptions des n commits mergés et vous proposer de modifier la description pour correspondre au regroupement de vos commis.&lt;/p&gt;
&lt;p&gt;Tout comme pour fixup, il est possible de définir directement un commit comme état &amp;ldquo;à squasher&amp;rdquo; :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git commit --squash &amp;lt;hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;puis, comme pour fixup,&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git rebase -i --autosquash &amp;lt;hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;modifier-lhistorique-dune-branche&#34;&gt;Modifier l&amp;rsquo;historique d&amp;rsquo;une branche&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git rebase -i &amp;lt;hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;annuler-un-rebase-en-cours&#34;&gt;Annuler un rebase en cours&lt;/h3&gt;
&lt;p&gt;Oula, qu&amp;rsquo;est ce qu&amp;rsquo;il se passe ici ?&lt;/p&gt;
&lt;p&gt;Je vais plutôt annuler ça !&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git rebase --abort
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;valider-une-résolution-de-conflit-dans-un-rebase&#34;&gt;Valider une résolution de conflit dans un rebase&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git add &amp;lt;file&amp;gt;
git rebase --continue
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;J&amp;rsquo;ajoute mon correctif de conflit et je continue le rebase !&lt;/p&gt;
&lt;p&gt;Mon correctif sera inclu dans le commit qui vient d&amp;rsquo;être appliqué. C&amp;rsquo;est pour cela que je n&amp;rsquo;ai pas besoin de commité à nouveau.&lt;/p&gt;
&lt;h3 id=&#34;pas-de-changement-lors-du-rebase-&#34;&gt;Pas de changement lors du rebase ?&lt;/h3&gt;
&lt;p&gt;Parfois, un message indique que l&amp;rsquo;application du commit n&amp;rsquo;apporte pas de changement.&lt;/p&gt;
&lt;p&gt;Le commit est donc déjà inclus dans une modification déjà appliqué au dépôt. Il peut être supprimé sans craintes.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git rebase --skip
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;retrouver-les-changements-effectuées-sur-une-fonction&#34;&gt;Retrouver les changements effectuées sur une fonction&lt;/h3&gt;
&lt;p&gt;Avec &lt;code&gt;git grep&lt;/code&gt; tu peux déjà avoir un certain niveau d’information (commit de la fonction, fichier dans laquelle elle est).&lt;/p&gt;
&lt;p&gt;Si tu as un changement de nom par contre…&lt;/p&gt;
&lt;p&gt;Exemple :&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git grep -p csv_import_get_ftp_params_provider_2 $(git rev-list --all)&lt;/code&gt; renvoi&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;a79ed97f14eede3cdd98ae53ce3b990b58bbd351:sites/all/modules/custom/csv_import/csv_import_query.inc:function csv_import_get_ftp_params_provider_2() {
8b7ca76ca554accd397fcec1073776d60280521e:sites/all/modules/custom/csv_import/csv_import_query.inc:function csv_import_get_ftp_params_provider_2() {
118ffd0839985555dbaadd9edd9846ce9c18eb05:sites/all/modules/custom/csv_import/csv_import.module:function csv_import_get_ftp_params_provider_2() {
2b5196af0dddd28744acbf0ec015b6d59bddedee:sites/all/modules/custom/csv_import/csv_import.module:function csv_import_get_ftp_params_provider_2() {
d58b7662c6a8d47793fd79ec25030ee5c7cee4a6:sites/all/modules/custom/csv_import/csv_import.module:function csv_import_get_ftp_params_provider_2() {
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;créer-partager-et-appliquer-un-patch&#34;&gt;Créer, partager et appliquer un patch&lt;/h2&gt;
&lt;h3 id=&#34;créer-un-patch&#34;&gt;Créer un patch&lt;/h3&gt;
&lt;h4 id=&#34;format-patch&#34;&gt;&lt;code&gt;format-patch&lt;/code&gt;&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git format-patch &amp;lt;hash&amp;gt;..HEAD
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;va générer n fichiers (où n est égale au nombre de commits entre le hash et HEAD)&lt;/p&gt;
&lt;p&gt;Si vous voulez regrouper les commits en 1 seul fichier&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git format-patch -k --stdout &amp;lt;hash&amp;gt;..&amp;lt;hash&amp;gt; &amp;gt; my.patch
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;L&amp;rsquo;option &lt;code&gt;-k&lt;/code&gt; permet de garder sujet/message du commit intact et ne pas avoir la mention &lt;code&gt;[PATCH]&lt;/code&gt; insérer automatiquement.&lt;/p&gt;
&lt;p&gt;Exemple : &lt;code&gt;wk-patch&lt;/code&gt; n&amp;rsquo;a pas l&amp;rsquo;option &lt;code&gt;-k&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;diff wk-patch.patch nok-patch.patch                
4c4
&amp;lt; Subject: fixup! new commit
---
&amp;gt; Subject: [PATCH 1/2] fixup! new commit
27c27
&amp;lt; Subject: change
---
&amp;gt; Subject: [PATCH 2/2] change
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;diff&#34;&gt;&lt;code&gt;diff&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Avec l&amp;rsquo;utilisation de la commande &lt;code&gt;git diff&lt;/code&gt; vous pouvez également géréner un patch.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git diff &amp;lt;hash&amp;gt;..&amp;lt;hash&amp;gt; &amp;gt; my.patch
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;La différence avec &lt;code&gt;format-patch&lt;/code&gt; est que l&amp;rsquo;on n&amp;rsquo;a pas de notions d&amp;rsquo;historique des commits et donc que :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;toutes les modifications se retrouveront unfiées dans un seul fichier&lt;/li&gt;
&lt;li&gt;on perd l&amp;rsquo;information sur l&amp;rsquo;auteur des commits&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;partager-un-patch&#34;&gt;Partager un patch&lt;/h3&gt;
&lt;p&gt;!! peu de chance que vous ayez à l&amp;rsquo;utiliser mais toujours marrant de savoir que cela existe !!&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git send-email --to=&amp;#34;jygastaud &amp;lt;jygastaud@clever-age.com&amp;gt;&amp;#34; 0001-fixup-new-commit.patch
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sur Ubuntu/Debian, peut nécessiter l&amp;rsquo;installation d&amp;rsquo;un paquet spécifique : &lt;code&gt;apt-get install git-email&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Il faut aussi un serveur smtp dispo, soit en passer un en ligne de commande&lt;/p&gt;
&lt;h3 id=&#34;appliquer-un-patch&#34;&gt;Appliquer un patch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Si le patch a été créé avec &lt;code&gt;format-patch&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git am &amp;lt;my-patch-files&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;Vous pouvez utiliser la commande &lt;code&gt;apply&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git apply &amp;lt;my-patch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;supprimer-un-patch&#34;&gt;Supprimer un patch&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git apply -R &amp;lt;my-patch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;description-dune-branche&#34;&gt;Description d&amp;rsquo;une branche&lt;/h3&gt;
&lt;h4 id=&#34;ajouter-une-description&#34;&gt;Ajouter une description&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git branch --edit-description
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;voir-la-description&#34;&gt;Voir la description&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git config branch.master.description
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git request-pull v1.0 origin master:v1.x -p
The following changes since commit 61739a74f55f6f08bfebbccfc00e5e2cbb9bda52:

  fixup! new commit (2019-04-25 17:51:22 +0200)

are available in the Git repository at:

  git@github.com:jygastaud/git-conferences.git v1.x

for you to fetch changes up to 967fbc53e959804b17acc90cec89bdafad2e63ce:

  change (2019-04-25 18:29:25 +0200)

----------------------------------------------------------------
(from the branch description for master local branch)

La branche de prod

----------------------------------------------------------------
Jean-Yves Gastaud (1):
      change

 README2.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/README2.md b/README2.md
index 504bc75..3a59441 100644
--- a/README2.md
+++ b/README2.md
@@ -12,3 +12,5 @@ Encore 1 ligne
 
 Derniere ligne ?
 
+A change
+
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;gérer-ses-repositories-distants&#34;&gt;Gérer ses repositories distants&lt;/h2&gt;
&lt;h3 id=&#34;fetch--rebase-vs-pull-rebase&#34;&gt;fetch + rebase VS pull (&amp;ndash;rebase)&lt;/h3&gt;
&lt;h3 id=&#34;gérer-plusieurs-remotes&#34;&gt;Gérer plusieurs remotes&lt;/h3&gt;
&lt;h2 id=&#34;les-hooks&#34;&gt;Les hooks&lt;/h2&gt;
&lt;h3 id=&#34;gérer-et-partager-ses-hooks-simplement&#34;&gt;Gérer et partager ses hooks simplement&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tree gitconfig 
gitconfig
|-- .gitconfig
|-- hooks
|   |-- pre-commit
|   `-- prepare-commit-msg
`-- templates
    `-- .gitmessage
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;puis &lt;code&gt;git config --local include.path ../gitconfig/.gitconfig&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;debuger&#34;&gt;Debuger&lt;/h2&gt;
&lt;h3 id=&#34;git-grep&#34;&gt;git grep&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;#retrouver-les-changements-effectuées-sur-une-fonction&#34;&gt;Voir la section précédente&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;savoir-ce-qui-est-déjà-commité--pushé-sur-une-autre-branche&#34;&gt;Savoir ce qui est déjà commité / pushé sur une autre branche&lt;/h3&gt;
&lt;h3 id=&#34;git-bisect&#34;&gt;git bisect&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git bisect start
git bisect good &amp;lt;hash&amp;gt;
git bisect bad
git bisect bad
git bisect reset
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Si vous avez des tests automatisés et que vous avez une erreur sur ces tests, il est possible de lancer un git bisect pour exécuter automatiquement les tests&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git bisect start
git bisect good &amp;lt;hash&amp;gt;
git bisect bad
git bisect run ./test.sh
git bisect reset
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;git-reflog&#34;&gt;git reflog&lt;/h3&gt;
&lt;p&gt;L&amp;rsquo;historique de toutes les actions que vous avez pu effectuer sur votre repository &lt;strong&gt;local&lt;/strong&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cc7ccc0 (HEAD -&amp;gt; squash, master) HEAD@{0}: rebase -i (finish): returning to refs/heads/squash
cc7ccc0 (HEAD -&amp;gt; squash, master) HEAD@{1}: rebase -i (start): checkout HEAD~5
cc7ccc0 (HEAD -&amp;gt; squash, master) HEAD@{2}: rebase -i (finish): returning to refs/heads/squash
cc7ccc0 (HEAD -&amp;gt; squash, master) HEAD@{3}: rebase -i (start): checkout HEAD~5
72f188e HEAD@{4}: commit: squash! vide2
74e13d7 HEAD@{5}: commit: vide3
7eb0740 HEAD@{6}: commit: vide2
2396775 HEAD@{7}: commit: vide
cc7ccc0 (HEAD -&amp;gt; squash, master) HEAD@{8}: checkout: moving from master to squash
cc7ccc0 (HEAD -&amp;gt; squash, master) HEAD@{9}: am: [PATCH 5/5] change
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Comme vous pouvez le constater, chaque action contient un hash spécifique.&lt;/p&gt;
&lt;p&gt;Avec ce hash, il vous ai possible de revenir revert simplement une action si nécessaire.&lt;/p&gt;
&lt;h3 id=&#34;git-worktree&#34;&gt;git worktree&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;git worktree&lt;/code&gt; permet de gérer plusieurs espaces de travail pour un même dépôt.&lt;/p&gt;
&lt;p&gt;Un cas typique d&amp;rsquo;utilisation :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Je travaille sur une nouvelle fonctionnalité et j&amp;rsquo;ai des modifications en cours&lt;/li&gt;
&lt;li&gt;Un ticket URGENT arrive et j&amp;rsquo;ai besoin de changer de branche pour faire une correction&lt;/li&gt;
&lt;li&gt;Je commite mon travail en cours (au risque d&amp;rsquo;ajouter des choses non voulues) et je change de branche&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;STOP ! Utilisez maintenant &lt;code&gt;worktree&lt;/code&gt; !&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git worktree add &amp;lt;path&amp;gt; [&amp;lt;branch&amp;gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;avec cette commande, je vais créer un nouvel espace de travail dans un dossier différent et travailler dessus comme sur ma branche courante.&lt;/p&gt;
&lt;p&gt;Une fois fini, le travail commité et poussé, il ne nous reste plus qu&amp;rsquo;à supprimer l&amp;rsquo;espace de travail :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git worktree prune
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;configurer-votre-profil&#34;&gt;Configurer votre profil&lt;/h2&gt;
&lt;h3 id=&#34;gérer-plusieurs-profils&#34;&gt;Gérer plusieurs profils&lt;/h3&gt;
&lt;p&gt;Voir article &lt;a href=&#34;https://gastaud.io/article/git-gerer-profils/&#34;&gt;Git - Gérer des profils distincts dans Git&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;partager-un-repository&#34;&gt;Partager un repository&lt;/h2&gt;
&lt;h3 id=&#34;git-bundle&#34;&gt;git bundle&lt;/h3&gt;
&lt;p&gt;Git bundle permet de partager une branche d&amp;rsquo;un dépôt avec tout son historique de commit, de commiter dessus et de réintégrer les modifications dans le dépôt d&amp;rsquo;origine.&lt;/p&gt;
&lt;p&gt;Pratique lorsque vous devez bosser avec des équipes distantes qui ne peuvent pas avoir un vrai accès au dépôt initial.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git bundle create &amp;lt;repo.bundle&amp;gt; &amp;lt;branch or hash or tag&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;puis partager le fichier &lt;code&gt;repo.bundle&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Sur le poste de l&amp;rsquo;autre développeur, il est maintenant possible de cloner le dépôt&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git clone -b &amp;lt;branch_name&amp;gt; &amp;lt;path/to/repo.bundle&amp;gt; &amp;lt;folder&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Le dev peut générer un nouveau bundle de diff à partager&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git bundle create gitconf.bundle origin/master..master
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;puis vous pouvez réintégrer le fichier dans le repo d&amp;rsquo;origine avec les mêmes commandes que pour la mise à jour via un dépôt distant&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avec un commit merge&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git pull ../testconf/gitconf.bundle master
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;Avec pull &amp;ndash;rebase&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git pull --rebase ../testconf/gitconf.bundle master
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Si des modifications ont été faites sur le dépôt d&amp;rsquo;origine et qu&amp;rsquo;elles doivent être repartagée au développeur, il suffira de générer un diff avec le bundle précédent. Le développeur n&amp;rsquo;aura plus qu&amp;rsquo;à remplacer son fichier initial et faire un pull dessus.&lt;/p&gt;
&lt;h2 id=&#34;tags&#34;&gt;Tags&lt;/h2&gt;
&lt;h3 id=&#34;tri-des-tags-et-semantic-versioning&#34;&gt;Tri des tags et Semantic Versioning&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git tag --sort&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;version:refname
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pour plus de détails, voir l&amp;rsquo;article &lt;a href=&#34;https://gastaud.io/article/git-sort-tags-semantic-version/&#34;&gt;Git - Trier les tags d&amp;rsquo;un repo utilisant du semantic versioning&lt;/a&gt;&lt;/p&gt;</description>
      
    </item>
    
    <item>
      <title>GoHugo - Générer des déclinaisons d&#39;images utilisables en page d&#39;accueil</title>
      <link>https://gastaud.io/article/hugo-homepage-images-processing/</link>
      <pubDate>Thu, 11 Apr 2019 16:51:22 +0200</pubDate>
      
      <guid>https://gastaud.io/article/hugo-homepage-images-processing/</guid>
      
        <description>&lt;p&gt;GoHugo, depuis la version 0.32, est capable de gérer des &lt;a href=&#34;https://gohugo.io/about/new-in-032/#page-resources&#34;&gt;ressources dédiées à une page&lt;/a&gt;
ainsi que de générer des &lt;a href=&#34;https://gohugo.io/about/new-in-032/#image-processing&#34;&gt;déclinaisons d&amp;rsquo;images&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Cette fonctionnalité est notamment très pratique pour gérer automatiquement des déclinaisons responsives de ces images et les utiliser dans un template ou shortcode.&lt;/p&gt;
&lt;p&gt;Cela fonctionne parfaitement lorsque l&amp;rsquo;on est dans un contenu.&lt;/p&gt;
&lt;h2 id=&#34;alors-cest-quoi-le-soucis-&#34;&gt;Alors c&amp;rsquo;est quoi le soucis ?&lt;/h2&gt;
&lt;p&gt;Admettons que nous voulions utiliser des images responsives sur la page d&amp;rsquo;accueil de notre site.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La page d&amp;rsquo;accueil ne fait pas parti d&amp;rsquo;une section ou d&amp;rsquo;un bundle et n&amp;rsquo;a donc pas accès à des ressources&lt;/li&gt;
&lt;li&gt;Les fichiers mis dans le répertoire &lt;code&gt;static&lt;/code&gt; ne sont pas traités comme des ressources par Hugo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il sera donc nécessaire de gérer &amp;ldquo;à la main&amp;rdquo;, la déclinaison de ces images et les inclure manuellement dans notre template.&lt;/p&gt;
&lt;p&gt;Pour simplifier, nous avons donc l&amp;rsquo;aborescence suivante :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;.
| content
| | _index.md
| layouts
| | index.html
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;quoi--mais-jai-trop-dimages-à-décliner-et-le-contenu-change-souvent-&#34;&gt;Quoi ? Mais j&amp;rsquo;ai trop d&amp;rsquo;images à décliner et le contenu change souvent ?!&lt;/h2&gt;
&lt;p&gt;Pour arriver à automatiser le processus de génération, nous allons utiliser introduit en version 0.35 : les &lt;a href=&#34;https://gohugo.io/news/0.35-relnotes/&#34;&gt;Headless Bundles&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ce nouveau type de bundle permet de gérer du contenu qui ne produira pas une page à part entière lors du rendu fait par Hugo.&lt;/p&gt;
&lt;p&gt;Il est donc pratique de s&amp;rsquo;en servir pour gérer des blocs, messages&amp;hellip; qui sont ensuite injecter dans les pages.&lt;/p&gt;
&lt;p&gt;En s&amp;rsquo;appuyant donc sur ce type de bundle et en le combinant avec la fonctionnalité de génération d&amp;rsquo;images, nous allons pouvoir obtenir automatiquement nos diverses déclinaisons d&amp;rsquo;images.&lt;/p&gt;
&lt;p&gt;Nous allons suivre les quesques étapes suivantes.&lt;/p&gt;
&lt;h3 id=&#34;création-dun-nouveau-bundle-headless-img&#34;&gt;Création d&amp;rsquo;un nouveau bundle &lt;code&gt;headless-img&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;On aura donc maintenant l&amp;rsquo;arborescence de contenus suivante :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;.
| content
| | _index.md
| | headless-img
| | | images
| | | | mon_image.png
| | | index.md
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Le fichier &lt;code&gt;headless-img/index.md&lt;/code&gt; contiendra&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+++
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;headless = true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;title = &amp;#34;homepage images&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+++
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&amp;lt; imghp src=&amp;#34;images/mon_image.png&amp;#34; alt=&amp;#34;A nice image for our homepage&amp;#34; &amp;gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nous avons donc créer ici une ressource &lt;code&gt;headless&lt;/code&gt; qui va appeler un shortcode hugo nommé &lt;code&gt;imghp&lt;/code&gt; et qui prend en paramètres un chemin et un texte alternatif.&lt;/p&gt;
&lt;h3 id=&#34;création-du-shortcode&#34;&gt;Création du shortcode&lt;/h3&gt;
&lt;p&gt;Dans l&amp;rsquo;aborescence &lt;code&gt;layouts/shortcodes&lt;/code&gt; nous allons créer un nouveau fichier nommé &lt;code&gt;imghp.html&lt;/code&gt; qui contiendra la logique de génération de nos images et leur rendu.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-golang&#34; data-lang=&#34;golang&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#75715e&#34;&gt;/* Le shortcode pour les images responsives de la HP */&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&lt;span style=&#34;color:#75715e&#34;&gt;/* get file that matches the filename as specified as src=&amp;#34;&amp;#34; in shortcode */&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; (.&lt;span style=&#34;color:#a6e22e&#34;&gt;Site&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;GetPage&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/headless-img&amp;#34;&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;Resources&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;GetMatch&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;*%s*&amp;#34;&lt;/span&gt; (.&lt;span style=&#34;color:#a6e22e&#34;&gt;Get&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;src&amp;#34;&lt;/span&gt;)) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&lt;span style=&#34;color:#75715e&#34;&gt;/* set image sizes, these are hardcoded for now, x dictates that images are resized to this width */&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;tinyw&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;500x&amp;#34;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;smallw&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;800x&amp;#34;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;mediumw&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1200x&amp;#34;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;largew&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1500x&amp;#34;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&lt;span style=&#34;color:#75715e&#34;&gt;/* resize the src image to the given sizes */&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ .&lt;span style=&#34;color:#a6e22e&#34;&gt;Scratch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Set&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tiny&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Resize&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;tinyw&lt;/span&gt;) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ .&lt;span style=&#34;color:#a6e22e&#34;&gt;Scratch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Set&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;small&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Resize&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;smallw&lt;/span&gt;) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ .&lt;span style=&#34;color:#a6e22e&#34;&gt;Scratch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Set&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;medium&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Resize&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;mediumw&lt;/span&gt;) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ .&lt;span style=&#34;color:#a6e22e&#34;&gt;Scratch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Set&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;large&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Resize&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;largew&lt;/span&gt;) }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&lt;span style=&#34;color:#75715e&#34;&gt;/* add the processed images to the scratch */&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;tiny&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; .&lt;span style=&#34;color:#a6e22e&#34;&gt;Scratch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Get&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tiny&amp;#34;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;small&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; .&lt;span style=&#34;color:#a6e22e&#34;&gt;Scratch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Get&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;small&amp;#34;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;medium&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; .&lt;span style=&#34;color:#a6e22e&#34;&gt;Scratch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Get&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;medium&amp;#34;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;large&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; .&lt;span style=&#34;color:#a6e22e&#34;&gt;Scratch&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Get&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;large&amp;#34;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&lt;span style=&#34;color:#75715e&#34;&gt;/* only use images smaller than or equal to the src (original) image size, as Hugo will upscale small images */&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&lt;span style=&#34;color:#75715e&#34;&gt;/* set the sizes attribute to (min-width: 35em) 1200px, 100vw unless overridden in shortcode */&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#a6e22e&#34;&gt;img&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;with&lt;/span&gt; .&lt;span style=&#34;color:#a6e22e&#34;&gt;Get&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sizes&amp;#34;&lt;/span&gt; }}&lt;span style=&#34;color:#a6e22e&#34;&gt;sizes&lt;/span&gt;=&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;{{.}}&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;{{ &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; }}&lt;span style=&#34;color:#a6e22e&#34;&gt;sizes&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;(min-width: 35em) 1200px, 100vw&amp;#34;&lt;/span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;end&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;srcset&lt;/span&gt;=&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ge&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Width&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;500&amp;#34;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#a6e22e&#34;&gt;with&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;tiny&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RelPermalink&lt;/span&gt; }}{{.}} &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;end&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;end&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ge&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Width&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;800&amp;#34;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#a6e22e&#34;&gt;with&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;small&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RelPermalink&lt;/span&gt; }}, {{.}} &lt;span style=&#34;color:#ae81ff&#34;&gt;800&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;end&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;end&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ge&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Width&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1200&amp;#34;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#a6e22e&#34;&gt;with&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;medium&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RelPermalink&lt;/span&gt; }}, {{.}} &lt;span style=&#34;color:#ae81ff&#34;&gt;1200&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;end&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;end&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ge&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Width&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1500&amp;#34;&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ &lt;span style=&#34;color:#a6e22e&#34;&gt;with&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;large&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RelPermalink&lt;/span&gt; }}, {{.}} &lt;span style=&#34;color:#ae81ff&#34;&gt;1500&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;w&lt;/span&gt; {{ &lt;span style=&#34;color:#a6e22e&#34;&gt;end&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;end&lt;/span&gt; }}&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; .&lt;span style=&#34;color:#a6e22e&#34;&gt;Get&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;medium&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{{ $medium.RelPermalink }}&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{{ $src.RelPermalink }}&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;end&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;with&lt;/span&gt; .&lt;span style=&#34;color:#a6e22e&#34;&gt;Get&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;alt&amp;#34;&lt;/span&gt; }}&lt;span style=&#34;color:#a6e22e&#34;&gt;alt&lt;/span&gt;=&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;{{.}}&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;{{ &lt;span style=&#34;color:#a6e22e&#34;&gt;end&lt;/span&gt; }}&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ce template peut être retrouvé sur de nombreux sites comme exemple.&lt;/p&gt;
&lt;p&gt;La principale différence avec les autres se situe dans cette ligne :&lt;br&gt;
&lt;code&gt;{{ $src := (.Site.GetPage &amp;quot;/headless-img&amp;quot;).Resources.GetMatch (printf &amp;quot;*%s*&amp;quot; (.Get &amp;quot;src&amp;quot;)) }}&lt;/code&gt;&lt;br&gt;
qui nous permet de récupérer les ressources du bundle &lt;code&gt;headless-img&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Lorsque ce shortcode est exécuté, il va donc chercher l&amp;rsquo;image définie dans le fichier &lt;code&gt;headless-img/index.md&lt;/code&gt; et génère automatiquement les déclinaisons.&lt;/p&gt;
&lt;h3 id=&#34;et-maintenant-jaffiche-ça-comment-sur-ma-page-daccueil-&#34;&gt;Et maintenant, j&amp;rsquo;affiche ça comment sur ma page d&amp;rsquo;accueil ?&lt;/h3&gt;
&lt;p&gt;Il ne nous reste plus qu&amp;rsquo;à appeler notre bundle dans notre template &lt;code&gt;index.html&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;si-vous-navez-quun-uniquement-1-seul-contenu-indexmd&#34;&gt;Si vous n&amp;rsquo;avez qu&amp;rsquo;un uniquement 1 seul contenu index.md&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;{{ define &amp;#34;content&amp;#34; }}
  {{ /* Le rendu de la section headless. Assume */ }}
  {{ $headless := .Site.GetPage &amp;#34;/headless-img&amp;#34; }}
  {{ $headless.Content }}
{{ end }}
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;si-vous-devez-rendre-plusieurs-fichiers-md-en-se-basant-sur-un-nom-img1-img2-par-lexemple&#34;&gt;Si vous devez rendre plusieurs fichiers .md en se basant sur un nom. &lt;code&gt;img1&lt;/code&gt;, &lt;code&gt;img2&lt;/code&gt;&amp;hellip; par l&amp;rsquo;exemple&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;{{ define &amp;#34;content&amp;#34; }}
  {{ $headless := .Site.GetPage &amp;#34;/headless-img&amp;#34; }}
  {{ $reusablePages := $headless.Resources.Match &amp;#34;img*&amp;#34; }}
  {{ range $reusablePages }}
    {{ .Content }}
  {{ end }}
{{ end }}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et voilà, maintenant vos images sont bien rendues sur votre page d&amp;rsquo;accueil et leurs versions responsives sont également disponibles.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Drupal, Gitlab CI et Clever Cloud sont dans un bateau</title>
      <link>https://gastaud.io/article/drupal-clever-cloud/</link>
      <pubDate>Wed, 10 Apr 2019 15:15:36 +0200</pubDate>
      
      <guid>https://gastaud.io/article/drupal-clever-cloud/</guid>
      
        <description>&lt;p&gt;Déployer un site Drupal 8 sur Clever Cloud avec Gitlab CI&lt;/p&gt;
&lt;h2 id=&#34;quest-ce-que-clever-cloud&#34;&gt;Qu&amp;rsquo;est-ce que Clever Cloud&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://www.clever-cloud.com/&#34;&gt;Clever Cloud&lt;/a&gt; est un hébergement PAAS (Platform As A Service).&lt;/p&gt;
&lt;h3 id=&#34;grands-principes&#34;&gt;Grands principes&lt;/h3&gt;
&lt;p&gt;A chaque déploiement de l&amp;rsquo;application, une nouvelle machine va être créée.&lt;br&gt;
Le code disponible dans un repository Git fournit par Clever Cloud va être déployer sur la machine et si aucune erreur n&amp;rsquo;est détectée, l&amp;rsquo;ancienne machine et la nouvelle sont switchées.&lt;br&gt;
Le stockage de données et le stockage permanent de fichiers sont assurés respectivement par l&amp;rsquo;add-on &lt;code&gt;mysql&lt;/code&gt; et &lt;code&gt;bucketFS&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Toutes les machines et services possèdent un identifiant unique et un alias.&lt;/p&gt;
&lt;h2 id=&#34;serveurs-et-services&#34;&gt;Serveurs et services&lt;/h2&gt;
&lt;p&gt;2 environnements sont provisionnées.&lt;/p&gt;
&lt;h3 id=&#34;preprod&#34;&gt;PREPROD&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;VM&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;type XS : 1GB de RAM, 1 CPU&lt;/li&gt;
&lt;li&gt;Pas d&amp;rsquo;autoscalling&lt;/li&gt;
&lt;li&gt;1 seule instance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Services&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MySQL (la base de données)
&lt;ul&gt;
&lt;li&gt;10GB d&amp;rsquo;espace&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2 FS Buckets
&lt;ul&gt;
&lt;li&gt;1 pour le répertoire public de Drupal&lt;/li&gt;
&lt;li&gt;1 pour le repertoire privé de Drupal&lt;/li&gt;
&lt;li&gt;Assure la persistance des données / fichiers uploadés&lt;/li&gt;
&lt;li&gt;Pas de taille min / max&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;prod&#34;&gt;PROD&lt;/h3&gt;
&lt;p&gt;Identique à la PREPROD avec une machine un peu plus puissante : type S, 2GB de RAM, 2 CPUs&lt;/p&gt;
&lt;h2 id=&#34;configurations-et-variables-denvironnement&#34;&gt;Configurations et variables d&amp;rsquo;environnement&lt;/h2&gt;
&lt;h3 id=&#34;variables-denvironnements&#34;&gt;Variables d&amp;rsquo;environnements&lt;/h3&gt;
&lt;p&gt;Afin d&amp;rsquo;accéder aux différents services associés depuis la VM, Clever Cloud fournit des variables d&amp;rsquo;environnement.&lt;/p&gt;
&lt;p&gt;Les variables standards sur Clever Cloud et disponibles par environnement sont documentées au lien suivant :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.clever-cloud.com/doc/admin-console/environment-variables/&#34;&gt;Général&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.clever-cloud.com/doc/php/php-apps/#environment-injection&#34;&gt;PHP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;variables-par-instances&#34;&gt;Variables par instances&lt;/h3&gt;
&lt;p&gt;Les variables ci-dessous sont définies et modifiées pour chacune des instances.&lt;/p&gt;
&lt;h5 id=&#34;variables-custom--customisables&#34;&gt;Variables custom / customisables&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;CC_FS_BUCKET=/web/sites/default/files:bucket-xxxx-xxxx-xxxx-xxxx-xxxx-fsbucket.services.clever-cloud.com
CC_FS_BUCKET=/private/files:bucket-xxxx-xxxx-xxxx-xxxx-xxxx-fsbucket.services.clever-cloud.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;permet de définir quels répertoires doivent être stockés de façon permanente dans le &lt;code&gt;FS BUCKETS&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;CC_PRE_RUN_HOOK=composer.phar run-script drupal-update-all
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Permet d&amp;rsquo;exécuter à la fin d&amp;rsquo;un déploiement les actions de migration de base de données / vidage de cache&amp;hellip;
Pour simplifier le process, on joue un script disponible dans le &lt;code&gt;composer.json&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;CC_WEBROOT=/web
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Permet de définir l&amp;rsquo;emplacement du fichier index.php/index.html pour l&amp;rsquo;affichage du site.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DRUPAL_SALT=xxxxxxx
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Le SALT Drupal est obligatoire&lt;/strong&gt;. Il sera nécessaire de le configurer également sur les instances de DEV/LOCAL en cas de redescente de base.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;PHP_VERSION=7.2
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Définie la version de PHP à utiliser&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;PORT=8080
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Ne pas changer le port. Il est configuré par défaut sur 8080 pour le bon fonctionnement Clever Cloud.&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;GIT_TAG=CURRENT_VERSION
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cette variable est définie automatiquement par Gitlab CI.&lt;/p&gt;
&lt;p&gt;Elle sert uniquement de repaire pour savoir quel est le dernier tag déployé&lt;/p&gt;
&lt;h4 id=&#34;variables-liées-aux-services&#34;&gt;Variables liées aux services&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;BUCKET_HOST
MYSQL_ADDON_DB
MYSQL_ADDON_HOST
MYSQL_ADDON_PASSWORD
MYSQL_ADDON_PORT
MYSQL_ADDON_URI
MYSQL_ADDON_USER
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;faire-communiquer-drupal-et-les-services-clever-cloud&#34;&gt;Faire communiquer Drupal et les services Clever Cloud&lt;/h2&gt;
&lt;p&gt;Afin de pouvoir utiliser pleinement les services de Clever Cloud, les adaptations suivantes ont été faites sur Drupal.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ajout au fichier &lt;code&gt;default.settings.php&lt;/code&gt; d&amp;rsquo;une condition pour inclure un fichier de settings propre à Clever Cloud&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;getenv&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;APP_ID&amp;#39;&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;include&lt;/span&gt; $app_root &lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt; $site_path &lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/settings.clevercloud.php&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Commit du fichier settings.php (iso default.settings.php)&lt;/li&gt;
&lt;li&gt;Création et commit du fichier &lt;code&gt;settings.clevercloud.php&lt;/code&gt; qui ne s&amp;rsquo;inclue que si la variable &lt;code&gt;APP_ID&lt;/code&gt; est disponible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sur Clever Cloud : &lt;code&gt;APP_ID&lt;/code&gt;: the ID of the application. Each application has a unique identifier used to identify it in our system. This ID is the same than the one you can find in the information section of your application.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Modification de la partie &lt;code&gt;scripts&lt;/code&gt; du fichier &lt;code&gt;composer.json&lt;/code&gt; pour y ajouter des scripts d&amp;rsquo;installation et de mise à jour.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Extract du fichier composer.json&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;scripts&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;drupal-config-update&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cd web &amp;amp;&amp;amp; ../vendor/bin/drush cr&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cd web &amp;amp;&amp;amp; ../vendor/bin/drush cim -y&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cd web &amp;amp;&amp;amp; ../vendor/bin/drush csim -y&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cd web &amp;amp;&amp;amp; ../vendor/bin/drush csim -y&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cd web &amp;amp;&amp;amp; ../vendor/bin/drush locale:check&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cd web &amp;amp;&amp;amp; ../vendor/bin/drush locale:update&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cd web &amp;amp;&amp;amp; ../vendor/bin/drush cr&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;drupal-db-update&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cd web &amp;amp;&amp;amp; ../vendor/bin/drush updb -y&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cd web &amp;amp;&amp;amp; ../vendor/bin/drush entup -y&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;drupal-monsite-default-install&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cd web &amp;amp;&amp;amp; ../vendor/bin/drush si monsite_profile --locale=en --account-name=admin --account-pass=admin -y&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cd web &amp;amp;&amp;amp; ../vendor/bin/drush cset system.site uuid 28ece100-1664-4072-9a92-55a5a53192f3 -y&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;@drupal-update-all&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;drupal-theme-build&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cd web/themes/custom/monsite &amp;amp;&amp;amp; npm install &amp;amp;&amp;amp; ./node_modules/.bin/gulp build -r&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;drupal-update-all&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;@drupal-theme-build&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;@drupal-db-update&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;@drupal-config-update&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;utiliser-les-outils-php-et-drupal-avec-clever-cloud&#34;&gt;Utiliser les outils PHP et Drupal avec Clever Cloud&lt;/h2&gt;
&lt;p&gt;Si besoin de lancer des commandes directement sur le serveur, il vous faudra passer par l&amp;rsquo;outil &lt;code&gt;Clever Tools&lt;/code&gt; en ligne de commande.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.clever-cloud.com/doc/clever-tools/getting_started/&#34;&gt;La documentation d&amp;rsquo;installation&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;connexion-ssh&#34;&gt;Connexion SSH&lt;/h3&gt;
&lt;p&gt;Clever Tools dispose d&amp;rsquo;une commande &lt;code&gt;ssh&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Comme nous avons 2 VMs définies dans le &lt;code&gt;.clever.json&lt;/code&gt;, il est nécessaire de préciser à cette commande l&amp;rsquo;environnement cible.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Connexion PREPROD : &lt;code&gt;clever ssh mon-site-preprod&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Connexion PROD : &lt;code&gt;clever ssh mon-site-prod&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;composer&#34;&gt;Composer&lt;/h3&gt;
&lt;p&gt;Composer est disponible directement et globalement sur les machines via &lt;code&gt;composer.phar&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Si vous avez besoin de lancer un &lt;code&gt;composer install&lt;/code&gt; directement sur la machine, il vous faudra donc exécuter &lt;code&gt;composer.phar install&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;drush-drupal-console-et-autres-binaires-du-projet&#34;&gt;Drush, Drupal Console et autres binaires du projet&lt;/h3&gt;
&lt;p&gt;Drush et Drupal Console sont à déclarer en dépendance composer du projet.&lt;/p&gt;
&lt;p&gt;Une fois le &lt;code&gt;composer install&lt;/code&gt; exécuté, il est possible d&amp;rsquo;aller utiliser les binaires dans le dossier &lt;code&gt;vendor/bin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Exemple pour Drush depuis la racine de l&amp;rsquo;application : &lt;code&gt;./vendor/bin/drush MA_COMMANDE&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;gitlab--gitlab-ci&#34;&gt;Gitlab / Gitlab CI&lt;/h2&gt;
&lt;p&gt;Afin de simplifier la gestion et le déploiement de l&amp;rsquo;application, les actions suivantes ont été menées sur l&amp;rsquo;Intégration Continue (via Gitlab-ci).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Activation d&amp;rsquo;un runner Gitlab CI sur l&amp;rsquo;instance de QA&lt;/li&gt;
&lt;li&gt;Activation de Gitlab CI dans le projet Drupal&lt;/li&gt;
&lt;li&gt;Création d&amp;rsquo;une tâche de déploiement pour la PREPROD
&lt;ul&gt;
&lt;li&gt;cette tâche se déclenche automatiquement que si des changements se produisent sur la branche &lt;code&gt;release&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;On force la mise à jour du code dans le dépôt Git de Clever Cloud à chaque déploiement.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Création d&amp;rsquo;une tâche de déploiement sur la PROD
&lt;ul&gt;
&lt;li&gt;Cette tâche doit être déclenché manuellement et n&amp;rsquo;est proposée que lorsque d&amp;rsquo;un tag est poussé&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Création de 2 jobs planifiés dans Gitlab
&lt;ul&gt;
&lt;li&gt;Mise en sommeil de la VM de PREPROD à 19h&lt;/li&gt;
&lt;li&gt;Reveil de la VM de PREPROD à 8h&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Commit du fichier &lt;code&gt;.clever.json&lt;/code&gt; qui contient les infos pour accéder aux 2 machines.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;L&amp;rsquo;ensemble des jobs/tâches sont définies dans le fichier &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; à la racine du repository Git.&lt;/p&gt;
&lt;p&gt;Des variables d&amp;rsquo;environnement ont été définies dans le projet Gitlab pour être accessible par Gitlab CI :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;APP_ID_PREPROD&lt;/li&gt;
&lt;li&gt;APP_ID_PROD&lt;/li&gt;
&lt;li&gt;APP_ALIAS_PREPROD&lt;/li&gt;
&lt;li&gt;APP_ALIAS_PROD&lt;/li&gt;
&lt;li&gt;APP_NAME_PREPROD&lt;/li&gt;
&lt;li&gt;APP_NAME_PROD&lt;/li&gt;
&lt;li&gt;CLEVER_SECRET&lt;/li&gt;
&lt;li&gt;CLEVER_TOKEN&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;réinstallation-des-environnements&#34;&gt;(Ré)Installation des environnements&lt;/h3&gt;
&lt;p&gt;2 jobs, à lancer manuellement sont disponibles dans Gitlab-ci.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;install_preprod&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;install_prod&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ces 2 jobs réinstallent complètement le site (réinstallation du profil d&amp;rsquo;install)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;install_preprod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;preproduction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;:  &lt;span style=&#34;color:#ae81ff&#34;&gt;https://$APP_NAME_PREPROD.cleverapps.io&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;when&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;manual&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/release/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;except&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;schedules&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/latest/clever-tools-latest_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-latest_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever login --token $CLEVER_TOKEN --secret $CLEVER_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever env set CC_PRE_RUN_HOOK &amp;#34;composer.phar run-script drupal-monsite-default-install&amp;#34; --alias $APP_ALIAS_PREPROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever deploy --alias $APP_ALIAS_PREPROD -f&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;install_prod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;production&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;:  &lt;span style=&#34;color:#ae81ff&#34;&gt;https://$APP_NAME_PROD.cleverapps.io&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;when&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;manual&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tags&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/latest/clever-tools-latest_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-latest_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever login --token $CLEVER_TOKEN --secret $CLEVER_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever env set CC_PRE_RUN_HOOK &amp;#34;composer.phar run-script drupal-monsite-default-install&amp;#34; --alias $APP_ALIAS_PROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever deploy --alias $APP_ALIAS_PROD -f&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Le déploiement est géré par 3 nouveaux stages.&lt;br&gt;
Le déploiement en prod, s&amp;rsquo;il est réussi, va déclencher le job &lt;code&gt;update_info_prod&lt;/code&gt; et modifier la variable d&amp;rsquo;environnement GIT_TAG qui peut nous permettre de tracker simplement la dernière version déployée.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;deploy_preprod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;deploy_preprod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;preproduction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;:  &lt;span style=&#34;color:#ae81ff&#34;&gt;https://$APP_NAME_PREPROD.cleverapps.io&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/release/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/clevercloud/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;except&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;schedules&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/1.0.0/clever-tools-1.0.0_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-1.0.0_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever env set CC_PRE_RUN_HOOK &amp;#34;composer.phar run-script drupal-update-all&amp;#34; --alias $APP_ALIAS_PREPROD -v&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever deploy --alias $APP_ALIAS_PREPROD -f -v&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;deploy_prod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;deploy_prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;production&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;:  &lt;span style=&#34;color:#ae81ff&#34;&gt;https://$APP_NAME_PROD.cleverapps.io&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;when&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;manual&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tags&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/latest/clever-tools-latest_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-latest_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever login --token $CLEVER_TOKEN --secret $CLEVER_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever env set CC_PRE_RUN_HOOK &amp;#34;composer.phar run-script drupal-update-all&amp;#34; --alias $APP_ALIAS_PROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever deploy --alias $APP_ALIAS_PROD -f&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;allow_failure&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;update_variable_prod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;update_info_prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;production&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;:  &lt;span style=&#34;color:#ae81ff&#34;&gt;https://$APP_NAME_PROD.cleverapps.io&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tags&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/latest/clever-tools-latest_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-latest_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever login --token $CLEVER_TOKEN --secret $CLEVER_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever env set GIT_TAG $CI_COMMIT_TAG --alias $APP_ALIAS_PROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;when&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;on_success&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pour la PREPROD, nous avons également planifiés des jobs automatiques qui vont arrêter et démarrer la machine.&lt;br&gt;
Ces 2 jobs sont définis via l&amp;rsquo;interface Gitlab et contiennent des variables dédiées (&lt;code&gt;SLEEPING&lt;/code&gt; et &lt;code&gt;WAKEUP&lt;/code&gt;)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;good_night_preprod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;money&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;$SLEEPING == &amp;#34;PREPROD&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/latest/clever-tools-latest_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-latest_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever login --token $CLEVER_TOKEN --secret $CLEVER_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever stop --alias $APP_ALIAS_PREPROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;wakeup_preprod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;money&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;$WAKEUP == &amp;#34;PREPROD&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/latest/clever-tools-latest_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-latest_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever login --token $CLEVER_TOKEN --secret $CLEVER_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever env set CC_PRE_RUN_HOOK &amp;#34;composer.phar run-script drupal-update-all&amp;#34; --alias $APP_ALIAS_PREPROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever restart --alias $APP_ALIAS_PREPROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Le fichier gitlab-ci.yml complet&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;debian:9-slim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;GIT_STRATEGY&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;clone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;stages&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;deploy_preprod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;deploy_prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;update_info_prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;money&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;deploy_preprod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;deploy_preprod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;preproduction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;:  &lt;span style=&#34;color:#ae81ff&#34;&gt;https://$APP_NAME_PREPROD.cleverapps.io&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/release/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/clevercloud/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;except&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;schedules&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/1.0.0/clever-tools-1.0.0_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-1.0.0_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever env set CC_PRE_RUN_HOOK &amp;#34;composer.phar run-script drupal-update-all&amp;#34; --alias $APP_ALIAS_PREPROD -v&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever deploy --alias $APP_ALIAS_PREPROD -f -v&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;deploy_prod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;deploy_prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;production&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;:  &lt;span style=&#34;color:#ae81ff&#34;&gt;https://$APP_NAME_PROD.cleverapps.io&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;when&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;manual&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tags&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/latest/clever-tools-latest_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-latest_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever login --token $CLEVER_TOKEN --secret $CLEVER_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever env set CC_PRE_RUN_HOOK &amp;#34;composer.phar run-script drupal-update-all&amp;#34; --alias $APP_ALIAS_PROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever deploy --alias $APP_ALIAS_PROD -f&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;allow_failure&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;update_variable_prod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;update_info_prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;production&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;:  &lt;span style=&#34;color:#ae81ff&#34;&gt;https://$APP_NAME_PROD.cleverapps.io&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tags&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/latest/clever-tools-latest_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-latest_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever login --token $CLEVER_TOKEN --secret $CLEVER_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever env set GIT_TAG $CI_COMMIT_TAG --alias $APP_ALIAS_PROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;when&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;on_success&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;good_night_preprod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;money&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;$SLEEPING == &amp;#34;PREPROD&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/latest/clever-tools-latest_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-latest_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever login --token $CLEVER_TOKEN --secret $CLEVER_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever stop --alias $APP_ALIAS_PREPROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;wakeup_preprod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;money&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#ae81ff&#34;&gt;$WAKEUP == &amp;#34;PREPROD&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/latest/clever-tools-latest_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-latest_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever login --token $CLEVER_TOKEN --secret $CLEVER_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever env set CC_PRE_RUN_HOOK &amp;#34;composer.phar run-script drupal-update-all&amp;#34; --alias $APP_ALIAS_PREPROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever restart --alias $APP_ALIAS_PREPROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;install_preprod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;preproduction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;:  &lt;span style=&#34;color:#ae81ff&#34;&gt;https://$APP_NAME_PREPROD.cleverapps.io&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;when&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;manual&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;/release/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;except&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;schedules&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/latest/clever-tools-latest_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-latest_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever login --token $CLEVER_TOKEN --secret $CLEVER_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever env set CC_PRE_RUN_HOOK &amp;#34;composer.phar run-script drupal-monsite-default-install&amp;#34; --alias $APP_ALIAS_PREPROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever deploy --alias $APP_ALIAS_PREPROD -f&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;install_prod&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;stage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;production&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;:  &lt;span style=&#34;color:#ae81ff&#34;&gt;https://$APP_NAME_PROD.cleverapps.io&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;when&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;manual&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;before_script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get update -yqq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;apt-get install git curl -y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;only&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tags&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;script&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;curl -O https://clever-tools.cellar.services.clever-cloud.com/releases/latest/clever-tools-latest_linux.tar.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;tar -xvf clever-tools-latest_linux.tar.gz --strip-components=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever login --token $CLEVER_TOKEN --secret $CLEVER_SECRET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever env set CC_PRE_RUN_HOOK &amp;#34;composer.phar run-script drupal-monsite-default-install&amp;#34; --alias $APP_ALIAS_PROD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#ae81ff&#34;&gt;./clever deploy --alias $APP_ALIAS_PROD -f&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      
    </item>
    
    <item>
      <title>Gérer des profils distincts dans Git</title>
      <link>https://gastaud.io/article/git-gerer-profils/</link>
      <pubDate>Thu, 24 Jan 2019 00:02:55 +0100</pubDate>
      
      <guid>https://gastaud.io/article/git-gerer-profils/</guid>
      
        <description>&lt;p&gt;Vous utilisez votre ordinateur pour travailler et, plus que jamais, il vous arrive sûrement d&amp;rsquo;utiliser Git (que feriez-vous sur cet article sinon ?).&lt;br&gt;
Peut-être vous arrive-t-il aussi de travailler sur un projet personnel sur ce même ordinateur ?&lt;br&gt;
Ou de contribuer à un projet Open-Source, toujours sur la même machine.&lt;/p&gt;
&lt;p&gt;Vous avez probablement défini une identité (nom + mail) globale à votre machine et vous la surchargée pour chaque projet en fonction du contexte.&lt;/p&gt;
&lt;p&gt;Parfait !&lt;/p&gt;
&lt;p&gt;Et pourtant malgré ces précautions d&amp;rsquo;usage, qui n&amp;rsquo;a jamais commité dans un projet avec une mauvaise identité ?
Parfois peut être vous en vous rendu compte tardivement et votre email personnel se retrouve maintenant &lt;em&gt;ad vitam æternam&lt;/em&gt; dans les logs d&amp;rsquo;un projet.&lt;/p&gt;
&lt;p&gt;Alors comment essayer de limiter le risque d&amp;rsquo;erreurs ?&lt;/p&gt;
&lt;p&gt;Pourrait-on automatiser la sélection de la bonne identité pour nos projets ?&lt;/p&gt;
&lt;p&gt;Et bien, la bonne nouvelle est que &lt;strong&gt;la réponse est OUI&lt;/strong&gt;  et que nous allons voir comment juste après.&lt;/p&gt;
&lt;h2 id=&#34;gitconfig-et-includes-conditionnels-grâce-à-includeif&#34;&gt;.gitconfig et includes conditionnels grâce à IncludeIf&lt;/h2&gt;
&lt;p&gt;Prenons le fichier &lt;code&gt;.gitconfig&lt;/code&gt;, généralement présent dans votre &lt;code&gt;$HOME&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[user]
	name = Jean-Yves Gastaud
	email = mon.super@mail.com

[alias]
  amend = commit --amend
  st = status
  co = checkout
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ce fichier défini notre identité par défaut et nos aliases globaux.&lt;/p&gt;
&lt;p&gt;Grâce à utilisation de la directive &lt;code&gt;includeIf&lt;/code&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; dans notre fichier &lt;code&gt;.gitconfig&lt;/code&gt;, nous pouvons maintenant ajouter des includes conditionnels liés, notamment à des répertoires.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[includeIf &amp;#34;gitdir:/workspace/work/&amp;#34;]
  path = ~/.gitconfig-work

[includeIf &amp;#34;gitdir:/workspace/opensource/&amp;#34;]
  path = ~/.gitconfig-opensource

[includeIf &amp;#34;gitdir:/workspace/perso/&amp;#34;]
  path = ~/.gitconfig-perso
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pour chaque &lt;code&gt;includeIf&lt;/code&gt; défini, il ne nous reste plus qu&amp;rsquo;à créer le fichier correspondant au chemin que nous avons défini dans &lt;code&gt;path&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Dans le fichier &lt;code&gt;~/.gitconfig-work&lt;/code&gt;, nous n&amp;rsquo;avons donc plus qu&amp;rsquo;à ajouter ou surcharger les configurations qui nous intéresse.&lt;/p&gt;
&lt;p&gt;Exemple :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[user]
        email = my.work@mail.com

[core]
        editor = &amp;#34;code -w&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Dans ce fichier, on surcharge donc notre email et on ajoute un éditeur de code par défaut.&lt;/p&gt;
&lt;p&gt;Maintenant, tout dossier sous le répertoire &lt;code&gt;/workspace/work&lt;/code&gt; bénéficiera automatiquement du chargement des configuration fichier &lt;code&gt;.gitconfig&lt;/code&gt;, surcharger ou compléter par celles du fichier &lt;code&gt;.gitconfig-work&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Pour vérifier votre configuration, allez dans n&amp;rsquo;importe quel répertoire sous le répertoire ciblé, &lt;code&gt;/workspace/work&lt;/code&gt; dans notre exemple et lancer la commande &lt;code&gt;git config -l&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Vous devriez voir la fusion de vos fichiers de configs.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;user.name=Jean-Yves Gastaud
email = mon.super@mail.com
alias.amend=commit --amend
alias.st=status
alias.co=checkout
includeif.gitdir:/workspace/work/.path=~/.gitconfig-work
user.email=my.work@mail.com
core.editor=code -w
includeif.gitdir:/workspace/opensource/.path=~/.gitconfig-opensource
includeif.gitdir:/workspace/perso/.path=~/.gitconfig-perso
core.repositoryformatversion=0
core.filemode=true
…
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Comme vous pouvez le constater, les 2 mails définis sont présents dans le listing.&lt;br&gt;
Le dernier &amp;ldquo;parlant&amp;rdquo; ayant raison, c&amp;rsquo;est donc bien la valeur du fichier &lt;code&gt;.gitconfig-work&lt;/code&gt; qui sera considéré lors du commit.&lt;/p&gt;
&lt;p&gt;Vous remarquerez aussi que les 2 autres includes sont listés mais n&amp;rsquo;ajoutent pas de nouvelles variables / surcharges car leur condition d&amp;rsquo;application n&amp;rsquo;est pas remplie.&lt;/p&gt;
&lt;p&gt;Cela nous laisse toujours la possibilité de surcharger, localement au repository, toutes configurations souhaitées, comme avant.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;En quelques lignes et une gestion simple de vos répertoires de travail, il vous est donc possible de ne plus risquer de vous tromper dans le changement de vos identités.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Depuis la version 2.13 de Git (mai 2017). &lt;a href=&#34;https://git-scm.com/docs/git-config#_includes&#34;&gt;Documentation sur les Includes dans Git&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
      
    </item>
    
    <item>
      <title>Mon workflow Git</title>
      <link>https://gastaud.io/article/git-workflow/</link>
      <pubDate>Tue, 22 Jan 2019 08:51:19 +0100</pubDate>
      
      <guid>https://gastaud.io/article/git-workflow/</guid>
      
        <description>&lt;p&gt;Résumé du workflow Git, en ligne de commande, que j&amp;rsquo;applique de façon quasi-systématique à mes projets.&lt;/p&gt;
&lt;p&gt;Dans cet article, je n&amp;rsquo;entrerai pas le détail de la gestion des Pull Request / Merge Request, des process de validation&amp;hellip;&lt;/p&gt;
&lt;p&gt;Ces éléments peuvent, bien entendu, modifier légèrement le process en fonction des contraintes que peuvent avoir les outils utilisés.&lt;/p&gt;
&lt;h2 id=&#34;branches-principales&#34;&gt;Branches principales&lt;/h2&gt;
&lt;p&gt;Au démarrage du projet, 3 branches principales et permanentes (qui seront toujours présentes) sont créées.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;master&lt;/code&gt; : La branche de production&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stage&lt;/code&gt; :  La branche de préproduction. Contient toutes les branches de story / ticket validées, prêtes à passer en production.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dev&lt;/code&gt; : La branche de développement. Contient les branches à tester. Les branches sont mergées dessus au fil de l&amp;rsquo;eau.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A l&amp;rsquo;initialisation, toutes les branches auront donc le même point de départ.&lt;/p&gt;

&lt;link rel=&#34;stylesheet&#34; href=&#34;https://gastaud.io/css/hugo-easy-gallery.css&#34; /&gt;
&lt;div class=&#34;box&#34;&gt;
&lt;figure  class=&#34;center&#34;  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; 
  style=&#34;max-width:400px&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;images/01-init.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;images/01-init.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;Au fil des développements, ces 3 branches, en plus des branches de tickets, vont vivres à des rythmes différents.&lt;/p&gt;
&lt;p&gt;Pour chaque ticket ou story, une nouvelle branche sera créée. Nous verrons plus loin l&amp;rsquo;origine de cette branche.&lt;/p&gt;
&lt;h2 id=&#34;cycle-de-vie-des-branches-principales&#34;&gt;Cycle de vie des branches principales&lt;/h2&gt;
&lt;h3 id=&#34;dev&#34;&gt;dev&lt;/h3&gt;
&lt;p&gt;La branche de &lt;code&gt;dev&lt;/code&gt; reçoit les &lt;em&gt;merges&lt;/em&gt; des branches de ticket au fil de l&amp;rsquo;eau.&lt;/p&gt;
&lt;p&gt;Les branches de ticket peuvent ne pas être rebase au moment du merge dans &lt;code&gt;dev&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Il est possible de merger plusieurs fois une même branche de ticket dans &lt;code&gt;dev&lt;/code&gt;.&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  class=&#34;center&#34;  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; 
  style=&#34;max-width:400px&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;images/02-dev-branch.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;images/02-dev-branch.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;h3 id=&#34;stage&#34;&gt;stage&lt;/h3&gt;
&lt;p&gt;Tous les développements ou les créations de nouvelles branches partent de la branche &lt;code&gt;stage&lt;/code&gt;.&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  class=&#34;center&#34;  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; 
  style=&#34;max-width:500px&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;images/03.1-stage-branch.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;images/03.1-stage-branch.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;&lt;h4&gt;merge de la branche t2 dans stage&lt;/h4&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;Les merges sur &lt;code&gt;stage&lt;/code&gt; doivent être &lt;strong&gt;obligatoirement&lt;/strong&gt; fait en &lt;code&gt;fast-forward&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Cela implique que chaque branche est &lt;code&gt;rebase&lt;/code&gt; avant d&amp;rsquo;être mergée dans &lt;code&gt;stage&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On garde ainsi un historique propre et linéaire.&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  class=&#34;center&#34;  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; 
  style=&#34;max-width:400px&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;images/03.1-stage-ff.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;images/03.1-stage-ff.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;&lt;h4&gt;merge avec fast-forward&lt;/h4&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;En cas de merge de multiples branches, le travail peut être un peu fastidieux car il implique de passer sur chaque branche 1 par 1 pour la rebase avant de la merger.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;master&#34;&gt;master&lt;/h3&gt;
&lt;p&gt;On ne merge sur &lt;code&gt;master&lt;/code&gt; que dans 2 cas :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;lors d&amp;rsquo;un passage en production de fin de sprint ou de cycle de release. Le merge se fait uniquement via la branche &lt;code&gt;stage&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;en cas de hotfix. Via une branche de ticket.&lt;/li&gt;
&lt;/ol&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  class=&#34;center&#34;  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; 
  style=&#34;max-width:400px&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;images/04-master-branch.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;images/04-master-branch.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;&lt;h4&gt;merge de stage dans master&lt;/h4&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;La branche &lt;code&gt;master&lt;/code&gt; ne doit &lt;strong&gt;jamais être rebase ou &amp;ldquo;push forcée&amp;rdquo;&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Idéalement la branche &lt;code&gt;master&lt;/code&gt; est protégée pour éviter les erreurs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;réinitialisation-des-branches&#34;&gt;Réinitialisation des branches&lt;/h3&gt;
&lt;h4 id=&#34;cas-1--merge-dans-master&#34;&gt;Cas 1 : Merge dans master&lt;/h4&gt;
&lt;p&gt;A la suite d&amp;rsquo;un merge dans &lt;code&gt;master&lt;/code&gt;, il conviendra,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;de rebase &lt;code&gt;stage&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  class=&#34;center&#34;  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; 
  style=&#34;max-width:500px&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;images/05-reinit-branches.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;images/05-reinit-branches.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;&lt;h4&gt;merge de stage dans master&lt;/h4&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;de réinitialiser &lt;code&gt;dev&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  class=&#34;center&#34;  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; 
  style=&#34;max-width:500px&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;images/05.1-reinit-branches.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;images/05.1-reinit-branches.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;&lt;h4&gt;réinitialisation de dev&lt;/h4&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;h4 id=&#34;cas-2--divergences-des-branches&#34;&gt;Cas 2 : Divergences des branches&lt;/h4&gt;
&lt;p&gt;Avec le fait d&amp;rsquo;accepter n&amp;rsquo;importe quel merge sur &lt;code&gt;dev&lt;/code&gt;, cette branche peut devenir rapidement très différentes, diverger, de la branche de production, &lt;code&gt;master&lt;/code&gt;, voir de &lt;code&gt;stage&lt;/code&gt; comme illustré ci-dessous :&lt;/p&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  class=&#34;center&#34;  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; 
  style=&#34;max-width:300px&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;images/06-divergences-branches.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;images/06-divergences-branches.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;&lt;h4&gt;Divergences importantes entre stage et dev&lt;/h4&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;La branche &lt;code&gt;dev&lt;/code&gt; sera donc régulièrement réinitialisée à partir de la branche &lt;code&gt;stage&lt;/code&gt;, qui rappelons-le contient la dernière version des tickets validés et prêts à passer en production.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Concrètement, nous allons donc faire un &lt;code&gt;git reset --hard origin/stage&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Une fois la réinitialisation faite, il conviendra, si cela est nécessaire, de :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;rebase&lt;/code&gt; les branches de développements à partir de &lt;code&gt;stage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;(Re)merger dans &lt;code&gt;dev&lt;/code&gt; les branches qui auraient pu être en attente de tests.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Dans notre exemple, les branches &lt;code&gt;t1-new-feat&lt;/code&gt;, &lt;code&gt;t2-new-feat&lt;/code&gt;, &lt;code&gt;t3-new-feat&lt;/code&gt; n&amp;rsquo;ont pas encore été mergées dans &lt;code&gt;stage&lt;/code&gt; et seront donc &lt;code&gt;rebase&lt;/code&gt; puis &lt;code&gt;merge&lt;/code&gt; dans &lt;code&gt;dev&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;div class=&#34;box&#34;&gt;
&lt;figure  class=&#34;center&#34;  itemprop=&#34;associatedMedia&#34;
  itemscope itemtype=&#34;http://schema.org/ImageObject&#34; 
  style=&#34;max-width:300px&#34; &gt;
    &lt;div class=&#34;img&#34;&gt;
      &lt;img itemprop=&#34;thumbnail&#34; src=&#34;images/06.1-divergences-branches.svg&#34; /&gt;
    &lt;/div&gt;
    &lt;a href=&#34;images/06.1-divergences-branches.svg&#34; itemprop=&#34;contentUrl&#34;&gt;&lt;/a&gt;
      &lt;figcaption&gt;&lt;h4&gt;Historique git propre&lt;/h4&gt;
      &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Détaillons maintenant le workflow de gestion des tickets via Git.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;workflow-ticket--story&#34;&gt;Workflow ticket / story&lt;/h2&gt;
&lt;p&gt;Pour traiter un nouveau ticket, nous commençons d&amp;rsquo;abord par se mettre sur la branche &lt;code&gt;stage&lt;/code&gt; et s&amp;rsquo;assurer qu&amp;rsquo;elle soit à jour de notre &lt;code&gt;remote&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git checkout stage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git fetch
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git reset --hard origin/stage
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nous avons ainsi une branche locale &lt;code&gt;stage&lt;/code&gt; à jour de notre &lt;code&gt;remote&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Si vous avez plusieurs remote, un &lt;code&gt;git fetch --all&lt;/code&gt; est recommandé et il conviendra d&amp;rsquo;adapter le &lt;code&gt;reset --hard&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Créons maintenant notre branche de ticket/story.&lt;/p&gt;
&lt;p&gt;Pour cela, nous partons &lt;strong&gt;toujours&lt;/strong&gt; de la branche &lt;code&gt;stage&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git checkout -b &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;NUM-TICKET&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;-&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;short-description&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Si vous utilisez Gitlab pour vos tickets, il existe une fonction permettant de générer directement des branches à partir d&amp;rsquo;un ticket et ainsi d&amp;rsquo;avoir un nommage de vos branches cohérent.&lt;br&gt;
Gitlab se base sur le titre du ticket pour nommer la branche.&lt;br&gt;
Il conviendra d&amp;rsquo;avoir définie la branche &lt;code&gt;stage&lt;/code&gt; comme branche par défaut dans Gitlab pour que le process expliqué ci-dessus s&amp;rsquo;applique automatiquement.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Une fois le ticket terminé, ou dans un état suffisamment stable pour être testé, nous pouvons merger la branche dans &lt;code&gt;dev&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git checkout dev
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git merge &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;NUM-TICKET&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;-&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;short-description&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Si le ticket n&amp;rsquo;est pas validé, vous pouvez merger à nouveau la branche de ticket dans &lt;code&gt;dev&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Si le ticket est validé (tests automatisés validés, recette OK&amp;hellip;), il est donc considéré comme pouvant potentiellement passer en production.&lt;/p&gt;
&lt;p&gt;Dans le cadre d&amp;rsquo;un projet Agile avec des sprints ou d&amp;rsquo;une TMA avec lotissement de correctifs / évolutions, le ticket ne passera potentiellement pas en production.&lt;/p&gt;
&lt;p&gt;Notre branche de ticket va donc être mergé dans la branche &lt;code&gt;stage&lt;/code&gt; (notre préproduction).&lt;/p&gt;
&lt;p&gt;Avant le merge, assurons nous de nouveau que &lt;code&gt;stage&lt;/code&gt; est (toujours) à jour localement.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git checkout stage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Mise à jour de stage si nécessaire; Voir plus haut&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git merge --ff-only &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;NUM-TICKET&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;-&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;short-description&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git push origin stage
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Si vous avez un message d&amp;rsquo;erreur, c&amp;rsquo;est probablement que la branche de ticket n&amp;rsquo;est pas à jour de &lt;code&gt;stage&lt;/code&gt;.&lt;br&gt;
Pensez à la &lt;code&gt;rebase&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Si une autre branche de ticket (également validée) doit être mergée sur &lt;code&gt;stage&lt;/code&gt;, nous devons donc rebase cette branche avant de pouvoir la merger.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git checkout &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;NUM-TICKET&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;-&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;short-description&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git rebase origin/stage
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et nous recommençons ensuite l&amp;rsquo;étape précédente.&lt;/p&gt;
&lt;p&gt;Le code de &lt;code&gt;stage&lt;/code&gt; peut ainsi être déployé en préproduction pour validation finale et globale.&lt;/p&gt;
&lt;p&gt;Une fois le sprint fini ou la release complétée, nous allons finalement merger l&amp;rsquo;ensemble de la branche &lt;code&gt;stage&lt;/code&gt; sur &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git checkout master
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Mise à jour de la branche master locale si nécessaire&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git merge origin/stage
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* git push origin master
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Ici, nous ne mergons pas la branche stage en &lt;code&gt;fast-forward&lt;/code&gt; afin d&amp;rsquo;avoir une lecture simplifiée / rapide, grâce au commit de merge, de la dernière livraison.&lt;br&gt;
Je vous laisse choisir si vous préférez cela ou non.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Enfin il est possible de tagger la branche &lt;code&gt;master&lt;/code&gt; et publier notre release.&lt;/p&gt;
&lt;p&gt;Une fois notre branche &lt;code&gt;stage&lt;/code&gt; mergée dans &lt;code&gt;master&lt;/code&gt;, nous pouvons réinitialiser nos branches &lt;code&gt;stage&lt;/code&gt; et &lt;code&gt;dev&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git checkout stage &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; git reset --hard origin/master
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;faq&#34;&gt;FAQ&lt;/h2&gt;
&lt;p&gt;Quelques questions / objections récurrentes reviennent régulièrement quand je présente ce workflow.&lt;/p&gt;
&lt;h3 id=&#34;pourquoi-avoir-une-branche-de-preproduction--stage-&#34;&gt;Pourquoi avoir une branche de preproduction / stage ?&lt;/h3&gt;
&lt;p&gt;C&amp;rsquo;est certainement le point qui fait le plus débat.&lt;/p&gt;
&lt;p&gt;Il serait possible de se passer de la branche &lt;code&gt;stage&lt;/code&gt; et merger directement nos tickets dans &lt;code&gt;master&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;master&lt;/code&gt; serait ainsi toujours la branche par défaut, le point d&amp;rsquo;origine de tous les nouveaux développements.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;apprécie d&amp;rsquo;avoir une branche &lt;code&gt;stage&lt;/code&gt; pour les raisons suivantes :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;En cas de bug sur ma branche &lt;code&gt;stage&lt;/code&gt;&lt;/strong&gt; : parceque 2 développements ne sont finalement pas totalement compatibles entre eux ou qu&amp;rsquo;ils entrainent une régression, il est possible simplement d&amp;rsquo;ajouter un &lt;code&gt;hotfix&lt;/code&gt; sur &lt;code&gt;stage&lt;/code&gt; en s&amp;rsquo;assurant qu&amp;rsquo;il ira en prod,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;En cas de non validation d&amp;rsquo;un ticket au sein d&amp;rsquo;une release&lt;/strong&gt; :  il est autorisé de ré-écrire l&amp;rsquo;historique de &lt;code&gt;stage&lt;/code&gt; (même si cela doit être exceptionnel) sans grosses contraintes de communication avec l&amp;rsquo;ensembe de l&amp;rsquo;équipe.&lt;br&gt;
Alors que la ré-écriture de l&amp;rsquo;historique de &lt;code&gt;master&lt;/code&gt; n&amp;rsquo;est pas autorisée.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Avoir une branche &lt;code&gt;stage&lt;/code&gt; offre donc une plus grande souplesse dans le workflow.&lt;/p&gt;
&lt;h3 id=&#34;rebase-chaque-branche-de-travail-avant-le-merge-sur-stage-peut-être-long-et-conflictuel&#34;&gt;Rebase chaque branche de travail avant le merge sur &lt;code&gt;stage&lt;/code&gt; peut être long et conflictuel&lt;/h3&gt;
&lt;p&gt;Cela n&amp;rsquo;est vrai que si vos branches de travail sont longues et trainent dans le temps.&lt;br&gt;
Éventuellement si vous êtes un très grand nombre de développeurs à travailler sur de nouvelles branches simultanéement.&lt;/p&gt;
&lt;p&gt;Il est donc nécessaire que l&amp;rsquo;équipe applique un minimum de rigeur sur la gestion des points suivants :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Rebase régulier des branches de travail depuis &lt;code&gt;stage&lt;/code&gt; : les principaux conflits sont ainsi résolus directement par le développeur. Il peut s&amp;rsquo;assurer que son travail n&amp;rsquo;a pas été impacté.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les branches de travail doivent avoir une durée de vie courte, quelques heures ou jours maximum.&lt;br&gt;
Au plus les process de tests / non régressions sont automatisés, au plus vous serez en mesure de réduire ce délai.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;comment-faire-si-une-branche-de-travail-dépend-dun-autre-développement-en-cours-et-non-disponible-sur-stage-&#34;&gt;Comment faire si une branche de travail dépend d&amp;rsquo;un autre développement en cours et non disponible sur &lt;code&gt;stage&lt;/code&gt; ?&lt;/h3&gt;
&lt;p&gt;C&amp;rsquo;est une question sans réelle solution que l&amp;rsquo;on retrouvera dans tous workflows.&lt;/p&gt;
&lt;p&gt;En fonction du niveau de dépendance, 2 cas peuvent s&amp;rsquo;appliquer :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Je ne dépend que d&amp;rsquo;un commit présent dans une autre branche&lt;/strong&gt; : dans ce cas, je préconise de &lt;code&gt;cherry-pick&lt;/code&gt; le commit dans la branche. On garde ainsi nos branches indépendantes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ma nouvelle feature vient compléter une autre branche&lt;/strong&gt; : dans ce cas, ma suggestion est d&amp;rsquo;avoir une branche commune qui regroupera les 2 développements au moment du merge dans &lt;code&gt;stage&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Notre nouvelle branche pourra donc, selon un choix à discuter avec les équipes,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;soit partir de la branche du ticket dont je dépend et être rebase régulièrement avec les nouveaux développements de cette branche,&lt;/li&gt;
&lt;li&gt;soit travailler directement sur la même branche.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Alors qu&amp;rsquo;en pensez-vous ? A vous maintenant de réagir et partager vos propres workflows&lt;/strong&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;graph git généré grace à &lt;a href=&#34;https://github.com/deuill/grawkit&#34;&gt;Grawkit&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
      
    </item>
    
    <item>
      <title>Git - Comparer les commits de 2 branches Git</title>
      <link>https://gastaud.io/article/git-compare-branches/</link>
      <pubDate>Fri, 18 Jan 2019 09:50:14 +0100</pubDate>
      
      <guid>https://gastaud.io/article/git-compare-branches/</guid>
      
        <description>&lt;p&gt;Listing des différentes manières de comparer des branches dans Git.&lt;/p&gt;
&lt;h2 id=&#34;tldr&#34;&gt;TLDR;&lt;/h2&gt;
&lt;p&gt;Toute la magie réside dans l&amp;rsquo;utilisation des plages de révision et la syntaxe &lt;code&gt;BRANCH_1..BRANCH_2&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;connaitre-les-différences-entre-2-branches&#34;&gt;Connaitre les différences entre 2 branches&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git diff [BRANCH_1]..[BRANCH_2]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;retourne les différences de code entre 2 branches.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;diff --git a/readme.txt b/readme.txt
index ac28f91..ae362e4 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1 @@
-Coucou
+Coucou2
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On constate ici que dans le fichier readme.txt de a branche &lt;code&gt;b&lt;/code&gt;, le mot &lt;code&gt;Coucou&lt;/code&gt; a été remplacé par &lt;code&gt;Coucou2&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;comparer-les-commits-de-2-branches&#34;&gt;Comparer les commits de 2 branches&lt;/h2&gt;
&lt;p&gt;Avec l&amp;rsquo;utilisation de &lt;code&gt;diff&lt;/code&gt;, nous n&amp;rsquo;avons cependant pas la vision sur les commits qui ont créé le delta.&lt;/p&gt;
&lt;p&gt;Pour ce type de comparaison, il est possible d&amp;rsquo;utiliser &lt;code&gt;git log&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git log [BRANCH_1]..[BRANCH_2]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;retourne uniquement les commits de &lt;code&gt;branch_2&lt;/code&gt; non présents dans &lt;code&gt;branch_1&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;commit fc372ddecf5d98a8ba0d000a3c1ccf77a4f1237b (b)
Author: Jean-Yves Gastaud &amp;lt;jeanyves@gastaud.io&amp;gt;
Date:   Thu Jan 10 16:53:07 2019 +0100

    third commit
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pour avoir plus de détails sur le contenu du changement, il est possible d&amp;rsquo;utiliser toutes la panoplie d&amp;rsquo;options de la commande &lt;code&gt;log&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;utilisation des options &lt;code&gt;--graph&lt;/code&gt; et &lt;code&gt;--stat&lt;/code&gt; est particulièrement utile dans ce cas.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ git log --oneline --decorate --graph --stat [BRANCH_1]..[BRANCH_2]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;retourne&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;* fc372dd (b) 3eme commit
   readme.txt | 2 +-
   1 file changed, 1 insertion(+), 1 deletion(-)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Admettons maintenant que &lt;code&gt;branch_1&lt;/code&gt; est été rebase par rapport à &lt;code&gt;master&lt;/code&gt; mais pas la &lt;code&gt;branch_2&lt;/code&gt;, est-ce que mon delta de commit sera toujours cohérent ?&lt;/p&gt;
&lt;p&gt;Prenons l&amp;rsquo;exemple suivant :&lt;/p&gt;
&lt;p&gt;&lt;code&gt;master&lt;/code&gt; contient&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;* 81faeea 2019-01-18 | a commit in master (master) [Jean-Yves Gastaud]
* 3be0b31 2019-01-10 | 1er commit [Jean-Yves Gastaud]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;branch_1&lt;/code&gt; a été rebase avec les données de &lt;code&gt;master&lt;/code&gt; et contient 2 commits de plus.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;* 5b3a95a 2019-01-18 | a commit (BRANCH_1) [Jean-Yves Gastaud]
* 19b7763 2019-01-10 | 2nd commit [Jean-Yves Gastaud]
* 81faeea 2019-01-18 | a commit in master (master) [Jean-Yves Gastaud]
* 3be0b31 2019-01-10 | 1er commit [Jean-Yves Gastaud]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;branch_2&lt;/code&gt; quant à elle n&amp;rsquo;est pas rebase et par toujours du 1er commit sur &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;* fc372dd 2019-01-10 | 3eme commit (BRANCH_2) [Jean-Yves Gastaud]
* 3be0b31 2019-01-10 | 1er commit [Jean-Yves Gastaud]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Retestons notre&lt;br&gt;
&lt;code&gt;git log --oneline --decorate --graph --stat [BRANCH_1]..[BRANCH_2]&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;* fc372dd (BRANCH_2) 3eme commit
   readme.txt | 2 +-
   1 file changed, 1 insertion(+), 1 deletion(-)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Super, nous voyons toujours notre commit non présent dans la &lt;code&gt;branch_1&lt;/code&gt; !&lt;/p&gt;
&lt;p&gt;Si besoin de savoir quelles sont les commits de la &lt;code&gt;branch_1&lt;/code&gt; non présents dans &lt;code&gt;branch_2&lt;/code&gt;, il est bien entendu possible d&amp;rsquo;inverser les arguments.&lt;/p&gt;
&lt;p&gt;Ainsi &lt;code&gt;git log --oneline --decorate --graph --stat [BRANCH_2]..[BRANCH_1]&lt;/code&gt; nous renverra&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;* 5b3a95a (BRANCH_1) a commit
|  readme.txt | 3 +--
|  1 file changed, 1 insertion(+), 2 deletions(-)
* 19b7763 2nd commit
|  readme.txt | 3 ++-
|  1 file changed, 2 insertions(+), 1 deletion(-)
* 81faeea (master) a commit in master
   readme.txt | 2 +-
   1 file changed, 1 insertion(+), 1 deletion(-)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Enfin, si notre &lt;code&gt;branch_1&lt;/code&gt; a été mergée dans &lt;code&gt;master&lt;/code&gt;, nous pouvons toujours avoir les mêmes résultats.&lt;/p&gt;
&lt;p&gt;Un &lt;code&gt;git log --oneline --decorate --graph --stat [BRANCH_2]..master&lt;/code&gt; renverra bien l&amp;rsquo;ensemble de l&amp;rsquo;arbre de commits absents.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;*   9eb6957 (HEAD -&amp;gt; master) Merge branch &amp;#39;a&amp;#39;
|\
| * 5b3a95a (a) a commit
| |  readme.txt | 3 +--
| |  1 file changed, 1 insertion(+), 2 deletions(-)
| * 19b7763 2nd commit
|/
|    readme.txt | 3 ++-
|    1 file changed, 2 insertions(+), 1 deletion(-)
* 81faeea a commit in master
   readme.txt | 2 +-
   1 file changed, 1 insertion(+), 1 deletion(-)
&lt;/code&gt;&lt;/pre&gt;</description>
      
    </item>
    
    <item>
      <title>Split JSON avec jq</title>
      <link>https://gastaud.io/article/split-json-jq/</link>
      <pubDate>Wed, 16 Jan 2019 16:36:46 +0100</pubDate>
      
      <guid>https://gastaud.io/article/split-json-jq/</guid>
      
        <description>&lt;p&gt;Vous êtes vous déjà demandé comment découper un JSON en plusieurs &amp;ldquo;sous-&amp;ldquo;fichiers&amp;rdquo; ?&lt;/p&gt;
&lt;p&gt;Si oui, cette ligne de commande est faite pour vous !&lt;/p&gt;
&lt;p&gt;La seule dépendance ici est l&amp;rsquo;utilisation de l&amp;rsquo;outils &lt;a href=&#34;https://stedolan.github.io/jq/&#34;&gt;jq&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Je vous encourage d&amp;rsquo;ailleurs à regarder cet outil très puissant sur la manipulation de JSON.&lt;/p&gt;
&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;jq -c -M &amp;#39;.[]&amp;#39; myfile.json | \
while read line; do echo $line &amp;gt; $(echo $line | jq -r -c &amp;#34;.id&amp;#34;).json; done
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;La commande va parser le fichier &lt;code&gt;myfile.json&lt;/code&gt; et créer 1 fichier pour chaque &lt;code&gt;id&lt;/code&gt; trouvé.&lt;/p&gt;
&lt;p&gt;Cela fonctionne également en récupérant directement la sortie d&amp;rsquo;un service / API&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;exemple&#34;&gt;Exemple&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;echo &amp;#39;[{ &amp;#34;id&amp;#34;: &amp;#34;16&amp;#34;, &amp;#34;name&amp;#34;: &amp;#34;produit 1&amp;#34; }, { &amp;#34;id&amp;#34;: &amp;#34;17&amp;#34;, &amp;#34;name&amp;#34;: &amp;#34;produit 2&amp;#34; }, { &amp;#34;id&amp;#34;: &amp;#34;18&amp;#34;, &amp;#34;name&amp;#34;: &amp;#34;produit 3&amp;#34; }, { &amp;#34;id&amp;#34;: &amp;#34;19&amp;#34;, &amp;#34;name&amp;#34;: &amp;#34;produit 4&amp;#34; }]&amp;#39; | \
jq -c -M &amp;#39;.[]&amp;#39; | \
while read line; do \
echo $line &amp;gt; $(echo $line | jq -r -c &amp;#34;.id&amp;#34;).json; \
done
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;détails&#34;&gt;Détails&lt;/h2&gt;
&lt;h3 id=&#34;parsing-du-fichier-json-initial&#34;&gt;Parsing du fichier JSON initial&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;jq -c -M &amp;#39;.[]&amp;#39; myfile.json
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On va parser le fichier &lt;code&gt;myfile.json&lt;/code&gt; et récupérér 1 ligne pour chaque entrée de 1er niveau.&lt;/p&gt;
&lt;h3 id=&#34;lire-chaque-ligne-et-créer-le-json-associé&#34;&gt;Lire chaque ligne et créer le json associé&lt;/h3&gt;
&lt;p&gt;Tant qu&amp;rsquo;il y a des lignes, on boucle dessus.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;while read line; do 
    ...
done
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On renvoi ensuite la ligne et on utilise de nouveau jq pour récupérer l&amp;rsquo;id afin de nommer le fichier&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;echo $line &amp;gt; $(echo $line | jq -r -c &amp;#34;.id&amp;#34;).json;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;fichier-myfilejson&#34;&gt;Fichier myfile.json&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[
    {
        &amp;#34;id&amp;#34;: &amp;#34;16&amp;#34;,
        &amp;#34;name&amp;#34;: &amp;#34;produit 1&amp;#34;
    },
    {
        &amp;#34;id&amp;#34;: &amp;#34;17&amp;#34;,
        &amp;#34;name&amp;#34;: &amp;#34;produit 2&amp;#34;
    },
    {
        &amp;#34;id&amp;#34;: &amp;#34;18&amp;#34;,
        &amp;#34;name&amp;#34;: &amp;#34;produit 3&amp;#34;
    },
    {
        &amp;#34;id&amp;#34;: &amp;#34;19&amp;#34;,
        &amp;#34;name&amp;#34;: &amp;#34;produit 4&amp;#34;
    }
]
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;options-de-la-commande&#34;&gt;Options de la commande&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-c             compact instead of pretty-printed output;&lt;/code&gt; : nous permet d&amp;rsquo;avoir 1 ligne affiché par résultat&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-M             monochrome (don&#39;t colorize JSON);&lt;/code&gt; : purement esthétique pour ne pas risquer de polluer l&amp;rsquo;extraction&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-r             output raw strings, not JSON texts;&lt;/code&gt; : permet de supprimer le guillemet de sortir de notre ID.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;bonus--ajouter-des-informations-à-un-fichier-json&#34;&gt;Bonus : Ajouter des informations à un fichier JSON&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ jq &amp;#39;. += { &amp;#34;category&amp;#34;: &amp;#34;ma categoie&amp;#34;, &amp;#34;subcategory&amp;#34;: &amp;#34;ma sous categorie&amp;#34; }&amp;#39; 19.json
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;jq va ajouter les entrées &lt;code&gt;category&lt;/code&gt; et &lt;code&gt;subcategory&lt;/code&gt; au fichier &lt;code&gt;19.json&lt;/code&gt; lors de l&amp;rsquo;affichage.&lt;/p&gt;
&lt;p&gt;Il vous ai bien entendu ensuite possible de passer ce nouveau JSON à un nouveau fichier et l&amp;rsquo;enregistrer.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Makefile et parallélisation des jobs</title>
      <link>https://gastaud.io/article/makefile-parallel/</link>
      <pubDate>Wed, 16 Jan 2019 15:18:58 +0100</pubDate>
      
      <guid>https://gastaud.io/article/makefile-parallel/</guid>
      
        <description>&lt;p&gt;PoC / Tests sur l&amp;rsquo;utilisation des jobs parallèles via Make et résultats constatés&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Parallel.html&#34;&gt;https://www.gnu.org/software/make/manual/html_node/Parallel.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;tests-basiques&#34;&gt;Tests basiques&lt;/h2&gt;
&lt;h3 id=&#34;makefile&#34;&gt;Makefile&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;all: test test2 test3 test4 test5 test6 test7

test:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 1&amp;#34;

test2:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 2&amp;#34;

test3: test test2 .FORCE
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 3&amp;#34;

test4:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 4&amp;#34;

test5:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 5&amp;#34;

test6:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 6&amp;#34;

test7:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 7&amp;#34;

.FORCE:
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;tests-sans-parallélisation&#34;&gt;Tests sans parallélisation&lt;/h2&gt;
&lt;p&gt;On exécute 7 jobs à la suite.&lt;/p&gt;
&lt;p&gt;Pour tester plus facilement nos résultats, chaque job dure environ 2 secondes.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ date +&amp;#39;%Y%m%d%H%M%S&amp;#39; &amp;amp;&amp;amp; make &amp;amp;&amp;amp;  date +&amp;#39;%Y%m%d%H%M%S&amp;#39;
20181213172307
---&amp;gt; 1
---&amp;gt; 2
---&amp;gt; 3
---&amp;gt; 4
---&amp;gt; 5
---&amp;gt; 6
---&amp;gt; 7
20181213172321
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Comme prévu, nos jobs mettent 14 secondes à s&amp;rsquo;éxécuter.&lt;/p&gt;
&lt;h3 id=&#34;tests-avec-parallélisation&#34;&gt;Tests avec parallélisation&lt;/h3&gt;
&lt;p&gt;On lance maintenant la même commande en parallélisant les 7 jobs.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ date  +&amp;#39;%Y%m%d%H%M%S&amp;#39; &amp;amp;&amp;amp; make -j7 &amp;amp;&amp;amp; date  +&amp;#39;%Y%m%d%H%M%S&amp;#39;
20181213172242
---&amp;gt; 1
---&amp;gt; 5
---&amp;gt; 7
---&amp;gt; 2
---&amp;gt; 6
---&amp;gt; 4
---&amp;gt; 3
20181213172246
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On a ici un temps d&amp;rsquo;éxécution de 4 secondes correspondant au temps d&amp;rsquo;éxécution du &lt;code&gt;test3&lt;/code&gt; qui est obligé d&amp;rsquo;attendre l&amp;rsquo;éxéution de &lt;code&gt;test1&lt;/code&gt; et &lt;code&gt;test2&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Soucis : Les jobs s&amp;rsquo;exécutent dans un ordre aléatoire.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;job-parallèles-indépendants&#34;&gt;Job Parallèles indépendants&lt;/h2&gt;
&lt;p&gt;Maintenant que nous avons vu comment fonctionne les jobs parallèle avec Make, comment gérer l&amp;rsquo;éxécution de plusieurs étapes ayant des dépendances de façon optimisée ?&lt;/p&gt;
&lt;p&gt;Dans notre exemple, nous allons simuler 2 étapes :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Le clone de 2 repositories Git&lt;/li&gt;
&lt;li&gt;Le lancement d&amp;rsquo;une commande &lt;code&gt;composer&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;makefile-1&#34;&gt;Makefile&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;steps: ## les 2 étapes, sans parallélisation
	$(MAKE) step1
	$(MAKE) step2

steps_j: ## les 2 étapes, avec parallélisation
	$(MAKE) step1 -j2
	$(MAKE) step2 -j2

step1: clone_toto clone_tata

clone_toto:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;git clone toto&amp;#34;

clone_tata:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;git clone tata&amp;#34;

step2: composer_toto composer_tata

composer_toto:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;composer toto&amp;#34;

composer_tata:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;composer tata&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;tests-sans-parallélisation-1&#34;&gt;Tests sans parallélisation&lt;/h3&gt;
&lt;p&gt;On lance notre test de référence&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ date +&amp;#39;%Y%m%d%H%M%S&amp;#39; &amp;amp;&amp;amp; make steps &amp;amp;&amp;amp;  date +&amp;#39;%Y%m%d%H%M%S&amp;#39;
20181213173756
make step1
make[1] : on entre dans le répertoire « /var/www/make-parallel »
git clone toto
git clone tata
make[1] : on quitte le répertoire « /var/www/make-parallel »
make step2
make[1] : on entre dans le répertoire « /var/www/make-parallel »
composer toto
composer tata
make[1] : on quitte le répertoire « /var/www/make-parallel »
20181213173804
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ce test met 48 secondes à s&amp;rsquo;éxécuter.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Make semble particulièrement lent dans les appels récursifs à lui même.&lt;br&gt;
Je n&amp;rsquo;ai pas creusé pourquoi.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Le même test en adaptant &lt;code&gt;steps&lt;/code&gt; comme suit nous fait revenir au timing initialement prévu (8 secondes)&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;steps2: step1 step2
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;tests-avec-parallélisation-1&#34;&gt;Tests avec parallélisation&lt;/h3&gt;
&lt;p&gt;En appliquant les capacités de paralélisation de Make, on peut donc maintenant assurer un ordre d&amp;rsquo;éxécution sur les jobs et lancer en même ceux indépendants.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ date +&amp;#39;%Y%m%d%H%M%S&amp;#39; &amp;amp;&amp;amp; make steps_j &amp;amp;&amp;amp;  date +&amp;#39;%Y%m%d%H%M%S&amp;#39;
20181213173803
make step1 -j2
make[1] : on entre dans le répertoire « /var/www/make-parallel »
git clone toto
git clone tata
make[1] : on quitte le répertoire « /var/www/make-parallel »
make step2 -j2
make[1] : on entre dans le répertoire « /var/www/make-parallel »
composer tata
composer toto
make[1] : on quitte le répertoire « /var/www/make-parallel »
20181213173807
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On obtient une exécution de seulement 4 secondes !&lt;/p&gt;
&lt;h2 id=&#34;notre-makefile-de-tests-complet&#34;&gt;Notre Makefile de tests complet&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;all: test test2 test3 test4 test5 test6 test7

test:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 1&amp;#34;

test2:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 2&amp;#34;

test3: test test2 .FORCE
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 3&amp;#34;

test4:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 4&amp;#34;

test5:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 5&amp;#34;

test6:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 6&amp;#34;

test7:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;---&amp;gt; 7&amp;#34;

.FORCE:

steps:
	$(MAKE) step1
	$(MAKE) step2

steps_j:
	$(MAKE) step1 -j2
	$(MAKE) step2 -j2

step1: clone_toto clone_tata

clone_toto:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;git clone toto&amp;#34;

clone_tata:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;git clone tata&amp;#34;

step2: composer_toto composer_tata

composer_toto:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;composer toto&amp;#34;

composer_tata:
	@sleep 2 &amp;amp;&amp;amp; \
	echo &amp;#34;composer tata&amp;#34;
&lt;/code&gt;&lt;/pre&gt;</description>
      
    </item>
    
    <item>
      <title>Kubernetes a gagné la bataille des orchestrateurs</title>
      <link>https://gastaud.io/article/kubernetes-a-gagne/</link>
      <pubDate>Thu, 05 Jul 2018 00:00:00 +0000</pubDate>
      
      <guid>https://gastaud.io/article/kubernetes-a-gagne/</guid>
      
        <description>&lt;p&gt;L&amp;rsquo;arrivée il y a quelques années de solutions permettant de simplifier la création et gestion de conteneurs, telles que &lt;a href=&#34;https://www.docker.com/&#34;&gt;Docker&lt;/a&gt; ou &lt;a href=&#34;https://coreos.com/rkt/&#34;&gt;rkt&lt;/a&gt;, combinées aux approches micro-services et leurs popularités croissantes ont entraîné rapidement le besoin de solutions dites d&amp;rsquo;&lt;code&gt;orchestration de conteneurs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;De nombreuses solutions d&amp;rsquo;orchestration ont vu le jour et se sont retrouvées disponibles en Open-Source.&lt;br&gt;
&lt;a href=&#34;https://mesosphere.github.io/marathon/&#34;&gt;Apache Mesos Marathon&lt;/a&gt;, &lt;a href=&#34;https://docs.docker.com/swarm/overview/&#34;&gt;Docker Swarm&lt;/a&gt;, &lt;a href=&#34;https://kubernetes.io/&#34;&gt;Kubernetes&lt;/a&gt; ou encore &lt;a href=&#34;https://docs.openstack.org/magnum/latest/&#34;&gt;OpenStack Magnum&lt;/a&gt; permettent toutes de traiter ces problématiques.&lt;/p&gt;
&lt;p&gt;Il y a encore 2 ou 3 ans, les communautés Mesos et Docker avait fait de gros efforts pour rendre Mesos capable d&amp;rsquo;orchestrer des Docker.&lt;/p&gt;
&lt;p&gt;Pourtant, cela n&amp;rsquo;empêcha pas Docker inc. de lancer sa propre solution, Docker Swarm, pour traiter ces aspects. Avec une volonté affichée d&amp;rsquo;être une solution d&amp;rsquo;orchestration plus intégrée à Docker, plus simple à mettre en place tout en  assumant une gestion moines &amp;ldquo;fines&amp;rdquo; des ressources que Mesos.&lt;/p&gt;
&lt;p&gt;Chacun a sa place, pour son besoin. Pas de vraie compétition entre les 2.&lt;/p&gt;
&lt;p&gt;Mesos (via Marathon) semblait avoir pris de l&amp;rsquo;avance sur ces concurrents. En milieu d&amp;rsquo;année 2017, une bascule a commencé à se produire vers Kubernetes, utilisé chez Google depuis plus de 10 ans.&lt;/p&gt;
&lt;p&gt;Alors pourquoi peut-on penser aujourd&amp;rsquo;hui que Kubernetes a gagné cette bataille et devient, un peu au même titre que Docker pour les conteneurs, le standard de l&amp;rsquo;industrie ?&lt;/p&gt;
&lt;h2 id=&#34;des-signes-qui-ne-trompent-pas&#34;&gt;Des signes qui ne trompent pas&lt;/h2&gt;
&lt;h3 id=&#34;une-croissance-très-rapide&#34;&gt;Une croissance très rapide&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Kubernetes est actuellement le projet le plus actif sur Github.&lt;/li&gt;
&lt;li&gt;Les plateformes comme OpenShift ou CoreOS intègrent Kubernetes.&lt;/li&gt;
&lt;li&gt;Le &lt;a href=&#34;https://www.cncf.io/&#34;&gt;CNCF (Cloud Native Computing Foundation)&lt;/a&gt; en a fait le 1er projet &lt;code&gt;Graduated&lt;/code&gt;, son rang le plus haut.&lt;/li&gt;
&lt;li&gt;L’écosystème autours de Kubernetes s&amp;rsquo;étoffe très vite pour plus d&amp;rsquo;intégrations autours des systèmes, du monitoring, la sécurité, le déploiement continue&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;










  &lt;a href=&#34;https://landscape.cncf.io/images/landscape.png&#34;&gt;
    &lt;img style=&#34;max-width: 100%; height: auto;&#34; src=&#34;https://gastaud.io/article/kubernetes-a-gagne/images/landscape_hu_8c2279c12e36cae6.png&#34; width=&#34;1200&#34; height=&#34;724&#34;&gt;
  &lt;/a&gt;



&lt;h3 id=&#34;le-cloud-public-la-adopté&#34;&gt;Le Cloud public l&amp;rsquo;a adopté&lt;/h3&gt;
&lt;p&gt;Toutes les principales plateformes Cloud proposent Kubernetes en tant services :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Google Cloud Platform avec GKE (Google Kubernetes Engine)&lt;/li&gt;
&lt;li&gt;Amazon Web Services avec EKS (Amazon Elastic Container Service for Kubernetes)&lt;/li&gt;
&lt;li&gt;Azure avec AKS (Azure Kubernetes Service)&lt;/li&gt;
&lt;li&gt;Digital Ocean propose une beta privée&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;docker-for-mac-intègre-nativement-kubernetes&#34;&gt;Docker (for mac) intègre nativement Kubernetes&lt;/h3&gt;
&lt;p&gt;Docker a annoncé l&amp;rsquo;année dernière intégrée directement Kubernetes dans son application Docker for mac et propose maintenant le choix entre Swarm et Kubernetes.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Faut-il donc oublier vraiment toutes les autres solutions et ne faire plus que Kubernetes ?&lt;/p&gt;
&lt;p&gt;Pour des problématiques d&amp;rsquo;orchestration combinant des applications non conteneurisées et/ou des conteneurs, alors une solution comme Mesos pourra vous être d&amp;rsquo;une grande aide.&lt;/p&gt;
&lt;p&gt;Pour des problématiques d&amp;rsquo;orchestration dédiés uniquement aux conteneurs, &lt;strong&gt;sur une petite volumétrie de serveurs et conteneurs&lt;/strong&gt;, une solution comme Docker Swarm sera certainement un bon tremplin, plus abordable.&lt;/p&gt;
&lt;p&gt;Enfin, si vous avez besoin d&amp;rsquo;une solution &lt;strong&gt;fiable, robuste, scalable et pérenne&lt;/strong&gt;, alors la balance tend clairement vers Kubernetes.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Drupal Behat afterFeature</title>
      <link>https://gastaud.io/article/behat-afterfeature/</link>
      <pubDate>Fri, 02 Sep 2016 17:12:10 +0200</pubDate>
      
      <guid>https://gastaud.io/article/behat-afterfeature/</guid>
      
        <description>&lt;p&gt;Snippet permettant d&amp;rsquo;éxécuter des actions à la fin de l&amp;rsquo;éxécution d&amp;rsquo;une feature Behat.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/**
 * Defines application features from the specific context.
 */
class FeatureContext extends RawDrupalContext implements SnippetAcceptingContext {

  /**
   * That function will be executed after the end of the feature.
   *
   * @AfterFeature
   */
  public static function cleanupSomethingAfterFeatureExcution() {
    // Do something.
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;ressources&#34;&gt;Ressources&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://docs.behat.org/en/v2.5/guides/3.hooks.html&#34;&gt;http://docs.behat.org/en/v2.5/guides/3.hooks.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.webomelette.com/content-fixtures-behat-testing-drupal-7&#34;&gt;https://www.webomelette.com/content-fixtures-behat-testing-drupal-7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.metaltoad.com/blog/what-i-learned-today-drupal-behat-scenario-cleanup&#34;&gt;http://www.metaltoad.com/blog/what-i-learned-today-drupal-behat-scenario-cleanup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
      
    </item>
    
    <item>
      <title>Obtenir l&#39;url d&#39;une page gérée via page_manager</title>
      <link>https://gastaud.io/article/panel-page-manager-obtenir-url/</link>
      <pubDate>Tue, 09 Aug 2016 14:48:18 +0200</pubDate>
      
      <guid>https://gastaud.io/article/panel-page-manager-obtenir-url/</guid>
      
        <description>&lt;p&gt;Ci-dessous une technique pour récupérer l&amp;rsquo;url définie dans une page gérée via le module page_manager (inclus dans Ctools).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Load ctools plugins.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ctools_include&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;page&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;page_manager&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;plugins/tasks&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Load path &amp;#34;my-page&amp;#34; page.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$path &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;page_manager_page_load&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;my-page&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;path&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      
    </item>
    
    <item>
      <title>Drupal 8 - Suppression de configurations à la désinstallation du module</title>
      <link>https://gastaud.io/article/drupal-8-suppression-config-desinstallation/</link>
      <pubDate>Mon, 02 May 2016 15:21:25 +0200</pubDate>
      
      <guid>https://gastaud.io/article/drupal-8-suppression-config-desinstallation/</guid>
      
        <description>&lt;p&gt;Lors de l&amp;rsquo;implémentation d&amp;rsquo;un module, il va vous arriver de créer des configurations lors de l&amp;rsquo;installation.&lt;/p&gt;
&lt;p&gt;Il est nécessaire de penser à les supprimer à la désinstallation.&lt;/p&gt;
&lt;p&gt;Pour cela, il vous suffit d&amp;rsquo;utiliser le &lt;code&gt;hook_uninstall&lt;/code&gt; dans le fichier &lt;code&gt;.install&lt;/code&gt; de votre module, comme cela pouvait être fait sur Drupal 7.&lt;/p&gt;
&lt;p&gt;Exemple avec une configuration du type &lt;em&gt;migration&lt;/em&gt; nommée &lt;em&gt;communique&lt;/em&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/**
 * Implements hook_uninstall().
 */
function migrate_communique_uninstall() {
    \Drupal::entityTypeManager()-&amp;gt;getStorage(&amp;#39;migration&amp;#39;)-&amp;gt;load(&amp;#39;communique&amp;#39;)-&amp;gt;delete();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;ui blue message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
      &lt;div class=&#34;header&#34;&gt;
        A lire aussi
      &lt;/div&gt;
    
    
    &lt;p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/drupal-8-migration-xml/&#34;&gt;Réaliser un import de fichier XML sous Drupal 8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/drupal-8-migration-xml-surcharge-source/&#34;&gt;Import de fichier XML sous Drupal 8 - Traitements spécifiques sur la source&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

</description>
      
    </item>
    
    <item>
      <title>Import de fichier XML sous Drupal 8 - Traitements spécifiques sur la source</title>
      <link>https://gastaud.io/article/drupal-8-migration-xml-surcharge-source/</link>
      <pubDate>Mon, 02 May 2016 10:13:54 +0200</pubDate>
      
      <guid>https://gastaud.io/article/drupal-8-migration-xml-surcharge-source/</guid>
      
        <description>&lt;p&gt;Dans l&amp;rsquo;article précédent, &lt;a href=&#34;https://gastaud.io/article/drupal-8-migration-xml/&#34;&gt;Réaliser un import de fichier XML sous Drupal 8&lt;/a&gt;, nous avons vu comment importer un fichier XML via Migrate.
La configuration était simple et nous avons pu faire l&amp;rsquo;ensemble du mapping sans manipuler les données du fichier XML.&lt;/p&gt;
&lt;p&gt;Nous allons étendre notre exemple précédent pour importer une date.&lt;br&gt;
Cependant cette date n&amp;rsquo;a pas un format de date &lt;em&gt;standard&lt;/em&gt; et n&amp;rsquo;est pas valide pour être importée dans Drupal directement.&lt;/p&gt;
&lt;h2 id=&#34;mise-à-jour-du-contexte&#34;&gt;Mise à jour du contexte&lt;/h2&gt;
&lt;h3 id=&#34;fichier-xml-à-importer&#34;&gt;Fichier XML à importer&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;utf-8&amp;#34;?&amp;gt;
&amp;lt;flux-communiques&amp;gt;
    &amp;lt;communique&amp;gt;
        &amp;lt;id-communique&amp;gt;1&amp;lt;/id-communique&amp;gt;
        &amp;lt;titre&amp;gt;Titre de l&amp;#39;article 1&amp;lt;/titre&amp;gt;
        &amp;lt;date-diffusion&amp;gt;2016-02-05 16:07:00&amp;lt;/date-diffusion&amp;gt;
        &amp;lt;corps&amp;gt;&amp;lt;![CDATA[&amp;lt;div style=&amp;#34;color: red&amp;#34;&amp;gt;Un texte bleu&amp;lt;/div&amp;gt;]]&amp;gt;&amp;lt;/corps&amp;gt;
        &amp;lt;pj1&amp;gt;http://example.com/monfichier.pdf&amp;lt;/pj1&amp;gt;
    &amp;lt;/communique&amp;gt;
    &amp;lt;communique&amp;gt;
        &amp;lt;id-communique&amp;gt;2&amp;lt;/id-communique&amp;gt;
        &amp;lt;titre&amp;gt;Titre de l&amp;#39;article 2&amp;lt;/titre&amp;gt;
        &amp;lt;date-diffusion&amp;gt;2016-01-14 16:24:00&amp;lt;/date-diffusion&amp;gt;
        &amp;lt;corps&amp;gt;&amp;lt;![CDATA[&amp;lt;div style=&amp;#34;color: red&amp;#34;&amp;gt;Un texte rouge&amp;lt;/div&amp;gt;]]&amp;gt;
        &amp;lt;/corps&amp;gt;
        &amp;lt;pj1&amp;gt;http://example.com/monfichier2.pdf&amp;lt;/pj1&amp;gt;
    &amp;lt;/communique&amp;gt;
&amp;lt;/flux-communiques&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;La champ &lt;code&gt;date-diffusion&lt;/code&gt; n&amp;rsquo;est pas valide et nous allons avoir besoin d&amp;rsquo;ajouter un &lt;strong&gt;T&lt;/strong&gt; entre la date et l&amp;rsquo;heure pour obtenir le format suivant : &lt;code&gt;2016-02-05T16:07:00&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;type-de-contenus&#34;&gt;Type de contenus&lt;/h3&gt;
&lt;p&gt;Nous possédons un type de contenus, nommé &lt;code&gt;Communique&lt;/code&gt; avec les champs suivants :&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Label&lt;/th&gt;
					&lt;th&gt;Nom machine&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Titre&lt;/td&gt;
					&lt;td&gt;title&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Corps&lt;/td&gt;
					&lt;td&gt;body&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Date de diffusion&lt;/td&gt;
					&lt;td&gt;field_communique_date&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Pièce jointe&lt;/td&gt;
					&lt;td&gt;field_communique_attachment&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Id du communiqué&lt;/td&gt;
					&lt;td&gt;field_communique_id&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;modifications-du-module-dimport&#34;&gt;Modifications du module d&amp;rsquo;import&lt;/h2&gt;
&lt;h3 id=&#34;nouveau-mapping-des-champs-source&#34;&gt;Nouveau mapping des champs source&lt;/h3&gt;
&lt;p&gt;Dans la partie &lt;code&gt;source&lt;/code&gt;, nous allons ajouter une entrée pour mapper la date de diffusion.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;source:
  #...
  fields:
    #...
    -
      name: date_diffusion
      label: Date Diffusion
      selector: date-diffusion
  #...
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;nouveau-mapping-des-champs-drupal&#34;&gt;Nouveau mapping des champs Drupal&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;process:
  #...
  field_press_release_date: date_diffusion
  #...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Si vous lancez un &lt;code&gt;drush migrate-fields-source&lt;/code&gt; vous devriez voir le nouveau champ apparaitre&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$drush mfs communique
ID              id_communique  
Titre           titre          
Corps           corps          
Date Diffusion  date_diffusion
Lien            pj1
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;modification-de-la-class-source&#34;&gt;Modification de la class Source&lt;/h2&gt;
&lt;p&gt;Comme indiqué précédemment, il va maintenant nous falloir altérer la valeur de la date de diffusion pour qu&amp;rsquo;elle est un format interprétable par Drupal et ainsi que l&amp;rsquo;import de ce champ se réalise correctement.&lt;/p&gt;
&lt;p&gt;Pour cela nous allons devoir modifier le comportement du plugin de la source (Url.php dans notre) et utiliser, comme sur Drupal 7, la méthode prepareRow().&lt;/p&gt;
&lt;p&gt;Nous allons donc créer une nouvelle class nommée Communique.php dans &lt;code&gt;./src/Plugin/migrate/source/Communique.php&lt;/code&gt;&lt;br&gt;
On obtient l&amp;rsquo;arborescence de module suivante :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;.
├── config
│   └── install
│       └── migrate_plus.migration.communique.yml
├── migrate_press_release.info.yml
└── src
    └── Plugin
        ├── migrate
        │   └── source
        │       └── Communique.php
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Notre nouvelle class &lt;code&gt;Communique.php&lt;/code&gt; :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;lt;?php

namespace Drupal\migrate_communique\Plugin\migrate\source;

use Drupal\migrate\Row;
use Drupal\migrate_plus\Plugin\migrate\source\Url;

/**
 * Source plugin for communique content.
 *
 * @MigrateSource(
 *   id = &amp;#34;communique&amp;#34;
 * )
 */

class Communique extends Url {

    /**
     * {@inheritdoc}
     */
    public function prepareRow(Row $row) {
        // Alter XML provided date.
        $row-&amp;gt;setSourceProperty(&amp;#39;date_diffusion&amp;#39;, $this-&amp;gt;processDateDiffusion($row-&amp;gt;getSource()[&amp;#39;date_diffusion&amp;#39;]));
        return parent::prepareRow($row);
    }

    /**
     * Format Date from XML to be compliant with DateTime format.
     *
     * @param $element
     * @return string
     */
    protected function processDateDiffusion($element) {

        $exploded = explode(&amp;#39; &amp;#39;, (string) $element);
        $data = implode(&amp;#39;T&amp;#39;, $exploded);

        return $data;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nous avons donc ici une class qui étant la class &lt;code&gt;Url&lt;/code&gt; et prépare le format de la date obtenue dans le champ &lt;em&gt;date_diffusion&lt;/em&gt; pour correspondre à ce qu&amp;rsquo;attend Drupal.&lt;br&gt;
L&amp;rsquo;utilisation de &lt;code&gt;$row-&amp;gt;setSourceProperty()&lt;/code&gt; permet de (re)définir  la valeur de la date de diffusion.&lt;/p&gt;
&lt;p&gt;Il ne nous reste plus qu&amp;rsquo;à préciser à notre migration de prendre en compte cette source en remplacement de la source &lt;code&gt;url&lt;/code&gt; initialement définie.&lt;/p&gt;
&lt;p&gt;Pour cela, nous allons modifier notre fichier &lt;code&gt;migrate_plus.migration.communique.yml&lt;/code&gt; pour lui renseigner l&amp;rsquo;id de notre source : &lt;em&gt;communique&lt;/em&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;source:
  # L&amp;#39;identifiant de notre source custom.
  plugin: communique
  #...
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;ui red message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;&lt;p&gt;Afin que les changements de configuration soient pris en compte, il vous faudra désinstaller le module, supprimer la config déjà enregistrée et réinstaller le module.
Voir l&amp;rsquo;article &lt;a href=&#34;https://gastaud.io/article/drupal-8-suppression-config-desinstallation/&#34;&gt;Drupal 8 - Suppression de configurations à la désinstallation du module&lt;/a&gt;&lt;/p&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Une fois les modifications effectuées, il ne vous reste plus qu&amp;rsquo;à relancer votre migration.&lt;/p&gt;

&lt;div class=&#34;ui blue message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
      &lt;div class=&#34;header&#34;&gt;
        A lire aussi
      &lt;/div&gt;
    
    
    &lt;p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/drupal-8-migration-xml/&#34;&gt;Réaliser un import de fichier XML sous Drupal 8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/drupal-8-suppression-config-desinstallation/&#34;&gt;Drupal 8 - Suppression de configurations à la désinstallation du module&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

</description>
      
    </item>
    
    <item>
      <title>Réaliser un import de fichier XML sous Drupal 8</title>
      <link>https://gastaud.io/article/drupal-8-migration-xml/</link>
      <pubDate>Mon, 02 May 2016 10:13:54 +0200</pubDate>
      
      <guid>https://gastaud.io/article/drupal-8-migration-xml/</guid>
      
        <description>&lt;p&gt;Dans cette article nous allons voir comment réaliser un import de contenu XML dans Drupal 8 à l&amp;rsquo;aide des modules migrate, &lt;a href=&#34;https://drupal.org/project/migrate_plus&#34;&gt;migrate_plus&lt;/a&gt; et &lt;a href=&#34;https://drupal.org/project/migrate_source_xml&#34;&gt;migrate_source_xml&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;récupération-des-modules-et-installation&#34;&gt;Récupération des modules et installation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;migrate&lt;/code&gt; est disponible dans le coeur de Drupal 8. Cependant il ne contient à ce jour que la possibilité de migrer des contenus en provenance d&amp;rsquo;une base SQL.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;migrate_plus&lt;/code&gt; est un module contribué qui permet notamment d&amp;rsquo;obtenir la possibilité de migrer des contenus à partir d&amp;rsquo;une URL.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;drush dl migrate_plus --dev
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;migrate_source_xml&lt;/code&gt; permet d&amp;rsquo;avoir une class de migration gérant des fichiers XML.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# depuis le dossier ./modules/[contrib]
git clone --branch refactor https://git.drupal.org/project/migrate_source_xml.git
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;contexte&#34;&gt;Contexte&lt;/h2&gt;
&lt;h2 id=&#34;fichier-xml-à-importer&#34;&gt;Fichier XML à importer&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;utf-8&amp;#34;?&amp;gt;
&amp;lt;flux-communiques&amp;gt;
    &amp;lt;communique&amp;gt;
        &amp;lt;id-communique&amp;gt;1&amp;lt;/id-communique&amp;gt;
        &amp;lt;titre&amp;gt;Titre de l&amp;#39;article 1&amp;lt;/titre&amp;gt;
        &amp;lt;corps&amp;gt;&amp;lt;![CDATA[&amp;lt;div style=&amp;#34;color: red&amp;#34;&amp;gt;Un texte bleu&amp;lt;/div&amp;gt;]]&amp;gt;&amp;lt;/corps&amp;gt;
        &amp;lt;pj1&amp;gt;http://example.com/monfichier.pdf&amp;lt;/pj1&amp;gt;
    &amp;lt;/communique&amp;gt;
    &amp;lt;communique&amp;gt;
        &amp;lt;id-communique&amp;gt;2&amp;lt;/id-communique&amp;gt;
        &amp;lt;titre&amp;gt;Titre de l&amp;#39;article 2&amp;lt;/titre&amp;gt;
        &amp;lt;date-diffusion&amp;gt;2016-01-14 16:24:00&amp;lt;/date-diffusion&amp;gt;
        &amp;lt;corps&amp;gt;&amp;lt;![CDATA[&amp;lt;div style=&amp;#34;color: red&amp;#34;&amp;gt;Un texte rouge&amp;lt;/div&amp;gt;]]&amp;gt;
        &amp;lt;/corps&amp;gt;
        &amp;lt;pj1&amp;gt;http://example.com/monfichier2.pdf&amp;lt;/pj1&amp;gt;
    &amp;lt;/communique&amp;gt;
&amp;lt;/flux-communiques&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;type-de-contenus&#34;&gt;Type de contenus&lt;/h3&gt;
&lt;p&gt;Nous possédons un type de contenus, nommé &lt;code&gt;Communique&lt;/code&gt; avec les champs suivants :&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Label&lt;/th&gt;
					&lt;th&gt;Nom machine&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Titre&lt;/td&gt;
					&lt;td&gt;title&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Corps&lt;/td&gt;
					&lt;td&gt;body&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Pièce jointe&lt;/td&gt;
					&lt;td&gt;field_communique_attachment&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Id du communiqué&lt;/td&gt;
					&lt;td&gt;field_communique_id&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;création-du-module-dimport&#34;&gt;Création du module d&amp;rsquo;import&lt;/h2&gt;
&lt;h3 id=&#34;création-du-module-migrate_communique&#34;&gt;Création du module migrate_communique&lt;/h3&gt;
&lt;p&gt;Nous allons nommer notre module &lt;code&gt;migrate_communique&lt;/code&gt; et commencer par créer le dossier du même nom dans le répertoire &lt;code&gt;modules&lt;/code&gt; à la racine de Drupal.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;./modules
├── migrate_communique
└── README.txt
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;et définir le fichier migrate_communique.info.yml&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;type: module
name: Migrate Communiqué
description: &amp;#39;Migration des communiqués.&amp;#39;
package: Migration
core: 8.x
dependencies:
  - migrate_plus
  - migrate_source_xml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On notera ici les dépendances aux modules &lt;code&gt;migrate_plus&lt;/code&gt; et &lt;code&gt;migrate_source_xml&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;définition-du-mapping-entre-le-xml-et-le-type-de-contenus&#34;&gt;Définition du mapping entre le XML et le type de contenus&lt;/h3&gt;
&lt;p&gt;Nous allons créer un fichier de configuration nommé &lt;code&gt;migrate_plus.migration.communique.yml&lt;/code&gt; dans le dossier &lt;code&gt;config/install&lt;/code&gt; à partir de la racine du module.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;.
├── config
│   └── install
│       └── migrate_plus.migration.pressrelease.yml
├── migrate_communique.info.yml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;La configuration contenue dans ce fichier sera initialisée à l&amp;rsquo;installation du module.&lt;/p&gt;
&lt;h4 id=&#34;contenu-du-fichier-migrate_plusmigrationcommuniqueyml&#34;&gt;Contenu du fichier migrate_plus.migration.communique.yml&lt;/h4&gt;
&lt;h4 id=&#34;contenu-intégral-du-fichier&#34;&gt;Contenu intégral du fichier&lt;/h4&gt;
&lt;p&gt;Nous détaillerons juste après le contenu de ce fichier&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Configuration de la migration des communiqués.
id: communique
label: Communique
migration_group: Communique
migration_dependencies: {}

source:
  plugin: url
  data_fetcher_plugin: http
  data_parser_plugin: xml
  urls: http://exemple/monfichier.xml
  item_selector: /flux-communiques/communique
  fields:
    -
      # Nom machine utilisé pour le mapping lors du processing.
      name: id_communique
      # Label qui sera affiché dans l&amp;#39;UI.
      label: ID
      # Nom du champ dans le XML.
      selector: id-communique
    -
      name: titre
      label: Titre
      selector: titre
    -
      name: corps
      label: Corps
      selector: corps
    -
      name: pj1
      label: Lien
      selector: pj1

  ids:
    id_communique:
      type: string

destination:
  plugin: entity:node

process:
  type:
    plugin: default_value
    default_value: communique

  title: titre
  field_communique_id: id_communique
  &amp;#39;field_communique_body/value&amp;#39;: corps
  &amp;#39;field_communique_body/format&amp;#39;:
      plugin: default_value
      default_value: full_html
  field_communique_attachment: pj1

  sticky:
    plugin: default_value
    default_value: 0

  uid:
    plugin: default_value
    default_value: 1
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;configuration-générale&#34;&gt;Configuration générale&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;id: communique
label: Communique
migration_group: Communique
migration_dependencies: {}
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;mapping-de-la-source&#34;&gt;Mapping de la source&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;source:
  plugin: url
  data_fetcher_plugin: http
  data_parser_plugin: xml
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;plugin&lt;/strong&gt; permet de définir le nom du plugin qui va servir de base pour la parsing de la source.&lt;br&gt;
Ici le plugin &lt;code&gt;url&lt;/code&gt; est fourni par le module &lt;code&gt;migrate_plus&lt;/code&gt; dans la class &lt;code&gt;Url.php&lt;/code&gt; (./modules/contrib/migrate_plus/src/Plugin/migrate/source/Url.php)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dans cette class, on retrouve notamment l&amp;rsquo;annotation suivante qui nous permet d&amp;rsquo;obtenir l&amp;rsquo;id du plugin :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/**
 * Source plugin for retrieving data via URLs.
 *
 * @MigrateSource(
 *   id = &amp;#34;url&amp;#34;
 * )
 */
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;data_fetcher_plugin&lt;/strong&gt; : plugin implémenté dans &lt;code&gt;migrate_plus&lt;/code&gt; pour permettre de récupérer un fichier depuis une URL (./modules/contrib/migrate_plus/src/Plugin/migrate_plus/data_fetcher/Http.php)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/**
 * Retrieve data over an HTTP connection for migration.
 *
 * @DataFetcher(
 *   id = &amp;#34;http&amp;#34;,
 *   title = @Translation(&amp;#34;HTTP&amp;#34;)
 * )
 */
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;data_parser_plugin&lt;/strong&gt; : plugin implémenté par &lt;code&gt;migrate_source_xml&lt;/code&gt; (./modules/contrib/migrate_source_xml/src/Plugin/migrate_plus/data_parser/Xml.php)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/**
 * Obtain XML data for migration.
 *
 * @DataParser(
 *   id = &amp;#34;xml&amp;#34;,
 *   title = @Translation(&amp;#34;XML&amp;#34;)
 * )
 */
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;urls&lt;/strong&gt; : une liste d&amp;rsquo;urls auxquelles récupérer le fichier XML.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  urls: http://exemple/monfichier.xml
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;item_selector&lt;/strong&gt; : permet de définir l&amp;rsquo;emplacement des items qui seront mappés et parsés (au format XPath)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  item_selector: /flux-communiques/communique
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;fields&lt;/strong&gt; : permet de définir le mapping entre les champs XML et la class de migration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On va ici définir pour chaque champs :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un nom machine - qui sera réutiliser plus tard lors du processing du champ&lt;/li&gt;
&lt;li&gt;un label (optionnel)&lt;/li&gt;
&lt;li&gt;un sélecteur - le nom du champ dans le XML&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  fields:
    -
      # Nom machine utilisé pour le mapping lors du processing.
      name: id_communique
      # Label qui sera affiché dans l&amp;#39;UI.
      label: ID
      # Nom du champ dans le XML.
      selector: id-communique
    -
      name: titre
      label: Titre
      selector: titre
    -
      name: corps
      label: Corps
      selector: corps
    -
      name: pj1
      label: Lien
      selector: pj1
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ids&lt;/strong&gt; : permet de définir l&amp;rsquo;identifiant unique dans le flux pour gérer les nouveaux imports et mises à jour&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  ids:
    id_communique:
      type: string
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;destination-de-la-migration&#34;&gt;Destination de la migration&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;destination:
  plugin: entity:node
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On définie ici une migration vers une entitité de type &lt;code&gt;node&lt;/code&gt;.
On peut tout à fait envisager également de migrer vers d&amp;rsquo;autres entités comme les utilisateurs ou .&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Exemple pour l&amp;#39;entité User.
destination:
  plugin: entity:user
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;mapping-avec-les-champs-drupal&#34;&gt;Mapping avec les champs Drupal&lt;/h4&gt;
&lt;p&gt;La partie &lt;code&gt;process&lt;/code&gt; du yaml permet de définir le type de contenus dans lequel importer les données.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;process:
  type:
    plugin: default_value
    default_value: communique
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Le &lt;code&gt;type&lt;/code&gt; est ici forcé à &lt;code&gt;Communique&lt;/code&gt;. Tous les contenus créés auront seront donc des communiqués.&lt;br&gt;
Le plugin &lt;code&gt;default_value&lt;/code&gt; permet de définir la valeur par défaut que prendra un champ.&lt;br&gt;
On réutilise ce plugin plus bas pour définir la valeur du champ Sticky et l&amp;rsquo;identifiant de l&amp;rsquo;utilisateur (uid)&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sticky:
  plugin: default_value
  default_value: 0

uid:
  plugin: default_value
  default_value: 1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nous retrouvons ensuite le mapping des champs à proprement parler.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  title: titre
  field_communique_id: id_communique
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Il s&amp;rsquo;écrit sous la forme :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  nom_machine_champ_drupal: nom_machine_source_yaml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Enfin on retrouvera une notation un peu particulière pour les champs &lt;em&gt;composés&lt;/em&gt; tels que le champ &lt;code&gt;body&lt;/code&gt; qui attend une valeur complète, un format et potentiellement un résumé.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  &amp;#39;field_communique_body/value&amp;#39;: corps
  &amp;#39;field_communique_body/format&amp;#39;:
      plugin: default_value
      default_value: full_html
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Comme vous l&amp;rsquo;avez sûrement remarqué, ces champs s&amp;rsquo;écrivent sous la forme &lt;code&gt;&#39;nom_champ/propriété&#39;&lt;/code&gt;.&lt;br&gt;
Il est important de ne pas omettre les guillemets simples autour du nom du champ.&lt;/p&gt;
&lt;h2 id=&#34;lancer-la-migration-avec-drush&#34;&gt;Lancer la migration avec Drush&lt;/h2&gt;
&lt;p&gt;Il est possible, comme sur Drupal 7 de lancer les migrations via Drush.
Pour cela, il va cependant nous falloir installer un module complémentaire : &lt;a href=&#34;https://drupal.org/project/migrate_tools&#34;&gt;migrate_tools&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Un simple &lt;code&gt;drush dl migrate_tools --dev&lt;/code&gt; et &lt;code&gt;drush en migrate_tools&lt;/code&gt; devrait suffire.&lt;/p&gt;
&lt;p&gt;Ce module permet de faire le pont entre drush et migrate, qui rappelons-le est maintenant inclus directement dans le coeur de Drupal.&lt;/p&gt;
&lt;p&gt;Une fois le module installé, on va avoir aux habituelles commandes drush migrate&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drush --filter&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;migrate_tools
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;All commands in migrate_tools: &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;migrate_tools&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; migrate-fields-sourc  List the fields available &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; mapping in a source.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; e &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;mfs&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;                                                                  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; migrate-import &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;mi&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;   Perform one or more migration processes.           
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; migrate-messages      View any messages associated with a migration.     
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;mmsg&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;                                                                   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; migrate-reset-status  Reset a active migration&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;s status to idle.         
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;mrs&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;                                                                    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; migrate-rollback      Rollback one or more migrations.                   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;mr&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;                                                                     
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; migrate-status &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;ms&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;   List all migrations with current status.           
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; migrate-stop &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;mst&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;    Stop an active migration operation.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;vérification-du-mapping-des-champs&#34;&gt;Vérification du mapping des champs&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;drush mfs communique
ID              id_communique  
Titre           titre          
Corps           corps          
Lien            pj1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On retrouve bien ici les champs mappés dans la partie &lt;code&gt;source&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;status-des-imports&#34;&gt;Status des imports&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;drush ms communique
 Group: Communique  Status  Total  Imported  Unprocessed  Last imported       
 communique         Idle    2      0         0            
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;lancer-la-migration&#34;&gt;Lancer la migration&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;drush mi communique --update
Processed 2 items (2 created, 0 updated, 0 failed, 0 ignored) - done with &amp;#39;communique&amp;#39;          

drush mi communique --update
Processed 2 items (0 created, 2 updated, 0 failed, 0 ignored) - done with &amp;#39;communique&amp;#39;          
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Voilà ! Vos noeuds ont été créés et sont maintenant visibles dans le back-office Drupal.&lt;/p&gt;

&lt;div class=&#34;ui blue message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
      &lt;div class=&#34;header&#34;&gt;
        A lire aussi
      &lt;/div&gt;
    
    
    &lt;p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/drupal-8-migration-xml-surcharge-source/&#34;&gt;Import de fichier XML sous Drupal 8 - Traitements spécifiques sur la source&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/drupal-8-suppression-config-desinstallation/&#34;&gt;Drupal 8 - Suppression de configurations à la désinstallation du module&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

</description>
      
    </item>
    
    <item>
      <title>Utiliser Tmux et Tmuxinator pour gérer vos confs projets</title>
      <link>https://gastaud.io/article/tmux-tmuxinator-confs-projets/</link>
      <pubDate>Wed, 27 Apr 2016 19:00:00 +0200</pubDate>
      
      <guid>https://gastaud.io/article/tmux-tmuxinator-confs-projets/</guid>
      
        <description>&lt;h2 id=&#34;pré-requis&#34;&gt;Pré-requis&lt;/h2&gt;
&lt;p&gt;Avoir installé sur vos machines&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://tmux.github.io/&#34;&gt;Tmux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/tmuxinator/tmuxinator&#34;&gt;Tmuxinator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;votre-nouveau-projet-en-3-étapes&#34;&gt;Votre nouveau projet en 3 étapes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;tmuxinator new [project_name]&lt;/code&gt; : Cette commande va générer un fichier YAML avec la configuration par défaut&lt;/li&gt;
&lt;li&gt;Editer le fichier généré : &lt;code&gt;~/.tmuxinator/[project_name].yml&lt;/code&gt; (voir exemple ci-dessous)&lt;/li&gt;
&lt;li&gt;Lancer &lt;code&gt;mux [project_name]&lt;/code&gt; dans votre terminal&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;exemple-de-configuration-tmuxinator-pour-le-projet-store-sous-drupal&#34;&gt;Exemple de configuration Tmuxinator pour le projet Store sous Drupal&lt;/h2&gt;
&lt;pre&gt;
&lt;code class=&#34;yml&#34;&gt;
# ~/.tmuxinator/store.yml

name: store
root: ~/www/store

windows:
  - drupal:
      layout: main-vertical
      panes:
        # Aller dans le réperoire docroot/ et utiliser l&#39;alias drush projet.local
        - cd www/store/docroot &amp;&amp; drush use @projet.local
        # crée simplement un panneau dans le répertoire root défini
        -
        # Lancer vagrant et se connecter dedans
        - vagrant up &amp;&amp; vagrant ssh
  - dev: drush use @projet.dev
  - staging: drush use @projet.test
  - prod:  drush use @projet.prod
  # Lancer PHPStorm
  - editor: pstorm .
&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;Dans le terminal, lancer &lt;code&gt;mux store&lt;/code&gt; permettra ainsi de lancer 5 fenêtres tmux + phpstorm.&lt;/p&gt;
&lt;h2 id=&#34;références&#34;&gt;Références&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://nils-blum-oeste.net/getting-started-with-tmux/&#34;&gt;Tame the command line: How to get started with tmux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.mediacurrent.com/blog/efficient-drupal-development-tmux-and-tmuxinator&#34;&gt;Drupal: Efficient Drupal Development with Tmux and Tmuxinator - See more at: http://www.mediacurrent.com/blog/efficient-drupal-development-tmux-and-tmuxinator#sthash.QBmP4vJZ.dpuf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://zdk.github.io/manage-different-tmux-configurations-with-tmuxinator/&#34;&gt;Manage different tmux configurations with tmuxinator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
      
    </item>
    
    <item>
      <title>Oubliez cURL et Wget grâce à HTTPie</title>
      <link>https://gastaud.io/article/httpie/</link>
      <pubDate>Thu, 14 Apr 2016 11:49:35 +0200</pubDate>
      
      <guid>https://gastaud.io/article/httpie/</guid>
      
        <description>&lt;p&gt;&lt;a href=&#34;https://github.com/jkbrzt/httpie&#34;&gt;HTTPie&lt;/a&gt; est un utilitaire en ligne de commande qui a vocation à remplacer simplement l&amp;rsquo;utilisation des commandes cURL et wget tout en ajoutant une petite touche bien agréable.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Plusieurs modes d&amp;rsquo;installation sont possibles. En effet HTTPie est disponible via les packages officiels (pas forcement la dernière version) ou via &lt;code&gt;pip&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Vous trouverez toutes les informations nécessaires dans le &lt;a href=&#34;https://github.com/jkbrzt/httpie#installation&#34;&gt;Readme du projet&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;formatage-et-couleur&#34;&gt;Formatage et couleur&lt;/h2&gt;
&lt;h3 id=&#34;formatage&#34;&gt;Formatage&lt;/h3&gt;
&lt;p&gt;Si vous avez déjà lancé des requêtes à une API via cURL, vous avez déjà du voir des résultats comme ci-dessous.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;curl &amp;#34;https://www.drupal.org/api-d7/user.json?name=jygastaud&amp;#34;

{&amp;#34;self&amp;#34;:&amp;#34;https:\/\/www.drupal.org\/api-d7\/user?name=jygastaud&amp;#34;,&amp;#34;first&amp;#34;:&amp;#34;https:\/\/www.drupal.org\/api-d7\/user?name=jygastaud\u0026page=0&amp;#34;,&amp;#34;last&amp;#34;:&amp;#34;https:\/\/www.drupal.org\/api-d7\/user?name=jygastaud\u0026page=0&amp;#34;,&amp;#34;list&amp;#34;:[{&amp;#34;field_industries_worked_in&amp;#34;:[],&amp;#34;field_organizations&amp;#34;:[{&amp;#34;uri&amp;#34;:&amp;#34;https:\/\/www.drupal.org\/api-d7\/field_collection_item\/468341&amp;#34;,&amp;#34;id&amp;#34;:&amp;#34;468341&amp;#34;,&amp;#34;resource&amp;#34;:&amp;#34;field_collection_item&amp;#34;},{&amp;#34;uri&amp;#34;:&amp;#34;https:\/\/www.drupal.org\/api-d7\/field_collection_item\/724935&amp;#34;,&amp;#34;id&amp;#34;:&amp;#34;724935&amp;#34;,&amp;#34;resource&amp;#34;:&amp;#34;field_collection_item&amp;#34;}],&amp;#34;field_bio&amp;#34;:[],&amp;#34;field_irc_nick&amp;#34;:&amp;#34;jygastaud&amp;#34;,&amp;#34;field_websites&amp;#34;:[{&amp;#34;url&amp;#34;:&amp;#34;http:\/\/www.clever-age.com&amp;#34;,&amp;#34;attributes&amp;#34;:[]}],&amp;#34;field_country&amp;#34;:&amp;#34;France&amp;#34;,&amp;#34;field_gender&amp;#34;:&amp;#34;male&amp;#34;,&amp;#34;field_languages&amp;#34;:[&amp;#34;English&amp;#34;,&amp;#34;French&amp;#34;],&amp;#34;field_terms_of_service&amp;#34;:true,&amp;#34;field_areas_of_expertise&amp;#34;:[],&amp;#34;field_contributed&amp;#34;:[&amp;#34;patches&amp;#34;,&amp;#34;modules&amp;#34;,&amp;#34;issues&amp;#34;,&amp;#34;applications&amp;#34;,&amp;#34;forums&amp;#34;,&amp;#34;services&amp;#34;,&amp;#34;irc&amp;#34;,&amp;#34;mentor&amp;#34;],&amp;#34;field_events_attended&amp;#34;:[],&amp;#34;field_mentors&amp;#34;:[],&amp;#34;field_drupal_contributions&amp;#34;:[],&amp;#34;field_first_name&amp;#34;:null,&amp;#34;field_last_name&amp;#34;:null,&amp;#34;og_user_node&amp;#34;:[],&amp;#34;og_membership&amp;#34;:[],&amp;#34;og_membership__1&amp;#34;:[],&amp;#34;og_membership__2&amp;#34;:[],&amp;#34;og_membership__3&amp;#34;:[],&amp;#34;og_user_node__og_membership&amp;#34;:[],&amp;#34;og_user_node__og_membership__1&amp;#34;:[],&amp;#34;og_user_node__og_membership__2&amp;#34;:[],&amp;#34;og_user_node__og_membership__3&amp;#34;:[],&amp;#34;uid&amp;#34;:&amp;#34;660334&amp;#34;,&amp;#34;name&amp;#34;:&amp;#34;jygastaud&amp;#34;,&amp;#34;url&amp;#34;:&amp;#34;https:\/\/www.drupal.org\/u\/jygastaud&amp;#34;,&amp;#34;edit_url&amp;#34;:&amp;#34;https:\/\/www.drupal.org\/user\/660334\/edit&amp;#34;,&amp;#34;created&amp;#34;:&amp;#34;1259343731&amp;#34;,&amp;#34;language&amp;#34;:&amp;#34;en&amp;#34;,&amp;#34;flag_sid&amp;#34;:0,&amp;#34;flag_drupalorg_user_spam_user&amp;#34;:[]}]}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pas très lisible, vous en conviendrez ?&lt;/p&gt;
&lt;p&gt;Avec HTTPie, fini les requêtes CURL à une API qui renvoi un gros bloc illisible. Vous pouvez maintenant avoir un retour lisible dans votre terminal.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;http &amp;#34;https://www.drupal.org/api-d7/user.json?name=jygastaud&amp;#34;

HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Credentials: false
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Origin: *
Age: 0
Cache-Control: no-cache
Connection: keep-alive
Content-Encoding: gzip
Content-Length: 546
Content-Security-Policy: frame-ancestors &amp;#39;self&amp;#39;
Content-Type: application/json
Date: Thu, 14 Apr 2016 10:16:55 GMT
Etag: &amp;#34;1460629015-1&amp;#34;
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Fastly-Debug-Digest: 760fd3aa9c342b8e1bbdc30d5ebbb895ba37763ccd3ce2e0bdab520ac08df17e
Last-Modified: Thu, 14 Apr 2016 10:16:55 GMT
Server: Apache
Strict-Transport-Security: max-age=10886400; includeSubDomains; preload
Vary: Cookie,Accept-Encoding
Via: 1.1 varnish
Via: 1.1 varnish
X-Cache: MISS, MISS
X-Cache-Hits: 0, 0
X-Content-Type-Options: nosniff
X-Drupal-Cache: MISS
X-Frame-Options: SAMEORIGIN
X-Served-By: cache-sea1924-SEA, cache-fra1227-FRA
x-host: www.drupal.org
x-url: /api-d7/user.json?name=jygastaud

{
    &amp;#34;first&amp;#34;: &amp;#34;https://www.drupal.org/api-d7/user?name=jygastaud&amp;amp;page=0&amp;#34;,
    &amp;#34;last&amp;#34;: &amp;#34;https://www.drupal.org/api-d7/user?name=jygastaud&amp;amp;page=0&amp;#34;,
    &amp;#34;list&amp;#34;: [
        {
            &amp;#34;created&amp;#34;: &amp;#34;1259343731&amp;#34;,
            &amp;#34;edit_url&amp;#34;: &amp;#34;https://www.drupal.org/user/660334/edit&amp;#34;,
            &amp;#34;field_areas_of_expertise&amp;#34;: [],
            &amp;#34;field_bio&amp;#34;: [],
            &amp;#34;field_contributed&amp;#34;: [
                &amp;#34;patches&amp;#34;,
                &amp;#34;modules&amp;#34;,
                &amp;#34;issues&amp;#34;,
                &amp;#34;applications&amp;#34;,
                &amp;#34;forums&amp;#34;,
                &amp;#34;services&amp;#34;,
                &amp;#34;irc&amp;#34;,
                &amp;#34;mentor&amp;#34;
            ],
            &amp;#34;field_country&amp;#34;: &amp;#34;France&amp;#34;,
            &amp;#34;field_drupal_contributions&amp;#34;: [],
            &amp;#34;field_events_attended&amp;#34;: [],
            &amp;#34;field_first_name&amp;#34;: null,
            &amp;#34;field_gender&amp;#34;: &amp;#34;male&amp;#34;,
            &amp;#34;field_industries_worked_in&amp;#34;: [],
            &amp;#34;field_irc_nick&amp;#34;: &amp;#34;jygastaud&amp;#34;,
            &amp;#34;field_languages&amp;#34;: [
                &amp;#34;English&amp;#34;,
                &amp;#34;French&amp;#34;
            ],
            &amp;#34;field_last_name&amp;#34;: null,
            &amp;#34;field_mentors&amp;#34;: [],
            &amp;#34;field_organizations&amp;#34;: [
                {
                    &amp;#34;id&amp;#34;: &amp;#34;468341&amp;#34;,
                    &amp;#34;resource&amp;#34;: &amp;#34;field_collection_item&amp;#34;,
                    &amp;#34;uri&amp;#34;: &amp;#34;https://www.drupal.org/api-d7/field_collection_item/468341&amp;#34;
                },
                {
                    &amp;#34;id&amp;#34;: &amp;#34;724935&amp;#34;,
                    &amp;#34;resource&amp;#34;: &amp;#34;field_collection_item&amp;#34;,
                    &amp;#34;uri&amp;#34;: &amp;#34;https://www.drupal.org/api-d7/field_collection_item/724935&amp;#34;
                }
            ],
            &amp;#34;field_terms_of_service&amp;#34;: true,
            &amp;#34;field_websites&amp;#34;: [
                {
                    &amp;#34;attributes&amp;#34;: [],
                    &amp;#34;url&amp;#34;: &amp;#34;http://www.clever-age.com&amp;#34;
                }
            ],
            &amp;#34;flag_drupalorg_user_spam_user&amp;#34;: [],
            &amp;#34;flag_sid&amp;#34;: 0,
            &amp;#34;language&amp;#34;: &amp;#34;en&amp;#34;,
            &amp;#34;name&amp;#34;: &amp;#34;jygastaud&amp;#34;,
            &amp;#34;og_membership&amp;#34;: [],
            &amp;#34;og_membership__1&amp;#34;: [],
            &amp;#34;og_membership__2&amp;#34;: [],
            &amp;#34;og_membership__3&amp;#34;: [],
            &amp;#34;og_user_node&amp;#34;: [],
            &amp;#34;og_user_node__og_membership&amp;#34;: [],
            &amp;#34;og_user_node__og_membership__1&amp;#34;: [],
            &amp;#34;og_user_node__og_membership__2&amp;#34;: [],
            &amp;#34;og_user_node__og_membership__3&amp;#34;: [],
            &amp;#34;uid&amp;#34;: &amp;#34;660334&amp;#34;,
            &amp;#34;url&amp;#34;: &amp;#34;https://www.drupal.org/u/jygastaud&amp;#34;
        }
    ],
    &amp;#34;self&amp;#34;: &amp;#34;https://www.drupal.org/api-d7/user?name=jygastaud&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;couleur&#34;&gt;couleur&lt;/h3&gt;
&lt;p&gt;Regarder l&amp;rsquo;image en exemple sur le dépôt github&lt;/p&gt;
&lt;center&gt;![curl vs httpie](https://raw.githubusercontent.com/jkbrzt/httpie/master/httpie.png)&lt;/center&gt;
&lt;p&gt;Comme vous pouvez le voir, HTTPie en plus d&amp;rsquo;apporter un formatage de la sortie vous apportera aussi une colorisation.&lt;/p&gt;
&lt;h2 id=&#34;uniformation&#34;&gt;Uniformation&lt;/h2&gt;
&lt;p&gt;Donc avant, vous aviez cURL pour requêter vos URLs et Wget pour télécharger des fichiers.&lt;/p&gt;
&lt;p&gt;Grâce à HTTPie, vous pouvez maintenant ne retenir qu&amp;rsquo;une seule syntaxe !&lt;/p&gt;
&lt;p&gt;Ainsi&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;wget https://ftp.drupal.org/files/projects/devel-8.x-1.x-dev.tar.gz
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;devient&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;http --download https://ftp.drupal.org/files/projects/devel-8.x-1.x-dev.tar.gz
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Le fait d&amp;rsquo;être capable d&amp;rsquo;utiliser une même commande pour les requêtes et pour le téléchargement va vite vous simplifier la vie. Une seule syntaxe à retenir.&lt;/p&gt;
&lt;p&gt;Le fait de n&amp;rsquo;avoir plus qu&amp;rsquo;une commande à retenir va nous simplifier la vie et cela est encore plus vrai si on doit utiliser des certificats SSL.&lt;/p&gt;
&lt;p&gt;Par exemple, nous avons une API que l&amp;rsquo;on doit requêter et une route de récupération de fichier zip, le tout accessible uniquement via une clé et un certificat SSL.&lt;/p&gt;
&lt;p&gt;On passera donc des commandes suivantes&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;curl -i -v --key ./certs/mon-certicat.key --cert ./certs/mon-certicat.pem &amp;#34;https://mon-api.com/infos&amp;#34;

wget --private-key=&amp;#34;./certs/mon-certicat.key&amp;#34; --certificate=&amp;#34;./certs/mon-certicat.pem&amp;#34; &amp;#34;https://mon-api.com/infos/images.zip&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;à&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;http --cert=./certs/mon-certicat.pem --cert-key=./certs/mon-certicat.key https://mon-api.com/infos

http --download --cert=./certs/mon-certicat.pem --cert-key=./certs/mon-certicat.key https://mon-api.com/infos/images.zip
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;C&amp;rsquo;est quand même plus simple à retenir quand on a qu&amp;rsquo;une seule syntaxe non ?&lt;/p&gt;
&lt;h2 id=&#34;pour-aller-plus-loin&#34;&gt;Pour aller plus loin&lt;/h2&gt;
&lt;p&gt;Lisez la documentation disponible sur le &lt;a href=&#34;https://github.com/jkbrzt/httpie&#34;&gt;dépôt Github HTTPie&lt;/a&gt; elle est vraiment très complète.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Tmux - Exemple de fichier de configuration</title>
      <link>https://gastaud.io/article/tmux-exemple-config/</link>
      <pubDate>Thu, 07 Apr 2016 13:49:38 +0200</pubDate>
      
      <guid>https://gastaud.io/article/tmux-exemple-config/</guid>
      
        <description>&lt;p&gt;Exemple de fichier .tmux.conf&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Update default binding of `Enter` to also use copy-pipe
unbind -t vi-copy Enter
bind-key -t vi-copy Enter copy-pipe &amp;#34;reattach-to-user-namespace pbcopy&amp;#34;

# Mouse scrolling and selection
set -g mode-mouse on
set -g default-terminal &amp;#34;screen-256color&amp;#34;

# Allows for faster key repetition
set -s escape-time 0

# C-b is not acceptable -- Vim uses it; Set ctrl+a as a prefix
set -g prefix C-a
unbind-key C-b
bind-key a send-prefix

bind-key C-a last-window

# Kill windows and panes faster, by rebinding the confirmation key
bind-key &amp;amp;amp; kill-window
bind-key x kill-pane
bind-key q kill-server

# Renumber windows sequentially after closing any of them
set -g renumber-windows on

# set window and pane index to 1 (0 by default)
set-option -g base-index 1
setw -g pane-base-index 1

# increase scrollback lines
set -g history-limit 10000

# get notification when something happend on a tmux window
setw -g monitor-activity on

# disable auto-rename from tmux
set-window-option -g allow-rename off
&lt;/code&gt;&lt;/pre&gt;</description>
      
    </item>
    
    <item>
      <title>[Vidéo] La gestion de produit Agile en 2 mots</title>
      <link>https://gastaud.io/article/gestion-produit-agile-2-mots/</link>
      <pubDate>Thu, 07 Apr 2016 13:32:21 +0200</pubDate>
      
      <guid>https://gastaud.io/article/gestion-produit-agile-2-mots/</guid>
      
        <description>&lt;p&gt;J&amp;rsquo;ai (re)découvert cette vidéo il y a quelque temps.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est une présentation synthétique de 15 minutes permettant de comprendre très simplement les grands concepts de l&amp;rsquo;agilité d&amp;rsquo;un point de vue métier dans le cadre de développement logiciel Agile.&lt;br&gt;
La vidéo a été réalisée par de Henrik Kniberg, traduite par Cédric Chevalérias et doublée par Florent Lothon.&lt;/p&gt;
&lt;p&gt;A diffuser sans modération !&lt;/p&gt;
&lt;center&gt;
[![IMAGE ALT TEXT](https://img.youtube.com/vi/3qMpB-UH9kA/0.jpg)](http://www.youtube.com/watch?v=3qMpB-UH9kA &#34;Voir la vidéo&#34;)
&lt;/center&gt;
</description>
      
    </item>
    
    <item>
      <title>HTTP 1.x ou HTTP/2  - Lequel choisir ?</title>
      <link>https://gastaud.io/article/http1x-http2-lequel-choisir/</link>
      <pubDate>Tue, 02 Feb 2016 13:45:17 +0200</pubDate>
      
      <guid>https://gastaud.io/article/http1x-http2-lequel-choisir/</guid>
      
        <description>&lt;p&gt;Le support de HTTP/2 est maintenant suffisamment stable et implémenté dans les serveurs les plus couramment utilisés alors qu&amp;rsquo;elles sont les raisons qui pourraient nous pousser à choisir une version ou l&amp;rsquo;autre dans nos projets ?&lt;/p&gt;
&lt;h2 id=&#34;http-1x&#34;&gt;HTTP 1.x&lt;/h2&gt;
&lt;p&gt;Vous serez obliger de continuer à utiliser HTTP 1.x dans les cas suivants :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;site en HTTP non sécurisé&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bien qu&amp;rsquo;HTTP/2 supporte officiellement le protocole HTTP non sécurisé, l&amp;rsquo;ensemble des navigateurs ont pour le moment fait le choix de ne pas l&amp;rsquo;implémenter.
Du coup, si vous n&amp;rsquo;avez pas de certificat pour votre nom de domaine, il vous faudra rester sur HTTP 1.x&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Restrictions techniques par rapport au serveur web utilisé&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Les cas sont rares maintenant.
Vous pouvez vérifier si le votre le supporte sur le &lt;a href=&#34;https://github.com/http2/http2-spec/wiki/Implementations&#34;&gt;Github HTTP2&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;mon hébergeur ne veut pas le faire&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Changer d&amp;rsquo;hébergeur ! :)&lt;/p&gt;
&lt;h2 id=&#34;http2&#34;&gt;HTTP/2&lt;/h2&gt;
&lt;p&gt;Si vous avez la main sur l&amp;rsquo;architecture serveur de votre application ou êtes à même d&amp;rsquo;être prescripteur sur les solutions à implémenter alors il est préconisé d&amp;rsquo;envisager de passer à HTTP/2 dès maintenant.&lt;/p&gt;
&lt;h2 id=&#34;les-contraintes&#34;&gt;Les contraintes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;un serveur supportant HTTP/2&lt;/li&gt;
&lt;li&gt;un certificat SSL&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Et vous alors êtes-vous déjà passer à HTTP/2 ?&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Bash - Récupérer le chemin absolu d&#39;exécution du script</title>
      <link>https://gastaud.io/article/bash-chemin-absolu/</link>
      <pubDate>Thu, 10 Dec 2015 13:50:52 +0200</pubDate>
      
      <guid>https://gastaud.io/article/bash-chemin-absolu/</guid>
      
        <description>&lt;p&gt;Lors de l&amp;rsquo;exécution d&amp;rsquo;un fichier &lt;em&gt;bash&lt;/em&gt;, il est parfois nécessaire de récupérer le chemin d&amp;rsquo;exécution du script.&lt;/p&gt;
&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$(dirname $(readlink -f $0))
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;ui negative message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;&lt;p&gt;&lt;strong&gt;Attention :&lt;/strong&gt; Sur Mac OS X, readlink ne fonctionne pas de la même façon que sur Linux.
Il vous faudra chercher une alternative. 3 pistes :&lt;/p&gt;
&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;la plus universelle &lt;code&gt;$( cd &amp;ldquo;$( dirname &amp;ldquo;${0}&amp;rdquo; )&amp;rdquo; &amp;amp;&amp;amp; pwd )&lt;/code&gt;&lt;/li&gt;&lt;/li&gt;
&lt;li&gt;utiliser &lt;code&gt;realpath -s $0&lt;/code&gt;&lt;/li&gt;&lt;/li&gt;
&lt;li&gt;installer &lt;code&gt;greadlink&lt;/code&gt;&lt;/li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&#34;la-commande-dirname&#34;&gt;La commande dirname&lt;/h2&gt;
&lt;p&gt;L&amp;rsquo;un des moyens les plus courant est d&amp;rsquo;utiliser la commande&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;`dirname &amp;#34;$0&amp;#34;`
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;$0 renvoi le nom du script&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le soucis ici c&amp;rsquo;est que le retour de &lt;code&gt;dirname&lt;/code&gt; ne sera pas identique en fonction de son lieu d&amp;rsquo;exécution.&lt;/p&gt;
&lt;p&gt;Par exemple, les appels suivants auront tous un retour différent :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;vagrant@store-dev:~$ sh www/store/updates/update_sample.sh
dirname: www/store/updates

vagrant@store-dev:~/www/store/updates$ sh update_sample.sh
dirname: .

vagrant@store-dev:~/www/store$ sh ./updates/update_sample.sh
dirname: ./updates

vagrant@store-dev:~/www/store/docroot$ sh ../updates/update_sample.sh
dirname: ../updates
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;readlink-pour-nous-sauver&#34;&gt;Readlink pour nous sauver&lt;/h2&gt;
&lt;p&gt;Pour s&amp;rsquo;assurer que &lt;code&gt;dirname&lt;/code&gt; nous renvoi toujours un chemin consistant, il est possible de le combiner avec la commande &lt;code&gt;readlink&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;La combinaison des 2 nous renverra ainsi un chemin absolu vers le script.
On aura donc maintenant un retour identique pour tous nos appels au script.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;vagrant@store-dev:~$ sh www/store/updates/update_sample.sh
dirname: www/store/updates
dirname/readlink: /home/vagrant/www/store/updates

vagrant@store-dev:~/www/store/updates$ sh update_sample.sh
dirname: .
dirname/readlink: /home/vagrant/www/store/updates

vagrant@store-dev:~/www/store$ sh ./updates/update_sample.sh
dirname: ./updates
dirname/readlink: /home/vagrant/www/store/updates

vagrant@store-dev:~/www/store/docroot$ sh ../updates/update_sample.sh
dirname: ../updates
dirname/readlink: /home/vagrant/www/store/updates
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;vérifier-ce-qui-marche-chez-vous&#34;&gt;Vérifier ce qui marche chez vous&lt;/h2&gt;
&lt;p&gt;A mettre dans un fichier test.sh&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pwd: `pwd`&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\$0: &lt;/span&gt;$0&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;basename: `basename &lt;/span&gt;$0&lt;span style=&#34;color:#e6db74&#34;&gt;`&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dirname: `dirname &lt;/span&gt;$0&lt;span style=&#34;color:#e6db74&#34;&gt;`&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dirname/readlink: &lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;dirname &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;readlink -f $0&lt;span style=&#34;color:#66d9ef&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;realpath: &lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;dirname &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;realpath -s $0&lt;span style=&#34;color:#66d9ef&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cd/pwd: &lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt; cd &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt; dirname &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;0&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &amp;amp;amp;&amp;amp;amp; pwd &lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&#34;mise-en-application&#34;&gt;Mise en application&lt;/h2&gt;
&lt;p&gt;L&amp;rsquo;exemple ci-dessous nous permet de définir, en fonction des paramètres d&amp;rsquo;appel du script, l&amp;rsquo;alias drush à utiliser.
Cependant si le script est appelé sans paramètre, nous souhaitons passer définir &lt;code&gt;--root&lt;/code&gt; en tant qu&amp;rsquo;alias.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Si pas de paramètres.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; -z &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;1&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    DIR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;dirname &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;readlink -f $0&lt;span style=&#34;color:#66d9ef&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# On vérifie que docroot existe.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; -d &lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;DIR&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/../docroot&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        drush_alias&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;--root=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;DIR&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/../docroot&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Script was not run.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        exit &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    drush_alias&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;@&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;1&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# La suite du script.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</description>
      
    </item>
    
    <item>
      <title>Git : Supprimer toutes les branches mergées sur le dépot distant</title>
      <link>https://gastaud.io/article/git-supprimer-branches-mergees/</link>
      <pubDate>Thu, 03 Dec 2015 13:51:38 +0200</pubDate>
      
      <guid>https://gastaud.io/article/git-supprimer-branches-mergees/</guid>
      
        <description>&lt;p&gt;Supprimer toutes les branches mergées sur votre dépot distant en 1 ligne de commande c&amp;rsquo;est possible !&lt;/p&gt;
&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git branch -r --merged master | grep -v master | sed &amp;#39;s/origin\///&amp;#39; | xargs -n 1 git push --delete origin
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;ui negative message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;&lt;p&gt;&lt;strong&gt;Attention :&lt;/strong&gt; cette commande permet de véritablement supprimer des branches dans le dépôt distant. Par exemple, si &lt;code&gt;develop&lt;/code&gt; est mergé avec &lt;code&gt;master&lt;/code&gt;, cela supprimera &lt;code&gt;develop&lt;/code&gt;. Mais peut-être que les développeurs n&amp;rsquo;ont pas le droit de pousser du code sur &lt;code&gt;master&lt;/code&gt; directement… et se retrouveront, du coup, bloqués. Pensez-y !&lt;/p&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&#34;exemple-excluant-une-branche-nommée-develop&#34;&gt;Exemple excluant une branche nommée &lt;code&gt;develop&lt;/code&gt;&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git branch -r --merged master | grep -v master | grep -v develop | sed &amp;#39;s/origin\///&amp;#39; | xargs -n 1 git push --delete origin
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;explications&#34;&gt;Explications&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git branch -r --merged master&lt;/code&gt; va récupérer la liste des branches distantes mergées (par rapport à master)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grep -v master&lt;/code&gt; va exclure la branche master des résultats (vous pouvez ajouter d&amp;rsquo;autres branches à exclure si nécessaire)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ces 2 premières commandes combinées vont renvoyés un résultat dans ce style :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  origin/t-619
  origin/t-63
  origin/t-675
  origin/t-707
  origin/t-808
  origin/t-809
  origin/t-819
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sed &#39;s/origin\///&#39;&lt;/code&gt; permet de supprimer le &lt;code&gt;origin/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xargs -n 1 git push --delete origin&lt;/code&gt; va prendre chaque ligne renvoyée et lancer la commande &lt;code&gt;git push --delete origin BRANCHE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
      
    </item>
    
    <item>
      <title>Envoyer des mails HTML via Drupal et Rules</title>
      <link>https://gastaud.io/article/drupal-rules-mails-html/</link>
      <pubDate>Tue, 03 Nov 2015 13:54:56 +0200</pubDate>
      
      <guid>https://gastaud.io/article/drupal-rules-mails-html/</guid>
      
        <description>&lt;h2 id=&#34;modules-de-la-contribution&#34;&gt;Modules de la contribution&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.drupal.org/project/htmlmail&#34;&gt;HTML Mail&lt;/a&gt; pour la gestion pure du mail au format HTML&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.drupal.org/project/mailsystem&#34;&gt;Mail System&lt;/a&gt; pour définir quel type de mail on envoi en fonction des actions&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.drupal.org/project/variable_email&#34;&gt;Variable Email&lt;/a&gt; vous permettra de stocker le mail dans une variable et l&amp;rsquo;envoyer via Rules.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;configuration-du-module-html-mail&#34;&gt;Configuration du module HTML Mail&lt;/h2&gt;
&lt;p&gt;Définissez dans le module HTMLMail le thème de votre site. Cela permettra de centraliser vos templates au sein de votre thème.&lt;/p&gt;
&lt;h2 id=&#34;configuration-du-module-mail-system&#34;&gt;Configuration du module Mail System&lt;/h2&gt;
&lt;p&gt;Configuré le module pour envoyer des mails passant par HTMLMail dans les cas qui vous intéressent, par exemple les mails système (création de compte, demande de renouvellement de mots de passe) en paramétrant la class &lt;code&gt;HTMLMailSystem&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Si vous voulez que les mails envoyés via Rules passent également par HTML Mail, il est possible de créer un &amp;ldquo;New settings&amp;rdquo; en sélectionnant le module Rules dans la liste.
Une fois le nouveau paramétrage créé, il est possible de lui associer la class &lt;code&gt;HTMLMailSystem&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;créer-une-nouvelle-variable-de-type-mail&#34;&gt;Créer une nouvelle variable de type mail&lt;/h2&gt;
&lt;p&gt;Dans le .info du module, ajouter une dépendance à&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;dependencies[] = variable
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Créer un fichier my_module.variable.inc&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * @file
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * my_module.variable.inc
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Implements hook_variable_info().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;my_module_variable_info&lt;/span&gt;($options) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $variable[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;mail_do_something_[mail_part]&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;title&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Send mail when something happend&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;type&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;mail_text&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;default&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;subject&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;My default subject&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;body&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;My default body&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;required&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TRUE&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;group&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;store_mails&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;token&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TRUE&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; $variable;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;permettre-la-modification-et-traduction-de-la-variable&#34;&gt;Permettre la modification et traduction de la variable&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Allez sur la page /admin/config/regional/i18n/variable et cocher la nouvelle variable créée.&lt;/li&gt;
&lt;li&gt;Enregistrer&lt;/li&gt;
&lt;li&gt;La variable devrait être disponible en édition pour les différentes langues de votre site sur la page /admin/store/mails&lt;/li&gt;
&lt;li&gt;Modifier les valeurs des différentes langues pour y inclure le markup HTML du mail&lt;/li&gt;
&lt;li&gt;Enregistrer&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;packaging-du-mail&#34;&gt;Packaging du mail&lt;/h2&gt;
&lt;p&gt;Ajouter à votre feature la variable à packager
Ajouter à votre feature la variable &lt;code&gt;variable_realm_list_language&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$strongarm &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;stdClass&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$strongarm&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;disabled&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FALSE&lt;/span&gt;; &lt;span style=&#34;color:#75715e&#34;&gt;/* Edit this to true to make a default strongarm disabled initially */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$strongarm&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;api_version&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$strongarm&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;name&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;variable_realm_list_language&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$strongarm&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;mail_do_something_[mail_part]&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$export[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;variable_realm_list_language&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; $strongarm;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&#34;utiliser-la-variable-dans-rules&#34;&gt;Utiliser la variable dans Rules&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Ajouter une Action : Send mail with Variable&lt;/li&gt;
&lt;li&gt;Sélectionner la variable créée&lt;/li&gt;
&lt;li&gt;Ajouter &lt;code&gt;node:author:language&lt;/code&gt; dans la partie Langue, ce qui permettra d&amp;rsquo;envoyer automatiquement la variable localisée à l&amp;rsquo;utilisateur&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lors du packaging de votre rules, une dépendance à variable_email devrait se créer.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;dependencies[] = variable_email
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Dans l&amp;rsquo;exemple, ci-dessous nous allons envoyer un mail à l&amp;rsquo;auteur du contenu à sa création et on obtient l&amp;rsquo;export suivant :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Implements hook_default_rules_configuration().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;my_module_default_rules_configuration&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $items &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $items[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rules_mail_to_author&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;entity_import&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rules_config&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{ &amp;#34;rules_mail_to_author&amp;#34; : {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      &amp;#34;LABEL&amp;#34; : &amp;#34;Send mail to author&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      &amp;#34;PLUGIN&amp;#34; : &amp;#34;reaction rule&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      &amp;#34;OWNER&amp;#34; : &amp;#34;rules&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      &amp;#34;REQUIRES&amp;#34; : [ &amp;#34;variable_email&amp;#34;, &amp;#34;rules&amp;#34; ],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      &amp;#34;ON&amp;#34; : { &amp;#34;node_insert--page&amp;#34; : { &amp;#34;bundle&amp;#34; : &amp;#34;page&amp;#34; } },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      &amp;#34;DO&amp;#34; : [
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        { &amp;#34;variable_email_mail&amp;#34; : {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            &amp;#34;to&amp;#34; : [ &amp;#34;node:author:mail&amp;#34; ],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            &amp;#34;variable&amp;#34; : &amp;#34;mail_do_something_[mail_part]&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            &amp;#34;language&amp;#34; : [ &amp;#34;node:author:language&amp;#34; ]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      ]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;  }&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; $items;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Et vous comment gérez-vous les envois de mails HTML dans Drupal ?&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Tests unitaires avec Simpletest dans Drupal 7</title>
      <link>https://gastaud.io/article/tests-unitaires-simpletest-drupal-7/</link>
      <pubDate>Thu, 22 Oct 2015 22:18:35 +0200</pubDate>
      
      <guid>https://gastaud.io/article/tests-unitaires-simpletest-drupal-7/</guid>
      
        <description>
&lt;div class=&#34;ui positive message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;&lt;p&gt;Si vous ne l&amp;rsquo;avez pas encore lu, allez lire l&amp;rsquo;article &lt;a href=&#34;https://gastaud.io/article/tester-modules-drupal-7/&#34;&gt;Tester ses modules Drupal 7&lt;/a&gt;.&lt;/p&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Les tests fonctionnels via Simpletest sont gérés par la class &lt;code&gt;DrupalUnitTestCase&lt;/code&gt; qu&amp;rsquo;il faut ensuite étendre dans son module.&lt;/p&gt;
&lt;p&gt;Drupal va exécuter chaque fonction commençant par &lt;code&gt;test&lt;/code&gt; définie dans la class.&lt;/p&gt;
&lt;p&gt;Contrairement aux tests fonctionnels, Drupal ne va pas reconstruire d&amp;rsquo;environnement pour lancer ce type de tests. Il va se contenter de charger les modules spécifiés dans l&amp;rsquo;initialisation et lancer les fonctions donner avec les bons paramètres.&lt;/p&gt;
&lt;p&gt;Les fonctions testées ne doivent donc pas dépendre de données récupérées en base. C&amp;rsquo;est le retour de la fonction qui sera ensuite vérifié.&lt;/p&gt;
&lt;h1 id=&#34;mise-en-place-des-tests&#34;&gt;Mise en place des tests&lt;/h1&gt;
&lt;p&gt;Comme pour les &lt;a href=&#34;https://gastaud.io/article/tests-fonctionnels-simpletest-drupal-7/&#34;&gt;tests fonctionnels&lt;/a&gt; il faut étendre une class de base de Drupal : &lt;code&gt;DrupalUnitTestCase&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MyModuleUnitTestCase&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DrupalUnitTestCase&lt;/span&gt; {}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On va également déclarer la méthode getInfo().&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getInfo&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Note: getInfo() strings should not be translated.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;My module unit tests&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;description&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Test that utilities functions used in my_module modules work fine.&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;group&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;My module group&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Déclaration les modules dont on va charger le code via la méthode &lt;code&gt;setUp()&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Set up the test environment.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Note that we use drupal_load() instead of passing our module dependency
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * to parent::setUp(). That&amp;#39;s because we&amp;#39;re using DrupalUnitTestCase, and
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * thus we don&amp;#39;t want to install the module, only load it&amp;#39;s code.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Also, DrupalUnitTestCase can&amp;#39;t actually install modules. This is by
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * design.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setUp&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;drupal_load&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;module&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;my_module&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;setUp&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;et enfin déclarer nos fonction de test qui doivent commencer par le mot clé &lt;code&gt;test&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Test my_module_check_login().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Note that no environment is provided; we&amp;#39;re just testing the correct
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * behavior of a function when passed specific arguments.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;testMyModuleCheckLoginFunction&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Your tests
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&#34;exemple&#34;&gt;Exemple&lt;/h2&gt;
&lt;p&gt;On souhaite pouvoir tester le retour de la fonction suivante :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Check the user login match the regex.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * @return
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;my_module_check_login&lt;/span&gt;($login) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Extract all regex defined.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $regex_list &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;explode&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;;&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/^[0-9]{7}[A-Z]$/i;/^(P|A|Z|F|E|S)[A-Z]{3}[0-9]{5}$/i;/^.*domain\.fr$/i&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Check if the login verify at least one regex.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;foreach&lt;/span&gt; ($regex_list &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; $regex) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// If there is one result.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;preg_match&lt;/span&gt;($regex, $login)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TRUE&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FALSE&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ce qui pourrait donner un test comme ceci :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Test my_module_check_login().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Note that no environment is provided; we&amp;#39;re just testing the correct
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * behavior of a function when passed specific arguments.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;testMyModuleCheckLoginFunction&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;my_module_check_login&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;NULL&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Note that test assertion messages should never be translated, so
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// this string is not wrapped in t().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $message &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;A NULL value should return FALSE.&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;assertFalse&lt;/span&gt;($result, $message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;my_module_check_login&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $message &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;An empty string should return FALSE.&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;assertFalse&lt;/span&gt;($result, $message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;my_module_check_login&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;something@domain.fr&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $message &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;An string with @domain.fr should return TRUE.&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;assertTrue&lt;/span&gt;($result, $message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;store_user_check_login&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;@domain.fr&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $message &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;An string with @domain.fr should return TRUE.&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;assertTrue&lt;/span&gt;($result, $message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;my_module_check_login&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;AZER01234&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $message &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;A string that looks like a CP code should return TRUE.&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;assertTrue&lt;/span&gt;($result, $message);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&#34;ui positive message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
      &lt;div class=&#34;header&#34;&gt;
        Pour en savoir plus
      &lt;/div&gt;
    
    
    &lt;p&gt;&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/tester-modules-drupal-7/&#34;&gt;Tester ses modules Drupal 7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/tests-fonctionnels-simpletest-drupal-7/&#34;&gt;Tests fonctionnels avec Drupal 7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

</description>
      
    </item>
    
    <item>
      <title>Tests fonctionnels avec Simpletest dans Drupal 7</title>
      <link>https://gastaud.io/article/tests-fonctionnels-simpletest-drupal-7/</link>
      <pubDate>Thu, 22 Oct 2015 22:17:56 +0200</pubDate>
      
      <guid>https://gastaud.io/article/tests-fonctionnels-simpletest-drupal-7/</guid>
      
        <description>
&lt;div class=&#34;ui positive message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;&lt;p&gt;Si vous ne l&amp;rsquo;avez pas encore lu, allez lire l&amp;rsquo;article &lt;a href=&#34;https://gastaud.io/article/tester-modules-drupal-7/&#34;&gt;Tester ses modules Drupal 7&lt;/a&gt;.&lt;/p&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Les tests fonctionnels via Simpletest sont gérés par la class &lt;code&gt;DrupalWebTestCase&lt;/code&gt; qu&amp;rsquo;il faut ensuite étendre dans son module.&lt;/p&gt;
&lt;p&gt;Pour chaque fonction commençant par &lt;code&gt;test&lt;/code&gt; définie dans la class, Simpletest va reconstruire entièrement une instance de Drupal, activer les modules désirés et exécuter les tests.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;avantage de ce type de tests réside dans le fait que Drupal a accès aux informations de la base de données et est donc en capacité d’exécuter la totalité des fonctions disponibles.&lt;/p&gt;
&lt;p&gt;Il est donc possible d&amp;rsquo;utiliser dans ces tests des fonctions comme node_save(), variable_get() &amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;mise-en-place-des-tests&#34;&gt;Mise en place des tests&lt;/h2&gt;
&lt;h3 id=&#34;déclarer-ces-fichier-de-tests&#34;&gt;Déclarer ces fichier de tests&lt;/h3&gt;
&lt;p&gt;Drupal décrit l&amp;rsquo;ensemble de ces tests dans des fichiers portant l&amp;rsquo;extension &lt;strong&gt;.test&lt;/strong&gt;.&lt;br&gt;
Chaque fichier de test doit ensuite être déclaré dans le &lt;strong&gt;.info&lt;/strong&gt; de votre module via la déclaration &lt;code&gt;files[]&lt;/code&gt; qui est notamment utilisé par Drupal pour charger ces class.&lt;/p&gt;
&lt;p&gt;Ainsi si vous nommez le fichier contenant vos tests &lt;em&gt;mon_module.test&lt;/em&gt;, il vous faudra ajouter la ligne suivante dans le .info : &lt;code&gt;files[] = mon_module.test&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;contenu-minimal-dun-fichier-de-tests&#34;&gt;Contenu minimal d&amp;rsquo;un fichier de tests&lt;/h3&gt;
&lt;h4 id=&#34;etendre-la-class-de-base-de-drupal&#34;&gt;Etendre la class de base de Drupal&lt;/h4&gt;
&lt;p&gt;Dans le cadre de tests fonctionnels, c&amp;rsquo;est donc la class &lt;code&gt;DrupalWebTestCase&lt;/code&gt; que l&amp;rsquo;on veut étendre.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;EditorListTests&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DrupalWebTestCase&lt;/span&gt; {}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&#34;déclaration-des-infos-de-notre-test&#34;&gt;Déclaration des infos de notre test&lt;/h3&gt;
&lt;p&gt;C&amp;rsquo;est la fonction static getInfo() qui se charge de recevoir ces informations.
Elle retourne un tableau contenant un nom, une description et un groupe.&lt;/p&gt;
&lt;p&gt;Le nom doit être unique pour votre class.
Le groupe peut être commun à plusieurs modules, ce qui est pratique pour pouvoir lancer par exemple l&amp;rsquo;ensemble des tests de vos modules custom en 1 fois.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getInfo&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Note: getInfo() strings should not be translated.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Editor List tests&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;description&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Test that editor_list module work fine.&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;group&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Editor List&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&#34;déclaration-des-modules-à-activer&#34;&gt;Déclaration des modules à activer&lt;/h4&gt;
&lt;p&gt;2nd fonction obligatoire à déclarer dans vos fichiers de tests, il s&amp;rsquo;agit de &lt;code&gt;setUp()&lt;/code&gt;.
Cette fonction vous permet de définir, notamment, les modules à charger lors de l&amp;rsquo;initialisation des environnements de test.&lt;/p&gt;
&lt;p&gt;Dans l&amp;rsquo;exemple ci-dessous, on déclare ainsi que les environnements doivent avoir le module &lt;em&gt;editor_list&lt;/em&gt; de charger.
A l&amp;rsquo;initialisation Drupal se charge de regarder les dépendances des modules à activer et les activer automatiquement.
Il n&amp;rsquo;est donc pas nécessaire de tous les déclarer explicitement.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * {@inheritdoc}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setUp&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;setUp&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;editor_list&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Il est également possible d&amp;rsquo;utiliser cette méthode &lt;em&gt;setUp()&lt;/em&gt; pour définir des éléments nécessaires à l&amp;rsquo;ensemble de vos tests.
Par exemple, création d&amp;rsquo;un compte admin, création de contenus de tests &amp;hellip;
Ces éléments pourront ainsi être exploiter directement dans vos tests sans avoir besoin de répéter la phase de création à chaque fois.&lt;/p&gt;
&lt;h4 id=&#34;déclarer-une-fonction-de-test&#34;&gt;Déclarer une fonction de test&lt;/h4&gt;
&lt;p&gt;Un fonction de test doit obligatoirement commencer par le mot clé &lt;code&gt;test&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Test Administration page access and edition.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;testAdministrationPage&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Your tests
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;L&amp;rsquo;obligation d&amp;rsquo;avoir le mot clé &lt;em&gt;test&lt;/em&gt; au début du nom de votre fonction vous permet de créer des fonctions utilitaires dans la même class en étant certains qu&amp;rsquo;elles ne seront pas exécuter par Simpletest si vous ne les appelez pas explicitement.&lt;/p&gt;
&lt;h1 id=&#34;exemple-complet&#34;&gt;Exemple complet&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://git.clever-age.net/clever-age-expertise/drupal-editor-list/blob/master/editor_list.test&#34;&gt;Module editor_list&lt;/a&gt;&lt;/p&gt;

&lt;div class=&#34;ui positive message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
      &lt;div class=&#34;header&#34;&gt;
        Pour en savoir plus
      &lt;/div&gt;
    
    
    &lt;p&gt;&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/tester-modules-drupal-7/&#34;&gt;Tester ses modules Drupal 7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/tests-unitaires-simpletest-drupal-7/&#34;&gt;Tests unitaires avec Drupal 7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

</description>
      
    </item>
    
    <item>
      <title>Tester ses modules Drupal</title>
      <link>https://gastaud.io/article/tester-modules-drupal-7/</link>
      <pubDate>Thu, 22 Oct 2015 22:17:21 +0200</pubDate>
      
      <guid>https://gastaud.io/article/tester-modules-drupal-7/</guid>
      
        <description>
&lt;div class=&#34;ui grey message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;&lt;p&gt;Les tests fonctionnels et encore plus unitaires sous Drupal c&amp;rsquo;est la galère.&lt;/p&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Voilà une phrase qu&amp;rsquo;il est fréquent d&amp;rsquo;entendre.&lt;/p&gt;
&lt;p&gt;Nous allons donc essayer via une série d&amp;rsquo;articles de voir quels types de tests s&amp;rsquo;offrent à nous, que ce soit via les outils fournis directement par Drupal ou via l&amp;rsquo;utilisation d&amp;rsquo;outils externes.&lt;/p&gt;
&lt;p&gt;Démarrons donc par une présentation du framework de tests embarqué dans Drupal 7 : &lt;strong&gt;Simpletest&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&#34;types-de-tests-disponibles&#34;&gt;Types de tests disponibles&lt;/h2&gt;
&lt;p&gt;Simpletest met à disposition 2 types de tests :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;des tests fonctionnels&lt;/li&gt;
&lt;li&gt;des tests unitaires&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;tests-fonctionnels&#34;&gt;Tests fonctionnels&lt;/h3&gt;
&lt;p&gt;Ces tests sont gérés par la class &lt;code&gt;DrupalWebTestCase&lt;/code&gt; qu&amp;rsquo;il faut ensuite étendre dans son module.&lt;/p&gt;
&lt;p&gt;Pour chaque fonction commençant par &lt;code&gt;test&lt;/code&gt; définie dans la class, Simpletest va reconstruire entièrement une instance de Drupal, activer les modules désirés et exécuter les tests.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;avantage de ce type de tests réside dans le fait que Drupal a accès aux informations de la base de données et est donc en capacité d’exécuter la totalité des fonctions disponibles.&lt;/p&gt;
&lt;p&gt;Il est donc possible d&amp;rsquo;utiliser dans ces tests des fonctions comme node_save(), variable_get() &amp;hellip;&lt;/p&gt;

&lt;div class=&#34;ui negative message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;&lt;p&gt;Si le nombre de tests lancé est conséquent, il est possible que ces tests prennent beaucoup de temps.&lt;/p&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;ui blue message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
      &lt;div class=&#34;header&#34;&gt;
        A lire aussi
      &lt;/div&gt;
    
    
    &lt;p&gt;&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/tests-fonctionnels-simpletest-drupal-7/&#34;&gt;Tests fonctionnels avec Simpletest sous Drupal 7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&#34;tests-unitaires&#34;&gt;Tests unitaires&lt;/h3&gt;
&lt;p&gt;Ces tests sont gérés par la class &lt;code&gt;DrupalUnitTestCase&lt;/code&gt; qu&amp;rsquo;il faut ensuite étendre dans son module.&lt;/p&gt;
&lt;p&gt;Comme pour les tests fonctionnels, Drupal va exécuter chaque fonction commençant par &lt;code&gt;test&lt;/code&gt; définie dans la class.&lt;/p&gt;
&lt;p&gt;Contrairement aux tests fonctionnels, Drupal ne va pas reconstruire d&amp;rsquo;environnement pour lancer ce type de tests. Il va se contenter de charger les modules spécifiés dans l&amp;rsquo;initialisation et lancer les fonctions donner avec les bons paramètres.&lt;/p&gt;
&lt;p&gt;Les fonctions testées ne doivent donc pas dépendre de données récupérées en base. C&amp;rsquo;est le retour de la fonction qui sera ensuite vérifié.&lt;/p&gt;

&lt;div class=&#34;ui blue message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
      &lt;div class=&#34;header&#34;&gt;
        A lire aussi
      &lt;/div&gt;
    
    
    &lt;p&gt;&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/tests-unitaires-simpletest-drupal-7/&#34;&gt;Tests unitaires dans Drupal 7 avec Simpletest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&#34;commandes-de-base&#34;&gt;Commandes de base&lt;/h2&gt;
&lt;p&gt;Pour pouvoir lancer vos tests sur Drupal, il faut activer le module Simpletest.&lt;br&gt;
&lt;code&gt;drush en simpletest -y&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lancer les tests via le coeur de Drupal
&lt;ul&gt;
&lt;li&gt;pour un groupe de tests&lt;br&gt;
&lt;code&gt;php scripts/run-tests.sh --url http://site.dev &amp;quot;Editor List&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;pour une class à tester&lt;br&gt;
&lt;code&gt;php scripts/run-tests.sh --url http://site.dev --class EditorListTests&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Lancer les tests via Drush
&lt;ul&gt;
&lt;li&gt;pour un groupe de tests&lt;br&gt;
&lt;code&gt;drush test-run --uri=http://site.dev &amp;quot;Editor List&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;pour une class à tester&lt;br&gt;
&lt;code&gt;drush test-run --uri=http://site.dev EditorListTests&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;stocker-les-résultats-des-tests&#34;&gt;Stocker les résultats des tests&lt;/h3&gt;
&lt;p&gt;Que ce soit via Drush ou le sh, vous pouvez spécifier l&amp;rsquo;option &amp;ndash;xml=chemin/dossier/resultats/de/tests qui recevra les récapitulatifs des tester effectués.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;drush test-run --uri=http://site.dev --xml=$PWD/tests MonModuleTests&lt;/code&gt;&lt;/p&gt;

&lt;div class=&#34;ui positive message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
      &lt;div class=&#34;header&#34;&gt;
        Pour en savoir plus
      &lt;/div&gt;
    
    
    &lt;p&gt;&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/tests-fonctionnels-simpletest-drupal-7/&#34;&gt;Tests fonctionnels avec Drupal 7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gastaud.io/article/tests-unitaires-simpletest-drupal-7/&#34;&gt;Tests unitaires avec Drupal 7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.drupal.org/node/265828&#34;&gt;Liste des assertions Simpletest disponibles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

</description>
      
    </item>
    
    <item>
      <title>Réinitiliser tous les emails et mots de passe utilisateur avec Drush</title>
      <link>https://gastaud.io/article/reinitiliser-tous-les-emails-et-mots-de-passe-utilisateur-avec-drush/</link>
      <pubDate>Mon, 05 Oct 2015 13:51:52 +0200</pubDate>
      
      <guid>https://gastaud.io/article/reinitiliser-tous-les-emails-et-mots-de-passe-utilisateur-avec-drush/</guid>
      
        <description>&lt;p&gt;Si vous récupérez une base de données Drupal en local, il peut être utile d&amp;rsquo;assigner des valeurs par défaut aux comptes utilisateurs.&lt;/p&gt;
&lt;p&gt;Cela permet entre autre :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;de se connecter simplement à l&amp;rsquo;ensemble des comptes&lt;/li&gt;
&lt;li&gt;d&amp;rsquo;éviter que des mails de tests soient envoyés aux contacts réels&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Avec Drush, cela est possible en une ligne de commande :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;drush sql-sanitize --sanitize-email=&amp;#34;user+%uid@localhost&amp;#34; --sanitize-password=&amp;#34;password&amp;#34;
&lt;/code&gt;&lt;/pre&gt;</description>
      
    </item>
    
    <item>
      <title>Installer la dernière version de Git sur Ubuntu</title>
      <link>https://gastaud.io/article/ubuntu-git-latest/</link>
      <pubDate>Wed, 30 Sep 2015 10:44:14 +0200</pubDate>
      
      <guid>https://gastaud.io/article/ubuntu-git-latest/</guid>
      
        <description>&lt;p&gt;Si vous utilisez régulièrement les systèmes de paquets fournis avec vos distributions, vous avez surement remarqué que les versions fournies sont généralement anciennes.&lt;/p&gt;
&lt;p&gt;Sur Ubuntu, Git ne déroge pas à la règle.&lt;/p&gt;
&lt;p&gt;En effet, Ubuntu 14.04 LTS donne accès à Git 1.9 et Ubuntu 15.05, Git 2.1. Au mieux une version sortie en fin 2014.&lt;/p&gt;
&lt;p&gt;Faites le test par vous même en ouvrant votre terminal et en lançant la commande suivante :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$&amp;gt; git --version
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;pourquoi-mettre-à-jour-&#34;&gt;Pourquoi mettre à jour ?&lt;/h2&gt;
&lt;p&gt;Dans un 1er temps pour profiter des corrections et optimisations apportées régulièrement au produit (amélioration des capacités de merge par exemple qui permet d&amp;rsquo;avoir une meilleure gestion des conflits), sans oublier les évolutions qui sont ajoutées régulièrement.&lt;/p&gt;
&lt;p&gt;On peux par exemple noté que la version 2.5 de Git apporte la possibilité d&amp;rsquo;avoir plusieurs &lt;code&gt;worktree&lt;/code&gt; - nos espaces de travail - simultanés via la commande &lt;a href=&#34;https://git-scm.com/docs/git-worktree&#34;&gt;&lt;code&gt;git worktree&lt;/code&gt;&lt;/a&gt; et depuis le 28 septembre 2015, la version 2.6.0 de Git est sortie.&lt;/p&gt;
&lt;p&gt;Alors comment mettre à jour simplement notre machine pour avoir accès aux dernières versions de Git.&lt;/p&gt;
&lt;h2 id=&#34;comment-on-fait-&#34;&gt;Comment on fait ?&lt;/h2&gt;
&lt;p&gt;La solution en 3 commandes (à lancer dans votre terminal)&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et voilà ! Vous devriez maintenant avoir accès à la dernière version de Git.&lt;/p&gt;
&lt;p&gt;Pour vérifier lancer à nouveau, dans votre terminal :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git --version
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Si la commande vous renvoie &lt;code&gt;git version 2.6.0&lt;/code&gt; (ou un nombre supérieure), c&amp;rsquo;est que tout c&amp;rsquo;est bien déroulé.&lt;/p&gt;
&lt;p&gt;Maintenant, votre version de Git continuera à se mettre à jour.&lt;/p&gt;
&lt;p&gt;Je vous invite donc à suivre régulièrement les &lt;a href=&#34;https://github.com/git/git/tree/master/Documentation/RelNotes&#34;&gt;Releases Notes  de Git&lt;/a&gt;, toujours pleines de bonnes informations à découvrir.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Gestion et surcharge d&#39;un field instance sous Drupal 8</title>
      <link>https://gastaud.io/article/entityconnect-d8/conversion-form-instance/</link>
      <pubDate>Mon, 31 Aug 2015 23:54:38 +0200</pubDate>
      
      <guid>https://gastaud.io/article/entityconnect-d8/conversion-form-instance/</guid>
      
        <description>&lt;center&gt;![entity connect](entityconnect.png)&lt;/center&gt;
&lt;p&gt;Retour sur le portage des options de configuration de champs pour le module &lt;a href=&#34;https://drupal.org/project/entityconnect&#34;&gt;Entity Connect&lt;/a&gt; sous Drupal 8.&lt;/p&gt;
&lt;p&gt;Entity Connect vient ajouter de nouvelles fonctionnalités aux champs de type Entity Reference. Le module propose de définir, pour chaque instance de champ, si les fonctionnalités proposées doivent être activées ou non.&lt;/p&gt;
&lt;h2 id=&#34;surcharge-de-linstance-du-champ-entity-reference&#34;&gt;Surcharge de l&amp;rsquo;instance du champ Entity Reference&lt;/h2&gt;
&lt;p&gt;Dans notre cas, nous avons besoin de surcharger la class &lt;code&gt;ConfigurableEntityReferenceItem&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;namespace&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Drupal\entityconnect&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;use&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Drupal\entity_reference\ConfigurableEntityReferenceItem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;use&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Drupal\Core\Form\FormStateInterface&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ConfigurableEntityconnectItem&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ConfigurableEntityReferenceItem&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Do something.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&#34;création-du-formulaire&#34;&gt;Création du formulaire&lt;/h2&gt;
&lt;h3 id=&#34;ajout-des-paramètres-au-field-instance&#34;&gt;Ajout des paramètres au field instance.&lt;/h3&gt;
&lt;h4 id=&#34;drupal-7&#34;&gt;Drupal 7&lt;/h4&gt;
&lt;p&gt;Sur Drupal 7, nous implémentions le &lt;code&gt;hook_field_instance_settings_form&lt;/code&gt; que nous invoquions ensuite via un &lt;code&gt;hook_form_alter&lt;/code&gt;.&lt;br&gt;
C&amp;rsquo;est l&amp;rsquo;utilisation du hook_form_alter qui permettait de passer de nouvelles valeurs de configuration au champ.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Add settings to an instance field settings form.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Invoked from field_ui_field_edit_form() to allow the module defining the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * field to add settings for a field instance.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * @return array
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; *   The form definition for the field instance settings.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;entityconnect_field_instance_settings_form&lt;/span&gt;($field, $instance) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $settings &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; $instance;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Add choice for user to not load entity connect &amp;#34;add&amp;#34; button
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// on the field.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect_unload_add&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#type&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;radios&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#title&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Display Entity Connect &amp;#34;add&amp;#34; button.&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#default_value&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;isset&lt;/span&gt;($settings[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect_unload_add&amp;#39;&lt;/span&gt;]) &lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;variable_get&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect_unload_add_default&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; $settings[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect_unload_add&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#description&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Choose &amp;#34;No&amp;#34; if you want to unload &amp;#34;add&amp;#34; button for the field&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#options&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Yes&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;No&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#weight&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Implements hook_FORM_ID_form_alter().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * @param $form
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * @param $form_state
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * @param $form_id
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;entityconnect_form_field_ui_field_edit_form_alter&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;$form, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;$form_state, $form_id) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $field_types &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_entityconnect_get_references_field_type_list&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Use to add choice field.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;in_array&lt;/span&gt;($form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#field&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;type&amp;#39;&lt;/span&gt;], $field_types)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $instance &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; $form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#instance&amp;#39;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $field &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; $form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#field&amp;#39;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $additions &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;module_invoke&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;field_instance_settings_form&amp;#39;&lt;/span&gt;, $field, $instance);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;is_array&lt;/span&gt;($additions) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;isset&lt;/span&gt;($form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;instance&amp;#39;&lt;/span&gt;])) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      $form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;instance&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; $additions;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&#34;drupal-8&#34;&gt;Drupal 8&lt;/h3&gt;
&lt;p&gt;Sur Drupal 8, la déclaration du formulaire va passer par la fonction &lt;code&gt;fieldSettingsForm()&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La récupération de la configuration va se faire via &lt;code&gt;$this-&amp;gt;getSettings()&lt;/code&gt;. Cette fonction renvoi un tableau.&lt;/li&gt;
&lt;li&gt;On va charger le formulaire parent (la configuration de notre champ Entity Reference) et ensuite ajouter nos champs. Sans cela, seuls nos nouveaux champs vont apparaitre.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   * {@inheritdoc}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fieldSettingsForm&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt; $form, &lt;span style=&#34;color:#a6e22e&#34;&gt;FormStateInterface&lt;/span&gt; $form_state) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $settings &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;getSettings&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $form &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;fieldSettingsForm&lt;/span&gt;($form, $form_state);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;buttons&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button_add&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#required&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#default_value&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; $settings[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;buttons&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button_add&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#description&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Default: &amp;#34;off&amp;#34;&amp;lt;br /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                            Choose &amp;#34;on&amp;#34; if you want the &amp;#34;add&amp;#34; buttons displayed by default.&amp;lt;br /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                            Each field can override this value.&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#weight&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#type&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;radios&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#options&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;on&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;off&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#title&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Default Entity Connect &amp;#34;add&amp;#34; button display&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&#34;ui positive message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;&lt;p&gt;Comme dans le formulaire d&amp;rsquo;administration, nous n&amp;rsquo;avons pas besoin de tester l&amp;rsquo;existance ou non d&amp;rsquo;une configuration.&lt;br&gt;
On se contente de récupérer la valeur configurée.&lt;/p&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&#34;définir-les-valeurs-par-défaut-de-notre-instance-de-champ&#34;&gt;Définir les valeurs par défaut de notre instance de champ&lt;/h2&gt;
&lt;h3 id=&#34;utiliser-des-valeurs-définies-en-dures&#34;&gt;Utiliser des valeurs définies en dures&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   * {@inheritdoc}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;defaultFieldSettings&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;buttons&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button_add&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button_edit&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;icons&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;icon_add&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;icon_edit&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ) &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;defaultFieldSettings&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&#34;ui red message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;&lt;p&gt;Attention à ne pas oublier l&amp;rsquo;appel à &lt;code&gt;+ parent::defaultFieldSettings();&lt;/code&gt; sous peine de ne pas avoir l&amp;rsquo;ensemble des settings disponibles.&lt;/p&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&#34;utiliser-les-valeurs-par-défaut-disponible-dans-la-configuration&#34;&gt;Utiliser les valeurs par défaut disponible dans la configuration&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   * {@inheritdoc}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;defaultFieldSettings&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $config &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;\Drupal&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;config&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect.administration_config&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; $config&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;getRawData&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; $data
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ) &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;defaultFieldSettings&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;\Drupal::config(&#39;entityconnect.administration_config&#39;)&lt;/code&gt; nous permet de charger les informations de configurations disponibles&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$config-&amp;gt;getRawData()&lt;/code&gt; nous permet de récupérer un tableau des valeurs (ci-dessous) par défaut (celles définies à l&amp;rsquo;installation ou configurées via le Back-Office).&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-perl&#34; data-lang=&#34;perl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Le retour de l&amp;#39;appel à $config-&amp;gt;getRawData();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Dans cet exemple, on voit que les valeurs par défaut&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#   ont été changées dans l&amp;#39;interface d&amp;#39;administration.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;array (size&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;buttons&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    array (size&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button_add&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; string &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; (length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button_edit&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; string &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt; (length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;icons&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    array (size&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;icon_add&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; string &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2&amp;#39;&lt;/span&gt; (length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;icon_edit&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; string &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; (length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Il ne nous reste plus qu&amp;rsquo;à remplacer nos valeurs en dures par nos valeurs dynamiques.&lt;/p&gt;
&lt;h2 id=&#34;prise-en-compte-de-notre-nouvelle-class&#34;&gt;Prise en compte de notre nouvelle class&lt;/h2&gt;
&lt;p&gt;Le module Entity Reference définie sa class dans son fichier .module et utilise le &lt;code&gt;hook_field_info_alter&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Implements hook_field_info_alter().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;entity_reference_field_info_alter&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;$info) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&lt;/span&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Make the entity reference field configurable.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&lt;/span&gt;&lt;span&gt;  $info[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entity_reference&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;no_ui&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FALSE&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#3c3d38&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&lt;/span&gt;&lt;span&gt;  $info[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entity_reference&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;class&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\Drupal\entity_reference\ConfigurableEntityReferenceItem&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&lt;/span&gt;&lt;span&gt;  $info[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entity_reference&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;list_class&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\Drupal\Core\Field\EntityReferenceFieldItemList&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&lt;/span&gt;&lt;span&gt;  $info[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entity_reference&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;default_widget&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entity_reference_autocomplete&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12&lt;/span&gt;&lt;span&gt;  $info[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entity_reference&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;default_formatter&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entity_reference_label&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13&lt;/span&gt;&lt;span&gt;  $info[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entity_reference&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;provider&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entity_reference&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Afin que notre class soit prise en compte, nous allons nous aussi utiliser ce hook et remplacer la class ConfigurableEntityReferenceItem par la notre.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Implements hook_field_info_alter().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;entityconnect_field_info_alter&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;$info) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#3c3d38&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&lt;/span&gt;&lt;span&gt;  $info[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entity_reference&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;class&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\Drupal\entityconnect\ConfigurableEntityconnectItem&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</description>
      
    </item>
    
    <item>
      <title>Création d&#39;un formulaire d&#39;administration sous Drupal 8</title>
      <link>https://gastaud.io/article/entityconnect-d8/formulaire-administration/</link>
      <pubDate>Thu, 27 Aug 2015 15:47:06 +0200</pubDate>
      
      <guid>https://gastaud.io/article/entityconnect-d8/formulaire-administration/</guid>
      
        <description>&lt;p&gt;Retour sur le portage de la partie d&amp;rsquo;administration du module &lt;a href=&#34;https://drupal.org/project/entityconnect&#34;&gt;Entity Connect&lt;/a&gt; sous Drupal 8.&lt;/p&gt;
&lt;h2 id=&#34;conversion-du-fichier-info&#34;&gt;Conversion du fichier .info&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Le nom du fichier change légèrement. Il passe ainsi de &lt;code&gt;*.info&lt;/code&gt; à &lt;code&gt;*.info.yml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Comme vous pouvez vous en douter en lisant le nom du nouveau fichier, le format utilisé dans ce fichier est le &lt;code&gt;YAML&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;drupal-7&#34;&gt;Drupal 7&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;.info&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;name = &amp;#34;Entity Connect&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;description = &amp;#34;Allows for referenced entity to be created and edited from the entity reference field&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;core = &amp;#34;7.x&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;package = Entity Connect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;configure = admin/config/content/entityconnect&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&#34;drupal-8&#34;&gt;Drupal 8&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;.info.yml&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Entity Connect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;module&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Allows for referenced entity to be created and edited from the entity reference field&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;core&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;8.&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;x&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Entity Connect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;configure&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;entityconnect.administration_form&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;dependencies&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#ae81ff&#34;&gt;entity_reference&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;La notation YAML fait que les &lt;code&gt;=&lt;/code&gt; deviennet des &lt;code&gt;:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Les guillemets sont toujours optionnels&lt;/li&gt;
&lt;li&gt;Il faut maintenant définir un type : &lt;code&gt;type: module&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Le lien &lt;code&gt;configure&lt;/code&gt; permettant d&amp;rsquo;afficher un lien direct vers l&amp;rsquo;interface d&amp;rsquo;administration ne contient plus directement un lien mais une référence à une route définie dans le fichier &lt;code&gt;entityconnect.routing.yml&lt;/code&gt; (voir ci-dessous).&lt;/li&gt;
&lt;li&gt;Le module &lt;code&gt;entityreference&lt;/code&gt; (sous D7) fait maintenant partie intégrante du coeur et s&amp;rsquo;appelle &lt;code&gt;entity_reference&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;définition-des-routes&#34;&gt;Définition des routes&lt;/h2&gt;
&lt;h3 id=&#34;drupal-7-1&#34;&gt;Drupal 7&lt;/h3&gt;
&lt;p&gt;la définition d&amp;rsquo;un nouveau chemin d&amp;rsquo;accès (route) passait par l&amp;rsquo;utilisation du hook_menu.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Implements hook_menu().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;entityconnect_menu&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $items &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $items[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;admin/config/content/entityconnect&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;title&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Entity Connect&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;description&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Configure default values for Entity Reference fields using Entity Connect&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;page callback&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;drupal_get_form&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;page arguments&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;_entityconnect_admin_form&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;access arguments&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;administer site configuration&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;file&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;includes/entityconnect.admin.inc&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; $items;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&#34;drupal-8-1&#34;&gt;Drupal 8&lt;/h3&gt;
&lt;p&gt;nous définissons maintenant ces éléments dans un fichier en &lt;code&gt;*.routing.yml&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;entityconnect.administration_form&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;path&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/admin/config/content/entityconnect&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;defaults&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;_form&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\Drupal\entityconnect\Form\AdministrationForm&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;_title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Entity Connect Administration&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;requirements&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;_permission&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;access administration pages&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&#34;conversion-du-formulaire&#34;&gt;Conversion du formulaire&lt;/h2&gt;
&lt;h3 id=&#34;drupal-7-2&#34;&gt;Drupal 7&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Defines the settings form.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_entityconnect_admin_form&lt;/span&gt;($form, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;$form_state) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $form &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#type&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;fieldset&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#title&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;EntityConnect default Parameters&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#type&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;fieldset&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#title&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Buttons display Parameters&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button_add&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#required&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#key_type_toggled&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#default_value&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;variable_get&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect_unload_add_default&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#description&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Default: &amp;#34;off&amp;#34;&amp;lt;br /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                          Choose &amp;#34;on&amp;#34; if you want the &amp;#34;add&amp;#34; buttons displayed by default.&amp;lt;br /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                          Each field can override this value.&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#weight&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#type&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;radios&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#options&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;on&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;off&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#title&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Default Entity Connect &amp;#34;add&amp;#34; button display&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button_edit&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#required&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#key_type_toggled&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#default_value&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;variable_get&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect_unload_edit_default&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#description&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Default: &amp;#34;off&amp;#34;&amp;lt;br /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                          Choose &amp;#34;on&amp;#34; if you want the &amp;#34;edit&amp;#34; buttons displayed by default.&amp;lt;br /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                          Each field can override this value.&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#weight&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#type&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;radios&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#options&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;on&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;off&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#title&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Default Entity Connect &amp;#34;edit&amp;#34; button display&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  $form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;submit&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#type&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;submit&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#value&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Save&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#weight&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; $form;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * The settings form submit.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_entityconnect_admin_form_submit&lt;/span&gt;($form, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;$form_state) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;variable_set&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect_unload_add_default&amp;#39;&lt;/span&gt;, $form_state[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;values&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button_add&amp;#39;&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;variable_set&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect_unload_edit_default&amp;#39;&lt;/span&gt;, $form_state[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;values&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button_edit&amp;#39;&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;drupal_set_message&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;The settings were saved.&amp;#39;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&#34;drupal-8-2&#34;&gt;Drupal 8&lt;/h3&gt;
&lt;p&gt;Nous allons devoir définir une class qui va étendre la class &lt;code&gt;ConfigFormBase&lt;/code&gt; de Drupal.&lt;br&gt;
Pour assurer l&amp;rsquo;autoload des classes, Drupal suit les conventions PSR-4.&lt;br&gt;
Nous allons donc créer notre nouvelle class au sein de l&amp;rsquo;arborescence suivante :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;.
├── src
│   └── Form
│       └── AdministrationForm.php
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On défini une namespace à notre class qui sera de la forme &lt;code&gt;Drupal\nom_du_module\Form\MyForm&lt;/code&gt;&lt;/p&gt;

&lt;div class=&#34;ui positive message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;Les modules avec un nom composé utilisent le caractère underscore ( _ ) comme séparateur.&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * @file
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Contains Drupal\entityconnect\Form\AdministrationForm.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;namespace&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Drupal\entityconnect\Form&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On va définir les classes utilisées dans notre Formulaire.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;use&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Drupal\Core\Form\ConfigFormBase&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;use&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Drupal\Core\Form\FormStateInterface&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On instancie notre class qui étend &lt;code&gt;ConfigFormBase&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Class DefaultForm.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * @package Drupal\entityconnect\Form
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AdministrationForm&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ConfigFormBase&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&#34;ui positive message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;ConfigFormBase nous permet ne pas avoir à redéfinir l&amp;rsquo;action de sauvegarde, l&amp;rsquo;instanciation du thème et du message de confirmation d&amp;rsquo;enregistrement.&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Nous commençons par initialiser la fonction getEditableConfigNames() qui va nous permettre de définir un tableau contenant les noms des objets de configuration que notre formulaire va pouvoir éditer.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   * {@inheritdoc}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getEditableConfigNames&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect.administration_config&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;La documentation Drupal fait généralement référence à un nom de la forme  &lt;code&gt;mon_module.settings&lt;/code&gt;. Cependant settings n&amp;rsquo;est pas un nom obligatoire. Le format attendu étant le suivant &lt;code&gt;&amp;lt;module_name&amp;gt;.&amp;lt;config_object_name&amp;gt;.&amp;lt;optional_sub_key&amp;gt;.yml&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&#34;ui positive message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;Ce nom sera utilisé à chaque fois qu&amp;rsquo;il est nécessaire de récupérer ou modifier cet élément de configuration. Il sera également utilisé pour instancier les valeurs par défaut.&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;On donne ensuite un Id à notre formulaire.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   * {@inheritdoc}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getFormId&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect_administration_form&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&#34;ui positive message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;Il est recommandé de faire commencer le formId par le nom du module.&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Et on construit notre formulaire via la fonction &lt;code&gt;buildFrom&lt;/code&gt;.&lt;br&gt;
Comme nous avons besoin de récupérer des éléments de configuration, nous allons charger la configuration via &lt;code&gt;$this-&amp;gt;config(&#39;entityconnect.administration_config&#39;)&lt;/code&gt; que l&amp;rsquo;on stocke dans une variable nommée &lt;code&gt;$config&lt;/code&gt;.&lt;br&gt;
Ainsi nous utiliserons la variable $config pour récupérer la valeur souhaitée via l&amp;rsquo;appel &lt;code&gt;$config-&amp;gt;get(&#39;ma_variable&#39;),&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   * {@inheritdoc}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;buildForm&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt; $form, &lt;span style=&#34;color:#a6e22e&#34;&gt;FormStateInterface&lt;/span&gt; $form_state) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $config &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;config&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect.administration_config&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#type&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;fieldset&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#title&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;EntityConnect default Parameters&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $form[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button_add&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#required&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#default_value&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; $config&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;button_add&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#description&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Default: &amp;#34;off&amp;#34;&amp;lt;br /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                            Choose &amp;#34;on&amp;#34; if you want the &amp;#34;add&amp;#34; buttons displayed by default.&amp;lt;br /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                            Each field can override this value.&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#weight&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#type&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;radios&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#options&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;on&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;off&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#title&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Default Entity Connect &amp;#34;add&amp;#34; button display&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Et on fini par retourner un appel à la class parent avec les éléments de formulaire ajoutés.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;buildForm&lt;/span&gt;($form, $form_state);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Enfin il est nécessaire de pouvoir enregistrer les valeurs après validation du formulaire.
Nous allons donc encore une fois utiliser l&amp;rsquo;objet &lt;code&gt;$this-&amp;gt;config(&#39;entityconnect.administration_config&#39;)&lt;/code&gt; et définir la variable avec la valeur du formulaire.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   * {@inheritdoc}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;submitForm&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;array&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;$form, &lt;span style=&#34;color:#a6e22e&#34;&gt;FormStateInterface&lt;/span&gt; $form_state) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;submitForm&lt;/span&gt;($form, $form_state);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $this&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;config&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;entityconnect.administration_config&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;set&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;icon_add&amp;#39;&lt;/span&gt;, $form_state&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;getValue&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;icon_add&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;set&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;icon_edit&amp;#39;&lt;/span&gt;, $form_state&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;getValue&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;icon_edit&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;save&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On a maintenant un formulaire prêt à fonctionner et enregistrer des éléments de configuration.&lt;/p&gt;
&lt;h2 id=&#34;définition-des-valeurs-par-défaut&#34;&gt;Définition des valeurs par défaut&lt;/h2&gt;
&lt;p&gt;Vous aurez peut être remarqué qu&amp;rsquo;à la différence de la fonction variable_get() dans Drupal 7, nous n&amp;rsquo;avons pas défini de valeurs par défaut à nos &lt;s&gt;variables&lt;/s&gt; configuration.&lt;/p&gt;
&lt;p&gt;Il n&amp;rsquo;est donc plus possible (et nécessaire) de redéfinir à chaque appel la valeur par défaut associée à une variable comme dans cet exemple &lt;code&gt;variable_get(&#39;entityconnect_unload_add_default&#39;, 1)&lt;/code&gt; où 1 était la valeur par défaut.&lt;/p&gt;
&lt;p&gt;Dans Drupal 8, les configurations sont maintenant stockées dans des fichiers.&lt;br&gt;
Pour définir une valeur par défaut à nos éléments de configuration, il est donc nécessaire de définir cela à l&amp;rsquo;installation du module.&lt;/p&gt;
&lt;p&gt;2 voies sont possibles :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;soit via le hook_install, si les valeurs a renseignée sont dynamiques
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; * Implements hook_install() in Drupal 8.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;modulename_install&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Set default values for config which require dynamic values.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;\Drupal&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;configFactory&lt;/span&gt;()&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;getEditable&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;modulename.settings&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;set&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;default_from_address&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;\Drupal&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;config&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;system.site&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;mail&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;save&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;soit via l&amp;rsquo;utilisation d&amp;rsquo;un fichier YAML qui contiendra les configurations par défaut (si les valeurs sont statiques).
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Contenu du fichier entityconnect.administration_config.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;button_add&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;button_edit&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;icon_add&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;icon_edit&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&#34;ui positive message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
    
    &lt;p&gt;Ce fichier doit se nommer avec le même nom que l&amp;rsquo;objet de configuration que nous appelons dans notre formulaire.&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Le fichier YAML créé doit être placé dans l&amp;rsquo;arborescence suivante :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;.
├── config
│   └── install
│       └── entityconnect.administration_config.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;ui positive message&#34;&gt;
  &lt;div class=&#34;content&#34;&gt;
    
      &lt;div class=&#34;header&#34;&gt;
        Pour en savoir plus
      &lt;/div&gt;
    
    
    &lt;p&gt;&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.drupal.org/node/1667896&#34;&gt;Upgrading Drupal 7 Variables to Drupal 8 Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.drupal.org/node/2120571&#34;&gt;Configuration Storage in Drupal 8&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&#34;organisation-des-fichiers-récapitulatif&#34;&gt;Organisation des fichiers (récapitulatif)&lt;/h2&gt;
&lt;p&gt;Drupal 7&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;.
├── entityconnect.info
├── entityconnect.module
├── includes
│   ├── entityconnect.admin.inc
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Drupal 8&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;.
├── config
│   └── install
│       └── entityconnect.administration_config.yml
├── entityconnect.info.yml
├── entityconnect.module
├── entityconnect.routing.yml
├── src
│   └── Form
│       └── AdministrationForm.php
&lt;/code&gt;&lt;/pre&gt;</description>
      
    </item>
    
    <item>
      <title>Docker - Comprendre le fonctionnement du tag latest</title>
      <link>https://gastaud.io/article/docker-comprendre-tag-latest/</link>
      <pubDate>Thu, 09 Apr 2015 00:00:00 +0000</pubDate>
      
      <guid>https://gastaud.io/article/docker-comprendre-tag-latest/</guid>
      
        <description>&lt;p&gt;Cet article est une synthèse d&amp;rsquo;une &lt;a href=&#34;https://medium.com/@mccode/the-misunderstood-docker-tag-latest-af3babfd6375&#34;&gt;publication parue sur Medium&lt;/a&gt; qui explique de manière précise le fonctionnement du tag &lt;strong&gt;latest&lt;/strong&gt; disponible sur les images Docker.&lt;/p&gt;
&lt;p&gt;Comme vous le savez surement, il est possible de tagger ces images Docker pour les déposer sur un registry.&lt;/p&gt;
&lt;p&gt;Cependant si vous avez essayé d&amp;rsquo;utiliser le tag &lt;strong&gt;lastest&lt;/strong&gt; disponible pour certaines images, notamment sur le &lt;a href=&#34;https://hub.docker.com/&#34;&gt;Hub Docker&lt;/a&gt;, vous avez pu vous rendre compte que ce tag n&amp;rsquo;a pas toujours le comportement espéré.&lt;/p&gt;
&lt;h2 id=&#34;un-secret-enfin-révélé&#34;&gt;Un secret enfin révélé&lt;/h2&gt;
&lt;p&gt;Ce que l&amp;rsquo;on apprend dans l&amp;rsquo;article, c&amp;rsquo;est que ce tag &amp;ldquo;latest&amp;rdquo; n&amp;rsquo;est pas vraiment un tag.&lt;/p&gt;
&lt;p&gt;Il n&amp;rsquo;est en réalité présent que pour désigner la dernière version commitée &lt;strong&gt;sans tag&lt;/strong&gt; et non pas la dernière version taggée/commitée.&lt;/p&gt;
&lt;p&gt;Il est ainsi probable que beaucoup de versions &amp;ldquo;latest&amp;rdquo; sur le Hub Docker ne soit en réalité pas les versions les plus à jour.
Cela implique en effet une forte rigeur (et connaissance du fonctionnement que l&amp;rsquo;on vient de décrire) de la part des auteurs des images disponibles car pour maintenir le tag &amp;ldquo;latest&amp;rdquo; à jour, il est obligatoire de toujours prévoir un double taggage de son image.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;une première fois sans numéro de tag&lt;/li&gt;
&lt;li&gt;une seconde fois avec une numéro de tag&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;le-conseil-de-lauteur&#34;&gt;Le conseil de l&amp;rsquo;auteur&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Oublier que ce tag latest existe&lt;/strong&gt; et ne jamais l&amp;rsquo;utiliser.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Toujours&lt;/strong&gt; penser à tagger vos images&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je vous invite à &lt;a href=&#34;https://medium.com/@mccode/the-misunderstood-docker-tag-latest-af3babfd6375&#34;&gt;lire l&amp;rsquo;intégralité de la démonstration&lt;/a&gt; pour plus de détails.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Docker - Erreurs de débutant</title>
      <link>https://gastaud.io/article/docker-erreurs-debutant/</link>
      <pubDate>Tue, 12 Aug 2014 00:00:00 +0000</pubDate>
      
      <guid>https://gastaud.io/article/docker-erreurs-debutant/</guid>
      
        <description>&lt;p&gt;Dans l&amp;rsquo;article précédent, je parlais du projet [Wintersmith Docker]((&lt;a href=&#34;https://github.com/jygastaud/wintersmith_docker&#34;&gt;https://github.com/jygastaud/wintersmith_docker&lt;/a&gt;) et mentionnais le fait que j&amp;rsquo;avais fait des erreurs dans la conception initiale, dûes à un manque de connaissance de Docker.&lt;/p&gt;
&lt;h2 id=&#34;le-dockerfile&#34;&gt;Le Dockerfile&lt;/h2&gt;
&lt;p&gt;L&amp;rsquo;une des premières erreurs que j&amp;rsquo;ai fait a été de vouloir tout mettre dans le Dockerfile en pensant que tout doit passer par là pour automatiser les choses.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est en partie vrai mais il est parfois préférable de séparer la partie stack logiciel, data et build.&lt;/p&gt;
&lt;p&gt;Mon 1er Dockerfile ressemblait à cela&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# DOCKER-VERSION 0.9.1
FROM  ubuntu

RUN     sudo apt-get update -qq
RUN     sudo apt-get install python-software-properties -y -qq
RUN     sudo apt-get install nodejs npm -y -qq
RUN     sudo apt-get install nodejs-legacy -y -qq

# Bundle app source
ADD ./www /www

# Install app dependencies
RUN sudo npm install wintersmith -g

# Create new site
WORKDIR /www
RUN wintersmith new site

# Launch Wintersmith preview
WORKDIR /www/site
CMD [&amp;#34;wintersmith&amp;#34;, &amp;#34;preview&amp;#34;]

EXPOSE  8080
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Rentrons un peu dans le détail du fichier pour voir les différentes problématiques:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FROM  ubuntu&lt;/code&gt;
nous ne spécifions aucune version ce qui a pour conséquence de provoquer le téléchargement de tous les layers Ubuntu et non pas ceux seulement dédiés à la version souhaitée.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il est donc préférable d&amp;rsquo;écrire l&amp;rsquo;instruction sous la forme suivante:
&lt;code&gt;FROM ubuntu:&amp;lt;VERSION&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;RUN wintersmith new site&lt;/code&gt;
était censé créé l&amp;rsquo;arborescence du site par défaut tel que présentée ci-dessous&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;www
└── site
    ├── contents
    │   ├── articles
    │   │   ├── XXXXXXXXXXX
    │   │   ├── YYYYYYYYYYY
    │   │   ├── ZZZZZZZZZZZ
    │   ├── authors
    │   └── css
    ├── plugins
    └── templates
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;La commande s&amp;rsquo;exécutait bien mais le dossier créé n&amp;rsquo;est pas récupérable.&lt;/p&gt;
&lt;p&gt;Avec quelques recherches, il s&amp;rsquo;avère que la commande &lt;code&gt;docker cp&lt;/code&gt; semblait être faite pour cela mais l&amp;rsquo;export de fonctionne pas car cp n&amp;rsquo;est, à ce jour, capable de ne copier qu&amp;rsquo;un fichier à la fois (nous y reviendrons dans un prochain article).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CMD [&amp;quot;wintersmith&amp;quot;, &amp;quot;preview&amp;quot;]&lt;/code&gt;
bien que cette commande ne soit pas fausse en soit, il est recommandé par par Docker l&amp;rsquo;utilisation de ENTRYPOINT[] et de garder au niveau du CMD[] uniquement les paramètres de la commande.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;J&amp;rsquo;apprenais d&amp;rsquo;ailleurs par la suite, en discutant sur le channel IRC de Docker, que ENTRYPOINT ne servait pas que au niveau des commandes du Dockerfile mais aussi du run d&amp;rsquo;un conteneur en définissant la commande par défaut exécutée.&lt;/p&gt;
&lt;p&gt;En effet, lors du run, il est possible de spécifier des paramètres d&amp;rsquo;exécution à l&amp;rsquo;image d&amp;rsquo;origine. Il est ainsi possible d&amp;rsquo;éxécuter différents types de conteneur:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker run -d jygastaud/wintersmith preview&lt;/code&gt; permettra de lancer le mode preview&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker run -d jygastaud/wintersmith new nouveau_site&lt;/code&gt; lancera la commande de génération de site de Wintersmith.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finalement, après qelques ajustements et changements de méthodes, mon Dockerfile ressemble à cela maintetenant:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;FROM ubuntu:14.04
MAINTAINER jygastaud

# Some stuff
# Here

ENTRYPOINT [&amp;#34;wintersmith&amp;#34;]

# Clean up APT when done.
RUN apt-get clean &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cette configuration nous donne un panel d&amp;rsquo;utilisation globale de Wintersmith en ne stockant qu&amp;rsquo;un minimum d&amp;rsquo;information.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Wintersmith Docker - Introduction</title>
      <link>https://gastaud.io/article/projet-wintersmith-docker-introduction/</link>
      <pubDate>Fri, 08 Aug 2014 00:00:00 +0000</pubDate>
      
      <guid>https://gastaud.io/article/projet-wintersmith-docker-introduction/</guid>
      
        <description>&lt;p&gt;Après plusieurs lectures et essais rapides de Docker, j&amp;rsquo;ai décidé d&amp;rsquo;y consacrer une peu plus de temps de manière concrête.&lt;/p&gt;
&lt;p&gt;Etant en pleine réflexions sur l&amp;rsquo;outil que j&amp;rsquo;allais utilisé pour la réalisation de ce blog, j&amp;rsquo;ai donc décidé de lancer le projet &lt;a href=&#34;https://github.com/jygastaud/wintersmith_docker&#34;&gt;Wintersmith Docker&lt;/a&gt; afin de pouvoir tester &lt;a href=&#34;http://wintersmith.io&#34;&gt;Wintersmith&lt;/a&gt;, un générateur de site statique basé sur &lt;a href=&#34;http://nodejs.org&#34;&gt;Nodejs&lt;/a&gt;, dans un conteneur &lt;a href=&#34;http://docker.com&#34;&gt;Docker&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;ca-sert-à-quoi-ce-projet&#34;&gt;Ca sert à quoi ce projet?&lt;/h2&gt;
&lt;p&gt;Le projet donne accès à 2 types d&amp;rsquo;utilisation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pour les utilisateurs de Vagrant&lt;/strong&gt;, un Vagrantfile est disponible en plus du Dockerfile afin d&amp;rsquo;avoir l&amp;rsquo;installation de Docker, la création de l&amp;rsquo;image et le lancement du conteneur Docker réalisé de manière automatisé.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pour les utilisateurs de Docker&lt;/strong&gt;, le Dockerfile permet de créer une image contenant Nodejs et Wintersmith pré-installés qui peut être ensuite appeler pour la création d&amp;rsquo;un ou plusieurs containers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La mise en place de ce projet a été extremement formatrice sur Docker.
Je vous invite à lire les &lt;a href=&#34;http://jygastaud.github.io/blog/articles/notes-docker/&#34;&gt;quelques notes en vracs&lt;/a&gt; que j&amp;rsquo;ai posté dans mon billet précédent.&lt;/p&gt;
&lt;h2 id=&#34;un-peu-dhistorique&#34;&gt;Un peu d&amp;rsquo;historique&lt;/h2&gt;
&lt;p&gt;L&amp;rsquo;idée initiale du projet était simple et se décomposait comme ceci:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Créer une image via Docker contenant Wintersmith et Nodejs pour pouvoir à volonté:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Créer un nouveau site Wintersmith: &lt;code&gt;wintersmith new &amp;lt;site name&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Partager un site existant&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Créer un conteneur Docker qui&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Lancerait Wintermith en mode preview: &lt;code&gt;wintersmith preview&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Permettrait de voir en live les modifications / ajouts faits dans le dossier de contenus.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Le tout sans avoir besoin d&amp;rsquo;installer Wintersmith et Nodejs en local&lt;/strong&gt; (comme avec une VM Vagrant en fait mais en plus léger).&lt;/p&gt;
&lt;h2 id=&#34;un-peu-dhonnêteté&#34;&gt;Un peu d&amp;rsquo;honnêteté&lt;/h2&gt;
&lt;p&gt;Soyons franc,tout n&amp;rsquo;a pas été tout beau et tout rose.&lt;/p&gt;
&lt;p&gt;Docker n&amp;rsquo;offre pas la même souplesse qu&amp;rsquo;un machine virtuelle complète et est notamment restreint par:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;le fait de ne devoir gérer qu&amp;rsquo;un seul processus par conteneur (tout du moins si l&amp;rsquo;on ne passe pas par des solutions de contournement telles que Supervisor)&lt;/li&gt;
&lt;li&gt;le fait de ne pas pouvoir exécuter plusieurs commandes lors du &lt;code&gt;run&lt;/code&gt; d&amp;rsquo;un conteneur&lt;/li&gt;
&lt;li&gt;le fait de ne pas avoir d&amp;rsquo;accès direct (via ssh par exemple) au conteneur lancé&lt;/li&gt;
&lt;li&gt;&lt;em&gt;etc&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ces quelques exemples montrent bien les différences, potentiellement mal perçues/comprises, entre un Docker et une VM.&lt;/p&gt;
&lt;p&gt;Les usages que l&amp;rsquo;on peut trouver aux 2
systèmes ne sont pas forcement concurrents. Pour preuves, Vagrant propose de faire son provisioning avec Docker.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Mes notes sur Docker</title>
      <link>https://gastaud.io/article/notes-docker/</link>
      <pubDate>Mon, 04 Aug 2014 00:00:00 +0000</pubDate>
      
      <guid>https://gastaud.io/article/notes-docker/</guid>
      
        <description>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Le fichier &lt;code&gt;Dockerfile&lt;/code&gt; produit une Image&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dans le Dockerfile il n&amp;rsquo;est possible de mettre qu&amp;rsquo;une seule instruction CMD.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Si 2 intructions (ou plus) sont dans le même fichier, seule la dernière sera exécutée.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Il est possible de commiter, pusher ou récupérer une image (à la façon de GIT)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;docker run ...&lt;/code&gt; produit une instance de l&amp;rsquo;image&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les fichiers ajoutés via l&amp;rsquo;image (et le Dockerfile) sont fixes à chaque lancement de run&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Si la commande run contient l&amp;rsquo;option &lt;code&gt;-v&lt;/code&gt; il est possible de partager un dossier local (alors dynamique dans le conteneur)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Si un &lt;code&gt;ADD&lt;/code&gt; dans le dockerfile contient le même chemin que celui que l&amp;rsquo;on veut rendre dynamique, cela ne marche pas.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Il est possible de partager des volumes entre les conteneurs lors du run via l&amp;rsquo;option &amp;ndash;volumes-from&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On peut nommer un conteneur (&amp;ndash;name) ce qui permet d&amp;rsquo;effectuer les opérations via son nom et non son ID (ne marche pas pour toutes les commandes)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
      
    </item>
    
    <item>
      <title>Configurer Nginx pour gérer automatiquement vos sous-domaines locaux</title>
      <link>https://gastaud.io/article/nginx-sousdomaines-auto/</link>
      <pubDate>Tue, 07 Jan 2014 00:00:00 +0000</pubDate>
      
      <guid>https://gastaud.io/article/nginx-sousdomaines-auto/</guid>
      
        <description>&lt;p&gt;Lors des développements locaux, nous avons pris l&amp;rsquo;habitude de toujours définir un nom de domaine local (mon_site.local dans notre exemple) afin de coller au plus proche de la réalité du site final.&lt;/p&gt;
&lt;h2 id=&#34;le-processus-classique-était-le-suivant&#34;&gt;Le processus classique était le suivant&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Ajout d&amp;rsquo;un nouveau dossier allant contenir notre site dans notre répertoire de développement (/var/www dans notre exemple). On obtient ainsi l&amp;rsquo;arborescence suivante:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/var/www/
├── mon_site1
│   └── index.html
├── mon_site2
│   └── index.html
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;Ajout d&amp;rsquo;un nouvel host local dans le fichier &lt;code&gt;/etc/hosts&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;127.0.0.1 mon_site.local
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;fonctionnement-désiré&#34;&gt;Fonctionnement désiré&lt;/h2&gt;
&lt;p&gt;Le but principal de notre implémentation est de pouvoir traiter un ensemble de sous-sites de manière générique pour ne pas avoir à recréer de nouveaux vhosts et aller modifier le fichier hosts local à chaque nouvelle implémentation.&lt;/p&gt;
&lt;p&gt;Ainsi avec l&amp;rsquo;arborescence ci-dessous,&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/var/www/
├── local.dev
│   └── www
│       ├── test1
│       │   └── index.html
│       └── test2
│           └── index.html
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;il nous sera immédiatement possible d&amp;rsquo;accéder aux sous-domaines suivants et de charger le bon fichier d&amp;rsquo;index:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;test1.local.dev
test2.local.dev
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;configuration-de-nginx&#34;&gt;Configuration de Nginx&lt;/h2&gt;
&lt;p&gt;Nous partons du prérequis que vous avez déjà Nginx installé sur votre machine.
Si ce n&amp;rsquo;est pas le cas, une bref recherche vous permettra de trouver de nombreux tutoriaux traitant de ce sujet.&lt;/p&gt;
&lt;p&gt;Dans notre exemple, la version de nginx utilisée est la suivante:
nginx version: nginx/1.4.1 (Ubuntu)&lt;/p&gt;
&lt;h3 id=&#34;création-dun-nouveau-site-nginx&#34;&gt;Création d&amp;rsquo;un nouveau site nginx&lt;/h3&gt;
&lt;p&gt;Configuration de notre site dans le dossier &lt;code&gt;/etc/nginx/sites-available&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;server {
    # On écoute le port 80.
    listen 80;

    # On va utiliser une expression régulière
    # pour récupérer le sous-domaine dans une variable nommée &amp;#34;sub&amp;#34;.
    server_name  ~^(?P&amp;lt;sub&amp;gt;.+)\.local\.dev$;

    location / {
         # On définie le chemin local
         # en utilisant la variable &amp;#34;sub&amp;#34; récupérée précédemment.
         root /var/www/local.dev/www/$sub;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On active notre site via un lien symbolique dans le dossier &lt;code&gt;/etc/nginx/sites-enable&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ln -s /etc/nginx/sites-available/local.dev /etc/nginx/sites-enable/local.dev
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;et on redémarre le serveur via la commande:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;service nginx restart
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;configuration-dun-hote-générique&#34;&gt;Configuration d&amp;rsquo;un hote générique&lt;/h2&gt;
&lt;h3 id=&#34;1ères-tentatives&#34;&gt;1ères tentatives&lt;/h3&gt;
&lt;p&gt;Notre 1ère logique a donc était d&amp;rsquo;essayer de définir un domaine générique au sein de notre fichier &lt;code&gt;/etc/hosts&lt;/code&gt; comme nous pouvions le faire avec notre domaine classique.&lt;/p&gt;
&lt;p&gt;Nous avons donc tenter l&amp;rsquo;ajout de plusieurs lignes avec ou sans wildcard (*) telles que:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;127.0.0.1 local.dev
127.0.0.1 .local.dev
127.0.0.1 *.local.dev
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;mais rien n&amp;rsquo;y fait, ces solutions ne marchent pas et il nous fallait toujours ajouter nos sous-domaines &amp;ldquo;à la main&amp;rdquo; dans le fichier hosts.&lt;/p&gt;
&lt;h3 id=&#34;le-problème&#34;&gt;Le problème&lt;/h3&gt;
&lt;p&gt;Le fichier hosts ne permet pas de définir de wildcards pour un domaine.&lt;/p&gt;
&lt;p&gt;Il est donc normal que nos tentitves précédentes ne fonctionnent pas.&lt;/p&gt;
&lt;h3 id=&#34;la-solution&#34;&gt;La solution&lt;/h3&gt;
&lt;p&gt;Nos diverses recherches nous ont emmené à découvrir que la seule solution possible pour obtenir le résultat escompté était de passer par un serveur de DNS installé en local et qui se chargerait de faire l&amp;rsquo;interprétation et la traduction du nom de domaine.&lt;/p&gt;
&lt;p&gt;Plusieurs solutions existes pour cela et dont la plus connue est &lt;strong&gt;Bind&lt;/strong&gt;.
Toutefois, Bind nous paraissait trop lourd à implémenter pour notre besoin et nous nous sommes finalement rabattus sur l&amp;rsquo;utilisation de &lt;strong&gt;DNSMasq&lt;/strong&gt; qui permet une implémentation rapide et une configuration très simple.&lt;/p&gt;
&lt;p&gt;###DNSmasq&lt;/p&gt;
&lt;p&gt;Dans le fichier /etc/dnsmasq.conf (le créer s&amp;rsquo;il n&amp;rsquo;existe pas), il vous suffit d&amp;rsquo;ajouter la ligne suivante:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;address=/mon_nom_de_domaine.extension/127.0.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;et c&amp;rsquo;est tout!&lt;/p&gt;
&lt;p&gt;Dans notre exemple, nous avons donc ajouter:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;address=/local.dev/127.0.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On redémarre dnsmasq (&lt;code&gt;service dnsmasq restart&lt;/code&gt; sur Ubuntu) et on peut constater que nos domaines sont accessibles.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Drupal Export des noeuds en Markdown</title>
      <link>https://gastaud.io/article/drupal-export-noeud-markdown/</link>
      <pubDate>Wed, 01 Jan 2014 00:00:00 +0000</pubDate>
      
      <guid>https://gastaud.io/article/drupal-export-noeud-markdown/</guid>
      
        <description>&lt;p&gt;Ressources utiles:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;* https://github.com/lukaswhite/Drupal-Markdownify
* https://github.com/lukaswhite/Drupal-Jekyll-Export
* http://www.gizra.com/content/dekyll-drupal-on-jekyll/
&lt;/code&gt;&lt;/pre&gt;
</description>
      
    </item>
    
    <item>
      <title>DrupalCamp Paris2013 - Behat et Drupal</title>
      <link>https://gastaud.io/article/drupalcamp/paris2013/behat/</link>
      <pubDate>Sat, 22 Jun 2013 15:00:28 +0100</pubDate>
      
      <guid>https://gastaud.io/article/drupalcamp/paris2013/behat/</guid>
      
        <description>&lt;h1 id=&#34;behat-et-drupal&#34;&gt;Behat et Drupal&lt;/h1&gt;
&lt;h3 id=&#34;selenium-api-et-ide&#34;&gt;Selenium API et IDE&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Comment automatiser les tests?
&lt;ul&gt;
&lt;li&gt;Selenium Server&lt;/li&gt;
&lt;li&gt;PHPUnit&lt;/li&gt;
&lt;li&gt;Selenium IDE&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Comment tester l&amp;rsquo;ajax?
&lt;ul&gt;
&lt;li&gt;Selenium à installer&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Comment tester le multi-domaine&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;behaviour-driven-development-bdd&#34;&gt;Behaviour Driven Development (BDD)&lt;/h3&gt;
&lt;p&gt;CF: Ryan Weaver
portland 2013&lt;/p&gt;
&lt;h2 id=&#34;gherkin&#34;&gt;Gherkin&lt;/h2&gt;
&lt;p&gt;Langage qui permet de définir des tests&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Feature
&lt;ul&gt;
&lt;li&gt;Scenario
&lt;ul&gt;
&lt;li&gt;Steps
&lt;ul&gt;
&lt;li&gt;Context: Given
&lt;ul&gt;
&lt;li&gt;And&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;When
&lt;ul&gt;
&lt;li&gt;And&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Result: Then&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;cucumber&#34;&gt;Cucumber&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Gherkin + Ruby&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;behat--mink&#34;&gt;Behat + Mink&lt;/h2&gt;
&lt;h3 id=&#34;behat&#34;&gt;Behat&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Gherkin + PHP =&amp;gt; Behat&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;mink&#34;&gt;Mink&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Drivers&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ZombieDriver&lt;/li&gt;
&lt;li&gt;Sahi&lt;/li&gt;
&lt;li&gt;Goutte (si pas besoin de js)&lt;/li&gt;
&lt;li&gt;Selenium (avec js)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MinkExtension sert à lier Behat et Mink&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Behat est indépendant de l&amp;rsquo;application web&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Behat s&amp;rsquo;installe via Composer&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Exécutable dans dossier bin/&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;FeatureContext.php doit être modifié pour étendre MinkContext
Il est possible de créer des subcontexts&lt;/p&gt;
&lt;p&gt;Attention le mouseover ne fonctionne que sur les éléments javascript, pas css&lt;/p&gt;
&lt;h2 id=&#34;projet-drupal&#34;&gt;Projet Drupal&lt;/h2&gt;
&lt;p&gt;DrupalExtension =&amp;gt; project/drupalextension&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>DrupalCamp Paris2013 - GED</title>
      <link>https://gastaud.io/article/drupalcamp/paris2013/ged/</link>
      <pubDate>Fri, 21 Jun 2013 15:00:28 +0100</pubDate>
      
      <guid>https://gastaud.io/article/drupalcamp/paris2013/ged/</guid>
      
        <description>&lt;h1 id=&#34;ged&#34;&gt;GED&lt;/h1&gt;
&lt;h2 id=&#34;acquisition&#34;&gt;Acquisition&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Imports: Feed, custom&lt;/li&gt;
&lt;li&gt;Services, CMIS API&lt;/li&gt;
&lt;li&gt;Solr&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;stockage&#34;&gt;Stockage&lt;/h2&gt;
&lt;p&gt;Versionning + diff
Archivage: Taxonomie
Workflow: Maestro&lt;/p&gt;
&lt;h2 id=&#34;classement&#34;&gt;Classement&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Gestion des permissions&lt;/li&gt;
&lt;li&gt;FacetAPI&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;principales&#34;&gt;Principales&lt;/h3&gt;
&lt;p&gt;Alfresco
Knowledge Tree&lt;/p&gt;
&lt;h3 id=&#34;annexes&#34;&gt;Annexes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ExoPatform&lt;/li&gt;
&lt;li&gt;Quotero&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;comparaison&#34;&gt;Comparaison&lt;/h2&gt;
&lt;p&gt;Faiblesses de Drupal:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Intégration avec MS et Google Docs&lt;/li&gt;
&lt;li&gt;WebDav&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Avantages de Drupal :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Garantie de support et d&amp;rsquo;évolutivité&lt;/li&gt;
&lt;li&gt;Confiance&lt;/li&gt;
&lt;li&gt;431 modules uniquement pour la gestion de fichiers&lt;/li&gt;
&lt;li&gt;Couverture fonctionnelle &amp;ldquo;sans limite&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cas-clients&#34;&gt;Cas clients&lt;/h2&gt;
&lt;h3 id=&#34;intranet-collaboratif--médecin-sans-frontière&#34;&gt;Intranet collaboratif : Médecin Sans Frontière&lt;/h3&gt;
&lt;p&gt;Problèmes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Documents non structurés&lt;/li&gt;
&lt;li&gt;Pas toujours à jour&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Solutions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FacetApi&lt;/li&gt;
&lt;li&gt;LDAP&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;constructeur-automobile&#34;&gt;Constructeur automobile&lt;/h3&gt;
&lt;p&gt;Problèmes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Médiathèque déjà en place&lt;/li&gt;
&lt;li&gt;Pas de partages&lt;/li&gt;
&lt;li&gt;Pas de visualisation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Solutions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Feed + Feeds Xpath Parser pour les imports&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;prêt-à-porter&#34;&gt;Prêt à porter&lt;/h3&gt;
&lt;p&gt;Problèmes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gestion manuelle des PDF&lt;/li&gt;
&lt;li&gt;Synchronisation journalière de l&amp;rsquo;ensemble des docs&lt;/li&gt;
&lt;li&gt;Uniquement accessible sur le réseau d&amp;rsquo;entreprise&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Solutions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Classement par taxo&lt;/li&gt;
&lt;li&gt;Module custom pour import automatique 1 fois / jour&lt;/li&gt;
&lt;li&gt;Versionning Drupal&lt;/li&gt;
&lt;li&gt;Apache Solr
&lt;ul&gt;
&lt;li&gt;6000 pdf / jour à importer en 2 heures&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Permissions gérées de façon hierarchique
&lt;ul&gt;
&lt;li&gt;Modules custom d&amp;rsquo;import du LDAP avec la hierachie associé&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Délégations des permissions
&lt;ul&gt;
&lt;li&gt;Le salarié C peut déléguer au salarié B&lt;/li&gt;
&lt;li&gt;Module Custom&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;drupal-est-il-toujours-pertinant&#34;&gt;Drupal est-il toujours pertinant?&lt;/h2&gt;
&lt;p&gt;Toujours faire le pendant entre le niveau de custom à faire vs autres solutions du marché&lt;/p&gt;
&lt;p&gt;Dans ce cas, penser à faire collaborer Alfresco et Drupal via module CMIS&lt;/p&gt;
&lt;p&gt;On peut donc toujours utiliser Drupal en pensant bien les besoins à l&amp;rsquo;avance.&lt;/p&gt;
&lt;h2 id=&#34;qa&#34;&gt;Q&amp;amp;A&lt;/h2&gt;
&lt;p&gt;Niveau indexation: Les optimisations sont plus simples à mettre en place coté Drupal que Alfresco&lt;/p&gt;
&lt;p&gt;Pas de modules contribués&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>DrupalCamp Paris2013 - Livraison continue avec Drupal 7</title>
      <link>https://gastaud.io/article/drupalcamp/paris2013/livraison-continue/</link>
      <pubDate>Fri, 21 Jun 2013 15:00:28 +0100</pubDate>
      
      <guid>https://gastaud.io/article/drupalcamp/paris2013/livraison-continue/</guid>
      
        <description>&lt;p&gt;Prise de note lors de la conférence du DrupalCamp Paris 2013.&lt;/p&gt;
&lt;h2 id=&#34;comment-faire-un-site-en-15-mois-sans-le-faire-à-larrache&#34;&gt;Comment faire un site en 1,5 mois sans le faire à l&amp;rsquo;arrache?&lt;/h2&gt;
&lt;p&gt;Faut le faire en agile!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On s&amp;rsquo;engage sur une date ou sur un périmètre mais pas les 2&lt;/li&gt;
&lt;li&gt;Définition du &amp;ldquo;Minimum Viable Product&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Comment livrer le plus souvent possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tout automatisé&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;construction-dun-build-pipeline&#34;&gt;Construction d&amp;rsquo;un build pipeline&lt;/h3&gt;
&lt;p&gt;Flux automatisé jusqu&amp;rsquo;à la mise en production&lt;/p&gt;
&lt;p&gt;commit -&amp;gt; Inté continue -&amp;gt; recette développeur -&amp;gt; déploiement en intégration -&amp;gt; recette métier -&amp;gt; déploiement en pré prod -&amp;gt; validation finale -&amp;gt; déploiement en production&lt;/p&gt;
&lt;p&gt;Tout a été orchestré avec Jenkinks&lt;/p&gt;
&lt;h4 id=&#34;quelle-base-de-données-fait-foi&#34;&gt;Quelle base de données fait foi?&lt;/h4&gt;
&lt;p&gt;La base de données de developpement doit être la base de référence&lt;/p&gt;
&lt;h4 id=&#34;comment-transposer-la-configuration-dun-environnement-à-lautre&#34;&gt;Comment transposer la configuration d&amp;rsquo;un environnement à l&amp;rsquo;autre?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Features&lt;/li&gt;
&lt;li&gt;hook_update&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;1 feature par grand domaine, pas par réelles fonctionnalités&lt;/p&gt;
&lt;p&gt;Toujours valider le déploiement (smoke tests)&lt;/p&gt;
&lt;p&gt;Lancement des tests d&amp;rsquo;intégration automatisés -&amp;gt; Dans le cadre du projet, seul le front a été testé automatiquement&lt;/p&gt;
&lt;h4 id=&#34;et-la-qualité-du-code&#34;&gt;Et la qualité du code?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Coder&lt;/li&gt;
&lt;li&gt;Lint&lt;/li&gt;
&lt;li&gt;phpmd&lt;/li&gt;
&lt;li&gt;phpcd&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;tests-de-performances&#34;&gt;Tests de performances&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;JMeter&lt;/li&gt;
&lt;li&gt;Gatling? en Scala&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;outils-utilisés&#34;&gt;Outils utilisés&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Déploiement en environnement de dév -&amp;gt; Capistrano&lt;/li&gt;
&lt;li&gt;Validation -&amp;gt; PHPUnit + cURL&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;capistrano&#34;&gt;Capistrano&lt;/h2&gt;
&lt;p&gt;Permet de faire de déploiement parallélisé via un domaine spécifique
Il permet de déployer les fichiers spécifiques aux devs et ne pas se préoccuper des fichiers spécifiques à l&amp;rsquo;environnement.&lt;/p&gt;
&lt;p&gt;Permet de sauvegarder l&amp;rsquo;ancienne version du code, partage des fichiers de config&lt;/p&gt;
&lt;p&gt;Quasi plus besoin d&amp;rsquo;actions manuelles sur le serveur au final.&lt;/p&gt;
&lt;h2 id=&#34;smoke-tests&#34;&gt;Smoke Tests&lt;/h2&gt;
&lt;p&gt;Permet de détecter les &amp;ldquo;fuites&amp;rdquo; coté Front&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Succession de curl
&lt;ul&gt;
&lt;li&gt;home en HTTP 200&lt;/li&gt;
&lt;li&gt;Pas de blocs d&amp;rsquo;erreurs&lt;/li&gt;
&lt;li&gt;Pas de 404 sur les assets&lt;/li&gt;
&lt;li&gt;Blocs importants bien présents&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;comment-on-monitore&#34;&gt;Comment on monitore?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Buildwall Jenkins&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;et-les-tests-unitaires-dans-tout-ça&#34;&gt;Et les tests unitaires dans tout ça?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Uniquement sur le front dans le cadre de ce projet&lt;/li&gt;
&lt;li&gt;SimpleTest trop lent&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Découpage pour la mise en production avec 2 taches&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 pour le merge de DEV vers PROD only&lt;/li&gt;
&lt;li&gt;1 pour la mise en prod de la branch &amp;ldquo;mergée&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;coordonnées-contact&#34;&gt;Coordonnées contact&lt;/h2&gt;
&lt;p&gt;twitter: @arnaudhuon
mail: &lt;a href=&#34;mailto:ahuon@octo.com&#34;&gt;ahuon@octo.com&lt;/a&gt;&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>DrupalCamp Paris2013 - Magnifiez votre backend</title>
      <link>https://gastaud.io/article/drupalcamp/paris2013/magnifiez-backend/</link>
      <pubDate>Fri, 21 Jun 2013 01:14:28 +0100</pubDate>
      
      <guid>https://gastaud.io/article/drupalcamp/paris2013/magnifiez-backend/</guid>
      
        <description>&lt;h2 id=&#34;les-formulaires-peuvent-être-très-long&#34;&gt;Les formulaires peuvent être très long&lt;/h2&gt;
&lt;p&gt;Création d&amp;rsquo;un concept =&amp;gt; FormMode basé sur le concept des ViewsMode : &lt;a href=&#34;https://drupal.org/sandbox/Artusamak/1796634&#34;&gt;https://drupal.org/sandbox/Artusamak/1796634&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Field Extra Widget : &lt;a href=&#34;https://drupal.org/project/field_extrawidgets&#34;&gt;https://drupal.org/project/field_extrawidgets&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Views Megarow =&amp;gt; Edition en ligne dans le backend : &lt;a href=&#34;https://drupal.org/project/views_megarow&#34;&gt;https://drupal.org/project/views_megarow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Démo du Back Cartier&lt;/p&gt;
&lt;p&gt;Bundle Switcher : &lt;a href=&#34;https://drupal.org/project/bundleswitcher&#34;&gt;https://drupal.org/project/bundleswitcher&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;créer-vos-propres-plugins-pour-lapi-de-views&#34;&gt;Créer vos propres plugins pour l&amp;rsquo;api de views&lt;/h2&gt;
&lt;p&gt;Views Matrix&lt;/p&gt;
&lt;h2 id=&#34;gérer-les-transitions-de-workflow&#34;&gt;Gérer les transitions de workflow&lt;/h2&gt;
&lt;p&gt;Une 12ene de type d&amp;rsquo;entité
Problématique avec les modules contrib qui ne gèrent que les nodes&lt;/p&gt;
&lt;p&gt;Statefield: &lt;a href=&#34;https://drupal.org/sandbox/damz/1550106&#34;&gt;https://drupal.org/sandbox/damz/1550106&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(hors session: &lt;a href=&#34;https://drupal.org/sandbox/andypost/1114392&#34;&gt;https://drupal.org/sandbox/andypost/1114392&lt;/a&gt;)&lt;/p&gt;
&lt;h2 id=&#34;créer-des-variantes-de-certaines-parties-du-contenus&#34;&gt;Créer des variantes de certaines parties du contenus&lt;/h2&gt;
&lt;p&gt;avec propriétés et champs surchargeables&lt;/p&gt;
&lt;p&gt;Objectif: Pas de duplication de nodes pour ce besoin&lt;/p&gt;
&lt;p&gt;Entity override : &lt;a href=&#34;https://drupal.org/project/entity_override&#34;&gt;https://drupal.org/project/entity_override&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Utiliser aussi pour la traduction!!
Exportable dans des features
Est capable de créer l&amp;rsquo;entité cible.&lt;/p&gt;
&lt;p&gt;Module Tree + TreeField&lt;/p&gt;
&lt;p&gt;Device Management&lt;/p&gt;
&lt;p&gt;EntityBundlePlugin : &lt;a href=&#34;https://drupal.org/project/entity_bundle_plugin&#34;&gt;https://drupal.org/project/entity_bundle_plugin&lt;/a&gt; ?&lt;/p&gt;
&lt;p&gt;Synchronisation des contenus via Migration et XMLRPC&lt;/p&gt;
&lt;p&gt;Le backend a été implémenté comme un sous-projet à part en tiers
18 mois du 1er jour à la mise en ligne 1 =&amp;gt; Par contre les nouveaux sites sont simples à mettre en ligne&lt;/p&gt;
&lt;p&gt;1 master pour piloter tous les sites, choisir si le site est Ecommerce ou non.
Les frontaux sont totalement passifs.&lt;/p&gt;
</description>
      
    </item>
    
  </channel>
</rss>