Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
A Microsoft se esforça para usar o One Engineering System para criar e implantar todos os produtos Microsoft com um sólido processo de DevOps centrado em um fluxo de ramificação e lançamento do Git. Este artigo destaca a implementação prática, como o sistema pode ser dimensionado de pequenos serviços para necessidades massivas de desenvolvimento de plataforma e lições aprendidas com o uso do sistema em várias equipes da Microsoft.
Adotar um processo de desenvolvimento padronizado é um empreendimento ambicioso. Os requisitos de diferentes organizações da Microsoft variam muito, e os requisitos de diferentes equipes dentro das organizações são dimensionados com tamanho e complexidade. Para atender a essas necessidades variadas, a Microsoft usa uma estratégia de ramificação baseada em tronco para ajudar a desenvolver produtos rapidamente, implantá-los regularmente e fornecer alterações com segurança à produção.
A Microsoft também usa princípios de engenharia de plataforma como parte de seu One Engineering System.
Fluxo de lançamento da Microsoft
Cada organização deve estabelecer um processo de liberação de código padrão para garantir a consistência entre as equipes. O fluxo de lançamento da Microsoft incorpora processos de DevOps do desenvolvimento ao lançamento. As etapas básicas do fluxo de liberação consistem em ramificação, push, pull request e merge.
Filial
Para corrigir um bug ou implementar um recurso, um desenvolvedor cria uma nova ramificação fora da ramificação de integração principal. O modelo de ramificação leve do Git cria essas ramificações de tópico de curta duração para cada contribuição de código. Os programadores comprometem-se antecipadamente e evitam ramificações de funcionalidades de longa duração usando sinalizadores de funcionalidades.
Push
Quando o desenvolvedor está pronto para integrar e enviar alterações para o resto da equipe, ele envia sua ramificação local para uma filial no servidor e abre uma solicitação pull. Repositórios com várias centenas de desenvolvedores trabalhando em muitas ramificações usam uma convenção de nomenclatura para ramificações de servidor para aliviar a confusão e a proliferação de ramificações. Os desenvolvedores geralmente criam ramificações com o nome users/<username>/feature, onde <username> é o nome da conta.
Pedido de Pull
Os pedidos de pull controlam a junção das ramificações de tópico nas ramificações principais e garantem que as políticas de branches sejam satisfeitas. O processo de solicitação pull cria as alterações propostas e executa um teste rápido. Os conjuntos de testes de primeiro e segundo nível executam cerca de 60.000 testes em menos de cinco minutos. Esta não é a matriz de teste completa da Microsoft, mas é suficiente para dar confiança rapidamente às solicitações pull.
Em seguida, outros membros da equipe revisam o código e aprovam as alterações. A revisão de código pega onde os testes automatizados pararam e é particularmente útil para detetar problemas de arquitetura. As revisões manuais de código garantem que outros engenheiros da equipe tenham visibilidade das alterações e que a qualidade do código permaneça alta.
Merge
Depois que o pull request satisfaz todas as políticas de compilação e os revisores aprovaram, a ramificação de tópico é fundida na ramificação de integração principal e o pull request é concluído.
Após a mesclagem, outros testes de aceitação são executados e levam mais tempo para serem concluídos. Esses testes tradicionais pós-check-in realizam uma validação mais completa. Esse processo de teste fornece um bom equilíbrio entre ter testes rápidos durante a revisão de solicitação pull e ter uma cobertura de teste completa antes da liberação.
Diferenças do fluxo do GitHub
O GitHub Flow é um fluxo de lançamento de desenvolvimento baseado em tronco popular para as organizações implementarem uma abordagem escalável ao Git. No entanto, algumas organizações acham que, à medida que suas necessidades crescem, elas devem divergir de partes do fluxo do GitHub.
Por exemplo, uma parte muitas vezes negligenciada do GitHub Flow é que as solicitações pull devem ser implantadas na produção para teste antes de poderem ser mescladas na ramificação principal. Esse processo significa que todos os pull requests aguardam na fila de implantação para fusão.
Algumas equipas têm várias centenas de desenvolvedores a trabalhar constantemente num único repositório e podem concluir mais de 200 pull requests para a ramificação principal por dia. Se cada pull request exigir uma implantação em vários data centers do Azure em todo o mundo para teste, os desenvolvedores gastarão tempo esperando que as branches se mesclem, em vez de escrever software.
Em vez disso, as equipes da Microsoft continuam desenvolvendo na ramificação principal e agrupam implantações em versões cronometradas, geralmente alinhadas com uma cadência de sprint de três semanas.
Detalhes da implementação
Aqui estão alguns detalhes de implementação importantes do fluxo de lançamento da Microsoft:
Estratégia de repositório Git
Equipes diferentes têm estratégias diferentes para gerenciar seus repositórios Git. Algumas equipes mantêm a maior parte de seu código em um repositório Git. O código é dividido em componentes, cada um em sua própria pasta de nível raiz. Componentes grandes, especialmente os mais antigos, podem ter vários subcomponentes que possuem subpastas distintas dentro do componente principal.
Repositórios adjuntos
Algumas equipes também gerenciam repositórios adjuntos. Por exemplo, agentes e tarefas de compilação e liberação, a extensão VS Code e projetos de código aberto são desenvolvidos no GitHub. As alterações de configuração são registadas num repositório separado. Outros pacotes dos quais a equipe depende vêm de outros lugares e são consumidos via NuGet.
Mono repo ou multi repo
Enquanto algumas equipes optam por ter um único repositório monolítico, o mono-repo, outros produtos da Microsoft usam uma abordagem multi-repo . O Skype, por exemplo, tem centenas de pequenos repositórios que se unem em várias combinações para criar muitos clientes, serviços e ferramentas diferentes. Especialmente para equipes que adotam microsserviços, o multi-repo pode ser a abordagem certa. Normalmente, softwares mais antigos que começaram como monólitos veem na abordagem mono-repo a forma mais fácil de transitar para o Git, e a organização do seu código reflete isso.
Liberar ramificações
O fluxo de lançamento da Microsoft mantém o ramo principal sempre pronto para construção. Os desenvolvedores trabalham em ramificações de tópicos de curta duração que se fundem ao main. Quando uma equipe está pronta para enviar, seja no final de um sprint ou para uma grande atualização, ela inicia uma nova ramificação de lançamento fora da ramificação principal. As ramificações de liberação nunca se fundem de volta à ramificação principal, por isso pode ser necessário realizar cherry-picking de alterações importantes.
O diagrama a seguir mostra ramos de curta duração em azul e ramos de liberação em preto. Um ramo com um compromisso que precisa ser escolhido a dedo aparece em vermelho.
Políticas e permissões de filiais
As políticas de ramo do Git ajudam a impor a estrutura do ramo de lançamento e a manter o ramo principal limpo. Por exemplo, as políticas de ramificação podem evitar pushes diretos para a ramificação principal.
Para manter a hierarquia de ramificações organizada, as equipes usam permissões para bloquear a criação de ramificações no nível raiz da hierarquia. No exemplo a seguir, todos podem criar ramificações em pastas como usuários/, recursos/, e equipes/. Somente os gerentes de versão têm permissão para criar ramificações em releases/, e algumas ferramentas de automação têm permissão para a pasta integrations/ .
Fluxo de trabalho do repositório Git
Dentro da estrutura do repositório e da filial, os desenvolvedores fazem seu trabalho diário. Os ambientes de trabalho variam muito consoante a equipa e o indivíduo. Alguns desenvolvedores preferem a linha de comando, outros como o Visual Studio e outros trabalham em plataformas diferentes. As estruturas e políticas em vigor nos repositórios da Microsoft garantem uma base sólida e consistente.
Um fluxo de trabalho típico envolve as seguintes tarefas comuns:
Crie um novo recurso
Criar um novo recurso é o núcleo do trabalho de um desenvolvedor de software. As partes não-Git do processo incluem examinar dados de telemetria, criar um design e uma especificação e escrever o código real. Em seguida, o programador começa a trabalhar com o repositório sincronizando-se ao commit mais recente no main. O ramo principal é sempre construível, portanto é garantido ser um bom ponto de partida. O desenvolvedor acede a um novo ramo de funcionalidade, faz alterações de código, confirma, envia por push para o servidor e inicia um novo pedido de pull.
Usar políticas e verificações de filiais
Após a criação de uma solicitação pull, os sistemas automatizados verificam se o novo código é compilado, não quebra nada e não viola nenhuma política de segurança ou conformidade. Este processo não impede que outros trabalhos aconteçam em paralelo.
As políticas e verificações de filiais podem exigir uma compilação bem-sucedida , incluindo testes aprovados, aprovação pelos proprietários de qualquer código tocado e várias verificações externas para verificar as políticas corporativas antes que uma solicitação pull possa ser concluída.
Integração com o Microsoft Teams
Muitas equipes configuram a integração com o Microsoft Teams, que anuncia a nova solicitação pull para os colegas de equipe dos desenvolvedores. Os proprietários de qualquer código tocado são adicionados automaticamente como revisores. As equipes da Microsoft geralmente usam revisores opcionais para códigos que muitas pessoas tocam, como geração de clientes REST e controles compartilhados, para obter olhares de especialistas sobre essas alterações.
Implantar com sinalizadores de recursos
Assim que os revisores, os proprietários do código e a automação estiverem satisfeitos, o desenvolvedor poderá concluir a solicitação pull. Se houver um conflito de mesclagem, o desenvolvedor receberá instruções sobre como sincronizar com o conflito, corrigi-lo e enviar novamente as alterações. A automação é executada novamente no código fixo, mas os humanos não precisam assinar novamente.
A ramificação funde-se no main, e o novo código é implementado no próximo ciclo de desenvolvimento ou na próxima versão principal. Isso não significa que o novo recurso aparecerá imediatamente. A Microsoft separa a implantação e a exposição de novos recursos usando sinalizadores de recursos.
Mesmo que o recurso precise de um pouco mais de trabalho antes de estar pronto para demonstração, é seguro proceder para main se o produto for compilado e implantado. Uma vez no main, o código se torna parte de uma compilação oficial, onde é novamente testado, confirmado para atender à política e assinado digitalmente.
Desloque para a esquerda para identificar problemas antecipadamente
Esse fluxo de trabalho do Git oferece vários benefícios. Primeiro, trabalhar a partir de um único ramo principal praticamente elimina a dívida de fusão. Em segundo lugar, o fluxo de solicitação pull fornece um ponto comum para impor testes, revisão de código e deteção de erros no início do pipeline. Essa estratégia de mudança para a esquerda ajuda a encurtar o ciclo de feedback para os desenvolvedores, pois pode detetar erros em minutos, não horas ou dias. Esta estratégia também dá confiança para a refatoração, porque todas as mudanças são testadas constantemente.
Atualmente, um produto com 200+ solicitações pull pode produzir 300+ compilações de integração contínua por dia, totalizando 500+ execuções de teste a cada 24 horas. Esse nível de teste seria impossível sem o fluxo de trabalho de ramificação e liberação baseado em tronco.
Lançamento em marcos de sprint
No final de cada sprint, a equipe cria uma ramificação de liberação da ramificação principal. Por exemplo, no final do sprint 129, a equipa cria uma nova ramificação de lançamento releases/M129. A equipe então coloca a ramificação sprint 129 em produção.
Após a ramificação da ramificação de lançamento, a ramificação principal permanece aberta para os desenvolvedores mesclarem as alterações. Essas alterações serão implantadas três semanas depois na próxima implantação de sprint.
Hotfixes de versão
Às vezes, as mudanças precisam entrar em produção rapidamente. A Microsoft geralmente não adiciona novos recursos no meio de um sprint, mas às vezes quer trazer uma correção de bug rapidamente para desbloquear usuários. Os problemas podem ser menores, como erros de digitação, ou grandes o suficiente para causar um problema de disponibilidade ou um incidente no site ativo.
A correção desses problemas começa com o fluxo de trabalho normal. Um desenvolvedor cria uma ramificação a partir de main, tem o código revisado, e conclui o pull request para mesclá-la. O processo começa sempre por fazer a alteração em main primeiro. Isso permite criar a correção rapidamente e validá-la localmente sem ter que alternar para a ramificação de versão.
Seguir esse processo também garante que a mudança entre no main, o que é fundamental. Corrigir um bug na ramificação de lançamento sem trazer a alteração de volta ao main significaria que o bug se repetiria durante a próxima implantação, quando as ramificações de lançamento do sprint 130 desde o main. É fácil esquecer de atualizar main durante a confusão e o estresse que podem surgir durante uma interrupção. Trazer mudanças para o main primeiro significa sempre ter as mudanças tanto no ramo principal quanto no ramo de lançamento.
A funcionalidade Git permite esse fluxo de trabalho. Para trazer as alterações imediatamente para a produção, assim que um desenvolvedor mescla uma solicitação pull no main, ele pode usar a página pull request para selecionar as alterações na ramificação de lançamento. Esse processo cria um novo pedido de pull direcionado à ramificação de release, retroportando o conteúdo que acabou de ser incluído no main.
O uso da funcionalidade cherry-pick abre um pedido de pull rapidamente, garantindo rastreabilidade e confiabilidade das políticas de ramo. A escolha seletiva pode acontecer no servidor, sem ter que baixar a ramificação de lançamento para um computador local. Fazer alterações, corrigir conflitos de mesclagem ou fazer pequenas alterações devido a diferenças entre as duas ramificações podem acontecer no servidor. As equipas podem editar as alterações diretamente a partir do editor de texto baseado no navegador ou através da Pull Request Merge Conflict Extension para uma experiência mais avançada.
Quando uma solicitação pull tem como alvo a ramificação de versão, o código da equipe a revisa novamente, avalia as políticas de ramificação, testa a solicitação pull e a mescla. Após a mesclagem, a correção é implantada no primeiro anel de servidores em minutos. A partir daí, a equipe implanta progressivamente a correção em mais contas usando anéis de implantação. À medida que as alterações são implantadas para mais usuários, a equipe monitora o sucesso e verifica se a alteração corrige o bug, sem introduzir nenhuma deficiência ou lentidão. A correção eventualmente é implantada em todos os data centers do Azure.
Passar para o próximo sprint
Durante as próximas três semanas, a equipe termina de adicionar recursos ao sprint 130 e se prepara para implantar essas alterações. Eles criam a nova ramificação de versão, releases/M130 a partir de main, e implantam essa ramificação.
Neste ponto, existem na verdade dois ramos na produção. Com uma implantação baseada em anel para trazer alterações para a produção com segurança, o anel rápido recebe as alterações do sprint 130 e os servidores de anel lento permanecem no sprint 129 enquanto as novas alterações são validadas na produção.
Corrigir uma alteração no meio de uma implantação pode exigir o hotfix de duas versões diferentes, a versão sprint 129 e a versão sprint 130. A equipe porta e implanta o hotfix para ambas as ramificações de versão. A ramificação 130 é reimplantada com o hotfix para os anéis que já foram atualizados. A ramificação 129 reimplementa-se com o hotfix para os anéis externos que ainda não foram atualizados para a próxima versão da sprint.
Uma vez que todos os anéis são implantados, a ramificação sprint 129 antiga é abandonada, porque todas as alterações trazidas para a ramificação sprint 129 como um hotfix também foram feitas no main. Então, essas mudanças também serão no releases/M130 ramo.
Resumo
O modelo de fluxo de lançamento está no centro de como a Microsoft se desenvolve com DevOps para fornecer serviços online. Este modelo usa uma estratégia de ramificação simples baseada em tronco. Mas, em vez de manter os desenvolvedores presos em uma fila de implantação, esperando para mesclar suas alterações, o fluxo de lançamento da Microsoft permite que os desenvolvedores continuem trabalhando.
Esse modelo de lançamento também permite implantar novos recursos em data centers do Azure em uma cadência regular, apesar do tamanho das bases de código da Microsoft e do número de desenvolvedores trabalhando nelas. O modelo também permite introduzir correções urgentes na produção de forma rápida e eficiente.