Bienvenue dans la maison publique de Dependabot.
Dependabot-Core est la bibliothèque au cœur des mises à jour de sécurité/version de Dependabot.
Utilisez-le pour générer des demandes d'extraction automatisées mettant à jour les dépendances pour les projets écrits en Ruby, JavaScript, Python, PHP, Dart, Elixir, Elm, Go, Rust, Java et .NET. Il peut également mettre à jour les sous-modules git, les fichiers Docker et les fichiers Terraform. Les fonctionnalités incluent :
La plupart des gens connaissent le service Dependabot qui s'exécute sur GitHub.com et GitHub Enterprise. L'activer est aussi simple que d'archiver un fichier de configuration dependabot.yml
dans le répertoire .github
de votre référentiel.
Cependant, si vous souhaitez exécuter une version personnalisée de Dependabot ou l'exécuter sur une autre plate-forme, vous n'êtes pas en reste. Ce dépôt fournit la logique nécessaire pour héberger votre propre Dependabot autonome. Il prend actuellement en charge l'ouverture de requêtes Pull sur des référentiels hébergés sur GitHub, Github Enterprise, Azure DevOps, GitLab, BitBucket et AWS CodeCommit.
Dependabot-Core est une bibliothèque, vous aurez donc besoin d'un script de point d'entrée quelconque. Voici quelques exemples pour vous aider à démarrer.
Remarque : Si vous souhaitez exécuter Dependabot localement à des fins de développement/débogage, consultez le Guide de développement.
Le référentiel dependabot-script fournit une collection d'exemples de scripts pour configurer la bibliothèque Dependabot-Core. Il est destiné à servir de point de départ aux utilisateurs avancés pour exécuter une version auto-hébergée de Dependabot au sein de leurs propres projets.
Remarque : Nous avons récemment refactorisé l'image Docker monolithique utilisée dans la bibliothèque Dependabot Core en une image par écosystème. Malheureusement, cela a cassé les scripts de dependabot et nous n'avons pas encore eu le temps de les mettre à jour. Nous sommes conscients du problème et espérons apporter une solution prochainement.
La CLI Dependabot est un outil plus récent qui pourrait éventuellement remplacer dependabot-script
pour les cas d'utilisation autonomes. Bien que cela crée des différences de dépendance, il manque actuellement la logique nécessaire pour transformer ces différences en véritables PR. Néanmoins, cela peut être utile pour les utilisateurs avancés qui recherchent des exemples de piratage de Dependabot.
Dans un environnement tel que GitHub où Dependabot s'exécute dans un conteneur, si vous souhaitez modifier votre processus de build ou d'installation selon que Dependabot vérifie ou non, vous pouvez le déterminer par l'existence de la variable d'environnement DEPENDABOT
.
Vous souhaitez nous faire part de votre retour sur Dependabot, ou y contribuer ? C'est super - merci beaucoup !
La plupart des rapports de bogues doivent être accompagnés d'un lien vers un référentiel public reproduisant le problème. Les rapports de bogues qui ne peuvent pas être reproduits sur un dépôt public à l'aide de l'outil CLI ou d'un script d'exécution à sec peuvent être fermés comme « impossible à reproduire ».
Notre outil de suivi des problèmes est très actif et, par conséquent, il y a de fortes chances que quelqu'un ait déjà signalé le même problème. Si tel est le cas, veuillez voter pour ce problème, car nous utilisons ? les réactions sur les problèmes comme un signal pour évaluer l’impact d’une demande de fonctionnalité ou d’un bug.
Cependant, veuillez ne pas laisser de commentaires qui n’apportent rien de nouveau à la discussion. Pour plus de détails, voir https://github.com/golang/go/wiki/NoPlusOne. Ceci est open source, si vous voyez quelque chose que vous souhaitez corriger, nous serons heureux de vous accompagner en contribuant à une pull request pour le corriger.
Le suivi des problèmes est uniquement destiné aux problèmes liés à la logique de mise à jour de Dependabot. Les problèmes concernant les alertes de sécurité ou le graphique de dépendance doivent plutôt être classés en tant que discussion sur la sécurité du code.
Une bonne règle de base est que si vous avez des questions sur la différence dans un PR, elles ont leur place ici.
Si vous pensez avoir trouvé une vulnérabilité de sécurité dans Dependabot, veuillez consulter notre politique de sécurité pour plus de détails sur la façon de les divulguer au programme GitHub Bug Bounty, afin que nous puissions travailler pour résoudre le problème avant qu'il ne soit divulgué publiquement.
Vous souhaitez contribuer à Dependabot ? C'est super - merci beaucoup !
Flux de travail des contributions :
Veuillez vous référer aux directives de CONTRIBUTION pour plus d'informations.
Si vous souhaitez contribuer au soutien d'un nouvel écosystème, veuillez vous référer aux lignes directrices de contribution pour plus d'informations.
La première étape pour déboguer un problème ou écrire une nouvelle fonctionnalité consiste à mettre en place un environnement de développement. Nous fournissons un shell de développement personnalisé basé sur Docker qui intègre toutes les dépendances requises. Dans la plupart des cas, c'est la meilleure façon de travailler sur le projet.
Le shell du développeur utilise des montages de volume pour incorporer vos modifications locales au code source de Dependabot. De cette façon, vous pouvez modifier localement à l'aide de votre éditeur préféré et les modifications sont immédiatement reflétées dans le conteneur Docker pour effectuer des essais à sec ou exécuter des tests. Remarque : consultez la mise en garde concernant la modification des scripts d'assistance du gestionnaire de packages natif.
Le script permettant de lancer le shell du développeur crée les images Docker à partir de zéro s'il ne parvient pas à les trouver localement. Cela peut prendre un certain temps.
Évitez l'attente en extrayant l'image prédéfinie de l'écosystème sur lequel vous souhaitez travailler. Le nom de l'image utilise le nom de l'écosystème YAML pour spécifier l'écosystème. Par exemple, pour les modules Go, le nom YAML est gomod
:
$ docker pull ghcr.io/dependabot/dependabot-updater-gomod
Remarque : les images prédéfinies ne sont actuellement disponibles que pour l'architecture AMD64/Intel. Ils fonctionneront sur ARM, mais 2 à 3 fois plus lentement que si vous créez manuellement des images spécifiques à ARM.
Ensuite, exécutez le shell du développeur en spécifiant l'écosystème souhaité en utilisant le nom du répertoire de niveau supérieur de l'écosystème dans ce projet . Par exemple, pour les modules Go, le répertoire de niveau supérieur est nommé go_modules
:
$ bin/docker-dev-shell go_modules
= > running docker development shell
[dependabot-core-dev] ~ $ cd go_modules && rspec spec # to run tests for a particular package
Normalement, le démarrage rapide suffit, mais vous devrez parfois reconstruire les images sous-jacentes.
Par exemple, même si nous ne publions pas encore d'images spécifiques à ARM, si vous travaillez sur une plate-forme basée sur ARM, nous vous recommandons de créer manuellement les images car les conteneurs résultants s'exécutent beaucoup plus rapidement.
Le shell du développeur s'exécute dans une image Docker Dependabot Development, qui est construite sur une image d'écosystème.
organigramme LR
A["script docker-dev-shell"] --> B("Image docker de développement Dependabot")
B --> C("Image docker de l'écosystème Dependabot Updater (spécifique à l'écosystème)")
C --> D("Image docker Dependabot Updater Core")
Les modifications apportées aux fichiers Docker pour l'une de ces images nécessitent la création d'une ou plusieurs images localement afin d'être reflétées dans le shell de développement.
Le moyen simple mais lent consiste à supprimer toutes les images existantes, puis à exécuter bin/docker-dev-shell
qui crée automatiquement les images manquantes.
Le moyen le plus rapide consiste à extraire toutes les images prédéfinies qui dépendent de l’image que vous devez réellement créer. Pour (re)construire un spécifique :
L'image principale du programme de mise à jour :
$ docker pull ghcr.io/dependabot/dependabot-updater-core # OR
$ docker build -f Dockerfile.updater-core . # recommended on ARM
L’image de l’écosystème Updater :
$ docker pull ghcr.io/dependabot/dependabot-updater-gomod # OR
$ script/build go_modules # recommended on ARM
Le conteneur de développement utilisant l'option --rebuild
:
$ bin/docker-dev-shell go_modules --rebuild
Plusieurs packages Dependabot utilisent des « assistants natifs », de petits exécutables dans leur langage hôte.
Les modifications apportées à ces fichiers ne sont pas automatiquement reflétées dans le conteneur de développement.
Une fois que vous avez apporté des modifications aux fichiers d'assistance, exécutez le script de build approprié pour mettre à jour la version installée avec vos modifications, comme suit :
$ bin/docker-dev-shell bundler
= > running docker development shell
$ bundler/helpers/v2/build
$ bin/dry-run.rb bundler dependabot/demo --dir= " /ruby "
Pour afficher les journaux et la sortie standard des assistants natifs du gestionnaire de packages, consultez débogage des assistants natifs.
La première étape du débogage consiste à faire fonctionner l’environnement de développement.
Dans l'environnement de développement, vous disposez de deux options pour simuler une tâche de mise à jour des dépendances : Vous pouvez utiliser l'outil CLI nouvellement développé ou le script d'exécution à sec d'origine.
La CLI Dependabot est un outil nouvellement développé qui intègre le proxy d'informations d'identification GitHub pour simuler de manière plus réaliste ce qui se passe au sein du service Dependabot-at-GitHub lorsque vous parlez à des registres privés.
Il dispose d'un guide de débogage dédié, incluant la prise en charge du passage dans le débogueur Ruby.
Remarque : Avant d'exécuter le script d'exécution à sec, vous devez exécuter l'environnement de développement.
Vous pouvez utiliser le script bin/dry-run.rb
pour simuler une tâche de mise à jour des dépendances, en imprimant le diff qui serait généré sur le terminal. Il prend deux arguments de position : le gestionnaire de packages et le nom du dépôt GitHub (y compris le compte) :
$ bin/docker-dev-shell go_modules
= > running docker development shell
$ bin/dry-run.rb go_modules rsc/quote
= > fetching dependency files
= > parsing dependency files
= > updating 2 dependencies
...
Le script Dry-Run prend en charge de nombreuses autres options, qui sont toutes documentées en haut du code source du script. Par exemple:
LOCAL_GITHUB_ACCESS_TOKEN="fake-GitHub-PAT"
permet de spécifier un jeton d'accès personnel (PAT) GitHub pour éviter la limitation de débit.--dir="path/to/subdir/containing/manifest
est requis si le fichier manifeste se trouve dans un sous-répertoire.--dep="dep-name-that-I-want-to-test"
permet de spécifier un seul dépôt à essayer de mettre à jour et tous les autres sont ignorés.--cache=files
permet de mettre en cache localement les fichiers dep distants pour des réexécutions plus rapides lors du test des changements de logique locale.--updater-options=feature_flag_name
permet de transmettre des indicateurs de fonctionnalité.Voici un exemple de la façon de relier tout cela ensemble
LOCAL_GITHUB_ACCESS_TOKEN=github_pat_123_fake_string
bin/dry-run.rb docker jeffwidman/secrets-store-driver
--dir " /manifest_staging/charts/secrets-store-provider "
--cache=files
--dep= " secrets-store "
--updater-options=kubernetes_updates
Vous pouvez ajouter une instruction debugger
n'importe où dans le code Ruby, par exemple :
def latest_resolvable_version
debugger
latest_version_finder . latest_version
end
Lorsque vous exécutez le travail, le débogueur Ruby s'ouvrira. Cela devrait ressembler à ceci :
[ 11 , 20 ] in ~/ go_modules / lib / dependabot / go_modules / update_checker . rb
11 | module GoModules
12 | class UpdateChecker < Dependabot :: UpdateCheckers :: Base
13 | require_relative "update_checker/latest_version_finder"
14 |
15 | def latest_resolvable_version
=> 16 | debugger
17 | latest_version_finder . latest_version
18 | end
19 |
20 | # This is currently used to short-circuit latest_resolvable_version,
=> #0 Dependabot::GoModules::UpdateChecker#latest_resolvable_version at ~/go_modules/lib/dependabot/go_modules/update_checker.rb:16
#1 Dependabot::GoModules::UpdateChecker#latest_version at ~/go_modules/lib/dependabot/go_modules/update_checker.rb:24
# and 9 frames (use `bt' command for all frames)
( rdbg )
À cette invite, vous pouvez exécuter des commandes du débogueur pour naviguer ou saisir des méthodes et des variables pour voir ce qu'elles contiennent. Essayez de saisir dependency
pour voir sur quelle dépendance Dependabot travaille actuellement.
Remarque Dans le débogueur, les modifications apportées au code source ne seront pas prises en compte. Vous devrez mettre fin à votre session de débogage et la redémarrer.
Lorsque vous déboguez un problème, vous devez souvent jeter un œil à ces scripts qui s'exécutent dans un processus distinct.
Imprimez toutes les instructions de journal des assistants natifs en utilisant DEBUG_HELPERS=true
:
DEBUG_HELPERS=true bin/dry-run.rb bundler dependabot/demo --dir= " /ruby "
Suspendez l'exécution pour déboguer une seule fonction d'assistance native à l'aide de DEBUG_FUNCTION=<function name>
. La fonction correspond à un nom de fonction d'assistance native, par exemple, l'une des fonctions de bundler/helpers/v2/lib/functions.rb
.
Lorsque cette fonction est en cours d'exécution, un debugger
est inséré, suspendant l'exécution du script bin/dry-run.rb
, ce qui laisse le répertoire tmp
des mises à jour actuelles en place, vous permettant d' cd
au répertoire et d'exécuter directement la fonction d'assistance native :
DEBUG_FUNCTION=parsed_gemfile bin/dry-run.rb bundler dependabot/demo --dir= " /ruby "
= > fetching dependency files
= > dumping fetched dependency files: ./dry-run/dependabot/demo/ruby
= > parsing dependency files
$ cd /home/dependabot/dependabot-core/tmp/dependabot_TEMP/ruby && echo " { " function " : " parsed_gemfile " , " args " :{ " gemfile_name " : " Gemfile " , " lockfile_name " : " Gemfile.lock " , " dir " : " /home/dependabot/dependabot-core/tmp/dependabot_TEMP/ruby " }} " | BUNDLER_VERSION=1.17.3 BUNDLE_GEMFILE=/opt/bundler/v1/Gemfile GEM_HOME=/opt/bundler/v1/.bundle bundle exec ruby /opt/bundler/v1/run.rb
Copiez et exécutez la commande cd...
:
cd /home/dependabot/dependabot-core/tmp/dependabot_TEMP/ruby && echo " { " function " : " parsed_gemfile " , " args " :{ " gemfile_name " : " Gemfile " , " lockfile_name " : " Gemfile.lock " , " dir " : " /home/dependabot/dependabot-core/tmp/dependabot_TEMP/ruby " }} " | BUNDLER_VERSION=1.17.3 BUNDLE_GEMFILE=/opt/bundler/v1/Gemfile GEM_HOME=/opt/bundler/v1/.bundle bundle exec ruby /opt/bundler/v1/run.rb
Cela devrait déconnecter la sortie de la fonction parsed_gemfile
:
{ "result" : [ { "name" : "business" , "requirement" : "~> 1.0.0" , "groups" : [ "default" ] , "source" : null , "type" : "runtime" } , { "name" : "uk_phone_numbers" , "requirement" : "~> 0.1.0" , "groups" : [ "default" ] , "source" : null , "type" : "runtime" } ] }
Gardez à l'esprit que contrairement aux modifications apportées à la source Ruby, les modifications apportées sur votre machine hôte au code source des assistants natifs ne sont pas synchronisées avec le conteneur de développement. Vous avez donc deux choix pour éditer l'assistant natif :
vi /opt/bundler/v1/lib/functions/file_parser.rb
. Et puis réexécutez la commande cd...
Il s'agit du moyen le plus rapide de déboguer, mais aucune modification ne sera enregistrée en dehors du conteneur. La plupart des écosystèmes de Dependabot-Core prennent en charge ignore
les conditions qui permettent à un utilisateur de spécifier des noms de dépendances ou des versions à exclure des mises à niveau. La documentation du service Dependabot sur GitHub décrit la fonctionnalité plus en détail.
La CLI Dependabot prend en charge la transmission des conditions d'ignorance dans le cadre de la définition de la tâche. Voir l'exemple.
Le script d'exécution à sec prend en charge la transmission d'une ou plusieurs conditions d'ignorance via la variable d'environnement IGNORE_CONDITIONS
:
IGNORE_CONDITIONS= ' [{"dependency-name":"*","update-types": ["version-update:semver-major"]}] '
bin/dry-run.rb docker test_org/test-dependabot `
De nombreux écosystèmes de Dependabot-Core prennent en charge les mises à jour de sécurité. Il s'agit d'une forme spéciale de mise à jour de version dans laquelle un nom de dépendance et une plage de versions vulnérables sont transmis. Dependabot-Core tentera de mettre à niveau toute instance de cette dépendance vers la version minimale non vulnérable. Cela contraste avec une mise à jour de version normale qui tente de mettre à jour vers la dernière version.
La variable d'environnement SECURITY_ADVISORIES
permet de transmettre une ou plusieurs notifications d'alerte de sécurité au script de simulation afin de simuler une mise à jour de sécurité :
SECURITY_ADVISORIES= ' [{"dependency-name":"buffer","patched-versions":[],"unaffected-versions":[],"affected-versions":["<= 2.0.0"]}] '
bin/dry-run.rb pub dart-lang/pub-dev --dir " /app " --cache=files --dep= " buffer "
Il existe une prise en charge intégrée pour exploiter la capacité de Visual Studio Code à déboguer dans un conteneur Docker. Après avoir installé l'extension Dev Containers
recommandée, appuyez simplement sur Ctrl+Shift+P
( ⇧⌘P
sur macOS) et sélectionnez Dev Containers: Reopen in Container
. Vous pouvez également accéder à la liste déroulante en cliquant sur le bouton vert dans le coin inférieur gauche de l'éditeur. Si l'image Docker de développement n'est pas présente sur votre machine, elle sera construite automatiquement. Une fois cela terminé, démarrez la configuration Debug Dry Run
(F5)
et vous serez invité à sélectionner un gestionnaire de packages et un référentiel sur lesquels effectuer une exécution à sec. N'hésitez pas à placer des points d'arrêt sur le code.
Il existe également une prise en charge pour déboguer des exécutions de tests individuelles en exécutant la configuration Debug Tests
(F5)
et vous serez invité à sélectionner un écosystème et à fournir un chemin rspec.
Clone Repository ...
de l'extension Remote Containers manquent actuellement de certaines fonctionnalités et ne sont donc pas prises en charge. Vous devez cloner le référentiel manuellement et utiliser la commande Reopen in Container
ou Open Folder in Container...
Une fois que vous avez lancé l'environnement de développement pour un écosystème particulier, exécutez les tests pour cet écosystème en exécutant rspec spec
dans le dossier de cet écosystème, par exemple
$ cd go_modules
$ rspec spec
Vous pouvez également limiter les tests au fichier sur lequel vous travaillez, ou uniquement aux tests qui ont échoué précédemment, par exemple :
$ rspec spec/dependabot/file_updaters/elixir --only-failures
Le style est appliqué par RuboCop. Pour vérifier les violations de style, exécutez simplement rubocop
dans chacun des packages, par exemple
$ cd go_modules
$ rubocop
Vous pouvez profiler une exécution à sec en passant l'indicateur --profile
lors de son exécution, ou baliser un test rspec
avec :profile
. Cela générera un fichier stackprof-<datetime>.dump
dans le dossier tmp/
, et vous pourrez générer un flamegraph à partir de celui-ci en exécutant :
stackprof --d3-flamegraph tmp/stackprof- < data or spec name > .dump > tmp/flamegraph.html
Dependabot-Core est une collection de packages Ruby (gemmes), qui contiennent la logique de mise à jour des dépendances dans plusieurs langages.
dependabot-common
Le package common
contient toutes les fonctionnalités générales/partagées. Par exemple, le code permettant de créer des requêtes pull pour les différentes plates-formes prises en charge se trouve ici, tout comme la plupart de la logique de gestion des dépendances Git (car la plupart des langages prennent en charge les dépendances Git d'une manière ou d'une autre). Il existe également des classes de base définies pour chacune des préoccupations majeures nécessaires à la mise en œuvre du support d'un langage ou d'un gestionnaire de packages.
dependabot-{package-manager}
Il existe une gemme pour chaque gestionnaire de packages ou langage pris en charge par Dependabot. Au minimum, chacune de ces gemmes implémentera les classes suivantes :
Service | Description |
---|---|
FileFetcher | Récupère les fichiers de dépendance pertinents pour un projet (par exemple, le Gemfile et Gemfile.lock ). Voir le README pour plus de détails. |
FileParser | Analyse un fichier de dépendances et extrait une liste de dépendances pour un projet. Voir le README pour plus de détails. |
UpdateChecker | Vérifie si une dépendance donnée est à jour. Voir le README pour plus de détails. |
FileUpdater | Met à jour un fichier de dépendances pour utiliser la dernière version d'une dépendance donnée. Voir le README pour plus de détails. |
MetadataFinder | Recherche les métadonnées sur une dépendance, telles que son URL GitHub. Voir le README pour plus de détails. |
Version | Décrit la logique de comparaison des versions de dépendance. Voir la classe hex Version pour un exemple. |
Requirement | Décrit le format d'une exigence de dépendance (par exemple >= 1.2.3 ). Voir la classe hex Requirement pour un exemple. |
Le flux de haut niveau ressemble à ceci :
dependabot-omnibus
Il s'agit d'un joyau "méta", qui dépend simplement de tous les autres. Si vous souhaitez inclure automatiquement la prise en charge de toutes les langues, vous pouvez simplement inclure ce joyau et vous obtiendrez tout ce dont vous avez besoin.
Pour de nombreux écosystèmes, Dependabot-Core prend en charge les registres privés. Parfois, cela se produit en transmettant les informations d'identification du registre privé directement aux gestionnaires de packages natifs ( npm
, pip
, bundler
, etc.), d'autres fois, cela se produit dans le code Ruby Dependabot-Core.
diagramme de séquence
Identifiants du registre privé->>Dependabot-Core :<br />
Dependabot-Core->>Gestionnaires de packages natifs :<br />
Gestionnaires de packages natifs ->>Registres de packages :<br />
Dependabot-Core->>Registres de packages :<br />
Bien que simple et direct, il s'agit d'un risque de sécurité pour les écosystèmes qui permettent d'exécuter du code non fiable dans leurs fichiers manifestes. Par exemple, setup.py
et .gemspec
permettent d'exécuter du code Python et Ruby natif. Si un package de l'arborescence des dépendances est piraté, un attaquant pourrait envoyer un manifeste malveillant qui obligerait le gestionnaire de packages natif à exposer les informations d'identification.
Pour se prémunir contre cela, pour le service Dependabot exécuté par Github, nous enveloppons Dependabot-Core avec un proxy d'informations d'identification afin que ces secrets de registre privé ne soient jamais exposés à Dependabot-Core.
diagramme de séquence
Dependabot-Core->>Credentials Proxy : toutes les demandes ne sont pas authentifiées
Proxy d'informations d'identification ->> Registres de packages : les informations d'identification sont injectées par le proxy
Remarque à gauche de Dependabot-Core : le service Dependabot<br /> exécuté par GitHub
Registres de packages ->> Proxy d'informations d'identification : les informations d'identification sont supprimées par le proxy
Credentials Proxy->>Dependabot-Core : Dependabot-Core ne voit jamais les informations d'identification du registre privé
Cela signifie également que si Dependabot-Core présente une faille de sécurité, ces crédits ne risquent toujours pas d'être exposés.
Ce projet peut contenir des marques ou des logos pour des projets, des produits ou des services. L'utilisation autorisée des marques ou logos GitHub est soumise et doit respecter les logos et l'utilisation de GitHub. L'utilisation des marques ou logos GitHub dans les versions modifiées de ce projet ne doit pas prêter à confusion ni impliquer le parrainage de GitHub. Toute utilisation de marques ou de logos tiers est soumise aux politiques de ces tiers.
Dependabot et dependabot-core ont commencé leur vie sous le nom de Bump and Bump Core, à l'époque où @hmarr et @greysteil travaillaient chez GoCardless.
Dependabot est devenu membre de GitHub en 2019 !
Publiez une nouvelle version sur RubyGems en exécutant le workflow Gems - Bump Version
et en suivant les instructions du résumé de la tâche.
En un mot, le processus sera le suivant :
v1.2.3
. Le résumé de la tâche contient une URL pré-remplie avec la version correcte du titre et de la balise.