1 pontos por GN⁺ 4 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • Copybara é uma ferramenta usada internamente no Google para transformar e mover código-fonte entre vários repositórios, em casos como a sincronização entre repositórios confidential e public
  • Ao escolher um repositório como repositório autoritativo, mantém-se uma única fonte da verdade, mas contribuições podem ser recebidas de qualquer repositório e releases também podem ser criadas a partir de qualquer repositório
  • O principal caso de uso é a movimentação repetitiva de código, com suporte a fluxos como levar parte do código de um repositório confidential para um repositório public ou trazer mudanças de um repositório public para o repositório autoritativo
  • O Copybara usa uma abordagem stateless que armazena o estado não em um servidor separado, mas em labels nas mensagens de commit do repositório de destino, permitindo que vários usuários ou serviços obtenham o mesmo resultado com a mesma configuração e os mesmos repositórios
  • O tipo de repositório atualmente suportado é Git; a leitura de Mercurial é um recurso experimental, e a arquitetura extensível permite adicionar origins e destinations personalizados

O problema que o Copybara resolve

  • Copybara é uma ferramenta para movimentação e transformação de código-fonte entre repositórios
  • Há casos em que o código-fonte precisa existir em vários repositórios, e o Copybara permite transformar e mover código entre esses repositórios
  • Um caso representativo é um projeto que mantém sincronizados um repositório confidential e um repositório public
  • A forma mais comum de uso é mover código repetidamente de um repositório para outro
  • Também pode ser usado para mover código uma única vez para um novo repositório

Repositório autoritativo e fluxo de contribuições

  • O Copybara exige que um dos repositórios seja escolhido como authoritative repository
    • Essa condição existe para que sempre haja uma única source of truth
  • Contribuições podem ser feitas em qualquer repositório
  • Releases também podem ser criadas a partir de qualquer repositório
  • Quando uma mudança ocorre em um repositório não autoritativo, o Copybara pode transformá-la e movê-la para o local apropriado no repositório autoritativo
    • Um exemplo é uma mudança feita por um contributor em um repositório public
    • Conflitos de merge são tratados da mesma forma que mudanças antigas dentro do repositório autoritativo

Exemplos de uso

  • Exemplos de uso do Copybara incluem
    • Levar parte do código de um repositório confidential para um repositório public
    • Trazer código de um repositório public para um repositório confidential
    • Trazer mudanças de um repositório non-authoritative para um repositório authoritative
  • A configuração de exemplo define origin e destination com core.workflow
    • O origin usa git.github_origin com o master de https://github.com/google/copybara.git
    • O destination usa git.destination com file:///tmp/foo
    • destination_files mira third_party/copybara/** e exclui README_INTERNAL.txt
    • core.replace e core.move realizam a substituição de caminho de arquivos BUILD e a movimentação de diretórios
  • O exemplo de execução consiste em criar um repositório Git bare e depois executar copybara copy.bara.sky

Forma de armazenamento de estado e suporte a repositórios

  • Uma das principais características do Copybara é sua arquitetura stateless
  • Mais precisamente, o estado é armazenado no repositório de destino
    • O local de armazenamento são os labels nas mensagens de commit
  • Com essa abordagem, vários usuários ou serviços podem obter o mesmo resultado usando a mesma combinação de configuração e repositórios
  • O tipo de repositório atualmente suportado é Git
  • A funcionalidade de leitura a partir de repositórios Mercurial é possível, mas ainda é experimental
  • Por meio de uma arquitetura extensível, é possível adicionar origins e destinations bespoke para praticamente qualquer caso de uso
  • O suporte oficial a outros tipos de repositório será adicionado no futuro

Instalação e build

  • A forma mais fácil de começar é usar uma snapshot release semanal com binários pré-compilados
  • Para usar uma versão ainda não lançada, é necessário fazer o build a partir do HEAD
    • É necessário instalar o JDK 11
    • É necessário instalar o Bazel
    • Clonar o código-fonte com git clone https://github.com/google/copybara.git
    • Fazer o build com bazel build //java/com/google/copybara
    • O uberjar executável é gerado com bazel build //java/com/google/copybara:copybara_deploy.jar
    • Os testes podem ser executados com bazel test //...
  • Alguns testes exigem a instalação de ferramentas subjacentes como Mercurial e Quilt
    • Se o Pull Request não estiver relacionado a esses módulos, esses testes podem ser ignorados
    • O CI executa todos os testes
  • No Arch Linux, é possível usar o pacote aur/copybara-git

Uso do Copybara pré-compilado no Bazel

  • A snapshot release semanal pode ser usada no Bazel
  • Como o Copybara é fornecido com class file version 65.0, ele deve ser executado em Java Runtime 21 ou superior
    • É necessário adicionar run --java_runtime_version=remotejdk_21 ao .bazelrc
  • Baixe o artefato da release com http_jar
    • Em WORKSPACE, use load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar")
    • Em MODULE.bazel, use http_jar = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar")
  • Em WORKSPACE ou MODULE.bazel, preencha o campo [version] para especificar copybara_deploy.jar
  • No arquivo BUILD, declare um java_binary usando com.google.copybara.Main como main class
  • Um exemplo de execução é bazel run //tools:copybara -- migrate copy.bara.sky

Build a partir do código-fonte como repositório Bazel externo

  • Um macro de conveniência para as dependências do Copybara é fornecido
  • Adicione http_archive ao WORKSPACE e preencha os valores {{ sha256sum }} e {{ commit }}
  • Depois, carregue e chame os seguintes macros
    • copybara_repositories()
    • copybara_maven_repositories()
    • copybara_go_repositories()
  • Dentro do workspace, é possível fazer build e executar com bazel run @com_github_google_copybara//java/com/google/copybara -- <args...>

Uso com Docker

  • Fazer build e executar o Copybara com Docker é atualmente experimental
  • O build é feito com docker build --rm -t copybara .
  • A execução é feita a partir da raiz do código de destino no formato docker run -it -v "$(pwd)":/usr/src/app copybara help
  • É possível usar variáveis de ambiente em vez de argumentos de execução do contêiner
    • COPYBARA_SUBCOMMAND=migrate: altera o comando a ser executado; o padrão é migrate
    • COPYBARA_CONFIG=copy.bara.sky: especifica o caminho do arquivo de configuração; o padrão é copy.bara.sky na raiz
    • COPYBARA_WORKFLOW=default: especifica o workflow a executar; o padrão é default
    • COPYBARA_SOURCEREF='': especifica o sourceref; sem padrão
    • COPYBARA_OPTIONS='': especifica opções do Copybara; sem padrão
  • Configurações do Git e credenciais SSH podem ser compartilhadas com o contêiner Docker
    • Um exemplo é montar ~/.gitconfig, ~/.ssh e SSH_AUTH_SOCK no contêiner

Documentação e contato

1 comentários

 
GN⁺ 4 시간 전
Opiniões no Hacker News
  • Achei engraçado este post aparecer logo depois de eu ter aberto como open source um patch com suporte a Perforce que fiz para usar em um estúdio de desenvolvimento de jogos
    Considerando que o principal uso do Copybara é distribuir código interno do Google, e que esse código fica no Piper, que tem relação com o Perforce, foi bem surpreendente não haver suporte a Perforce e haver, de forma significativa, apenas suporte a Git
    Antes de criar o PR, olhei o histórico do Git e vi muitas marcações de Gerrit Change-ID, então também fiquei preocupado que houvesse em algum lugar um sistema de code review Gerrit ao qual eu não tenho acesso e que meu PR talvez não fosse upstreamado
    Também é uma pena não haver Gerrit/Rietveld para Perforce, mas não dá para querer tudo
    https://github.com/google/copybara/pull/347

    • Um dos motivos para o Gerrit/Rietveld não ter suporte a Perforce é que o Google não usa essas ferramentas para mudanças de código armazenadas no Piper. Em vez disso, usa o Critique
      https://abseil.io/resources/swe-book/html/ch19.html
      https://read.engineerscodex.com/p/how-google-takes-the-pain-...
      Ainda não encontrei uma ferramenta externa tão boa quanto o Critique, e acho surpreendente que as ferramentas fracas de revisão de PR do GitHub sejam aceitas pela maioria. Se alguém souber de uma ferramenta de nível parecido, gostaria de saber
      Quando saí do Google, alguns anos atrás, procurei com bastante cuidado, e https://codeapprove.com/ foi o mais próximo que encontrei, mas ainda faltava muita coisa
    • O Piper não é um fork do Perforce. Ele é compatível com a API do Perforce, mas é uma implementação completamente diferente
    • Esse repositório aceita PRs. Só que eles fazem o merge internamente e depois exportam de volta para fora
      Projetos open source como gVisor ou Bazel, que vivem no monorepo interno, também têm pequenas diferenças, mas em geral operam de modo parecido
  • Outra ferramenta interessante nessa área é que o Rust usa uma ferramenta chamada Josh para sincronização de commits
    https://josh-project.dev
    Também há um post no blog do Rust
    https://blog.rust-lang.org/inside-rust/2026/06/04/how-josh-h...
    A Meta tinha antigamente uma ferramenta open source chamada fbshipit, mas, segundo o repositório público, ela não é mais usada
    https://github.com/facebookarchive/fbshipit
    Será que existem outras ferramentas nesse campo?

  • Isso também é conveniente quando vários repositórios querem compartilhar um pouco de código, mas não vale o trabalho de separar em uma biblioteca, criar referências, publicar releases de versão e atualizar os repositórios dependentes?
    Por exemplo, fico curioso se daria para usar apenas sincronizando uma pasta com modelos de domínio comuns de um repositório principal para outros repositórios
    Seria um uso mais próximo da filosofia em Go de que “é melhor copiar um pouco do que ter um monte de dependências”

    • É usado principalmente para sincronizar projetos open source externos com o monorepo interno. A política exige importar código-fonte em vez de artefatos de build, embora seja possível obter exceções
      Alguns projetos são desenvolvidos no monorepo e exportados para fora com o Copybara
      Nossa equipe também o usa internamente para versionar conjuntos de regras Starlark
    • É uma ferramenta para quando você tem um monorepo interno e quer abrir parte dele como open source para o mundo. Ainda assim, o código precisa continuar dentro do monorepo, então essa vira a solução
      Ter um repositório público como dependência de um repositório privado interno é bem problemático do ponto de vista de desenvolvimento. Quando essas dependências começam a crescer em forma de árvore, vira uma dor de cabeça de verdade
    • Dá para fazer esse tipo de coisa com o Copybara, mas, se usado assim, é provável que seja irritante e tedioso. Pode acabar sendo mais trabalhoso do que separar uma biblioteca ou empurrar alguns arquivos para um repositório separado
  • Uso há bastante tempo, principalmente quando uma ferramenta criada dentro de um projeto grande cresceu o suficiente para merecer um lançamento independente
    É poderoso o bastante para fazer toda a distribuição bidirecional, exportando o código e trazendo de volta, mas isso dá trabalho demais, então prefiro evitar
    Em geral, uso para uma exportação simples e pontual: separo uma pasta do repositório original, mas preservo o histórico. Depois, o desenvolvimento passa para o novo repositório
    Fico satisfeito porque o Git blame funciona mesmo que a nova estrutura do projeto seja completamente diferente

    • Esse padrão unidirecional é, na prática, o modo como ele também é usado internamente no Google. Faz a sincronização para fora, do monorepo para o GitHub
      O bidirecional fica bagunçado, porque transformações como remapeamento de caminhos, exclusão de arquivos e remoção de cabeçalhos são fáceis em uma direção, mas nem sempre dá para inverter de forma limpa
      Quando os dois lados divergem, o rastreamento de linha de base do Copybara começa a produzir resultados confusos. Isso porque commits semanticamente iguais geram SHAs diferentes depois da transformação
      Um ponto que vale saber é que a “preservação” do histórico não é uma migração real, mas sim um cherry-pick de commits reescritos. O conteúdo dos arquivos e as informações de autoria são transferidos, então o Git blame funciona, mas os SHAs são novos
      O Copybara coloca o SHA original no trailer de mensagem de commit GitOrigin-RevId, o que é útil quando depois é preciso comparar commits entre repositórios
  • Mais de 52 anos de progresso :-)
    Julho de 2026: o copybara do Google permite mover código entre dois repositórios de produção
    Março de 1974: o IBM COPY permitia mover código entre dois conjuntos de dados particionados de produção. OS/MVT e OS/VS2 TSO Data Utilities COPY, FORMAT, LIST, MERGE User's Guide and Reference https://www.computinghistory.org.uk/downloads/8987

  • Na Dagster, usamos o Copybara para configurar um modelo hub-and-spoke em que o repositório público pudesse viver dentro de um monorepo interno maior. Funcionou, mas exigiu bastante tratamento indireto
    https://dagster.io/blog/monorepos-the-hub-and-spoke-model-an...

  • Se você só precisa sincronizar repositórios, sem exclusões nem transformações, acho que eu não usaria. Pode ser adequado no momento, mas pode virar um problema se for arquivado ou descontinuado, como o kaniko e muitos produtos/ferramentas do Google
    O GitLab tem uma forma bem simples de fazer espelhamento do GitLab para o GitHub ou outros provedores/servidores Git

    • Acho realmente improvável que o Copybara seja descontinuado. Pelo que sei, é uma ferramenta central para a forma como o google3 e grandes projetos open source são mantidos e vendorizados
    • Isso, o Copybara é mais uma ferramenta para fazer transformações em uma ou nas duas direções
      Por exemplo, transformar bzl externo em um formato compatível com BUILD do Blaze interno, ou converter entre imports externos e imports no estilo interno de third_party
      Para um espelho puro, o Copybara é pesado demais
  • Legal. Eu também criei algo parecido há uns 5 anos, com repositórios Git aninhados e scripts, para lidar com repositórios privados e públicos juntos
    Meu script de shell, obviamente, não era em escala Google

    • Comigo foi parecido. No começo achei que seria um wrapper de git subtree, mas pelo visto ele faz muito mais coisas
      Por exemplo, também tem um recurso para mudar o e-mail do autor do commit durante a sincronização