Ciclo de lançamento da empresa ímpar: Go Distributed Source Control?


13

Desculpe por este longo post, mas acho que vale a pena.

Acabei de começar com uma pequena loja .NET que funciona de maneira um pouco diferente de outros lugares em que trabalhei. Diferentemente de qualquer uma das minhas posições anteriores, o software escrito aqui é direcionado a vários clientes e nem todo cliente obtém a versão mais recente do software ao mesmo tempo. Como tal, não há "versão de produção atual". Quando um cliente recebe uma atualização, ele também recebe todos os recursos adicionados ao software desde a última atualização, o que pode ser há muito tempo. O software é altamente configurável e os recursos podem ser ativados e desativados: o chamado "recurso alterna". Os ciclos de lançamento são muito restritos aqui, na verdade eles não estão dentro do cronograma: quando um recurso é concluído, o software é implantado no cliente relevante.

A equipe apenas no ano passado mudou do Visual Source Safe para o Team Foundation Server. O problema é que eles ainda usam o TFS como se fosse VSS e impõem bloqueios do Checkout em uma única ramificação de código. Sempre que uma correção de bug é lançada em campo (mesmo para um único cliente), eles simplesmente criam o que estiver no TFS, testam se o bug foi corrigido e implantam no cliente! (Eu mesmo, vindo de uma experiência em software farmacêutico e de dispositivos médicos, é inacreditável!). O resultado é que o código de desenvolvimento meio cozido é colocado em produção sem ser testado. Os bugs estão sempre entrando nas versões de lançamento, mas geralmente um cliente que acaba de obter uma versão não os vê se não usar o recurso em que está o erro. O diretor sabe que isso é um problema, pois a empresa está começando a crescer. de repente, com alguns grandes clientes chegando e outros mais pequenos.

Foi-me pedido que olhasse as opções de controle de origem para eliminar a implantação de códigos com erros ou inacabados, mas para não sacrificar a natureza um tanto assíncrona dos lançamentos das equipes. Eu usei VSS, TFS, SVN e Bazaar em minha carreira, mas o TFS é onde a maior parte da minha experiência foi.

Anteriormente, a maioria das equipes com as quais trabalhei usa uma solução de duas ou três ramificações do Dev-Test-Prod, onde por um mês os desenvolvedores trabalham diretamente no Dev e, em seguida, as alterações são mescladas no Test then Prod, ou promovidas "quando estiver pronto" em vez de no um ciclo fixo. Construções automatizadas foram usadas, usando o Cruise Control ou o Team Build. No meu trabalho anterior, o Bazaar era usado em cima do SVN: os desenvolvedores trabalhavam em suas próprias ramificações de recursos pequenos e depois enviaram suas alterações para o SVN (vinculado ao TeamCity). Isso foi bom, pois era fácil isolar as mudanças e compartilhá-las com os ramos de outras pessoas.

Com os dois modelos, havia um ramo central de desenvolvimento e prod (e às vezes teste), através do qual o código era enviado (e os rótulos eram usados ​​para marcar as compilações no prod a partir do qual os lançamentos eram feitos ... e estes eram transformados em ramos para correções de erros) para lançamentos e mesclados de volta ao dev). No entanto, isso não se adequa à maneira de trabalhar aqui: não há ordem para quando vários recursos serão lançados, eles serão pressionados quando estiverem completos.

Com esse requisito, a abordagem de "integração contínua", como eu a vejo, se decompõe. Para obter um novo recurso com integração contínua, ele deve ser enviado via dev-test-prod e isso capturará qualquer trabalho inacabado no dev.

Estou pensando que, para superar isso, devemos reduzir um modelo fortemente ramificado de recursos sem ramificações de dev-test-prod, mas a fonte deve existir como uma série de ramificações de características que, quando o trabalho de desenvolvimento é concluído, são bloqueadas, testadas, fixas, bloqueadas , testado e liberado. Outras ramificações de recursos podem obter alterações de outras ramificações quando precisam / desejam, portanto, eventualmente, todas as alterações são absorvidas pelos demais usuários. Isso se encaixa muito bem em um modelo de Bazaar puro do que eu experimentei no meu último emprego.

Por mais flexível que isso pareça, parece estranho não ter um tronco de desenvolvimento ou ramo de produção em algum lugar, e estou preocupado com os ramos que não precisam se reintegrar ou com pequenas alterações tardias feitas que nunca são atraídas para outros ramos e desenvolvedores reclamando sobre mesclar desastres ...

Quais são os pensamentos das pessoas sobre isso?

Uma segunda pergunta final: Estou um pouco confuso sobre a definição exata de controle de fonte distribuído: algumas pessoas parecem sugerir que se trata apenas de não ter um repositório central como o TFS ou o SVN, outros dizem que se trata de ser desconectado (o SVN é 90% desconectado e o TFS possui um modo offline perfeitamente funcional) e outros dizem que é sobre a ramificação de recursos e a facilidade de mesclagem entre filiais sem relacionamento pai-filho (o TFS também possui mesclagem sem base!). Talvez esta seja uma segunda pergunta!


Respostas:


5

O que define um DVCS?

A distribuição no DVCS significa que todo clone de um repositório possui todas as informações necessárias para confirmar, atualizar, ramificar, mesclar ou procurar qualquer revisão nesse repositório, sem nunca tocar em um servidor . A única coisa em que você pode fazer offline svné editar os arquivos - você precisa de acesso ao servidor para quase todos os svncomandos, incluindo fazer algo tão simples quanto grepping an svn log, para que fique realmente perto de 0% a 90%!

Qualquer repositório central autorizado que você possa configurar em um fluxo de trabalho DVCS é apenas mais um clone , e o único momento em que você precisa interagir com ele é quando você baixa as atualizações de outras pessoas ou pressiona suas próprias alterações para que outras pessoas possam vê-las. , praticamente tudo o resto pode ser feito off-line.

Que modelo de ramificação é apropriado?

Eu estive na situação em que você está agora. Tais sistemas podem ser uma verdadeira dor, mas você precisa entender as razões pragmáticas em que elas se tornaram assim e perceber que elas não estão além da redenção . Muitas ferramentas foram desenvolvidas que podem ajudar a gerenciar esse tipo de complexidade .

Antes de tudo, faça o que fizer, não mostre às pessoas o modelo de ramificação git bem - sucedido , isso apenas as confundirá e as desativará. Em vez disso, desenvolva seu próprio modelo que reflete seu fluxo de trabalho existente , mas resolva os problemas com seu fluxo de trabalho existente .

Alguns recursos que você pode considerar incluem itens como sub-módulos git, que permitirão que diferentes releases do cliente especifiquem diferentes combinações de configuração do cliente, módulos de aplicativos e bibliotecas. Outra opção seria o uso de um sistema de gerenciamento de patches para aplicar filas de patches específicas de clientes / produtos.

Essas duas opções fornecerão muito mais flexibilidade, transparência e segurança do que o fluxo de trabalho atual e podem ser mais fáceis de usar do que uma estratégia ainda mais complexa de ramificação. Eu certamente gostaria de ter acesso a essas ferramentas quando estivesse na sua situação.

Para obter mais informações sobre essas opções, consulte minhas respostas à Strategy para usar o controle de versão em um sistema modular . Como usar o repositório do Subversion dentro do repositório Git? e Controle de origem / versão para aplicativo usado por várias empresas .

Em última análise, isso é realmente algo que você terá que desenvolver com o resto da equipe. Se você tem a visão de propor algo que funcione melhor do que o que você já tem e pode obter o apoio de seus colegas desenvolvedores, você terá muito mais facilidade com isso.

O mais importante é mostrar a seus colegas como o que você propõe facilitará a vida deles . Uma vez convencidos, você tem uma chance muito maior de fazer com que a gerência jogue fora seu investimento no TFS e comece a usar um modelo mais apropriado aos seus métodos de trabalho.


1
+1 para encontrar o git bem sucedido modelo que ramificação funciona para você
jcmeloni

1
+1 em "facilitar a vida deles". Este é o principal motivador.

5

Em primeiro lugar, o DVCS é um problema para os problemas que você tem - a ferramenta de controle de versão em uso não é a raiz dos problemas que precisam ser resolvidos. Pode ser que haja aspectos das soluções DVCS "melhores" que o TFS, mas não é o que precisa ser corrigido neste momento.

Você identificou que precisa de uma estrutura de ramificação viável que se adapte à sua organização - acho que ainda encontrará um tronco, quando um recurso é concluído, ele é mesclado de volta ao tronco e fechado. Existem algumas boas idéias sobre como você implementa dependências comuns também.

Você também precisa que a integração contínua funcione (não há razão para não ter uma construção automatizada para cada ramo ativo para garantir que você pode construir esse ramo e que ele passa nos testes relevantes). Fico desconfortável quando um commit (ou pelo menos um "push") não aciona uma compilação para mim.

E você precisa iniciar testes automatizados em todos os níveis, especialmente testes de unidade e testes de integração, para começar a reduzir as chances de novos bugs escaparem à natureza. Este último é enorme e algo com o qual ainda estou lutando, mas está claro que, uma vez que você saiba que pode construir coisas, isso terá mais valor.

Você precisa combinar isso para garantir que seus pacotes de implantação venham do servidor de compilação e que a implantação seja automatizada o máximo possível (você poderá passar do artefato do servidor de compilação para o código implementado ativo com o mínimo esforço e o mínimo de estresse).

Hmm, presumi que existe uma boa e bem ordenada configuração de rastreamento de problemas ... você também precisa disso e tenha certeza de que está sendo usada corretamente. Idealmente, você deseja que seus aplicativos ao vivo retornem erros para este sistema (ou para triagem) automaticamente.

Por fim, não tente resolver todos os seus problemas de uma só vez - construir e testar parece-me o lugar em que você deve se concentrar primeiro.


Há uma parte de mim que concorda que o DVCS também pode ser um problema: eu certamente concordo que a questão está no processo mais do que qualquer outra coisa. Eu acho que a integração contínua pode ser um trecho aqui e o teste de unidade simplesmente não vai acontecer, pois será visto como muito trabalho. De qualquer forma, a base de código não pode ser testada, pois é um sistema monolítico fortemente acoplado e tudo é baseado em tipos de conrete: sem interfaces.
MrLane

@ MrLane - Eu sei que vai ser difícil explicar isso para as pessoas, mas desde que comecei a desenvolver de forma TDD , estou cada vez mais convencido de que não tenho tempo para não escrever testes.
Mark Booth

1

A segunda pergunta é mais fácil e mais curta, então tentarei começar com ela

DVCS é um sistema em que nenhuma fonte "autorizada" de código (exceto "mediante acordo", quando usada) e a troca de dados P2P é possível sem camadas adicionais (definição pessoal e não canônica)

Sobre o tema, a primeira pergunta

Receio que a empresa tenha que reconstruir o fluxo de trabalho e repensar sobre o estilo para obter "código de alguma forma gerenciado e previsível". Não posso dizer sobre o TFS (exceto opinião e sentimento pessoal, que é um sistema fraco na parte do controle de versão / mesclagem sem fundamento é ruim /), mas para qualquer VCS na sua situação ("Produto" é um conjunto de "Módulos" independentes, cada "Cliente" obtém "Produtos" diferentes - essa suposição está correta?) Preferirei dividir o desenvolvimento de módulos em ramificações separadas, ter o Produto como "Supermodule" (também ramificação?), cada módulo vinculado a uma revisão específica do módulo - branch, o módulo-development usa o paradigma de branch-per-task (e o module-branch consiste apenas em mesclagens).

Dessa forma, você sempre pode saber qual "Coleção" (ou seja, conjunto de módulos e suas revisões correspondentes) forma cada "Produto", tem a possibilidade de executar IC (para ramos de tarefas concluídos e mesclados ), Teste de Unidade e Compilações


1

Pergunta principal do anúncio: Eu acredito que você está falando exatamente sobre o que é o modelo de ramificação bem-sucedido do git (e o fluxo git da ferramenta auxiliar para suportá-lo). Tenha uma ramificação principal, que esteja sempre no estado implementável e faça todo o trabalho nas ramificações de recursos.

Você também pode usar o processo usado pelo próprio git, que é derivado do mesmo princípio básico. No desenvolvimento do git-core, todo o trabalho acontece nas ramificações dos recursos. Os ramos do recurso são enviados ao integrador, que executa um script para mesclar todos eles para criar um ramo chamado pu(atualizações propostas). Várias pessoas pegam esse ramo e trabalham com ele para testá-lo.

Em vez de integrador, você pode fazer com que o servidor de integração contínua faça essa mesclagem no início de uma construção. Dessa forma, sempre que alguém da equipe envia alterações para o repositório central como uma ramificação de recursos (provavelmente usando alguma convenção de nomenclatura para dizer quais ramificações devem ser selecionadas).

No git, o ramo de recursos do qual prossegue next, masterou maintdependendo de qual versão é direcionada (maint é para corrigir erros da versão atual, mestre para a versão atual em preparação e a próxima para a seguinte), mas você não terá muitas.

Enquanto os recursos estão em pu("culinária" na terminologia do mantenedor do git), eles são rebobinados e o puramo é descartado e criado novamente a cada vez, o que facilita a revisão, mas inadequado para basear outros trabalhos. Quando o ramo do recurso é mesclado em uma das linhas principais, ele é fechado para retrocessos e outras correções são feitas conforme novas confirmações.

Pessoalmente, eu recomendaria gitmelhor. É um pouco mais difícil aprender inicialmente, porque cresce mais organicamente, mas no final parece mais flexível. Mas qualquer um dos três sistemas distribuídos, git, mercurial e bazar, irá atendê-lo bem (e muitas vezes você pode até misturá-los, por exemplo, o mercurial pode puxar e empurrar de / para o repositório git e acredito que o mesmo pode fazer bazar).

Segunda pergunta: fui ensinado que "distribuído", em geral, significa que você pode mover objetos e eles mantêm sua identidade. Qual é exatamente o que o controle de versão distribuído faz: você clona o repositório e ele contém os mesmos commits e permite fazer as mesmas coisas com eles. A facilidade de ramificação e a operação desconectada são os principais recursos em nível de usuário que seguem o princípio da movimentação de commit e o layout do gráfico direcionado que permite isso.


1

Infelizmente, não há solução conhecida para bugs no código :)

Portanto, você está procurando impedir que os check-ins inacabados sejam apanhados no release principal, e a única resposta para isso é a junção do trabalho de ramificação para cada desenvolvedor. Eu fiz isso em uma empresa anterior usando o Clearcase, funcionou muito bem (embora precisássemos ter uma dúzia de administradores de clearcase).

Agora, suponho também que você executa a correção de erros na versão do produto que cada cliente possui atualmente ... portanto, você tem um problema de mesclagem trazendo correções da versão A até a versão Z. Não há maneira fácil de lidar com elas. isso, mas você precisará ter uma ramificação para cada versão enviada. A melhor maneira de lidar com isso é manter as ramificações dos recursos apenas na versão mais recente e fazer com que os clientes atualizem para obter os novos recursos, ao mesmo tempo em que executam correções de bugs diretamente no ramo de lançamento e os mesclam para todos os outros ramos de lançamento quando completo.

Não é muito bom, mas pode funcionar notavelmente bem. Você mantém o código organizado e bem separado. Também é fácil de entender para os outros desenvolvedores - pequenas correções de bugs diretamente no "código", qualquer coisa mais do que algumas linhas são feitas em um ramo dedicado, onde podem demorar o tempo que quiserem para ser concluído. (você terá que resolver os problemas de mesclagem e garantir que não há problema se 2 desenvolvedores funcionarem em dois recursos ao mesmo tempo!)

Depois de um tempo, você pode introduzir ramos de recursos também nos ramos de lançamento, onde os erros são corrigidos e depois mesclados, mas IMHO isso normalmente é mais esforço do que o necessário. Se você precisar adicionar recursos a versões antigas, precisará seguir esta abordagem - ramificar uma ramificação de release, mesclar o código de volta para esse release e mesclar a alteração para os releases posteriores. Isso deixará sua equipe de teste muito infeliz, pois os lançamentos sofrerão um grande atraso devido à necessidade de testar várias versões repetidamente, e a equipe de desenvolvimento, infeliz, pois eles terão que fazer muita fusão antes que possam iniciar o novo código (na minha empresa atual isso acontece, principalmente devido à quantidade de trabalho que temos que sempre precisa ser concluído o mais rápido possível).

DVCS:

basicamente, um DVCS é onde todos têm sua própria cópia do repositório do servidor. Ele tem algumas vantagens (especialmente em equipes distribuídas com comunicação limitada), mas também possui algumas desvantagens, portanto, verifique-as antes de mudar para um DVCS. Se você é uma loja do Windows, provavelmente encontrará o Mercurial como o melhor DVCS para você.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.