Comment manager les versions de dépendance avec Composer?

Nous avons vu comment définir une version de dépendance avec Composer. Voyons à présent comment les charger et gérer les conflits.

Installation des dépendances

Si vous utilisez Composer, vous avez déjà certainement remarqué que, à la racine de vos projets, se rajoute automatiquement le fichier composer.lock. Ce fichier permet de geler les versions exactes qui sont chargées lors de l’installation initiale des dépendances. Ce freeze contribue à garantir la stabilité du comportement de l’application après son build telle que développée. C’est le processus qu’on privilégiera pour la mise en prod d’une application.

require

Ainsi, lorsque l’on ajoute une nouvelle dépendance (avec la commande require), Composer spécifie la version téléchargée exacte dans composer.lock. Par exemple, si la contrainte d’une dépendance est "^2.1.2", et que la dernière version stable est "2.2.4", cette dernière sera téléchargée puis rajoutée dans le fichier.

install

Lorsque l’on rebuildera le projet par la suite (avec la commande install), l’installation des dépendances se fera sur base des versions précises telles qu’elles ont été répertoriées dans ce fichier (et plus sur base des contraintes). Dans notre exemple, ce sera donc la version "2.2.4" qui sera installée, même si, entre temps, une nouvelle version a vu le jour qui satisfasse également à la contrainte, "2.5.1".

update

Les versions des dépendances peuvent toutefois être mises à jour (avec la commande update). Composer va récupérer la dernière version en date d’une librairie qui corresponde à la contrainte et remplacer la version précise dans composer.lock. Par rapport à notre exemple, la dépendance sera actualisée à "2.5.1".

Portée de composer.lock

Attention, composer.lock n’a d’effet que pour le projet courant (le root package), et pas pour les projets dont il est dépendant. C’est pour cette raison que les librairies de dépendances ne vont pas forcément versionner ce fichier. A l’inverse, une application web doit absolument freezer ses dépendances pour assurer que le comportement de prod soit identique.

Gestion des conflits

Il n’est pas impossible de rencontrer des conflits entre contraintes de dépendances. Par exemple, vous avez besoin d’une librairie avec une version minimum "^2.1.4". Et une autre de vos dépendances a elle-même besoin de cette même librairie, mais avec la contrainte "^1.8.7". Composer ne pourra pas trancher entre ces deux contraintes s’excluant mutuellement. Il n’y a pas vraiment de solution miracle, et il faudra composer (mauvais jeu de mot) avec cela. Essayer de trouver une version compatible, etc.

Si le conflit touche une de vos dépendances directes, vous gardez une possibilité d’action dans vos propres définitions de contraintes. Vous pourriez également connaître des problèmes de stabilité minimum si vous travaillez avec des branches de dev. Mais si le problème se situe dans des dépendances de dépendances, cela devient compliqué…

conflict

Composer vous offre la possibilité de blacklister certaines versions de dépendances avec la propriété conflict. Les dépendances listées ne seront alors pas téléchargées.

1
2
3
"conflict": {
    "vendor/package": "<1.0.7"
 }

alias

Une autre solution envisageable consiste à utiliser un aliasing de vos contraintes:

1
2
3
"require": {
    "vendor/package": "dev-master as 1.1.2"
}

Vous installerez alors la branche master tout en la déclarant en tant que version "1.1.2".

Surcharge de fork

De même, vous pourriez avoir besoin de surcharger une dépendance. Par exemple, si vous fixez un bug sur une librairie mais que votre patch ne sera mergé que dans un certains temps, vous pouvez surcharger la librairie avec votre fork.

alias

Pour ce faire, il vous faudra aliasser votre fork pour qu’il puisse satisfaire les contraintes des autres dépendances qui l’appellent.

1
2
3
4
5
6
7
8
9
10
11
12
{
    "require": {
        "doctrine/orm": "2.3.*",
        "doctrine/common": "dev-myFix as 2.3.0"
    },
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/you/doctrine-common"
        }
    ]
}

Ici, notre fork « myFix » surchargera « doctrine/common » sans que « doctrine/orm », qui appelle également cette dépendance, n’en trouve rien à redire.

replace

On peut arriver au même résultat d’aliassing depuis le fork, en utilisant la propriété replace.

1
2
3
"replace": {
    "vendor/package": "2.1.3"
}

Monitorer les versions

Il existe plusieurs services de monitoring des dépendances. L’idée est d’informer sur l’état des dépendances d’un projet pour savoir si elles sont toujours à jour ou si de nouvelles versions ont été développées.

Par exemple, VersionEye permet deux choses:

  • Comme Packagist, une vision sur les dépendances d’un projet. Mais, en plus, VersionEye indique (en se basant sur le fichier composer.lock) si ses dépendances sont à jour.
  • Un aperçu du nombre de librairies dépendantes.

Un autre exemple: Depending qui travaille spécifiquement avec Composer.

Conclusion

Composer possède plusieurs fonctionnalités pour gérer les dépendances, depuis leur téléchargement avec require, install et update, jusqu’à certaines possibilités de gestion des conflits avec conflict, replace et alias.

Pourtant, les dépendances demeurent parfois à double tranchant. Certes, elles permettent des fonctionnalités souvent complètes. Mais les dépendances entraînent les dépendances et se démultiplient de manière exponentielle. C’est alors qu’on peut connaître des difficultés de maintenance et de compatibilité.

5 réflexions au sujet de « Comment manager les versions de dépendance avec Composer? »

  1. Hello,

    Je me permets de partager un outil que j’ai développé permettant également de monitorer ses propres projets : http://checkmycomposer.com
    L’idée est d’avoir une dashboard de ses projets et d’être averti par e-mail (selon nos préférences) lorsque l’un d’entre eux contient une ou plusieurs dépendances dépassées. Je fournis également une commande qui permet de voir l’état des dépendances d’un projet en ligne de commandes.

    N’hésitez pas à me faire des retours !

    Adrien

Répondre à Adrien Annuler la réponse.

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>