Bem-vindo à casa pública do Dependabot.
Dependabot-Core é a biblioteca central das atualizações de segurança/versão do Dependabot.
Use-o para gerar solicitações pull automatizadas, atualizando dependências para projetos escritos em Ruby, JavaScript, Python, PHP, Dart, Elixir, Elm, Go, Rust, Java e .NET. Ele também pode atualizar submódulos git, arquivos Docker e arquivos Terraform. Os recursos incluem:
A maioria das pessoas está familiarizada com o serviço Dependabot executado em GitHub.com e GitHub Enterprise. Habilitar isso é tão simples quanto verificar um arquivo de configuração dependabot.yml
no diretório .github
do seu repositório.
No entanto, se você deseja executar uma versão personalizada do Dependabot ou em outra plataforma, você não ficará de fora. Este repositório fornece a lógica necessária para hospedar seu próprio Dependabot independente. Atualmente, ele oferece suporte à abertura de solicitações pull em repositórios hospedados no GitHub, Github Enterprise, Azure DevOps, GitLab, BitBucket e AWS CodeCommit.
Dependabot-Core é uma biblioteca, então você precisará de algum tipo de script de ponto de entrada. Aqui estão alguns exemplos para ajudá-lo a começar.
Nota: Se você deseja executar o Dependabot localmente para fins de desenvolvimento/depuração, consulte o Guia de Desenvolvimento.
O repositório dependebot-script fornece uma coleção de scripts de exemplo para configurar a biblioteca Dependabot-Core. O objetivo é ser um ponto de partida para usuários avançados executarem uma versão auto-hospedada do Dependabot em seus próprios projetos.
Observação: recentemente refatoramos a imagem monolítica do docker usada na biblioteca Dependabot Core em uma imagem por ecossistema. Infelizmente, isso quebrou os scripts do dependebot e ainda não tivemos tempo de atualizá-los. Estamos cientes do problema e esperamos fornecer uma solução em breve.
O Dependabot CLI é uma ferramenta mais recente que pode eventualmente substituir dependabot-script
para casos de uso independentes. Embora crie diferenças de dependência, atualmente falta a lógica para transformar essas diferenças em PRs reais. No entanto, pode ser útil para usuários avançados que procuram exemplos de como hackear o Dependabot.
Em um ambiente como o GitHub onde o Dependabot está sendo executado em um contêiner, se você quiser alterar seu processo de construção ou instalação dependendo se o Dependabot está verificando, você pode determiná-lo pela existência da variável de ambiente DEPENDABOT
.
Quer nos dar feedback sobre o Dependabot ou contribuir com ele? Isso é ótimo - muito obrigado!
A maioria dos relatórios de bugs deve ser acompanhada de um link para um repositório público que reproduza o problema. Relatórios de bugs que não podem ser reproduzidos em um repositório público usando a ferramenta CLI ou script de simulação podem ser fechados como "não é possível reproduzir".
Nosso rastreador de problemas está bastante ativo e, como resultado, há uma boa chance de alguém já ter registrado o mesmo problema. Em caso afirmativo, vote positivamente nesse problema, porque usamos ? reações sobre problemas como um sinal para avaliar o impacto de uma solicitação de recurso ou bug.
No entanto, por favor, não deixe comentários que não contribuam com nada de novo para a discussão. Para obter detalhes, consulte https://github.com/golang/go/wiki/NoPlusOne. Este é um código aberto. Se você encontrar algo que deseja consertar, ficaremos felizes em orientá-lo na contribuição de uma solicitação pull para corrigi-lo.
O rastreador de problemas destina-se exclusivamente a problemas relacionados à lógica de atualização do Dependabot. Questões sobre alertas de segurança ou Gráfico de Dependência devem ser arquivadas como uma discussão de Segurança de Código.
Uma boa regra é que se você tiver dúvidas sobre a diferença em um PR, ela deve estar aqui.
Se você acredita ter encontrado uma vulnerabilidade de segurança no Dependabot, revise nossa política de segurança para obter detalhes sobre como divulgá-la ao programa GitHub Bug Bounty, para que possamos trabalhar para resolver o problema antes que ele seja divulgado publicamente.
Quer contribuir com o Dependabot? Isso é ótimo - muito obrigado!
Fluxo de trabalho de contribuição:
Consulte as diretrizes de CONTRIBUIÇÃO para obter mais informações.
Se você estiver interessado em contribuir com suporte para um novo ecossistema, consulte as diretrizes de contribuição para obter mais informações.
A primeira etapa para depurar um problema ou escrever um novo recurso é colocar o ambiente de desenvolvimento em funcionamento. Fornecemos um shell de desenvolvedor personalizado baseado em Docker que integra todas as dependências necessárias. Na maioria dos casos esta é a melhor forma de trabalhar com o projeto.
O shell do desenvolvedor usa montagens de volume para incorporar suas alterações locais ao código-fonte do Dependabot. Dessa forma, você pode editar localmente usando seu editor favorito e as alterações são refletidas imediatamente no contêiner do docker para realizar simulações ou testes. Nota: Consulte a advertência sobre a edição dos scripts auxiliares do gerenciador de pacotes nativos.
O script para iniciar o shell do desenvolvedor cria as imagens do docker do zero, caso não consiga encontrá-las localmente. Isso pode demorar um pouco.
Evite a espera extraindo a imagem pré-construída do ecossistema no qual deseja trabalhar. O nome da imagem usa o nome do ecossistema YAML para especificar o ecossistema. Por exemplo, para módulos Go, o nome YAML é gomod
:
$ docker pull ghcr.io/dependabot/dependabot-updater-gomod
Nota: Atualmente, imagens pré-construídas estão disponíveis apenas para arquitetura AMD64/Intel. Eles serão executados em ARM, mas 2x-3x mais lentos do que se você construísse manualmente imagens específicas do ARM.
Em seguida, execute o shell do desenvolvedor, especificando o ecossistema desejado usando o nome do diretório de nível superior do ecossistema neste projeto . Por exemplo, para módulos Go, o diretório de nível superior é denominado 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
Normalmente, o Quickstart é tudo que você precisa, mas ocasionalmente você precisará reconstruir as imagens subjacentes.
Por exemplo, embora ainda não publiquemos imagens específicas do ARM, se você estiver trabalhando em uma plataforma baseada em ARM, recomendamos a construção manual das imagens porque os contêineres resultantes são executados muito mais rapidamente.
O shell do desenvolvedor é executado em uma imagem docker do Dependabot Development, que é construída sobre uma imagem do ecossistema.
fluxograma LR
A["docker-dev-shell script"] -> B("Imagem do docker de desenvolvimento do Dependabot")
B -> C ("Imagem da janela de encaixe do ecossistema do Dependabot Updater (específica do ecossistema)")
C -> D("Imagem da janela de encaixe do Dependabot Updater Core")
Alterações nos arquivos docker para qualquer uma dessas imagens requerem a construção de uma ou mais imagens localmente para serem refletidas no shell de desenvolvimento.
A maneira simples, mas lenta, é excluir todas as imagens existentes e, em seguida, executar bin/docker-dev-shell
que cria automaticamente as imagens ausentes.
A maneira mais rápida é extrair todas as imagens pré-construídas que são dependências da imagem que você realmente precisa construir. Para (re)construir um específico:
A imagem principal do atualizador:
$ docker pull ghcr.io/dependabot/dependabot-updater-core # OR
$ docker build -f Dockerfile.updater-core . # recommended on ARM
A imagem do ecossistema do Updater:
$ docker pull ghcr.io/dependabot/dependabot-updater-gomod # OR
$ script/build go_modules # recommended on ARM
O contêiner de desenvolvimento usando o sinalizador --rebuild
:
$ bin/docker-dev-shell go_modules --rebuild
Vários pacotes Dependabot fazem uso de 'ajudantes nativos', pequenos executáveis em sua linguagem host.
As alterações nesses arquivos não são refletidas automaticamente no contêiner de desenvolvimento.
Depois de fazer qualquer edição nos arquivos auxiliares, execute o script de construção apropriado para atualizar a versão instalada com suas alterações, como esta:
$ bin/docker-dev-shell bundler
= > running docker development shell
$ bundler/helpers/v2/build
$ bin/dry-run.rb bundler dependabot/demo --dir= " /ruby "
Para visualizar logs e stdout dos auxiliares nativos do gerenciador de pacotes, consulte depuração de auxiliares nativos.
A primeira etapa para a depuração é colocar o ambiente de desenvolvimento em execução.
No ambiente de desenvolvimento, você tem duas opções para simular um trabalho de atualização de dependência: Você pode usar a ferramenta CLI recém-desenvolvida ou o script de simulação original.
A CLI do Dependabot é uma ferramenta recém-desenvolvida que incorpora o GitHub Credentials Proxy para simular de forma mais realista o que está acontecendo no serviço Dependabot-at-GitHub ao conversar com registros privados.
Possui um guia de depuração dedicado, incluindo suporte para entrar no depurador Ruby.
Observação: antes de executar o script de simulação, você precisará colocar o ambiente de desenvolvimento em execução.
Você pode usar o script bin/dry-run.rb
para simular um trabalho de atualização de dependência, imprimindo o diff que seria gerado no terminal. São necessários dois argumentos posicionais: o gerenciador de pacotes e o nome do repositório GitHub (incluindo a conta):
$ 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
...
O script Dry-Run oferece suporte a muitas outras opções, todas documentadas na parte superior do código-fonte do script. Por exemplo:
LOCAL_GITHUB_ACCESS_TOKEN="fake-GitHub-PAT"
permite especificar um GitHub Personal Access Token (PAT) para evitar limitação de taxa.--dir="path/to/subdir/containing/manifest
é necessário se o arquivo de manifesto estiver localizado em um subdiretório.--dep="dep-name-that-I-want-to-test"
permite especificar um único dep para tentar atualizar e todos os outros são ignorados.--cache=files
permite armazenar em cache arquivos dep remotos localmente para execuções mais rápidas ao testar alterações de lógica local.--updater-options=feature_flag_name
permite passar sinalizadores de recursos.Aqui está um exemplo de como juntar tudo isso
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
Você pode adicionar uma instrução debugger
em qualquer lugar do código Ruby, por exemplo:
def latest_resolvable_version
debugger
latest_version_finder . latest_version
end
Ao executar o trabalho, o depurador Ruby será aberto. Deve ser algo assim:
[ 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 )
Neste prompt, você pode executar comandos do depurador para navegar ou inserir métodos e variáveis para ver o que eles contêm. Tente inserir dependency
para ver em qual dependência o Dependabot está trabalhando atualmente.
Nota Enquanto estiver no depurador, as alterações feitas no código-fonte não serão detectadas. Você terá que encerrar sua sessão de depuração e reiniciá-la.
Ao depurar um problema, muitas vezes você precisa dar uma olhada nesses scripts que são executados em um processo separado.
Imprima todas as instruções de log dos auxiliares nativos usando DEBUG_HELPERS=true
:
DEBUG_HELPERS=true bin/dry-run.rb bundler dependabot/demo --dir= " /ruby "
Pause a execução para depurar uma única função auxiliar nativa usando DEBUG_FUNCTION=<function name>
. A função é mapeada para um nome de função auxiliar nativa, por exemplo, uma das funções em bundler/helpers/v2/lib/functions.rb
.
Quando esta função está sendo executada, um debugger
é inserido, pausando a execução do script bin/dry-run.rb
, isso deixa o diretório tmp
de atualizações atuais no lugar, permitindo que você faça cd
no diretório e execute a função auxiliar nativa diretamente:
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
Copie e execute o comando 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
Isso deve desconectar a saída da função 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" } ] }
Tenha em mente que, diferentemente das alterações na fonte Ruby, as alterações na máquina host no código-fonte dos auxiliares nativos não são sincronizadas com o contêiner de desenvolvimento. Então você tem duas opções para editar o auxiliar nativo:
vi /opt/bundler/v1/lib/functions/file_parser.rb
. E então execute novamente o comando cd...
Esta é a maneira mais rápida de depurar, mas nenhuma alteração será salva fora do contêiner. A maioria dos ecossistemas no suporte ao Dependabot-Core ignore
as condições que permitem ao usuário especificar nomes de dependências ou versões a serem excluídas das atualizações. A documentação do serviço Dependabot no GitHub descreve o recurso com mais detalhes.
A CLI do Dependabot oferece suporte à passagem de condições de ignorar como parte da definição do trabalho. Veja o exemplo.
O script de simulação suporta a passagem de uma ou mais condições de ignorar por meio do env var IGNORE_CONDITIONS
:
IGNORE_CONDITIONS= ' [{"dependency-name":"*","update-types": ["version-update:semver-major"]}] '
bin/dry-run.rb docker test_org/test-dependabot `
Muitos dos ecossistemas no Dependabot-Core oferecem suporte a atualizações de segurança. Esta é uma forma especial de atualização de versão onde um nome de dependência e um intervalo de versões vulneráveis são passados. O Dependabot-Core tentará atualizar qualquer instância dessa dependência para a versão mínima não vulnerável. Isso contrasta com uma atualização de versão normal que tenta atualizar para a versão mais recente .
O env var SECURITY_ADVISORIES
permite passar uma ou mais notificações de alerta de segurança para o script de simulação para simular uma atualização de segurança:
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 "
Há suporte integrado para aproveitar a capacidade do Visual Studio Code de depuração dentro de um contêiner do Docker. Depois de instalar a extensão Dev Containers
recomendada, basta pressionar Ctrl+Shift+P
( ⇧⌘P
no macOS) e selecionar Dev Containers: Reopen in Container
. Você também pode acessar o menu suspenso clicando no botão verde no canto inferior esquerdo do editor. Se a imagem Docker de desenvolvimento não estiver presente em sua máquina, ela será construída automaticamente. Quando terminar, inicie a configuração Debug Dry Run
(F5)
e você será solicitado a selecionar um gerenciador de pacotes e um repositório para realizar uma simulação. Sinta-se à vontade para colocar pontos de interrupção no código.
Também há suporte para depurar execuções de testes individuais executando a configuração Debug Tests
(F5)
e você será solicitado a selecionar um ecossistema e fornecer um caminho rspec.
Clone Repository ...
da extensão Remote Containers estão faltando algumas funcionalidades e, portanto, não são suportados. Você deve clonar o repositório manualmente e usar o comando Reopen in Container
ou Open Folder in Container...
Depois de iniciar o ambiente de desenvolvimento para um ecossistema específico, execute os testes para esse ecossistema executando rspec spec
dentro da pasta desse ecossistema, por exemplo
$ cd go_modules
$ rspec spec
Você também pode limitar os testes apenas ao arquivo em que está trabalhando ou apenas aos testes que falharam anteriormente, por exemplo:
$ rspec spec/dependabot/file_updaters/elixir --only-failures
O estilo é aplicado pelo RuboCop. Para verificar violações de estilo, simplesmente execute rubocop
em cada um dos pacotes, por exemplo
$ cd go_modules
$ rubocop
Você pode criar o perfil de uma simulação passando o sinalizador --profile
ao executá-lo ou marcar um teste rspec
com :profile
. Isso irá gerar um arquivo stackprof-<datetime>.dump
na pasta tmp/
, e você pode gerar um flamegraph a partir dele executando:
stackprof --d3-flamegraph tmp/stackprof- < data or spec name > .dump > tmp/flamegraph.html
Dependabot-Core é uma coleção de pacotes Ruby (gems), que contém a lógica para atualização de dependências em diversas linguagens.
dependabot-common
O pacote common
contém todas as funcionalidades de uso geral/compartilhadas. Por exemplo, o código para criar solicitações pull para as diferentes plataformas suportadas reside aqui, assim como a maior parte da lógica para lidar com dependências do Git (já que a maioria das linguagens suporta dependências do Git de uma forma ou de outra). Existem também classes base definidas para cada uma das principais preocupações necessárias para implementar o suporte a uma linguagem ou gerenciador de pacotes.
dependabot-{package-manager}
Há uma joia para cada gerenciador de pacotes ou linguagem suportada pelo Dependabot. No mínimo, cada uma dessas gems implementará as seguintes classes:
Serviço | Descrição |
---|---|
FileFetcher | Busca os arquivos de dependência relevantes para um projeto (por exemplo, Gemfile e Gemfile.lock ). Consulte o README para obter mais detalhes. |
FileParser | Analisa um arquivo de dependência e extrai uma lista de dependências para um projeto. Consulte o README para obter mais detalhes. |
UpdateChecker | Verifica se uma determinada dependência está atualizada. Consulte o README para obter mais detalhes. |
FileUpdater | Atualiza um arquivo de dependência para usar a versão mais recente de uma determinada dependência. Consulte o README para obter mais detalhes. |
MetadataFinder | Procura metadados sobre uma dependência, como o URL do GitHub. Consulte o README para obter mais detalhes. |
Version | Descreve a lógica para comparar versões de dependência. Veja a classe hexadecimal Version para ver um exemplo. |
Requirement | Descreve o formato de um requisito de dependência (por exemplo, >= 1.2.3 ). Veja a classe hexadecimal Requirement para ver um exemplo. |
O fluxo de alto nível é assim:
dependabot-omnibus
Esta é uma “meta” joia, que simplesmente depende de todas as outras. Se você deseja incluir suporte automaticamente para todos os idiomas, basta incluir esta joia e você terá tudo o que precisa.
Para muitos ecossistemas, o Dependabot-Core oferece suporte a registros privados. Às vezes isso acontece passando as credenciais do registro privado diretamente para os gerenciadores de pacotes nativos ( npm
, pip
, bundler
, etc), outras vezes acontece dentro do código Ruby do Dependabot-Core.
diagrama de sequência
Credenciais de registro privado->>Dependabot-Core:<br />
Dependabot-Core->>Gerenciadores de pacotes nativos:<br />
Gerenciadores de pacotes nativos->>Registros de pacotes:<br />
Dependabot-Core->>Registros de pacotes:<br />
Embora simples e direto, este é um risco de segurança para ecossistemas que permitem a execução de código não confiável em seus arquivos de manifesto. Por exemplo, setup.py
e .gemspec
permitem a execução de código Python e Ruby nativo. Se um pacote na árvore de dependências for hackeado, um invasor poderá enviar um manifesto malicioso que forçará o gerenciador de pacotes nativo a expor os créditos.
Para se proteger contra isso, para o serviço Dependabot executado pelo Github, envolvemos o Dependabot-Core com um proxy de credencial para que esses segredos de registro privado nunca sejam expostos ao Dependabot-Core.
diagrama de sequência
Dependabot-Core->>Proxy de credenciais: todas as solicitações não são autenticadas
Proxy de credenciais->>Registros de pacotes: as credenciais são injetadas pelo proxy
Nota à esquerda de Dependabot-Core: O serviço Dependabot<br /> que o GitHub executa
Registros de pacotes->>Proxy de credenciais: as credenciais são removidas pelo proxy
Proxy de credenciais->>Dependabot-Core: Dependabot-Core nunca vê credenciais de registro privadas
Isso também significa que se o Dependabot-Core tiver uma vulnerabilidade de segurança, essas credenciais ainda não correm o risco de serem expostas.
Este projeto pode conter marcas registradas ou logotipos de projetos, produtos ou serviços. O uso autorizado de marcas registradas ou logotipos do GitHub está sujeito e deve seguir os logotipos e uso do GitHub. O uso de marcas registradas ou logotipos do GitHub em versões modificadas deste projeto não deve causar confusão ou implicar patrocínio do GitHub. Qualquer uso de marcas registradas ou logotipos de terceiros está sujeito às políticas desses terceiros.
Dependabot e dependebot-core começaram como Bump e Bump Core, quando @hmarr e @greysteil trabalhavam na GoCardless.
O Dependabot tornou-se parte do GitHub em 2019!
Publique uma nova versão no RubyGems executando o fluxo de trabalho Gems - Bump Version
e seguindo as instruções no resumo do trabalho.
Em poucas palavras o processo será:
v1.2.3
. O resumo da vaga contém um URL pré-preenchido com a versão correta do título e da tag.