Puxando o gatilho: migrando do SVN para o Git

Matt Shelton
Matt Shelton
Voltar para a lista

A gente está migrando para o Git e descobriu como usar o git-flow e o Maven juntos em um fluxo de trabalho de desenvolvimento eficiente. Antes de entrar na aparência atual do fluxo de trabalho, é importante saber de onde a gente partiu.

De volta aos velhos tempos...

No nosso mundo anterior, antes de migrar do SVN para o Git, todo o nosso gerenciamento de versões era manual. O desenvolvimento ocorreu no tronco simultaneamente em todos os recursos ativos da equipe. Quando um desenvolvedor fazia o commit das suas alterações no SVN, o Bamboo iniciava um build de instantâneo (1.0.0-SNAPSHOT). Se o trabalho deles passasse no teste de integração, eles executariam o plano de versão depois de verificar manualmente que ninguém mais executou um instantâneo subsequente[1]. Seria feito logo um smoke test para o build dessa versão (1.0.0-1)[2] e depois ele seria entregue ao controle de qualidade para validação funcional.

Estávamos "lançando" o tempo todo; cada build que foi para o controle de qualidade era de um objetivo de versão do Maven sem aumentar o número menor ou o número do patch. Tínhamos o Bamboo alinhado ao -buildnumber em cada versão para que pudéssemos rastrear versões específicas para o controle de qualidade.

Então, após o "último" ser liberado pelo controle de qualidade para essa versão, incrementávamos a versão secundária usando mvn version:set. Ou seja: se o produto final não estivesse na sua melhor forma, corríamos o risco de esquecer de aumentar o número da versão e construir uma "versão" 1.0.0-x depois do que lançamos para produção. Muita bagunça. Muita dor. Mas assim cada build fora do desenvolvimento tinha um número claro, rastreável e permanente.

Era "bom", mas era um pesadelo para rastrear.

Não queríamos mais que fosse assim. Só queríamos lançar quando algo fosse sair pela porta já pronto para o cliente. Além disso, sem mais números de build em produção — apenas major.minor.patch.

No entanto, também queríamos garantir que o controle de qualidade tivesse uma maneira de rastrear uma entrega específica para uma versão específica. O controle de qualidade não podia testar versões de SNAPSHOT o tempo todo. Felizmente, o Jira Software facilita esse ponto mostrando links entre itens do Jira, repositórios do Bitbucket e planos de build contendo builds para esse item.

No final, decidimos seguir algumas regras:

  1. Os desenvolvedores realizam testes de integração a partir do branch feature, que eles estão mantendo atualizados com o branch develop.
  2. Depois que o teste de integração é concluído e aprovado, eles emitem uma pull request e têm seu código puxado para o branch develop.
  3. Eles promovem um corte do candidato a controle de qualidade do nosso projeto comum e, em seguida, acionam um corte de desenvolvimento do candidato a controle de qualidade para seu projeto de produto. Como precisamos usar uma versão de projeto comum específica no momento do build[3], solicitamos a um desenvolvedor a versão de lançamento candidata ao controle de qualidade comum mencionada antes.
  4. Os testes de controle de qualidade testam somente builds de candidatos a testes de controle de qualidade. Nunca instantâneos.

Repetimos as etapas de 1 a 5 para todos os recursos, bugs encontrados no controle de qualidade, etc. Então, quando terminamos os esforços de uma versão, seguimos o git-flow e fazemos o branch para um branch de versão promovendo um build candidato a controle de qualidade específico no Bamboo. Assim é criado nosso primeiro conjunto de candidatos à versão, e o controle de qualidade realiza testes finais, testes de regressão, etc.

Construindo da maneira certa

Fazer os builds da maneira certa pode ser complicado. Antes de mudarmos todos do SVN e nossos planos de build originais do Bamboo, montamos um projeto de POC e, em seguida, elaboramos todos os nossos planos do Bamboo usando esses recursos. No final, descobrimos que os seguintes planos atenderam às nossas necessidades:

  1. develop: acionado a partir do Bitbucket Server, ele cria builds SNAPSHOT com cada alteração obtida de pull requests. O plano de build tem três etapas:
    1. Instantâneo - cria instantâneos e não toca nas versões.
    2. Build de controle de qualidade - cria uma versão "candidata do controle de qualidade" numerada X.Y.Z-qa {buildnumber} a partir do mesmo commit do git usado para criar esse instantâneo.
    3. Promover para lançamento - cria o branch de versão e incrementa o número da versão menor de desenvolvimento, tudo a partir do mesmo commit do git usado para criar o build de controle de qualidade.
  2. recurso: configurado com um plano de build padrão, mas o principal é observar novos branches criados com feature/* no nome, usando o recurso de branches de plano do Bamboo e cria um plano para esse branch sempre que for esse o caso. Ele tem apenas um estágio, que cria SNAPSHOTs. [4] Além disso, como não queremos que o recurso seja criado por si mesmo, apontamos seu repositório para um branch chamado "fake-branch" para que ele nunca seja acionado.
  3. versão e hotfix: eles têm o mesmo conjunto de etapas de build e versão para que possam compartilhar um plano. O plano também aponta para um "fake-branch" e apenas corta versões baseadas em planos de branch com os dois estágios a seguir:
    1. Criar versão candidata - essa etapa cria uma versão com o número X.Y.Z-rc {buildnumber}.
    2. Finalizar versão - essa etapa define o número final da versão, faz o merge até o principal e cria uma tag. Em seguida, ele remove o branch da versão que desativa o plano.
  4. suporte: é quase idêntico à versão e ao hotfix, mas nunca passa por merge para o principal. Em vez disso, incrementamos a versão secundária no final da etapa Finalizar versão.

Como o recurso, o hotfix de versão e os planos de suporte estão executando planos de branch, quando você os visualiza no Bamboo, aparece escrito “Nunca construído” para cada plano. Na primeira vez que aconteceu, todos ficaram com cara de paisagem pensando onde estavam os builds, mas então percebemos que as coisas faziam sentido.

Temos tantos planos de build[5] que se o Bamboo exibisse todos os planos em linha, incluindo planos de branch, você ficaria rolando a tela pelo resto da vida. A sobrecarga de informações seria, na verdade, menos útil. Então, clicamos mais uma vez para ver o status do nosso plano de branch. Não é grande coisa, mas seria bom encontrar uma maneira fácil de ver todos eles.[6]

Processo de migração

Uma vez que ficamos satisfeitos que o projeto POC funcionou da maneira que queríamos e tínhamos um fluxo de trabalho do desenvolvedor consistente e confiável, executamos uma importação de nossa base de código SVN para o Git e executamos várias outras iterações de teste de cada fluxo de trabalho possível para resolver problemas de build, esquisitices de fluxo de trabalho, etc.

Encontramos algumas coisas, como minha nota acima sobre limpar o espaço de trabalho do Maven toda vez que você executa um build de branch de recurso no Bamboo, e certas vezes precisávamos de várias marcações para um ciclo de vida específico do Maven. Geralmente, era fácil de descobrir, mas de vez em quando tinha um monte de mãos tremendo e dentes rangendo.[8]

Depois disso, decidimos que era agora ou nunca e anunciamos nossa data de migração. Como parte da migração, decidimos fazer várias limpezas para que nosso repositório Git tenha um bom ponto de partida. Fizemos coisas como:

  • Reformatação de código em massa para que possamos habilitar algumas verificações de estilo mais rígidas como parte do processo de build
  • Convertemos todas as terminações de linha para UNIX
  • Comprimimos três projetos de dependência de nível superior em um e refatoramos todo o código dependente como resultado

Com essas coisas fora do caminho, expulsamos todo mundo do SVN, trocamos para somente leitura e fizemos uma extração final para o Git. Conduzimos uma sessão de treinamento com todos os nossos desenvolvedores para analisar nosso fluxo de trabalho mais uma vez e mostrar ele em ação com a base de código real.

Foi a migração mais tranquila que eu já experimentei. Congelamos o SVN por volta das 17h de uma segunda-feira e às 22h resolvemos com todos os nossos itens de build inicial. Não houve itens difíceis; algumas coisas exigiram muita espera. O treinamento foi na manhã seguinte e ficamos fazendo trabalho de gestão de recursos até o almoço.

Novo fluxo de desenvolvedor

Depois da migração, pudemos ver como esse fluxo de trabalho funcionaria no mundo real. Quando um desenvolvedor começa a trabalhar em um recurso (ABC-4321), ele precisa fazer algumas coisas antes de começar:

  1. No Jira Software, na área de Desenvolvimento do item, clique em Criar branch.
  2. Essa ação abre uma tela no Bitbucket Server que permite selecionar o tipo de branch (em geral feature), o repositório e o nome do branch. Devido à nossa extensão Maven que mencionei no texto anterior, o nome do branch é sempre a chave do item do Jira, sem descrição.
  3. Repita as etapas de 1 a 2 para cada um dos projetos associados a esse recurso, sempre usando a mesma chave do item.
  4. git pull && git checkout origin/feature/ABC-4321 feature/ABC-4321[7]

Esse fluxo de trabalho é direto, repetível e confiável. Os desenvolvedores podem trabalhar isolados e extrair contribuições de mudanças do desenvolvimento à medida que avançam. A ação de criação de branches pode parecer um pouco repetitiva se, digamos, uma história do usuário funcionar em todas as quatro verticais de nossos produtos e no projeto comum. Estamos pensando em criar uma automatização com algum tipo de pós-função do fluxo de trabalho do Jira para chamar a API REST do Bitbucket Server, mas pode ser um exagero para algo que não está nos custando muito tempo do desenvolvedor.

Lições aprendidas

Esse processo para nos levar do SVN ao git com um fluxo de trabalho novinho em folha foi longo - do início à migração, levamos quase sete meses. A grande maioria desse tempo foi gasto lutando com o Maven.

Admito que tivemos algumas preocupações com a equipe ao longo do caminho; em paralelo a esse trabalho, o mesmo grupo de engenheiros que trabalhava na migração apoiava um departamento de 800 pessoas no conjunto de ferramentas da Atlassian, oferecendo suporte de produção para nossos aplicativos de plataforma e trabalhando em outros projetos operacionais de P&D. Quando conseguimos colocar três pessoas na migração quase em tempo integral, terminamos em cerca de um mês.

Apesar desses aspectos, aprendemos muito:

  1. Nenhuma preparação é suficiente para a coisa de verdade. Por exemplo, cada tipo de build de versão que tentamos executar falhou na primeira vez que tentamos por um ou outro motivo. Depois de corrigir o build de um projeto para esse tipo, copiamos a configuração para os outros e não tivemos uma única repetição.
  2. Esse fluxo de trabalho gera muitos builds. Muitos. Builds. Mesmo. Precisávamos dobrar nossos agentes do Bamboo para acompanhar.
  3. Esse fluxo de trabalho gera muitos artefatos de build. Na primeira semana, ficamos sem espaço em disco em nossa instância do Artifactory e tivemos que passar um dia inteiro limpando manualmente os candidatos das versões antigas e os builds de controle de qualidade que não eram mais necessários. Em seguida, precisávamos pensar em uma maneira de garantir que, quando os branches de recursos fossem removidos, também removêssemos todos os artefatos de instantâneos específicos do branch.
  4. A equipe não gosta muito de ter que escolher entre um hotfix ou um branch de suporte. Faz sentido poder cortar um hotfix, mas na maioria das vezes eles querem um branch de suporte. Podemos decidir usar hotfixes apenas em ocasiões especiais quando o merge for simples de verdade.
  5. A combinação de Jira Software, Bitbucket Server e Bamboo é um grande deboche. Observar alguém começar a trabalhar no Jira Software, criar um branch e ter um plano de branch criado e pronto de imediato para validar seu trabalho é lindo.
  6. As pull requests no Bitbucket Server são a melhor invenção depois da fritadeira elétrica. Entre manter um engenheiro feliz à distância ou garantir que estamos prontos para as contribuições de uma equipe offshore, não poderíamos estar mais felizes com o processo de pull request. Dado que realizamos inspeção de código no Crucible em vez de na pull request, ele também pode ser usado para verificações rápidas de integridade.
  7. Nossas tags anteriores baseadas em SVN foram marcadas por uma conta de serviço que estava executando o build. Como esse usuário não era real, quando tentamos criar branches a partir de tags, o git-hook para validar o usuário era válido para um determinado commit que falhou. Eu escrevi um artigo no meu blog pessoal sobre como mudar o autor de um único commit no Git, o que foi útil na primeira vez que precisamos criar um branch de suporte a partir de uma tag antiga baseada em SVN... que aconteceu um dia após a migração!

Resumindo, nossa migração foi um grande sucesso. Nem todos os problemas que minha equipe teve foram resolvidos, mas com certeza muitos foram e nos foi dada uma base mais estável para seguir em frente.

[1]: Rolou uma quantidade desconfortável de conversas do Hipchat em nossa sala de desenvolvedores para perguntar se alguém precisava fazer commit de alterações antes que um build de versão fosse feito. Antes do Hipchat: Lync, e-mail ou gritaria sobre as paredes do cubículo.

[2]: O -1 é um número de build incrementador para o plano que nunca é redefinido para 1. Não demorou muito para que os builds de lançamento tivessem números na casa dos 100.

[3]: O POM ainda se refere a uma versão -SNAPSHOT comum aqui e não pode arriscar que o build extraia o SNAPSHOT errado.

[4]: Ele também limpa à força o espaço de trabalho toda vez que é gerado. Sua experiência pode ser diferente, mas achamos essa etapa necessária.

[5]: Em toda a organização, temos cerca de 120 planos nessa instância específica do Bamboo, aumentando o tempo todo. Filtrado apenas para os planos da minha equipe, somos aproximadamente metade dessa lista. Com todos os branches, estamos chegando em 200.

[6]: Um dos meus engenheiros escreveu um script do Greasemonkey que permite que ele veja todos os planos de branch. Só funciona se você não for administrador do Bamboo devido ao número de planos visíveis. Estou trabalhando para preparar um AtlasBoard dedicado para mim.

[7]: As etapas exatas aqui variam dependendo se o desenvolvedor está usando a linha de comando ou usando o Eclipse para alternar entre branches.

[8]: Só fizemos malhação de Judas com o Maven uma ou duas vezes.

Pronto(a) para aprender Git?

Tente este tutorial interativo.

Comece agora mesmo