Estrutura do Repositório Mercurial com comunicações corporativas pesadas, gerenciamento de configuração e requisitos de teste

15

Eu sou outro usuário do Subversion lutando para me reeducar no Tao do controle de versão distribuída.

Ao usar o Subversion, eu era um grande fã da abordagem do projeto menor e, com a maioria dos meus antigos empregadores, nós estruturávamos nossas ramificações de repositório; tags & tronco da seguinte forma:

branches-+
         +-personal-+
         |          +-alice-+
         |          |       +-shinyNewFeature
         |          |       +-AUTOMATED-+
         |          |                   +-shinyNewFeature
         |          +-bob-+
         |                +-AUTOMATED-+
         |                            +-bespokeCustomerProject
         +-project-+
                   +-shinyNewFeature
                   +-fixStinkyBug
tags-+
     +-m20110401_releaseCandidate_0_1
     +-m20110505_release_0_1
     +-m20110602_milestone
trunk

Dentro da árvore de fontes propriamente dita, usaríamos (algo como) a seguinte estrutura:

  (src)-+
        +-developmentAutomation-+
        |                       +-testAutomation
        |                       +-deploymentAutomation
        |                       +-docGeneration
        |                       +-staticAnalysis
        |                       +-systemTest
        |                       +-performanceMeasurement
        |                       +-configurationManagement
        |                       +-utilities
        +-libraries-+
        |           +-log-+
        |           |     +-build
        |           |     +-doc
        |           |     +-test
        |           +-statistics-+
        |           |            +-build
        |           |            +-doc
        |           |            +-test
        |           +-charting-+
        |           |          +-build
        |           |          +-doc
        |           |          +-test
        |           +-distributedComputing-+
        |           |                      +-build
        |           |                      +-doc
        |           |                      +-test
        |           +-widgets-+
        |                     +-build
        |                     +-doc
        |                     +-test
        +-productLines-+
        |              +-flagshipProduct-+
        |              |                 +-coolFeature
        |              |                 +-anotherCoolFeature
        |              |                 +-build
        |              |                 +-doc
        |              |                 +-test
        |              +-coolNewProduct
        +-project-+
                  +-bigImportantCustomer-+
                  |                      +-bespokeProjectOne
                  |                      +-bespokeProjectTwo
                  +-anotherImportantCustomer-+
                                             +-anotherBespokeProject

A ideia era (e ainda é) usar a estrutura do repositório para ajudar a estruturar a comunicação entre a equipe de engenharia; a parte voltada para o cliente do negócio e várias outras partes interessadas & especialistas de domínio.

A saber: documentos de origem que estão em um dos diretórios de "projeto" são usados (e ganham dinheiro) apenas uma vez. Os documentos que estão em um dos diretórios "productLines" ganham dinheiro quantas vezes um produto dessa determinada linha for vendido. Os documentos que ficam em um dos diretórios de "bibliotecas" ganham dinheiro tantas vezes quantas os produtos que os usam vendidos.

Torna explícita a noção de amortização de custos e ajuda a criar suporte para a reutilização de documentos de origem em toda a empresa.

Isso também significa que existe uma estrutura comum sobre a qual nossas ferramentas de automação de construção podem operar. (Nossos scripts de construção percorrem a árvore de fontes procurando por pastas "compilar", dentro das quais eles localizam arquivos de configuração especificando como cada componente deve ser construído; um processo similar acontece para geração e teste de documentação).

Significativamente, os produtos nos quais trabalho normalmente levam muito tempo para executar a avaliação de desempenho & testes de caracterização; de 20 a 200 horas; gerar algo entre vários GB para vários TB de resultados de teste processados / dados intermediários (que devem ser armazenados e vinculados a uma configuração de sistema específica para que a melhoria de desempenho ao longo do tempo possa ser medida). Essa questão torna o gerenciamento de configuração uma consideração importante e também impõe algum requisito de centralização, pois normalmente os recursos computacionais necessários para executar a medição de desempenho e os testes de caracterização são limitados; (um pequeno grupo de 64-128 núcleos).

Como uma nota final; o sistema de integração contínua sabe que precisa disparar uma construção; análise estática; teste de fumaça & teste de unidade executado a cada vez que o tronco é modificado, sempre que qualquer ramificação "tag" é modificada e sempre que qualquer ramificação "AUTOMATED" é modificada. Desta forma, os desenvolvedores individuais podem usar o sistema de CI com suas ramificações pessoais, um recurso importante, IMHO.

Agora, aqui está a minha pergunta: Como posso replicar todos os itens acima (e melhorá-lo, se possível), com o Mercurial.

- editar:

Minha linha de pensamento atual é usar um Repositório do Subversion central, para definir a estrutura geral, mas permitir o uso de hg como um cliente para que os desenvolvedores possam ter repositórios disponíveis localmente.

    
por William Payne 04.01.2012 / 18:22
fonte

2 respostas

9

A resposta de Spoike é excelente, mas há algumas coisas que eu acho que valeria a pena acrescentar, que também são grande para comentários.

Organização de filiais

Com o Mercurial, você pode ignorar todo o seu primeiro organograma. Como diz Spoke, cada repositório tem seu próprio conjunto de tags, branches (named e anonymous) e pode ser organizado de acordo com a necessidade do negócio.

Se bespokeProjectTwo precisar de uma versão especial da biblioteca charting , você ramificará charting , adicionará as novas instalações e as usará em bespokeProjectTwo . As novas instalações (e seus bugs) não seriam usadas por outros projetos que referenciariam a biblioteca padrão charting . Se a biblioteca principal charting tivesse erros corrigidos, você poderia mesclar essas mudanças na ramificação. Se outros projetos também precisassem desses recursos, você poderia obter esses projetos para usar a ramificação especial , ou mesclar a ramificação na linha principal e fechar a ramificação.

Além disso, não há nada que o impeça de ter uma política para estruturar nomes de ramificações para fornecer recursos específicos, como suas ramificações AUTOMATION.

Organização de diretório

Não há motivo para você não poder manter seu diretório de origem exatamente como é com o Mercurial. A única diferença é que, enquanto com o Subversion você tem um único repositório (src) monolítico, com o Mercurial é melhor dividir em repositórios que são logicamente agrupados. De sua estrutura de árvore de origem, eu provavelmente extrairia cada um dos seguintes itens como repositórios individuais:

src-+
      +-(developmentAutomation)
      +-libraries-+
      |           +-(log)
      |           +-(statistics)
      |           +-(charting)
      |           +-(distributedComputing)
      |           +-(widgets)
      +-productLines-+
      |              +-(flagshipProduct)
      |              +-(coolNewProduct)
      +-project-+
                +-bigImportantCustomer-+
                |                      +-(bespokeProjectOne)
                |                      +-(bespokeProjectTwo)
                +-anotherImportantCustomer-+
                                           +-(anotherBespokeProject)

Isso permite que qualquer produto ou projeto sob medida use qualquer combinação de bibliotecas, em qualquer revisão. Dê uma olhada nos sub-repositórios do mercurial para obter uma maneira fácil de gerenciar quais bibliotecas são usadas para qualquer versão de um produto ou projeto.

Fluxo de trabalho

Uma alternativa ao fluxo de trabalho sugerido por Spoike (o desenvolvedor puxa de um repositório abençoado, trabalha localmente, emite um pedido de pull e, finalmente, o integrador obtém essas alterações e as funde) seria usar o sistema de integração contínua como intermediário.

Como antes, o desenvolvedor puxa de repositório abençoado e trabalha localmente, mas quando feito, eles puxam o repo abençoado novamente e se fundem antes de empurrar para um repositório não abençoado. Quaisquer alterações no repositório não-abençoado são revisadas (manual ou automaticamente) e movidas para o repositório abençoado somente se forem aprovadas.

Isso significa que o integrador só aceita ou rejeita uma alteração, não a mesclagem. Na minha experiência, é quase sempre melhor para o desenvolvedor que escreveu o código realizar a mesclagem do que para outra pessoa fazer isso.

Como sugerido no livro do mercurial, os ganchos podem ser usados para automatizar este procedimento:

When someone pushes a changeset to the server that everyone pulls from, the server will test the changeset before it accepts it as permanent, and reject it if it fails to pass the test suite. If people only pull changes from this filtering server, it will serve to ensure that all changes that people pull have been automatically vetted.

Outras questões

O problema dos grandes conjuntos de dados de teste também pode ser resolvido colocando os dados do teste em um <-href="http://mercurial.selenic.com/wiki/Subrepository"> sub-repositório comercial . Isso evitará que o repositório de código fique inchado com dados de teste, mantendo os dados de teste sob controle de revisão.

    
por 05.01.2012 / 12:55
fonte
8

Ok, tentando responder isso simplesmente.

O que você precisa saber

A primeira coisa que você precisa saber: o Mercurial é o controle de versão distribuído e tem algumas propriedades que você deve conhecer abaixo.

  • A origem vem de um repositório, onde esse repositório pode ser clonado. Todos os repositórios clonados podem compartilhar código entre si por meio de sincronização (com comandos pull e push, que podem ter acesso restrito).
  • Todo usuário que possui uma cópia do código possui um clone do repositório. Se eles querem ramificar, eles podem fazer isso em seu clone local. Isso significa que você não precisa organizar como cada usuário deve se ramificar. Eles podem fazer isso por si mesmos.
  • Tags são criadas no mercurial por um commit (o que é o mesmo que hard tags no git). Isso significa que você não precisa de um diretório dentro de sua estrutura de repositório para tags.
  • O modelo usual com o qual as pessoas trabalham no DVCS (que é empregado no github e no bitbucket) é fazê-lo de forma semi-centralizada.

    Cada usuário possui um repositório público (em algum compartilhamento ou em um servidor seguro) e um repositório privado (em suas próprias estações de trabalho). Ambos são clones do repositório "abençoado" de um integrador. Sempre que se sentem prontos para publicar seu código, podem enviar as alterações para o repositório público. Um integrador pode então escolher quais usuários colocarão o código no repositório "abençoado".

    Se o integrador não puder mesclar o código de algum usuário com facilidade, as alterações serão rejeitadas e cabe a esse usuário específico atualizar seu repositório e corrigir a mesclagem. Geralmente, não é tão difícil se você mescla com frequência (já que é menos código que precisa ser mesclado) e geralmente esse usuário deve saber o que deu errado com a mesclagem.

Configuração de repositórios por projeto

Portanto, a configuração usual é que, para cada projeto, há o seguinte:

  • Um repositório público somente para leitura pelo qual o integrador é responsável. É "abençoado".

    Ou seja. todos os usuários podem obter / buscar conteúdo, mas não têm acesso para enviá-lo.

  • Cada usuário pode ter seu próprio clone público do repositório.

    Configuração mais fácil como colocar em um drive de compartilhamento (embora você possa considerar hospedagem como bitbucket). O integrador recebe solicitações pull dos usuários e tenta extrair o novo código desses repositórios. Quando as mesclagens são feitas sem problemas, elas são colocadas no repositório somente leitura. Caso contrário, os usuários são solicitados a corrigir os conflitos de mesclagem que surgem atualizando e mesclando-os localmente.

  • Cada usuário pode ter seus próprios clones privados do repositório.

    A boa prática é extrair do clone público deles, mas não importa se eles saem do público ou do integrador. Todos os commits são unicamente identificáveis, de modo que os commits de fusão que você esqueceu de buscar no público são relativamente fáceis de consertar (empurrando as mudanças do privado para o público, ele também recebe automaticamente as alterações do integrador).

Organização do código fonte

Como em como organizar a fonte do projeto em si é algo que você precisa pensar. Se um artefato precisar ser controlado por fonte, coloque-o no controle de origem. Pessoalmente, não gosto da idéia de fazer check-in de artefatos que são feitos pela construção ou pelo tempo de execução (devido ao alto risco de conflitos de mesclagem nesses tipos de artefatos), como binários ou arquivos de log.

Você também pode verificar a configuração, desde que facilite o desenvolvimento dos desenvolvedores e não atrapalhe a configuração de lançamentos ou ambiente de produção / produção (como configurações de aplicativos / servidores web). Isso leva à noção de que, se a configuração prejudicar seriamente o desenvolvimento dos desenvolvedores dentro de cinco minutos após o check-out do código, ele precisará ser refatorado. Outro requisito é que deve ser difícil para os desenvolvedores bagunçar o ambiente de lançamento ou ao vivo / produção.

Você menciona que possui dados de teste que precisam ser vinculados a alguma versão do código. Agora, isso é um pouco mais complicado porque os sistemas DVCS, como o Mercurial e o Git, tendem a ficar lentos quando você registra dados que são ENORMES. Na minha experiência, fica realmente insuportável após 5 GB de arquivos binários (sua milhagem pode variar, então você deve testar como isso funciona para você). No entanto, eu recomendo que você coloque os dados gerados em seu próprio repositório e faça com que seu sistema de teste os marque apropriadamente ao fazer a verificação (e / ou crie arquivos de texto para os mesmos propósitos de metadados).

Espero que tudo isso faça sentido. Por favor, comente abaixo se eu perdi algum detalhe ou se algo precisa de mais explicações e vou tentar editar.

    
por 04.01.2012 / 22:14
fonte