Depois de dividir nosso código em bits reutilizáveis, como testamos e implantamos?

9

Começamos com um desenvolvedor e um repositório svn contendo todo o nosso código:

^/foo/trunk/module-a
^/foo/trunk/module-b
^/foo/trunk/module-b/submodule-b1
^/foo/trunk/website1

(na época, isso foi uma grande melhoria). Depois disso, tivemos a chance de crescer um pouco e começamos a ter problemas com dependências circulares, testes lentos e dificuldades gerais em reutilizar o código (uma vez que, por exemplo, o conjunto de recursos do website1 havia entrado no módulo-a genérico).

Querendo modularizar a base de código e esperando que passemos para o git em breve (e depois de ler em algum lugar que o git não gosta de mega-repos svn), passamos a uma estrutura muito mais granular:

^/module-a/trunk/
^/module-b/trunk/
^/module-b/trunk/sumbmodule-b1
^/earlier-sub-sub-sub-module-c/trunk
etc. (about 120 such modules)

Isso foi conceitualmente ótimo. Código mais modular, suítes de teste muito mais rápidas, mais fáceis de documentar, etc. Fornecemos código-fonte para alguns de nossos componentes mais genéricos e tornamos todos os módulos instaláveis ​​(usando pip install -e .para instalá-los no developmentvirtualenv).

Criamos um ^/srv/trunkrepositório contendo a estrutura de pastas do ambiente de tempo de execução, ou seja. ^/srv/trunk/libpara os módulos, /srv/trunk/srcpara os restos de ^/foo/trunk, ^/srv/trunk/wwwpara sites etc.

E finalmente (usando uma ideia do forforce, com a qual trabalhei há muito tempo [ https://www.perforce.com/perforce/r12.1/manuals/cmdref/client.html] ), criamos um "vcs- buscar "arquivo de texto que listou todos os repositórios relevantes e onde eles devem ser verificados no ambiente dev, e um comando correspondente para fazer isso. Por exemplo, uma linha vcs-fetc:

svn srv/lib/module-a ^/module-a/trunk

causaria (primeira vez)

cd /srv/lib && svn co ^/module-a/trunk module-a

ou (depois)

cd /srv/lib/module-a && svn up

e da mesma forma para repositórios do github (pacotes de fornecedores próprios e alterados / inalterados).

Usamos o mesmo processo vcs-fetch para criar o ambiente de produção, mas estamos descobrindo rapidamente que não temos como saber qual versão costumava ser executada no prod depois de fazer uma busca vcs.

Com o mega-repo, podíamos apenas anotar o número da revisão antes de atualizar o prod do trunk, e voltar era simples svn -r nnn up .. Com o código no svn e no git (e um módulo em hg) - e ~ 120 repositórios, não é óbvio como fazer isso.

Eu li http://12factor.net/ hoje, e o primeiro fator é "Uma base de código", então também estou me perguntando se estou fora do caminho certo aqui.

Uma idéia que tive foi criar um script de implantação que criaria "deploy" instalável em pip-wheel e os agruparia em um requirements.txtarquivo. Uma implantação envolveria a criação de um novo virtualenv, a instalação pelo pip do arquivo requirements.txt, listando as rodas de implantação e a troca do virtualenv ativo. A reversão para o anterior envolveria apenas a troca do virtualenv de volta (mas, a menos que desejássemos manter os virtualenvs por toda a eternidade, não nos permitiríamos voltar a nenhum ponto no tempo - na minha experiência, que nunca foi necessária).

Neste ponto, estou me perguntando se estou caminhando na direção errada ou se simplesmente não andei o suficiente no caminho certo ..? (tudo o que estou lendo continua falando sobre "seu aplicativo", e não sei como isso se traduz na execução de 14 sites da mesma base de código ...)

thebjorn
fonte
Posso assumir que os componentes individuais agora são desenvolvidos por diferentes equipes com ciclos de desenvolvimento divergentes? Nesse caso, é inevitável desmembrar o repositório. Mesmo com o git, você colocaria tags de versão sincronizadas para configurações principais e estáveis. Dê uma olhada na ferramenta de recompra do Google. Tentar combinar versões de desenvolvimento por metadados integrados é praticamente inútil. Vincular o aplicativo por meio do pip também é perfeitamente legítimo.
Ext3h
Se você incluir estimativas KLOC (1000 linhas de código) e medidas de bytes do código, podemos ter uma idéia fácil do tamanho, por exemplo "2000 linhas de código. Código fonte de 50 kilobytes". ou "40 KLOC, 2 GB XML". . Parece que você precisa apenas migrar para o git e o git tem funções de importação. Você pode começar lendo o livro git .
26616 Niklas #
11
@ Programmer400 a base de código é: .py 670 kloc, .js: 135kloc, .less: 25kloc, .html: 130kloc. Tão grande, mas não enorme. Pelo que li, o git realmente não gosta de repositórios desse tamanho, então imagino que teremos que dividir em repositórios menores antes de mudar para o git ..?
thebjorn

Respostas:

2

Parece que você está perdendo ramificações (ou melhor, 'tags' ou 'release' branches).

Em vez de usar o revnum do SVN como referência para determinar qual versão você está instalando, você deve criar uma ramificação nessa revisão lançada. Você então implanta o nome da ramificação.

Isso facilita a ramificação, mesmo que não haja alterações, de modo que todos os módulos mantêm o mesmo número de versão; no entanto, seus pacotes OSS podem não gostar de ser ramificados sem alterações, portanto, a próxima melhor coisa é manter um script de dependências - para a versão 5 do seu produto requer o módulo OSS X v2 e assim por diante.

Você alteraria seu script para parar de se referir às versões e, em vez disso, trabalharia com os nomes das filiais (embora elas possam ser qualquer coisa, é melhor decidir sobre uma convenção de nomenclatura fixa, por exemplo, Release_1_2_3)

Outra dica é manter um arquivo com cada módulo que descreve a versão atual; você pode gerá-los automaticamente, se necessário, e talvez também inclua um log de alterações completo, mas significa que qualquer um pode ver qual versão é implantada apenas olhando.

gbjbaanb
fonte
1

Eu acho que você já tem muitas idéias boas, usei a maioria delas em vários projetos ao longo dos anos, e sua principal preocupação parece ser a incapacidade de dizer qual versão de todos os módulos foi incluída em um determinado pacote se você dividir eles.

Sou a favor de dividi-los, em algum nível de granularidade, especialmente se você tiver várias equipes e ciclos de lançamento variados, como o @ Ext3h menciona.

Como não tenho certeza de quão isolados são seus módulos ou de quão detalhados você deseja que seu versionamento seja, sugiro algumas opções.


Use submódulos git. Com os submódulos, você pode armazenar cada módulo em um repositório git separado, semelhante à sua configuração svn e também ao que você está pensando. Em seguida, você vincula esses módulos ao projeto raiz que conterá uma referência ao commit relevante de cada submódulo, para cada um de seus próprios commit.

OMI é uma configuração teoricamente agradável e razoavelmente simples. As principais desvantagens são que o fluxo de trabalho dos submódulos é um pouco estranho, no entanto, você parece ter resolvido essas coisas muito bem com os scripts antes, portanto pode não ser um problema real.

A outra ressalva é que as referências de submissão do submódulo serão apenas um SHA1, nunca há detalhes legíveis por humanos sobre qual ramificação você é, e você pode acabar precisando fazer check-out manualmente da ramificação correta quando quiser trabalhar diretamente no submódulo.

No entanto, eu não usei esse padrão extensivamente, então não sei quanto de um problema pode ser para um projeto grande como o seu.


Outra alternativa é usar algum tipo de gerenciador de dependências. Isso requer que cada módulo ou conjunto de módulos possa ser versionado, empacotado e publicado individualmente, e que você tenha um sistema que possa reunir esses pacotes da maneira que desejar quando desejar.

Você já está sugerindo o pip e o que parece estar faltando em sua sugestão é armazenar os requisitos.txt resultantes junto com a compilação ou no repositório raiz do projeto, para que você possa recriar o virtualenv mais tarde, em vez de precisar salvar no disco.

Existem outros sistemas também; Configurei um projeto bastante grande usando uma versão ligeiramente personalizada do Apache Ivy como ferramenta para empacotar e publicar cada módulo, além de reuni-los para o projeto final. Ivy também armazena um manifesto listando todas as versões de todos os módulos aos quais você está referenciando, se precisar recriar a configuração posteriormente.

axl
fonte