packmon - Analyse des paquets installés

J’ai eu besoin d’analyser les paquets d’un projet Django pour le boulot, et n’ayant rien trouvé de suite, j’ai pris 3h pour monter un truc moche et rapide.

L’idée de base était de pouvoir :

  • Lister les paquets installés avec leur version en cours
  • Visualiser si des paquets avaient une version à la rue (par rapport à la dernière sortie)
  • Visualiser également le statut de développement des paquets
  • Visualiser si la dernière release était pas très vieille indiquant, potentiellement, un paquet moins/plus maintenu…

Depuis, j’ai découvert (merci IRC) tout un tas de choses intéressantes depuis pip lui-même jusqu’à des outils plus ou moins intéressants/obsolètes/payants :

  • pip list --outdated
  • pip-check
  • pip-chill
  • pip-date
  • pip-outated
  • piprot
  • pur
  • safety

Certes, ces projets peuvent être intéressants, mais je trouve qu’ils ne répondent jamais à tout ce que j’en attends.

J’ai donc repris mon premier jet un peu moche et me suis ajouté la contrainte de ne dépendre d’aucun paquet externe. Voici ce que ça donne pour le moment en prenant le requirements.txt du site de l’AFPy (https://github.com/AFPy/site/blob/master/requirements.txt) :

On voit donc bien ici en jaune (warning) les paquets qui sont dans des statuts pas idéaux, les versions un peu en retard, et les dernières releases qui date de plus de 360 jours (oui, j’ai dit que c’était moche). On voit également en rouge (danger) les paquets vraiment en retard…

5 « J'aime »

Suite à un oubli, je précise que l’API de pypi fourni également les CVE (vulnérabilités officielles) pour chaque projet. J’ai commencé à les ajouter car c’est un des points les plus intéressant en matière de risque. La présentation est pas idéale, à retravailler :

2 « J'aime »

Amélioration de l’affichage des vulnérabilités en mode 88 colonnes max) :

1 « J'aime »

Et maintenant que le machin fonctionne, voici la suite à donner que j’ai prévue (outre le mettre à disposition dans un paquet pypi si ça peut intéresser des gens) :

Idées pour le futur

options

  • Permettre de donner le nombre de jours à partir duquel un paquet
    est considéré comme potentiellement obsolète. (days/delay)
  • Permettre différents formats de sortie (format)
    • colonnes
    • colones sur écran large ou limité (88 colonnes)
    • json
    • csv
    • markdown
  • Permettre de sortir en erreur (non-zero exit) pour utilisation
    dans une CI (ci ?)
  • Gérer un proxy pour les requêtes vers internet (proxy)
    • host (ou IP), port, protocole (http(s))
  • Permettre de sauver le résultat dans un fichier (output/o)
  • Permettre de ne rien sortir sur la console (quiet)
  • Pouvoir exclure des paquets (exclude)
  • Pouvoir inclure les paquets de gestion (pip, setuptools, wheel, …)
  • Limiter le résultat aux paquets à problème
    • Ceux avec vulnérabilités
    • Ceux en retard de version
    • Ceux considérés comme obsolètes
  • Ne pas avoir la coloration

source

Se baser potentiellement sur :

  • un fichier requirements.txt
  • un fichier setup.cfg
  • un fichier pyproject.toml
  • un des fichiers, depuis un dépôt github
  • un des fichiers, depuis un dépôt git
  • un des fichiers, depuis un dépôt autre (mercurial, bazaar, etc…)
  • etc…

cache

Gérer un cache permettant de ne pas avoir à aller interroger
un site comme pypi. Avec, bien entendu, la possibilité de
mettre à jour ce cache.

  • Mettre à jour le cache (update)
  • Ne pas utiliser le cache (no-cache)

mise à jour du requirements.txt

Affichage d’un fichier requirements.txt qui permet de sélectionner
les versions les plus récentes des paquets installés.

  • Permettre de poser la question de mise à jour pour chaque
    paquet (interactive)

vulnérabilités

Voir si la base de pyup est plus à jour que l’API de pypi.org ?

licence

Ajouter la licence du paquet dans les informations récupérées ?

Je suis désolé, mais j’ai du mal à comprendre le lien avec mon sujet ? Tu peux préciser ton idée ?

Je pensait, peut être à tord que tu en avait besoins pour un projet spécifique, l’utilisation d’une solution clé en main aurait directement résolu le problème.
J’ai du me tromper, tan pis.
J’ai supprimé l’information fournie, comme ça elle n’interfèrera plus avec ton projet.
Bonne chance.

Pas besoin de supprime rle message !
Ce que je ne comprends pas c’est que tu parlais d’auto-import alors que je parle plutôt d’inspecter les paquets liés à un projet. Je ne vois pas le rapport entre les deux, d’où ma question car je pense avoir mal compris ton message.

Enfin, si, il ne faut pas faire des discours super long pour rien, enfin, lorsque tu programme de façon modulaire, tu importe des objets ou des fonctions depuis des fichiers extérieurs, ils peuvent soit être déjà présent dans ton projet, soit être issue de l’importation d’une librairie extérieur.
Tu parlais simplement de lire les fichiers requirements ou autres, je pensait que tu cherchait un peu plus loin lorsqu’un programmeur oubliait d’importer une librairie.
En fait c’est moi qui me suis trompé sur la portée du projet :D.

Ok, je pige mieux ta remarque. Là l’idée est bien de vérifier la vulnérabilité des composants d’une application; pas forcément de ton environnement de dev :wink:

J’aime beaucoup ton mini projet.

2 « J'aime »

Merci, je lui cherche un p’tit nom qui va bien pour le déposer sur pypi maintenant… Si vous avez des idées, je prends !

Je me suis dit que “moult” serrait pas mal pour évoquer un serpent qui se dégage de sa peau morte mais ca existe déjà, et pourrait servir aussi !

1 « J'aime »

Très sympa ! Tu ne nous partages pas le code ? :smiling_face_with_tear:

Je suis sûr qu’il y a plein de choses à faire autour du semantic versioning. Par exemple, ça m’intéresserait d’utiliser ton outil pour mettre à jour mon requirements.txt en ne considérant que les releases de fix, et automatiquement de préférence !

À quoi correspondent les couleurs aujourd’hui ?

:slight_smile:

abcdefghijklmnopq

@dancergraham merci je vais aller voir ce qu’il permet !

@ramnes alors, dans la seconde version (qui est bugguée dans ce que j’ai fourni, mais plus maintenant), en rouge tu as les vulnérabilités (CVE), les versions en retard par rapport à la version majeure ainsi que les paquets au statut planning, pre-alpha, alpha et inactive. En jaune, les versions mineurs ou patchs en retard, les paquets dont la dernière version date de plus de 360 jours, ainsi que les paquets au statut beta.
L’idée ici est donc de mettre en avant les plus gros soucis (en rouge donc) pour s’en occuper rapidement. Le jaune étant une liste de potentiels problèmes à venir :wink:

Logiquement je pousserai le code à travers pypi dès que je valide un nom. J’ai pensé à obsolete par exemple.

Enfin, pour le semantic versioning, il faut être très prudent car je vois des versions qui sont vraiment pas simple à appréhender parfois !

@dancergraham bon je viens de vérifier, mais moult est en fait un utiltaire permettant de scanner des fichiers (ou des répertoires) python pour voir si tel ou tel paquet est encore utilisé. Pas si ceux-ci sont obsolètes :wink:

@dancergraham @Mindiell Pardon, ma question n’était pas assez précise (je faisais implicitement le lien avec le semantic versioning), permettez-moi de reformuler. :slight_smile:

Comment tu définis si une version doit être en rouge ou en jaune ? Pour les dates et les statuts c’est très clair, moins pour les versions.

Par ailleurs, pour les CVE, tu pourrais peut-être mettre des codes couleurs différents par score de gravité.

1 « J'aime »

Ah, je split sur le caractère “.” et si la première chaine remontée est différente, je mets en rouge. Sinon, je mets en jaune si les chaines sont différentes.

C’est une idée, mais pour moi toute CVE indique clairement un souci problématique; je vais regarder ça de plus près (et je n’ai pas cette info avec l’API de pypi).

C’est marrant, si on suit le semantic versioning, naturellement j’aurais voulu faire quasiment l’exact inverse : rouge pour un commit de fix, jaune pour le reste (et peut-être même quelque chose comme bleu pour les majeurs). Ça me paraît plus important d’appliquer les patchs de fix que de pull les nouvelles fonctionnalités de ma dépendance.

Après je suis clairement idéaliste, il n’y a probablement pas grand monde qui à la fois suit le semantic versioning et backport les fix sur des branches de release. :slight_smile:

Mais si on en revient à mon besoin primaire : j’aimerais beaucoup pouvoir appliquer les fix facilement. Aujourd’hui de toutes les solutions que je connais pour gérer ses dépendances en Python, c’est soit on update à la dernière version, soit on update pas. (Si quelqu’un peut me donner tord, ce serait avec plaisir !)

Donc les options “Permettre de sauver le résultat dans un fichier (output/o)” et “Limiter le résultat aux paquets à [certains] problèmes” me semblent vraiment être celles qui donneraient le plus de valeur à ton outil. Ce serait fou de pouvoir donner des règles sur ce qu’on veut appliquer à son requirements.txt, et de pouvoir les appliquer en une commande.

Ensuite, permettre de contrôler les changements que ça implique, avec par exemple un mode interactif qui te montrerait pour chaque dépendance qui change de version le changelog ou, à défaut de pouvoir le récupérer facilement, les commits de la dépendance entre les deux versions… Ça serait vraiment dingo. :exploding_head:

Et enfin, pouvoir faire tout ça d’un coup sur plusieurs dépôts (ou plusieurs fichiers de gestion de dépendance). Ça m’aurait fait gagner beaucoup de temps à une période où je gérais pas mal de micro-services.

1 « J'aime »

Merci pour ces retours, tout ça est vraiment très intéressant ! On va y aller pas à pas je pense.

En effet, la réflexion sur les versions : applique run patch ou risquer de casser son appli c’est pas la même chose. Comme la date de mise à jour est importante et également soulignée, on pourrait appliquer ton idée pour les versions.

J’ai d’ailleurs découvert : django-package-monitor, une ancienne app qui propose de faire un peu pareil et qui propose d’ailleurs, comme tu le dis, la prochaine version, ainsi que la dernière. Ca permet de visualiser son retard potentiel mais surtout de se concentrer sur juste ses patchs. Je vais surement m’en nourrir prochainement…